Merge pull request #3005 from RedHatter/devtools

Debug events
pull/3540/head
Rich Harris 6 years ago committed by GitHub
commit 3d0a3cd943
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

2
package-lock.json generated

@ -1,6 +1,6 @@
{
"name": "svelte",
"version": "3.10.1",
"version": "3.11.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

@ -6,7 +6,12 @@ import Stats from '../Stats';
import { globals, reserved } from '../utils/names';
import { namespaces, valid_namespaces } from '../utils/namespaces';
import create_module from './create_module';
import { create_scopes, extract_names, Scope, extract_identifiers } from './utils/scope';
import {
create_scopes,
extract_names,
Scope,
extract_identifiers,
} from './utils/scope';
import Stylesheet from './css/Stylesheet';
import { test } from '../config';
import Fragment from './nodes/Fragment';
@ -41,7 +46,13 @@ childKeys.EachBlock = childKeys.IfBlock = ['children', 'else'];
childKeys.Attribute = ['value'];
childKeys.ExportNamedDeclaration = ['declaration', 'specifiers'];
function remove_node(code: MagicString, start: number, end: number, body: Node, node: Node) {
function remove_node(
code: MagicString,
start: number,
end: number,
body: Node,
node: Node
) {
const i = body.indexOf(node);
if (i === -1) throw new Error('node not in list');
@ -101,7 +112,12 @@ export default class Component {
node_for_declaration: Map<string, Node> = new Map();
partly_hoisted: string[] = [];
fully_hoisted: string[] = [];
reactive_declarations: Array<{ assignees: Set<string>; dependencies: Set<string>; node: Node; declaration: Node }> = [];
reactive_declarations: Array<{
assignees: Set<string>;
dependencies: Set<string>;
node: Node;
declaration: Node;
}> = [];
reactive_declaration_nodes: Set<Node> = new Set();
has_reactive_assignments = false;
injected_reactive_declaration_vars: Set<string> = new Set();
@ -114,7 +130,10 @@ export default class Component {
locate: (c: number) => { line: number; column: number };
// TODO this does the same as component.locate! remove one or the other
locator: (search: number, startIndex?: number) => {
locator: (
search: number,
startIndex?: number
) => {
line: number;
column: number;
};
@ -144,27 +163,46 @@ export default class Component {
this.source = source;
this.compile_options = compile_options;
this.file = compile_options.filename && (
this.file =
compile_options.filename &&
// eslint-disable-next-line no-useless-escape
typeof process !== 'undefined' ? compile_options.filename.replace(process.cwd(), '').replace(/^[\/\\]/, '') : compile_options.filename
);
(typeof process !== 'undefined'
? compile_options.filename
.replace(process.cwd(), '')
.replace(/^[\/\\]/, '')
: compile_options.filename);
this.locate = getLocator(this.source);
this.code = new MagicString(source);
// styles
this.stylesheet = new Stylesheet(source, ast, compile_options.filename, compile_options.dev);
this.stylesheet = new Stylesheet(
source,
ast,
compile_options.filename,
compile_options.dev
);
this.stylesheet.validate(this);
this.component_options = process_component_options(this, this.ast.html.children);
this.namespace = namespaces[this.component_options.namespace] || this.component_options.namespace;
this.component_options = process_component_options(
this,
this.ast.html.children
);
this.namespace =
namespaces[this.component_options.namespace] ||
this.component_options.namespace;
if (compile_options.customElement) {
if (this.component_options.tag === undefined && compile_options.tag === undefined) {
const svelteOptions = ast.html.children.find(child => child.name === 'svelte:options') || { start: 0, end: 0 };
if (
this.component_options.tag === undefined &&
compile_options.tag === undefined
) {
const svelteOptions = ast.html.children.find(
child => child.name === 'svelte:options'
) || { start: 0, end: 0 };
this.warn(svelteOptions, {
code: 'custom-element-no-tag',
message: `No custom element 'tag' option was specified. To automatically register a custom element, specify a name with a hyphen in it, e.g. <svelte:options tag="my-thing"/>. To hide this warning, use <svelte:options tag={null}/>`
message: `No custom element 'tag' option was specified. To automatically register a custom element, specify a name with a hyphen in it, e.g. <svelte:options tag="my-thing"/>. To hide this warning, use <svelte:options tag={null}/>`,
});
}
this.tag = this.component_options.tag || compile_options.tag;
@ -199,7 +237,7 @@ export default class Component {
this.add_var({
name,
injected: true,
referenced: true
referenced: true,
});
} else if (name[0] === '$') {
this.add_var({
@ -207,7 +245,7 @@ export default class Component {
injected: true,
referenced: true,
mutated: true,
writable: true
writable: true,
});
const subscribable_name = name.slice(1);
@ -257,35 +295,52 @@ export default class Component {
const { compile_options, name } = this;
const { format = 'esm' } = compile_options;
const banner = `/* ${this.file ? `${this.file} ` : ``}generated by Svelte v${"__VERSION__"} */`;
const banner = `/* ${
this.file ? `${this.file} ` : ``
}generated by Svelte v${'__VERSION__'} */`;
result = result
.replace(/__svelte:self__/g, this.name)
.replace(compile_options.generate === 'ssr' ? /(@+|#+)(\w*(?:-\w*)?)/g : /(@+)(\w*(?:-\w*)?)/g, (_match: string, sigil: string, name: string) => {
if (sigil === '@') {
if (name[0] === '_') {
return this.global(name.slice(1));
}
.replace(
compile_options.generate === 'ssr'
? /(@+|#+)(\w*(?:-\w*)?)/g
: /(@+)(\w*(?:-\w*)?)/g,
(_match: string, sigil: string, name: string) => {
if (sigil === '@') {
if (name[0] === '_') {
return this.global(name.slice(1));
}
if (!internal_exports.has(name)) {
throw new Error(`compiler error: this shouldn't happen! generated code is trying to use inexistent internal '${name}'`);
}
if (!internal_exports.has(name)) {
throw new Error(
`compiler error: this shouldn't happen! generated code is trying to use inexistent internal '${name}'`
);
}
if (compile_options.dev) {
if (internal_exports.has(`${name}_dev`)) name = `${name}_dev`;
else if (internal_exports.has(`${name}Dev`))
name = `${name}Dev`;
}
if (compile_options.dev && internal_exports.has(`${name}Dev`)) {
name = `${name}Dev`;
return this.helper(name);
}
return this.helper(name);
return sigil.slice(1) + name;
}
);
return sigil.slice(1) + name;
});
const referenced_globals = Array.from(this.globals, ([name, alias]) => name !== alias && ({ name, alias })).filter(Boolean);
const referenced_globals = Array.from(
this.globals,
([name, alias]) => name !== alias && { name, alias }
).filter(Boolean);
if (referenced_globals.length) {
this.helper('globals');
}
const imported_helpers = Array.from(this.helpers, ([name, alias]) => ({ name, alias }));
const imported_helpers = Array.from(this.helpers, ([name, alias]) => ({
name,
alias,
}));
const module = create_module(
result,
@ -296,10 +351,12 @@ export default class Component {
imported_helpers,
referenced_globals,
this.imports,
this.vars.filter(variable => variable.module && variable.export_name).map(variable => ({
name: variable.name,
as: variable.export_name
})),
this.vars
.filter(variable => variable.module && variable.export_name)
.map(variable => ({
name: variable.name,
as: variable.export_name,
})),
this.source
);
@ -343,16 +400,16 @@ export default class Component {
add_string(final_chunk);
css = compile_options.customElement ?
{ code: null, map: null } :
this.stylesheet.render(compile_options.cssOutputFilename, true);
css = compile_options.customElement
? { code: null, map: null }
: this.stylesheet.render(compile_options.cssOutputFilename, true);
js = {
code: compiled.toString(),
map: compiled.generateMap({
includeContent: true,
file: compile_options.outputFilename,
})
}),
};
}
@ -361,17 +418,19 @@ export default class Component {
css,
ast: this.ast,
warnings: this.warnings,
vars: this.vars.filter(v => !v.global && !v.internal).map(v => ({
name: v.name,
export_name: v.export_name || null,
injected: v.injected || false,
module: v.module || false,
mutated: v.mutated || false,
reassigned: v.reassigned || false,
referenced: v.referenced || false,
writable: v.writable || false
})),
stats: this.stats.render()
vars: this.vars
.filter(v => !v.global && !v.internal)
.map(v => ({
name: v.name,
export_name: v.export_name || null,
injected: v.injected || false,
module: v.module || false,
mutated: v.mutated || false,
reassigned: v.reassigned || false,
referenced: v.referenced || false,
writable: v.writable || false,
})),
stats: this.stats.render(),
};
}
@ -406,8 +465,7 @@ export default class Component {
let alias = name;
for (
let i = 1;
this.used_names.has(alias) ||
local_used_names.has(alias);
this.used_names.has(alias) || local_used_names.has(alias);
alias = `${name}_${i++}`
);
local_used_names.add(alias);
@ -432,7 +490,7 @@ export default class Component {
source: this.source,
start: pos.start,
end: pos.end,
filename: this.compile_options.filename
filename: this.compile_options.filename,
});
}
@ -467,7 +525,8 @@ export default class Component {
end,
pos: pos.start,
filename: this.compile_options.filename,
toString: () => `${warning.message} (${start.line + 1}:${start.column})\n${frame}`,
toString: () =>
`${warning.message} (${start.line + 1}:${start.column})\n${frame}`,
});
}
@ -490,7 +549,7 @@ export default class Component {
if (node.type === 'ExportDefaultDeclaration') {
this.error(node, {
code: `default-export`,
message: `A component cannot have a default export`
message: `A component cannot have a default export`,
});
}
@ -498,7 +557,7 @@ export default class Component {
if (node.source) {
this.error(node, {
code: `not-implemented`,
message: `A component currently cannot have an export ... from`
message: `A component currently cannot have an export ... from`,
});
}
if (node.declaration) {
@ -538,7 +597,8 @@ export default class Component {
if (this.hoistable_nodes.has(node)) return false;
if (this.reactive_declaration_nodes.has(node)) return false;
if (node.type === 'ImportDeclaration') return false;
if (node.type === 'ExportDeclaration' && node.specifiers.length > 0) return false;
if (node.type === 'ExportDeclaration' && node.specifiers.length > 0)
return false;
return true;
});
@ -551,8 +611,11 @@ export default class Component {
let result = '';
script.content.body.forEach((node) => {
if (this.hoistable_nodes.has(node) || this.reactive_declaration_nodes.has(node)) {
script.content.body.forEach(node => {
if (
this.hoistable_nodes.has(node) ||
this.reactive_declaration_nodes.has(node)
) {
if (a !== b) result += `[✂${a}-${b}✂]`;
a = node.end;
}
@ -580,10 +643,10 @@ export default class Component {
if (node.type === 'LabeledStatement' && node.label.name === '$') {
component.warn(node, {
code: 'module-script-reactive-declaration',
message: '$: has no effect in a module script'
message: '$: has no effect in a module script',
});
}
}
},
});
this.add_sourcemap_locations(script.content);
@ -595,7 +658,7 @@ export default class Component {
if (name[0] === '$') {
this.error(node, {
code: 'illegal-declaration',
message: `The $ prefix is reserved, and cannot be used for variable and import names`
message: `The $ prefix is reserved, and cannot be used for variable and import names`,
});
}
@ -603,7 +666,7 @@ export default class Component {
name,
module: true,
hoistable: true,
writable: node.kind === 'var' || node.kind === 'let'
writable: node.kind === 'var' || node.kind === 'let',
});
});
@ -611,12 +674,12 @@ export default class Component {
if (name[0] === '$') {
this.error(node, {
code: 'illegal-subscription',
message: `Cannot reference store value inside <script context="module">`
message: `Cannot reference store value inside <script context="module">`,
});
} else {
this.add_var({
name,
global: true
global: true,
});
}
});
@ -648,7 +711,9 @@ export default class Component {
});
});
const { scope: instance_scope, map, globals } = create_scopes(script.content);
const { scope: instance_scope, map, globals } = create_scopes(
script.content
);
this.instance_scope = instance_scope;
this.instance_scope_map = map;
@ -656,7 +721,7 @@ export default class Component {
if (name[0] === '$') {
this.error(node, {
code: 'illegal-declaration',
message: `The $ prefix is reserved, and cannot be used for variable and import names`
message: `The $ prefix is reserved, and cannot be used for variable and import names`,
});
}
@ -664,7 +729,7 @@ export default class Component {
name,
initialised: instance_scope.initialised_declarations.has(name),
hoistable: /^Import/.test(node.type),
writable: node.kind === 'var' || node.kind === 'let'
writable: node.kind === 'var' || node.kind === 'let',
});
this.node_for_declaration.set(name, node);
@ -679,12 +744,12 @@ export default class Component {
injected: true,
writable: true,
reassigned: true,
initialised: true
initialised: true,
});
} else if (name === '$$props') {
this.add_var({
name,
injected: true
injected: true,
});
} else if (name[0] === '$') {
if (name === '$' || name[1] === '$') {
@ -698,7 +763,7 @@ export default class Component {
name,
injected: true,
mutated: true,
writable: true
writable: true,
});
this.add_reference(name.slice(1));
@ -708,7 +773,7 @@ export default class Component {
} else {
this.add_var({
name,
global: true
global: true,
});
}
});
@ -768,7 +833,7 @@ export default class Component {
if (map.has(node)) {
scope = scope.parent;
}
}
},
});
}
@ -784,10 +849,14 @@ export default class Component {
scope = map.get(node);
}
if (node.type === 'LabeledStatement' && node.label.name === '$' && parent.type !== 'Program') {
if (
node.type === 'LabeledStatement' &&
node.label.name === '$' &&
parent.type !== 'Program'
) {
component.warn(node, {
code: 'non-top-level-reactive-declaration',
message: '$: has no effect outside of the top-level'
message: '$: has no effect outside of the top-level',
});
}
@ -805,7 +874,7 @@ export default class Component {
if (map.has(node)) {
scope = scope.parent;
}
}
},
});
}
@ -820,7 +889,13 @@ export default class Component {
return `${name.slice(1)}.set(${name})`;
}
if (variable && !variable.referenced && !variable.is_reactive_dependency && !variable.export_name && !name.startsWith('$$')) {
if (
variable &&
!variable.referenced &&
!variable.is_reactive_dependency &&
!variable.export_name &&
!name.startsWith('$$')
) {
return value || name;
}
@ -832,7 +907,9 @@ export default class Component {
const deps = new Set([name]);
deps.forEach(name => {
const reactive_declarations = this.reactive_declarations.filter(x => x.assignees.has(name));
const reactive_declarations = this.reactive_declarations.filter(x =>
x.assignees.has(name)
);
reactive_declarations.forEach(declaration => {
declaration.dependencies.forEach(name => {
deps.add(name);
@ -840,7 +917,9 @@ export default class Component {
});
});
return Array.from(deps).map(n => `$$invalidate('${n}', ${n})`).join(', ');
return Array.from(deps)
.map(n => `$$invalidate('${n}', ${n})`)
.join(', ');
}
rewrite_props(get_insert: (variable: Var) => string) {
@ -876,7 +955,7 @@ export default class Component {
if (variable.export_name) {
component.error(declarator, {
code: 'destructured-prop',
message: `Cannot declare props in destructured declaration`
message: `Cannot declare props in destructured declaration`,
});
}
@ -887,7 +966,11 @@ export default class Component {
if (inserts.length > 0) {
if (next) {
code.overwrite(declarator.end, next.start, `; ${inserts.join('; ')}; ${node.kind} `);
code.overwrite(
declarator.end,
next.start,
`; ${inserts.join('; ')}; ${node.kind} `
);
} else {
code.appendLeft(declarator.end, `; ${inserts.join('; ')}`);
}
@ -909,7 +992,11 @@ export default class Component {
: null;
if (!current_group || (current_group.insert && insert)) {
current_group = { kind: node.kind, declarators: [declarator], insert };
current_group = {
kind: node.kind,
declarators: [declarator],
insert,
};
coalesced_declarations.push(current_group);
} else if (insert) {
current_group.insert = insert;
@ -918,17 +1005,28 @@ export default class Component {
current_group.declarators.push(declarator);
}
if (variable.writable && variable.name !== variable.export_name) {
code.prependRight(declarator.id.start, `${variable.export_name}: `);
if (
variable.writable &&
variable.name !== variable.export_name
) {
code.prependRight(
declarator.id.start,
`${variable.export_name}: `
);
}
if (next) {
const next_variable = component.var_lookup.get(next.id.name);
const new_declaration = !next_variable.export_name
|| (current_group.insert && next_variable.subscribable);
const new_declaration =
!next_variable.export_name ||
(current_group.insert && next_variable.subscribable);
if (new_declaration) {
code.overwrite(declarator.end, next.start, ` ${node.kind} `);
code.overwrite(
declarator.end,
next.start,
` ${node.kind} `
);
}
}
} else {
@ -938,7 +1036,11 @@ export default class Component {
const insert = get_insert(variable);
if (next) {
code.overwrite(declarator.end, next.start, `; ${insert}; ${node.kind} `);
code.overwrite(
declarator.end,
next.start,
`; ${insert}; ${node.kind} `
);
} else {
code.appendLeft(declarator.end, `; ${insert}`);
}
@ -957,7 +1059,7 @@ export default class Component {
if (map.has(node)) {
scope = scope.parent;
}
}
},
});
coalesced_declarations.forEach(group => {
@ -980,11 +1082,11 @@ export default class Component {
});
if (combining) {
const insert = group.insert
? `; ${group.insert}`
: '';
const insert = group.insert ? `; ${group.insert}` : '';
const suffix = `${writable ? ` } = $$props` : ``}${insert}` + (code.original[c] === ';' ? `` : `;`);
const suffix =
`${writable ? ` } = $$props` : ``}${insert}` +
(code.original[c] === ';' ? `` : `;`);
code.appendLeft(c, suffix);
}
});
@ -996,7 +1098,11 @@ export default class Component {
// reference instance variables other than other
// hoistable functions. TODO others?
const { hoistable_nodes, var_lookup, injected_reactive_declaration_vars } = this;
const {
hoistable_nodes,
var_lookup,
injected_reactive_declaration_vars,
} = this;
const top_level_function_declarations = new Map();
@ -1011,7 +1117,12 @@ export default class Component {
if (v.export_name) return false;
if (this.var_lookup.get(d.id.name).reassigned) return false;
if (this.vars.find(variable => variable.name === d.id.name && variable.module)) return false;
if (
this.vars.find(
variable => variable.name === d.id.name && variable.module
)
)
return false;
return true;
});
@ -1027,7 +1138,11 @@ export default class Component {
}
}
if (node.type === 'ExportNamedDeclaration' && node.declaration && node.declaration.type === 'FunctionDeclaration') {
if (
node.type === 'ExportNamedDeclaration' &&
node.declaration &&
node.declaration.type === 'FunctionDeclaration'
) {
top_level_function_declarations.set(node.declaration.id.name, node);
}
@ -1079,18 +1194,21 @@ export default class Component {
if (variable.hoistable) return;
if (top_level_function_declarations.has(name)) {
const other_declaration = top_level_function_declarations.get(name);
const other_declaration = top_level_function_declarations.get(
name
);
if (walking.has(other_declaration)) {
hoistable = false;
} else if (other_declaration.type === 'ExportNamedDeclaration' && walking.has(other_declaration.declaration)) {
} else if (
other_declaration.type === 'ExportNamedDeclaration' &&
walking.has(other_declaration.declaration)
) {
hoistable = false;
} else if (!is_hoistable(other_declaration)) {
hoistable = false;
}
}
else {
} else {
hoistable = false;
}
}
@ -1103,7 +1221,7 @@ export default class Component {
if (map.has(node)) {
scope = scope.parent;
}
}
},
});
checked.add(fn_declaration);
@ -1162,7 +1280,8 @@ export default class Component {
const owner = scope.find_owner(name);
const variable = component.var_lookup.get(name);
if (variable) variable.is_reactive_dependency = true;
const is_writable_or_mutated = variable && (variable.writable || variable.mutated);
const is_writable_or_mutated =
variable && (variable.writable || variable.mutated);
if (
(!owner || owner === component.instance_scope) &&
(name[0] === '$' || is_writable_or_mutated)
@ -1179,15 +1298,21 @@ export default class Component {
if (map.has(node)) {
scope = scope.parent;
}
}
},
});
add_indentation(this.code, node.body, 2);
const expression = node.body.expression && unwrap_parens(node.body.expression);
const expression =
node.body.expression && unwrap_parens(node.body.expression);
const declaration = expression && expression.left;
unsorted_reactive_declarations.push({ assignees, dependencies, node, declaration });
unsorted_reactive_declarations.push({
assignees,
dependencies,
node,
declaration,
});
}
});
@ -1236,9 +1361,10 @@ export default class Component {
declaration.dependencies.forEach(name => {
if (declaration.assignees.has(name)) return;
const earlier_declarations = lookup.get(name);
if (earlier_declarations) earlier_declarations.forEach(declaration => {
add_declaration(declaration);
});
if (earlier_declarations)
earlier_declarations.forEach(declaration => {
add_declaration(declaration);
});
});
this.reactive_declarations.push(declaration);
@ -1285,11 +1411,12 @@ export default class Component {
if (globals.has(name)) return;
let message = `'${name}' is not defined`;
if (!this.ast.instance) message += `. Consider adding a <script> block with 'export let ${name}' to declare a prop`;
if (!this.ast.instance)
message += `. Consider adding a <script> block with 'export let ${name}' to declare a prop`;
this.warn(node, {
code: 'missing-declaration',
message
message,
});
}
@ -1308,10 +1435,11 @@ export default class Component {
function process_component_options(component: Component, nodes) {
const component_options: ComponentOptions = {
immutable: component.compile_options.immutable || false,
accessors: 'accessors' in component.compile_options
? component.compile_options.accessors
: !!component.compile_options.customElement,
preserveWhitespace: !!component.compile_options.preserveWhitespace
accessors:
'accessors' in component.compile_options
? component.compile_options.accessors
: !!component.compile_options.customElement,
preserveWhitespace: !!component.compile_options.preserveWhitespace,
};
const node = nodes.find(node => node.name === 'svelte:options');
@ -1346,12 +1474,13 @@ function process_component_options(component: Component, nodes) {
const message = `'tag' must be a string literal`;
const tag = get_value(attribute, code, message);
if (typeof tag !== 'string' && tag !== null) component.error(attribute, { code, message });
if (typeof tag !== 'string' && tag !== null)
component.error(attribute, { code, message });
if (tag && !/^[a-zA-Z][a-zA-Z0-9]*-[a-zA-Z0-9-]+$/.test(tag)) {
component.error(attribute, {
code: `invalid-tag-property`,
message: `tag name must be two or more words joined by the '-' character`
message: `tag name must be two or more words joined by the '-' character`,
});
}
@ -1364,19 +1493,20 @@ function process_component_options(component: Component, nodes) {
const message = `The 'namespace' attribute must be a string literal representing a valid namespace`;
const ns = get_value(attribute, code, message);
if (typeof ns !== 'string') component.error(attribute, { code, message });
if (typeof ns !== 'string')
component.error(attribute, { code, message });
if (valid_namespaces.indexOf(ns) === -1) {
const match = fuzzymatch(ns, valid_namespaces);
if (match) {
component.error(attribute, {
code: `invalid-namespace-property`,
message: `Invalid namespace '${ns}' (did you mean '${match}'?)`
message: `Invalid namespace '${ns}' (did you mean '${match}'?)`,
});
} else {
component.error(attribute, {
code: `invalid-namespace-property`,
message: `Invalid namespace '${ns}'`
message: `Invalid namespace '${ns}'`,
});
}
}
@ -1387,13 +1517,13 @@ function process_component_options(component: Component, nodes) {
case 'accessors':
case 'immutable':
case 'preserveWhitespace':
{
case 'preserveWhitespace': {
const code = `invalid-${name}-value`;
const message = `${name} attribute must be true or false`;
const value = get_value(attribute, code, message);
if (typeof value !== 'boolean') component.error(attribute, { code, message });
if (typeof value !== 'boolean')
component.error(attribute, { code, message });
component_options[name] = value;
break;
@ -1402,15 +1532,13 @@ function process_component_options(component: Component, nodes) {
default:
component.error(attribute, {
code: `invalid-options-attribute`,
message: `<svelte:options> unknown attribute`
message: `<svelte:options> unknown attribute`,
});
}
}
else {
} else {
component.error(attribute, {
code: `invalid-options-attribute`,
message: `<svelte:options> can only have static 'tag', 'namespace', 'accessors', 'immutable' and 'preserveWhitespace' attributes`
message: `<svelte:options> can only have static 'tag', 'namespace', 'accessors', 'immutable' and 'preserveWhitespace' attributes`,
});
}
});

@ -7,6 +7,7 @@ import { escape } from '../utils/stringify';
export interface BlockOptions {
parent?: Block;
name: string;
type: string;
renderer?: Renderer;
comment?: string;
key?: string;
@ -18,6 +19,7 @@ export default class Block {
parent?: Block;
renderer: Renderer;
name: string;
type: string;
comment?: string;
wrappers: Wrapper[];
@ -65,6 +67,7 @@ export default class Block {
this.parent = options.parent;
this.renderer = options.renderer;
this.name = options.name;
this.type = options.type;
this.comment = options.comment;
this.wrappers = [];
@ -370,11 +373,20 @@ export default class Block {
${!this.builders.init.is_empty() && this.builders.init}
return {
${properties}
};
`.replace(/(#+)(\w*)/g, (_match: string, sigil: string, name: string) => {
return sigil === '#' ? this.alias(name) : sigil.slice(1) + name;
${dev
? deindent`
const block = {
${properties}
};
@dispatch_dev("SvelteRegisterBlock", { block, id: ${this.name || 'create_fragment'}.name, type: "${this.type}", source: "${this.comment ? this.comment.replace(/"/g, '\\"') : ''}", ctx });
return block;`
: deindent`
return {
${properties}
};`
}
`.replace(/([^{])(#+)(\w*)/g, (_match: string, pre: string, sigil: string, name: string) => {
return pre + (sigil === '#' ? this.alias(name) : sigil.slice(1) + name);
});
/* eslint-enable @typescript-eslint/indent,indent */
}

@ -30,6 +30,7 @@ export default class Renderer {
this.block = new Block({
renderer: this,
name: null,
type: 'component',
key: null,
bindings: new Map(),

@ -157,21 +157,20 @@ export default function dom(
}
` : deindent`
() => {
return {}
return {};
}
`;
inject_state = (uses_props || writable_props.length > 0) ? deindent`
const writable_vars = component.vars.filter(variable => !variable.module && variable.writable);
inject_state = (uses_props || writable_vars.length > 0) ? deindent`
${$$props} => {
${uses_props && component.invalidate('$$props', `$$props = @assign(@assign({}, $$props), $$new_props)`)}
${component.vars.filter(prop => prop.writable).map(prop => deindent`
${writable_vars.map(prop => deindent`
if ('${prop.name}' in $$props) ${component.invalidate(prop.name, `${prop.name} = ${$$props}.${prop.name}`)};
`)}
}
` : deindent`
${$$props} => {
return
}
${$$props} => {}
`;
}
@ -443,6 +442,7 @@ export default function dom(
super(${options.dev && `options`});
${should_add_css && `if (!@_document.getElementById("${component.stylesheet.id}-style")) ${add_css}();`}
@init(this, options, ${definition}, create_fragment, ${not_equal}, ${prop_names});
${options.dev && `@dispatch_dev("SvelteRegisterComponent", { component: this, tagName: "${name}", options, id: create_fragment.name });`}
${dev_props_check}
}

@ -30,7 +30,8 @@ class AwaitBlockBranch extends Wrapper {
this.block = block.child({
comment: create_debugging_comment(node, this.renderer.component),
name: this.renderer.component.get_unique_name(`create_${status}_block`)
name: this.renderer.component.get_unique_name(`create_${status}_block`),
type: status
});
this.fragment = new FragmentWrapper(

@ -28,7 +28,8 @@ export class ElseBlockWrapper extends Wrapper {
this.block = block.child({
comment: create_debugging_comment(node, this.renderer.component),
name: this.renderer.component.get_unique_name(`create_else_block`)
name: this.renderer.component.get_unique_name(`create_else_block`),
type: 'else'
});
this.fragment = new FragmentWrapper(
@ -82,6 +83,7 @@ export default class EachBlockWrapper extends Wrapper {
this.block = block.child({
comment: create_debugging_comment(this.node, this.renderer.component),
name: renderer.component.get_unique_name('create_each_block'),
type: 'each',
// @ts-ignore todo: probably error
key: node.key as string,

@ -140,7 +140,9 @@ export default class AttributeWrapper {
block.builders.hydrate.add_line(
`${element.var}.${property_name} = ${init};`
);
updater = `${element.var}.${property_name} = ${should_cache ? last : value};`;
updater = block.renderer.options.dev
? `@prop_dev(${element.var}, "${property_name}", ${should_cache ? last : value});`
: `${element.var}.${property_name} = ${should_cache ? last : value};`;
} else {
block.builders.hydrate.add_line(
`${method}(${element.var}, "${name}", ${init});`

@ -151,7 +151,8 @@ export default class ElementWrapper extends Wrapper {
if (!(owner as InlineComponentWrapper).slots.has(name)) {
const child_block = block.child({
comment: create_debugging_comment(node, this.renderer.component),
name: this.renderer.component.get_unique_name(`create_${sanitize(name)}_slot`)
name: this.renderer.component.get_unique_name(`create_${sanitize(name)}_slot`),
type: 'slot'
});
const lets = this.node.lets;

@ -62,7 +62,10 @@ class IfBlockBranch extends Wrapper {
this.block = block.child({
comment: create_debugging_comment(node, parent.renderer.component),
name: parent.renderer.component.get_unique_name(is_else ? `create_else_block` : `create_if_block`)
name: parent.renderer.component.get_unique_name(
is_else ? `create_else_block` : `create_if_block`
),
type: (node as IfBlock).expression ? 'if' : 'else'
});
this.fragment = new FragmentWrapper(renderer, this.block, node.children, parent, strip_whitespace, next_sibling);

@ -70,7 +70,8 @@ export default class InlineComponentWrapper extends Wrapper {
if (this.node.children.length) {
const default_slot = block.child({
comment: create_debugging_comment(node, renderer.component),
name: renderer.component.get_unique_name(`create_default_slot`)
name: renderer.component.get_unique_name(`create_default_slot`),
type: 'slot'
});
this.renderer.blocks.push(default_slot);

@ -12,20 +12,31 @@ export default function add_event_handlers(
if (handler.modifiers.has('stopPropagation')) snippet = `@stop_propagation(${snippet})`;
if (handler.modifiers.has('self')) snippet = `@self(${snippet})`;
const opts = ['passive', 'once', 'capture'].filter(mod => handler.modifiers.has(mod));
let opts_string = '';
if (opts.length) {
const opts_string = (opts.length === 1 && opts[0] === 'capture')
? 'true'
: `{ ${opts.map(opt => `${opt}: true`).join(', ')} }`;
if (block.renderer.options.dev) {
if (handler.modifiers.has('stopPropagation')) {
opts_string = ', true';
}
block.event_listeners.push(
`@listen(${target}, "${handler.name}", ${snippet}, ${opts_string})`
);
} else {
block.event_listeners.push(
`@listen(${target}, "${handler.name}", ${snippet})`
);
if (handler.modifiers.has('preventDefault')) {
opts_string = ', true' + opts_string;
} else if (opts_string) {
opts_string = ', false' + opts_string;
}
}
const opts = ['passive', 'once', 'capture'].filter(mod => handler.modifiers.has(mod));
if (opts.length) {
opts_string = (opts.length === 1 && opts[0] === 'capture')
? ', true'
: `, { ${opts.map(opt => `${opt}: true`).join(', ')} }`;
} else if (opts_string) {
opts_string = ', false' + opts_string;
}
block.event_listeners.push(
`@listen(${target}, "${handler.name}", ${snippet}${opts_string})`
);
});
}
}

@ -197,20 +197,3 @@ export class SvelteComponent {
// overridden by instance, if it has props
}
}
export class SvelteComponentDev extends SvelteComponent {
constructor(options) {
if (!options || (!options.target && !options.$$inline)) {
throw new Error(`'target' is a required option`);
}
super();
}
$destroy() {
super.$destroy();
this.$destroy = () => {
console.warn(`Component was already destroyed`); // eslint-disable-line no-console
};
}
}

@ -0,0 +1,97 @@
import { custom_event, append, insert, detach, listen, attr } from './dom';
import { SvelteComponent } from './Component';
export function dispatch_dev<T=any>(type: string, detail?: T) {
document.dispatchEvent(custom_event(type, detail));
}
export function append_dev(target: Node, node: Node) {
dispatch_dev("SvelteDOMInsert", { target, node });
append(target, node);
}
export function insert_dev(target: Node, node: Node, anchor?: Node) {
dispatch_dev("SvelteDOMInsert", { target, node, anchor });
insert(target, node, anchor);
}
export function detach_dev(node: Node) {
dispatch_dev("SvelteDOMRemove", { node });
detach(node);
}
export function detach_between_dev(before: Node, after: Node) {
while (before.nextSibling && before.nextSibling !== after) {
detach_dev(before.nextSibling);
}
}
export function detach_before_dev(after: Node) {
while (after.previousSibling) {
detach_dev(after.previousSibling);
}
}
export function detach_after_dev(before: Node) {
while (before.nextSibling) {
detach_dev(before.nextSibling);
}
}
export function listen_dev(node: Node, event: string, handler: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions | EventListenerOptions, has_prevent_default?: boolean, has_stop_propagation?: boolean) {
const modifiers = options === true ? [ "capture" ] : options ? Array.from(Object.keys(options)) : [];
if (has_prevent_default) modifiers.push('preventDefault');
if (has_stop_propagation) modifiers.push('stopPropagation');
dispatch_dev("SvelteDOMAddEventListener", { node, event, handler, modifiers });
const dispose = listen(node, event, handler, options);
return () => {
dispatch_dev("SvelteDOMRemoveEventListener", { node, event, handler, modifiers });
dispose();
};
}
export function attr_dev(node: Element, attribute: string, value?: string) {
attr(node, attribute, value);
if (value == null) dispatch_dev("SvelteDOMRemoveAttribute", { node, attribute });
else dispatch_dev("SvelteDOMSetAttribute", { node, attribute, value });
}
export function prop_dev(node: Element, property: string, value?: any) {
node[property] = value;
dispatch_dev("SvelteDOMSetProperty", { node, property, value });
}
export function dataset_dev(node: HTMLElement, property: string, value?: any) {
node.dataset[property] = value;
dispatch_dev("SvelteDOMSetDataset", { node, property, value });
}
export function set_data_dev(text, data) {
data = '' + data;
if (text.data === data) return;
dispatch_dev("SvelteDOMSetData", { node: text, data });
text.data = data;
}
export class SvelteComponentDev extends SvelteComponent {
constructor(options) {
if (!options || (!options.target && !options.$$inline)) {
throw new Error(`'target' is a required option`);
}
super();
}
$destroy() {
super.$destroy();
this.$destroy = () => {
console.warn(`Component was already destroyed`); // eslint-disable-line no-console
};
}
}

@ -12,3 +12,4 @@ export * from './ssr';
export * from './transitions';
export * from './utils';
export * from './Component';
export * from './dev';

@ -91,7 +91,7 @@ function create_fragment(ctx) {
let y = 1;
function instance($$self, $$props, $$invalidate) {
let z = 2;
function input_input_handler() {

@ -2,14 +2,15 @@
import {
SvelteComponentDev,
add_location,
append,
detach,
append_dev,
detach_dev,
dispatch_dev,
element,
init,
insert,
insert_dev,
noop,
safe_not_equal,
set_data,
set_data_dev,
space,
text
} from "svelte/internal";
@ -19,7 +20,7 @@ const file = undefined;
function create_fragment(ctx) {
var h1, t0, t1, t2, t3;
return {
const block = {
c: function create() {
h1 = element("h1");
t0 = text("Hello ");
@ -35,16 +36,16 @@ function create_fragment(ctx) {
},
m: function mount(target, anchor) {
insert(target, h1, anchor);
append(h1, t0);
append(h1, t1);
append(h1, t2);
insert(target, t3, anchor);
insert_dev(target, h1, anchor);
append_dev(h1, t0);
append_dev(h1, t1);
append_dev(h1, t2);
insert_dev(target, t3, anchor);
},
p: function update(changed, ctx) {
if (changed.name) {
set_data(t1, ctx.name);
set_data_dev(t1, ctx.name);
}
debugger;
@ -55,11 +56,13 @@ function create_fragment(ctx) {
d: function destroy(detaching) {
if (detaching) {
detach(h1);
detach(t3);
detach_dev(h1);
detach_dev(t3);
}
}
};
dispatch_dev("SvelteRegisterBlock", { block, id: create_fragment.name, type: "component", source: "", ctx });
return block;
}
function instance($$self, $$props, $$invalidate) {
@ -89,6 +92,7 @@ class Component extends SvelteComponentDev {
constructor(options) {
super(options);
init(this, options, instance, create_fragment, safe_not_equal, ["name"]);
dispatch_dev("SvelteRegisterComponent", { component: this, tagName: "Component", options, id: create_fragment.name });
const { ctx } = this.$$;
const props = options.props || {};

@ -2,15 +2,16 @@
import {
SvelteComponentDev,
add_location,
append,
append_dev,
destroy_each,
detach,
detach_dev,
dispatch_dev,
element,
init,
insert,
insert_dev,
noop,
safe_not_equal,
set_data,
set_data_dev,
space,
text
} from "svelte/internal";
@ -27,7 +28,7 @@ function get_each_context(ctx, list, i) {
function create_each_block(ctx) {
var span, t0_value = ctx.thing.name + "", t0, t1;
return {
const block = {
c: function create() {
span = element("span");
t0 = text(t0_value);
@ -42,14 +43,14 @@ function create_each_block(ctx) {
},
m: function mount(target, anchor) {
insert(target, span, anchor);
append(span, t0);
insert(target, t1, anchor);
insert_dev(target, span, anchor);
append_dev(span, t0);
insert_dev(target, t1, anchor);
},
p: function update(changed, ctx) {
if ((changed.things) && t0_value !== (t0_value = ctx.thing.name + "")) {
set_data(t0, t0_value);
set_data_dev(t0, t0_value);
}
if (changed.foo || changed.bar || changed.baz || changed.things) {
@ -61,11 +62,13 @@ function create_each_block(ctx) {
d: function destroy(detaching) {
if (detaching) {
detach(span);
detach(t1);
detach_dev(span);
detach_dev(t1);
}
}
};
dispatch_dev("SvelteRegisterBlock", { block, id: create_each_block.name, type: "each", source: "(8:0) {#each things as thing}", ctx });
return block;
}
function create_fragment(ctx) {
@ -79,7 +82,7 @@ function create_fragment(ctx) {
each_blocks[i] = create_each_block(get_each_context(ctx, each_value, i));
}
return {
const block = {
c: function create() {
for (let i = 0; i < each_blocks.length; i += 1) {
each_blocks[i].c();
@ -101,10 +104,10 @@ function create_fragment(ctx) {
each_blocks[i].m(target, anchor);
}
insert(target, t0, anchor);
insert(target, p, anchor);
append(p, t1);
append(p, t2);
insert_dev(target, t0, anchor);
insert_dev(target, p, anchor);
append_dev(p, t1);
append_dev(p, t2);
},
p: function update(changed, ctx) {
@ -131,7 +134,7 @@ function create_fragment(ctx) {
}
if (changed.foo) {
set_data(t2, ctx.foo);
set_data_dev(t2, ctx.foo);
}
},
@ -142,11 +145,13 @@ function create_fragment(ctx) {
destroy_each(each_blocks, detaching);
if (detaching) {
detach(t0);
detach(p);
detach_dev(t0);
detach_dev(p);
}
}
};
dispatch_dev("SvelteRegisterBlock", { block, id: create_fragment.name, type: "component", source: "", ctx });
return block;
}
function instance($$self, $$props, $$invalidate) {
@ -182,6 +187,7 @@ class Component extends SvelteComponentDev {
constructor(options) {
super(options);
init(this, options, instance, create_fragment, safe_not_equal, ["things", "foo", "bar", "baz"]);
dispatch_dev("SvelteRegisterComponent", { component: this, tagName: "Component", options, id: create_fragment.name });
const { ctx } = this.$$;
const props = options.props || {};

@ -2,15 +2,16 @@
import {
SvelteComponentDev,
add_location,
append,
append_dev,
destroy_each,
detach,
detach_dev,
dispatch_dev,
element,
init,
insert,
insert_dev,
noop,
safe_not_equal,
set_data,
set_data_dev,
space,
text
} from "svelte/internal";
@ -27,7 +28,7 @@ function get_each_context(ctx, list, i) {
function create_each_block(ctx) {
var span, t0_value = ctx.thing.name + "", t0, t1;
return {
const block = {
c: function create() {
span = element("span");
t0 = text(t0_value);
@ -42,14 +43,14 @@ function create_each_block(ctx) {
},
m: function mount(target, anchor) {
insert(target, span, anchor);
append(span, t0);
insert(target, t1, anchor);
insert_dev(target, span, anchor);
append_dev(span, t0);
insert_dev(target, t1, anchor);
},
p: function update(changed, ctx) {
if ((changed.things) && t0_value !== (t0_value = ctx.thing.name + "")) {
set_data(t0, t0_value);
set_data_dev(t0, t0_value);
}
if (changed.foo) {
@ -61,11 +62,13 @@ function create_each_block(ctx) {
d: function destroy(detaching) {
if (detaching) {
detach(span);
detach(t1);
detach_dev(span);
detach_dev(t1);
}
}
};
dispatch_dev("SvelteRegisterBlock", { block, id: create_each_block.name, type: "each", source: "(6:0) {#each things as thing}", ctx });
return block;
}
function create_fragment(ctx) {
@ -79,7 +82,7 @@ function create_fragment(ctx) {
each_blocks[i] = create_each_block(get_each_context(ctx, each_value, i));
}
return {
const block = {
c: function create() {
for (let i = 0; i < each_blocks.length; i += 1) {
each_blocks[i].c();
@ -101,10 +104,10 @@ function create_fragment(ctx) {
each_blocks[i].m(target, anchor);
}
insert(target, t0, anchor);
insert(target, p, anchor);
append(p, t1);
append(p, t2);
insert_dev(target, t0, anchor);
insert_dev(target, p, anchor);
append_dev(p, t1);
append_dev(p, t2);
},
p: function update(changed, ctx) {
@ -131,7 +134,7 @@ function create_fragment(ctx) {
}
if (changed.foo) {
set_data(t2, ctx.foo);
set_data_dev(t2, ctx.foo);
}
},
@ -142,11 +145,13 @@ function create_fragment(ctx) {
destroy_each(each_blocks, detaching);
if (detaching) {
detach(t0);
detach(p);
detach_dev(t0);
detach_dev(p);
}
}
};
dispatch_dev("SvelteRegisterBlock", { block, id: create_fragment.name, type: "component", source: "", ctx });
return block;
}
function instance($$self, $$props, $$invalidate) {
@ -178,6 +183,7 @@ class Component extends SvelteComponentDev {
constructor(options) {
super(options);
init(this, options, instance, create_fragment, safe_not_equal, ["things", "foo"]);
dispatch_dev("SvelteRegisterComponent", { component: this, tagName: "Component", options, id: create_fragment.name });
const { ctx } = this.$$;
const props = options.props || {};

@ -1,6 +1,7 @@
/* generated by Svelte vX.Y.Z */
import {
SvelteComponentDev,
dispatch_dev,
init,
noop,
safe_not_equal
@ -9,7 +10,7 @@ import {
const file = undefined;
function create_fragment(ctx) {
return {
const block = {
c: function create() {
{
const { obj } = ctx;
@ -36,6 +37,8 @@ function create_fragment(ctx) {
o: noop,
d: noop
};
dispatch_dev("SvelteRegisterBlock", { block, id: create_fragment.name, type: "component", source: "", ctx });
return block;
}
let kobzol = 5;
@ -44,11 +47,12 @@ function instance($$self) {
let obj = { x: 5 };
$$self.$capture_state = () => {
return {}
return {};
};
$$self.$inject_state = $$props => {
return
if ('obj' in $$props) $$invalidate('obj', obj = $$props.obj);
if ('kobzol' in $$props) $$invalidate('kobzol', kobzol = $$props.kobzol);
};
return { obj };
@ -58,6 +62,7 @@ class Component extends SvelteComponentDev {
constructor(options) {
super(options);
init(this, options, instance, create_fragment, safe_not_equal, []);
dispatch_dev("SvelteRegisterComponent", { component: this, tagName: "Component", options, id: create_fragment.name });
}
}

@ -2,14 +2,15 @@
import {
SvelteComponentDev,
add_location,
append,
detach,
append_dev,
detach_dev,
dispatch_dev,
element,
init,
insert,
insert_dev,
noop,
safe_not_equal,
set_data,
set_data_dev,
space,
text
} from "svelte/internal";
@ -19,7 +20,7 @@ const file = undefined;
function create_fragment(ctx) {
var p, t0_value = Math.max(0, ctx.foo) + "", t0, t1, t2;
return {
const block = {
c: function create() {
p = element("p");
t0 = text(t0_value);
@ -33,19 +34,19 @@ function create_fragment(ctx) {
},
m: function mount(target, anchor) {
insert(target, p, anchor);
append(p, t0);
append(p, t1);
append(p, t2);
insert_dev(target, p, anchor);
append_dev(p, t0);
append_dev(p, t1);
append_dev(p, t2);
},
p: function update(changed, ctx) {
if ((changed.foo) && t0_value !== (t0_value = Math.max(0, ctx.foo) + "")) {
set_data(t0, t0_value);
set_data_dev(t0, t0_value);
}
if (changed.bar) {
set_data(t2, ctx.bar);
set_data_dev(t2, ctx.bar);
}
},
@ -54,10 +55,12 @@ function create_fragment(ctx) {
d: function destroy(detaching) {
if (detaching) {
detach(p);
detach_dev(p);
}
}
};
dispatch_dev("SvelteRegisterBlock", { block, id: create_fragment.name, type: "component", source: "", ctx });
return block;
}
function instance($$self, $$props, $$invalidate) {
@ -94,6 +97,7 @@ class Component extends SvelteComponentDev {
constructor(options) {
super(options);
init(this, options, instance, create_fragment, safe_not_equal, ["foo"]);
dispatch_dev("SvelteRegisterComponent", { component: this, tagName: "Component", options, id: create_fragment.name });
const { ctx } = this.$$;
const props = options.props || {};

Loading…
Cancel
Save