Events for DOM methods

pull/3005/head
Timothy Johnson 6 years ago
parent 126c515d22
commit 6b58a1d2f6

@ -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';
@ -39,7 +44,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');
@ -97,7 +108,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();
@ -110,7 +126,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;
};
@ -140,27 +159,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;
@ -195,7 +233,7 @@ export default class Component {
this.add_var({
name,
injected: true,
referenced: true
referenced: true,
});
} else if (name[0] === '$') {
this.add_var({
@ -203,7 +241,7 @@ export default class Component {
injected: true,
referenced: true,
mutated: true,
writable: true
writable: true,
});
const subscribable_name = name.slice(1);
@ -253,35 +291,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,
@ -292,10 +347,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
);
@ -339,16 +396,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,
})
}),
};
}
@ -357,17 +414,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(),
};
}
@ -402,8 +461,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);
@ -428,7 +486,7 @@ export default class Component {
source: this.source,
start: pos.start,
end: pos.end,
filename: this.compile_options.filename
filename: this.compile_options.filename,
});
}
@ -459,7 +517,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}`,
});
}
@ -482,7 +541,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`,
});
}
@ -490,7 +549,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) {
@ -530,7 +589,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;
});
@ -543,8 +603,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;
}
@ -572,10 +635,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);
@ -587,7 +650,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`,
});
}
@ -595,7 +658,7 @@ export default class Component {
name,
module: true,
hoistable: true,
writable: node.kind === 'var' || node.kind === 'let'
writable: node.kind === 'var' || node.kind === 'let',
});
});
@ -603,12 +666,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,
});
}
});
@ -640,7 +703,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;
@ -648,7 +713,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`,
});
}
@ -656,7 +721,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);
@ -671,19 +736,19 @@ 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] === '$') {
this.add_var({
name,
injected: true,
mutated: true,
writable: true
writable: true,
});
this.add_reference(name.slice(1));
@ -693,7 +758,7 @@ export default class Component {
} else {
this.add_var({
name,
global: true
global: true,
});
}
});
@ -753,7 +818,7 @@ export default class Component {
if (map.has(node)) {
scope = scope.parent;
}
}
},
});
}
@ -769,10 +834,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',
});
}
@ -790,7 +859,7 @@ export default class Component {
if (map.has(node)) {
scope = scope.parent;
}
}
},
});
}
@ -805,7 +874,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;
}
@ -817,7 +892,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);
@ -825,7 +902,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) {
@ -861,7 +940,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`,
});
}
@ -872,7 +951,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('; ')}`);
}
@ -894,7 +977,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;
@ -903,17 +990,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 {
@ -923,7 +1021,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}`);
}
@ -942,7 +1044,7 @@ export default class Component {
if (map.has(node)) {
scope = scope.parent;
}
}
},
});
coalesced_declarations.forEach(group => {
@ -965,11 +1067,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);
}
});
@ -981,7 +1083,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();
@ -996,7 +1102,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;
});
@ -1012,7 +1123,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);
}
@ -1061,18 +1176,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;
}
}
@ -1085,7 +1203,7 @@ export default class Component {
if (map.has(node)) {
scope = scope.parent;
}
}
},
});
checked.add(fn_declaration);
@ -1144,7 +1262,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)
@ -1161,15 +1280,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,
});
}
});
@ -1192,7 +1317,7 @@ export default class Component {
if (seen.has(declaration)) {
this.error(declaration.node, {
code: 'cyclical-reactive-declaration',
message: 'Cyclical dependency detected'
message: 'Cyclical dependency detected',
});
}
@ -1205,9 +1330,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);
@ -1246,11 +1372,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,
});
}
}
@ -1258,10 +1385,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');
@ -1296,12 +1424,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`,
});
}
@ -1314,19 +1443,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}'`,
});
}
}
@ -1337,13 +1467,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;
@ -1352,15 +1482,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`,
});
}
});

@ -11,20 +11,31 @@ export default function add_event_handlers(
if (handler.modifiers.has('preventDefault')) snippet = `@prevent_default(${snippet})`;
if (handler.modifiers.has('stopPropagation')) snippet = `@stop_propagation(${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})`
);
});
}
}

@ -198,20 +198,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,85 @@
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", { 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 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
};
}
}

@ -256,7 +256,3 @@ export function custom_event<T=any>(type: string, detail?: T) {
e.initCustomEvent(type, false, false, detail);
return e;
}
export function dispatch_dev(type: string, detail?: T) {
document.dispatchEvent(custom_event(type, detail))
}

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

Loading…
Cancel
Save