Merge pull request #3 from sveltejs/master

Sync Fork from Upstream Repo
pull/3941/head
Stefan Hagen 6 years ago committed by GitHub
commit c289c491b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

37
package-lock.json generated

@ -30,6 +30,16 @@
"integrity": "sha512-KioOCsSvSvXx6xUNLiJz+P+VMb7NRcePjoefOr74Y5P6lEKsiOn35eZyZzgpK4XCNJdXTDR7+zykj0lwxRvZ2g==",
"dev": true
},
"@rollup/plugin-replace": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.2.1.tgz",
"integrity": "sha512-dgq5ijT8fK18KTb1inenZ61ivTayV7pvbz2+ivT+VN20BOgJVM1fqoBETqGHKgFVm/J9BhR82mQyAtxfpPv1lQ==",
"dev": true,
"requires": {
"magic-string": "^0.25.2",
"rollup-pluginutils": "^2.6.0"
}
},
"@types/eslint-visitor-keys": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
@ -499,6 +509,17 @@
"is-reference": "^1.1.4",
"periscopic": "^1.0.2",
"sourcemap-codec": "^1.4.6"
},
"dependencies": {
"periscopic": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/periscopic/-/periscopic-1.1.0.tgz",
"integrity": "sha512-sUdDgd8G35JjpBqHGnuc2MECoyUryHGfjtsKFPS6N8MEGHtxoIML8yEWydL1zf+W8EoChX4L7A9AvVRJuM6Lqg==",
"dev": true,
"requires": {
"is-reference": "^1.1.4"
}
}
}
},
"codecov": {
@ -2713,9 +2734,9 @@
"dev": true
},
"periscopic": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/periscopic/-/periscopic-1.0.2.tgz",
"integrity": "sha512-KpKBKadLf8THXOxswQBhOY8E1lVVhfUidacPtQBrq7KDXaNkQLUPiTmXagzqpJGECP3/0gDXYFO6CZHVbGvOSw==",
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/periscopic/-/periscopic-2.0.0.tgz",
"integrity": "sha512-2YVtztswd6ud5b0+IDD26UhEm1QvlTsR3s7G59CD0txGyhfvQ39YhNuueSmzT5VzHUxiIH0E8S04JSQpXMJ8/g==",
"dev": true,
"requires": {
"is-reference": "^1.1.4"
@ -3109,16 +3130,6 @@
"rollup-pluginutils": "^2.8.1"
}
},
"rollup-plugin-replace": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/rollup-plugin-replace/-/rollup-plugin-replace-2.2.0.tgz",
"integrity": "sha512-/5bxtUPkDHyBJAKketb4NfaeZjL5yLZdeUihSfbF2PQMz+rSTEb8ARKoOl3UBT4m7/X+QOXJo3sLTcq+yMMYTA==",
"dev": true,
"requires": {
"magic-string": "^0.25.2",
"rollup-pluginutils": "^2.6.0"
}
},
"rollup-plugin-sucrase": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/rollup-plugin-sucrase/-/rollup-plugin-sucrase-2.1.0.tgz",

@ -60,6 +60,7 @@
"@types/node": "^8.10.53",
"@typescript-eslint/eslint-plugin": "^1.13.0",
"@typescript-eslint/parser": "^2.1.0",
"@rollup/plugin-replace": "^2.2.1",
"acorn": "^7.1.0",
"agadoo": "^1.1.0",
"c8": "^5.0.1",
@ -76,12 +77,12 @@
"locate-character": "^2.0.5",
"magic-string": "^0.25.3",
"mocha": "^6.2.0",
"periscopic": "^2.0.0",
"puppeteer": "^1.19.0",
"rollup": "^1.21.4",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-json": "^4.0.0",
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-replace": "^2.2.0",
"rollup-plugin-sucrase": "^2.1.0",
"rollup-plugin-typescript": "^1.0.1",
"rollup-plugin-virtual": "^1.0.1",

@ -1,5 +1,5 @@
import fs from 'fs';
import replace from 'rollup-plugin-replace';
import replace from '@rollup/plugin-replace';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import json from 'rollup-plugin-json';

@ -43,8 +43,8 @@
width: 100%;
height: 100%;
background-color: #666;
-webkit-mask: url(logo-mask.svg) 50% 50% no-repeat;
mask: url(logo-mask.svg) 50% 50% no-repeat;
-webkit-mask: url(svelte-logo-mask.svg) 50% 50% no-repeat;
mask: url(svelte-logo-mask.svg) 50% 50% no-repeat;
}
</style>

@ -43,8 +43,8 @@
width: 100%;
height: 100%;
background-color: #666;
-webkit-mask: url(logo-mask.svg) 50% 50% no-repeat;
mask: url(logo-mask.svg) 50% 50% no-repeat;
-webkit-mask: url(svelte-logo-mask.svg) 50% 50% no-repeat;
mask: url(svelte-logo-mask.svg) 50% 50% no-repeat;
}
</style>

@ -43,8 +43,8 @@
width: 100%;
height: 100%;
background-color: #666;
-webkit-mask: url(logo-mask.svg) 50% 50% no-repeat;
mask: url(logo-mask.svg) 50% 50% no-repeat;
-webkit-mask: url(svelte-logo-mask.svg) 50% 50% no-repeat;
mask: url(svelte-logo-mask.svg) 50% 50% no-repeat;
}
</style>

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 103 124">
<path style="fill:black" d='M96.33,20.61C85.38,4.93,63.74.28,48.09,10.25L20.61,27.77A31.46,31.46,0,0,0,6.37,48.88,33.22,33.22,0,0,0,9.64,70.2,31.52,31.52,0,0,0,4.93,82a33.61,33.61,0,0,0,5.73,25.41c11,15.68,32.6,20.33,48.25,10.36l27.48-17.52a31.48,31.48,0,0,0,14.24-21.11A33.22,33.22,0,0,0,97.36,57.8,31.52,31.52,0,0,0,102.07,46a33.57,33.57,0,0,0-5.74-25.41
M45.41,108.86A21.81,21.81,0,0,1,22,100.18,20.2,20.2,0,0,1,18.53,84.9a19,19,0,0,1,.65-2.57l.52-1.58,1.41,1a35.32,35.32,0,0,0,10.75,5.37l1,.31-.1,1a6.2,6.2,0,0,0,1.11,4.08A6.57,6.57,0,0,0,41,95.19a6,6,0,0,0,1.68-.74L70.11,76.94a5.76,5.76,0,0,0,2.59-3.83,6.09,6.09,0,0,0-1-4.6,6.58,6.58,0,0,0-7.06-2.62,6.21,6.21,0,0,0-1.69.74L52.43,73.31a19.88,19.88,0,0,1-5.58,2.45,21.82,21.82,0,0,1-23.43-8.68A20.2,20.2,0,0,1,20,51.8a19,19,0,0,1,8.56-12.7L56,21.59a19.88,19.88,0,0,1,5.58-2.45A21.81,21.81,0,0,1,85,27.82,20.2,20.2,0,0,1,88.47,43.1a19,19,0,0,1-.65,2.57l-.52,1.58-1.41-1a35.32,35.32,0,0,0-10.75-5.37l-1-.31.1-1a6.2,6.2,0,0,0-1.11-4.08,6.57,6.57,0,0,0-7.06-2.62,6,6,0,0,0-1.68.74L36.89,51.06a5.71,5.71,0,0,0-2.58,3.83,6,6,0,0,0,1,4.6,6.58,6.58,0,0,0,7.06,2.62,6.21,6.21,0,0,0,1.69-.74l10.48-6.68a19.88,19.88,0,0,1,5.58-2.45,21.82,21.82,0,0,1,23.43,8.68A20.2,20.2,0,0,1,87,76.2a19,19,0,0,1-8.56,12.7L51,106.41a19.88,19.88,0,0,1-5.58,2.45' />
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

@ -3,6 +3,7 @@ import Stylesheet from './Stylesheet';
import { gather_possible_values, UNKNOWN } from './gather_possible_values';
import { CssNode } from './interfaces';
import Component from '../Component';
import Element from '../nodes/Element';
enum BlockAppliesToNode {
NotPossible,
@ -34,8 +35,8 @@ export default class Selector {
this.used = this.blocks[0].global;
}
apply(node: CssNode, stack: CssNode[]) {
const to_encapsulate: CssNode[] = [];
apply(node: Element, stack: Element[]) {
const to_encapsulate: any[] = [];
apply_selector(this.local_blocks.slice(), node, stack.slice(), to_encapsulate);
@ -132,7 +133,7 @@ export default class Selector {
}
}
function apply_selector(blocks: Block[], node: CssNode, stack: CssNode[], to_encapsulate: any[]): boolean {
function apply_selector(blocks: Block[], node: Element, stack: Element[], to_encapsulate: any[]): boolean {
const block = blocks.pop();
if (!block) return false;
@ -259,16 +260,84 @@ function attribute_matches(node: CssNode, name: string, expected_value: string,
const attr = node.attributes.find((attr: CssNode) => attr.name === name);
if (!attr) return false;
if (attr.is_true) return operator === null;
if (attr.chunks.length > 1) return true;
if (!expected_value) return true;
const value = attr.chunks[0];
if (!value) return false;
if (value.type === 'Text') return test_attribute(operator, expected_value, case_insensitive, value.data);
if (attr.chunks.length === 1) {
const value = attr.chunks[0];
if (!value) return false;
if (value.type === 'Text') return test_attribute(operator, expected_value, case_insensitive, value.data);
}
const possible_values = new Set();
gather_possible_values(value.node, possible_values);
let prev_values = [];
for (const chunk of attr.chunks) {
const current_possible_values = new Set();
if (chunk.type === 'Text') {
current_possible_values.add(chunk.data);
} else {
gather_possible_values(chunk.node, current_possible_values);
}
// impossible to find out all combinations
if (current_possible_values.has(UNKNOWN)) return true;
if (prev_values.length > 0) {
const start_with_space = [];
const remaining = [];
current_possible_values.forEach((current_possible_value: string) => {
if (/^\s/.test(current_possible_value)) {
start_with_space.push(current_possible_value);
} else {
remaining.push(current_possible_value);
}
});
if (remaining.length > 0) {
if (start_with_space.length > 0) {
prev_values.forEach(prev_value => possible_values.add(prev_value));
}
const combined = [];
prev_values.forEach((prev_value: string) => {
remaining.forEach((value: string) => {
combined.push(prev_value + value);
});
});
prev_values = combined;
start_with_space.forEach((value: string) => {
if (/\s$/.test(value)) {
possible_values.add(value);
} else {
prev_values.push(value);
}
});
continue;
} else {
prev_values.forEach(prev_value => possible_values.add(prev_value));
prev_values = [];
}
}
current_possible_values.forEach((current_possible_value: string) => {
if (/\s$/.test(current_possible_value)) {
possible_values.add(current_possible_value);
} else {
prev_values.push(current_possible_value);
}
});
if (prev_values.length < current_possible_values.size) {
prev_values.push(' ');
}
if (prev_values.length > 20) {
// might grow exponentially, bail out
return true;
}
}
prev_values.forEach(prev_value => possible_values.add(prev_value));
if (possible_values.has(UNKNOWN)) return true;
for (const value of possible_values) {

@ -151,6 +151,10 @@ export default class Element extends Node {
}
}
// Binding relies on Attribute, defer its evaluation
const order = ['Binding']; // everything else is -1
info.attributes.sort((a, b) => order.indexOf(a.type) - order.indexOf(b.type));
info.attributes.forEach(node => {
switch (node.type) {
case 'Action':

@ -1,8 +1,6 @@
import Node from './shared/Node';
import Expression from './shared/Expression';
import Component from '../Component';
import { b, x } from 'code-red';
import Block from '../render_dom/Block';
import { sanitize } from '../../utils/names';
import { Identifier } from 'estree';
@ -14,6 +12,7 @@ export default class EventHandler extends Node {
handler_name: Identifier;
uses_context = false;
can_make_passive = false;
reassigned?: boolean;
constructor(component: Component, parent, template_scope, info) {
super(component, parent, template_scope, info);
@ -22,7 +21,7 @@ export default class EventHandler extends Node {
this.modifiers = new Set(info.modifiers);
if (info.expression) {
this.expression = new Expression(component, this, template_scope, info.expression, true);
this.expression = new Expression(component, this, template_scope, info.expression);
this.uses_context = this.expression.uses_context;
if (/FunctionExpression/.test(info.expression.type) && info.expression.params.length === 0) {
@ -42,34 +41,12 @@ export default class EventHandler extends Node {
if (node && (node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration' || node.type === 'ArrowFunctionExpression') && node.params.length === 0) {
this.can_make_passive = true;
}
this.reassigned = component.var_lookup.get(info.expression.name).reassigned;
}
}
} else {
const id = component.get_unique_name(`${sanitize(this.name)}_handler`);
component.add_var({
name: id.name,
internal: true,
referenced: true
});
component.partly_hoisted.push(b`
function ${id}(event) {
@bubble($$self, event);
}
`);
this.handler_name = id;
this.handler_name = component.get_unique_name(`${sanitize(this.name)}_handler`);
}
}
// TODO move this? it is specific to render-dom
render(block: Block) {
if (this.expression) {
return this.expression.manipulate(block);
}
// this.component.add_reference(this.handler_name);
return x`#ctx.${this.handler_name}`;
}
}

@ -203,13 +203,11 @@ export default class Block {
}
add_variable(id: Identifier, init?: Node) {
this.variables.forEach(v => {
if (v.id.name === id.name) {
throw new Error(
`Variable '${id.name}' already initialised with a different value`
);
}
});
if (this.variables.has(id.name)) {
throw new Error(
`Variable '${id.name}' already initialised with a different value`
);
}
this.variables.set(id.name, { id, init });
}
@ -376,6 +374,8 @@ export default class Block {
d: ${properties.destroy}
}`;
const block = dev && this.get_unique_name('block');
const body = b`
${Array.from(this.variables.values()).map(({ id, init }) => {
return init
@ -387,9 +387,15 @@ export default class Block {
${dev
? b`
const block = ${return_value};
@dispatch_dev("SvelteRegisterBlock", { block, id: ${this.name || 'create_fragment'}.name, type: "${this.type}", source: "${this.comment ? this.comment.replace(/"/g, '\\"') : ''}", ctx: #ctx });
return block;`
const ${block} = ${return_value};
@dispatch_dev("SvelteRegisterBlock", {
block: ${block},
id: ${this.name || 'create_fragment'}.name,
type: "${this.type}",
source: "${this.comment ? this.comment.replace(/"/g, '\\"') : ''}",
ctx: #ctx
});
return ${block};`
: b`
return ${return_value};`
}
@ -398,6 +404,21 @@ export default class Block {
return body;
}
has_content() {
return this.renderer.options.dev ||
this.first ||
this.event_listeners.length > 0 ||
this.chunks.intro.length > 0 ||
this.chunks.outro.length > 0 ||
this.chunks.create.length > 0 ||
this.chunks.hydrate.length > 0 ||
this.chunks.claim.length > 0 ||
this.chunks.mount.length > 0 ||
this.chunks.update.length > 0 ||
this.chunks.destroy.length > 0 ||
this.has_animation;
}
render() {
const key = this.key && this.get_unique_name('key');

@ -241,11 +241,16 @@ export default function dom(
args.push(x`$$props`, x`$$invalidate`);
}
body.push(b`
function create_fragment(#ctx) {
${block.get_contents()}
}
const has_create_fragment = block.has_content();
if (has_create_fragment) {
body.push(b`
function create_fragment(#ctx) {
${block.get_contents()}
}
`);
}
body.push(b`
${component.extract_javascript(component.ast.module)}
${component.fully_hoisted}
@ -437,7 +442,7 @@ export default function dom(
${css.code && b`this.shadowRoot.innerHTML = \`<style>${css.code.replace(/\\/g, '\\\\')}${options.dev ? `\n/*# sourceMappingURL=${css.map.toUrl()} */` : ''}</style>\`;`}
@init(this, { target: this.shadowRoot }, ${definition}, create_fragment, ${not_equal}, ${prop_names});
@init(this, { target: this.shadowRoot }, ${definition}, ${has_create_fragment ? 'create_fragment': 'null'}, ${not_equal}, ${prop_names});
${dev_props_check}
@ -489,7 +494,7 @@ export default function dom(
constructor(options) {
super(${options.dev && `options`});
${should_add_css && b`if (!@_document.getElementById("${component.stylesheet.id}-style")) ${add_css}();`}
@init(this, options, ${definition}, create_fragment, ${not_equal}, ${prop_names});
@init(this, options, ${definition}, ${has_create_fragment ? 'create_fragment': 'null'}, ${not_equal}, ${prop_names});
${options.dev && b`@dispatch_dev("SvelteRegisterComponent", { component: this, tagName: "${name.name}", options, id: create_fragment.name });`}
${dev_props_check}

@ -3,21 +3,24 @@ import Wrapper from './shared/Wrapper';
import { b } from 'code-red';
import Body from '../../nodes/Body';
import { Identifier } from 'estree';
import EventHandler from './Element/EventHandler';
export default class BodyWrapper extends Wrapper {
node: Body;
render(block: Block, _parent_node: Identifier, _parent_nodes: Identifier) {
this.node.handlers.forEach(handler => {
const snippet = handler.render(block);
this.node.handlers
.map(handler => new EventHandler(handler, this))
.forEach(handler => {
const snippet = handler.get_snippet(block);
block.chunks.init.push(b`
@_document.body.addEventListener("${handler.name}", ${snippet});
`);
block.chunks.init.push(b`
@_document.body.addEventListener("${handler.node.name}", ${snippet});
`);
block.chunks.destroy.push(b`
@_document.body.removeEventListener("${handler.name}", ${snippet});
`);
});
block.chunks.destroy.push(b`
@_document.body.removeEventListener("${handler.node.name}", ${snippet});
`);
});
}
}

@ -0,0 +1,69 @@
import EventHandler from '../../../nodes/EventHandler';
import Wrapper from '../shared/Wrapper';
import Block from '../../Block';
import { b, x, p } from 'code-red';
const TRUE = x`true`;
const FALSE = x`false`;
export default class EventHandlerWrapper {
node: EventHandler;
parent: Wrapper;
constructor(node: EventHandler, parent: Wrapper) {
this.node = node;
this.parent = parent;
if (!node.expression) {
this.parent.renderer.component.add_var({
name: node.handler_name.name,
internal: true,
referenced: true,
});
this.parent.renderer.component.partly_hoisted.push(b`
function ${node.handler_name.name}(event) {
@bubble($$self, event);
}
`);
}
}
get_snippet(block) {
const snippet = this.node.expression ? this.node.expression.manipulate(block) : x`#ctx.${this.node.handler_name}`;
if (this.node.reassigned) {
block.maintain_context = true;
return x`function () { ${snippet}.apply(this, arguments); }`;
}
return snippet;
}
render(block: Block, target: string) {
let snippet = this.get_snippet(block);
if (this.node.modifiers.has('preventDefault')) snippet = x`@prevent_default(${snippet})`;
if (this.node.modifiers.has('stopPropagation')) snippet = x`@stop_propagation(${snippet})`;
if (this.node.modifiers.has('self')) snippet = x`@self(${snippet})`;
const args = [];
const opts = ['passive', 'once', 'capture'].filter(mod => this.node.modifiers.has(mod));
if (opts.length) {
args.push((opts.length === 1 && opts[0] === 'capture')
? TRUE
: x`{ ${opts.map(opt => p`${opt}: true`)} }`);
} else if (block.renderer.options.dev) {
args.push(FALSE);
}
if (block.renderer.options.dev) {
args.push(this.node.modifiers.has('stopPropagation') ? TRUE : FALSE);
args.push(this.node.modifiers.has('preventDefault') ? TRUE : FALSE);
}
block.event_listeners.push(
x`@listen(${target}, "${this.node.name}", ${snippet}, ${args})`
);
}
}

@ -24,6 +24,7 @@ import bind_this from '../shared/bind_this';
import { changed } from '../shared/changed';
import { is_head } from '../shared/is_head';
import { Identifier } from 'estree';
import EventHandler from './EventHandler';
const events = [
{
@ -113,6 +114,7 @@ export default class ElementWrapper extends Wrapper {
fragment: FragmentWrapper;
attributes: AttributeWrapper[];
bindings: Binding[];
event_handlers: EventHandler[];
class_dependencies: string[];
slot_block: Block;
@ -194,6 +196,8 @@ export default class ElementWrapper extends Wrapper {
// e.g. <audio bind:paused bind:currentTime>
this.bindings = this.node.bindings.map(binding => new Binding(block, binding, this));
this.event_handlers = this.node.handlers.map(event_handler => new EventHandler(event_handler, this));
if (node.intro || node.outro) {
if (node.intro) block.add_intro(node.intro.is_local);
if (node.outro) block.add_outro(node.outro.is_local);
@ -643,7 +647,7 @@ export default class ElementWrapper extends Wrapper {
}
add_event_handlers(block: Block) {
add_event_handlers(block, this.var, this.node.handlers);
add_event_handlers(block, this.var, this.event_handlers);
}
add_transitions(
@ -894,7 +898,7 @@ function to_html(wrappers: Array<ElementWrapper | TextWrapper | TagWrapper>, blo
attr.node.chunks.forEach(chunk => {
if (chunk.type === 'Text') {
state.quasi.value.raw += chunk.data;
state.quasi.value.raw += escape_html(chunk.data);
} else {
literal.quasis.push(state.quasi);
literal.expressions.push(chunk.manipulate(block));

@ -16,6 +16,7 @@ import is_dynamic from '../shared/is_dynamic';
import bind_this from '../shared/bind_this';
import { changed } from '../shared/changed';
import { Node, Identifier, ObjectExpression } from 'estree';
import EventHandler from '../Element/EventHandler';
export default class InlineComponentWrapper extends Wrapper {
var: Identifier;
@ -365,7 +366,8 @@ export default class InlineComponentWrapper extends Wrapper {
});
const munged_handlers = this.node.handlers.map(handler => {
let snippet = handler.render(block);
const event_handler = new EventHandler(handler, this);
let snippet = event_handler.get_snippet(block);
if (handler.modifiers.has('once')) snippet = x`@once(${snippet})`;
return b`${name}.$on("${handler.name}", ${snippet});`;
@ -396,12 +398,12 @@ export default class InlineComponentWrapper extends Wrapper {
`);
block.chunks.create.push(
b`if (${name}) ${name}.$$.fragment.c();`
b`if (${name}) @create_component(${name}.$$.fragment);`
);
if (parent_nodes && this.renderer.options.hydratable) {
block.chunks.claim.push(
b`if (${name}) ${name}.$$.fragment.l(${parent_nodes});`
b`if (${name}) @claim_component(${name}.$$.fragment, ${parent_nodes});`
);
}
@ -437,7 +439,7 @@ export default class InlineComponentWrapper extends Wrapper {
${munged_bindings}
${munged_handlers}
${name}.$$.fragment.c();
@create_component(${name}.$$.fragment);
@transition_in(${name}.$$.fragment, 1);
@mount_component(${name}, ${update_mount_node}, ${anchor});
} else {
@ -472,11 +474,11 @@ export default class InlineComponentWrapper extends Wrapper {
${munged_handlers}
`);
block.chunks.create.push(b`${name}.$$.fragment.c();`);
block.chunks.create.push(b`@create_component(${name}.$$.fragment);`);
if (parent_nodes && this.renderer.options.hydratable) {
block.chunks.claim.push(
b`${name}.$$.fragment.l(${parent_nodes});`
b`@claim_component(${name}.$$.fragment, ${parent_nodes});`
);
}

@ -8,6 +8,7 @@ import add_actions from './shared/add_actions';
import { changed } from './shared/changed';
import { Identifier } from 'estree';
import { TemplateNode } from '../../../interfaces';
import EventHandler from './Element/EventHandler';
const associated_events = {
innerWidth: 'resize',
@ -34,9 +35,11 @@ const readonly = new Set([
export default class WindowWrapper extends Wrapper {
node: Window;
handlers: EventHandler[];
constructor(renderer: Renderer, block: Block, parent: Wrapper, node: TemplateNode) {
super(renderer, block, parent, node);
this.handlers = this.node.handlers.map(handler => new EventHandler(handler, this));
}
render(block: Block, _parent_node: Identifier, _parent_nodes: Identifier) {
@ -47,7 +50,7 @@ export default class WindowWrapper extends Wrapper {
const bindings: Record<string, string> = {};
add_actions(component, block, '@_window', this.node.actions);
add_event_handlers(block, '@_window', this.node.handlers);
add_event_handlers(block, '@_window', this.handlers);
this.node.bindings.forEach(binding => {
// in dev mode, throw if read-only values are written to

@ -1,39 +1,10 @@
import Block from '../../Block';
import EventHandler from '../../../nodes/EventHandler';
import { x, p } from 'code-red';
const TRUE = x`true`;
const FALSE = x`false`;
import EventHandler from '../Element/EventHandler';
export default function add_event_handlers(
block: Block,
target: string,
handlers: EventHandler[]
) {
handlers.forEach(handler => {
let snippet = handler.render(block);
if (handler.modifiers.has('preventDefault')) snippet = x`@prevent_default(${snippet})`;
if (handler.modifiers.has('stopPropagation')) snippet = x`@stop_propagation(${snippet})`;
if (handler.modifiers.has('self')) snippet = x`@self(${snippet})`;
const args = [];
const opts = ['passive', 'once', 'capture'].filter(mod => handler.modifiers.has(mod));
if (opts.length) {
args.push((opts.length === 1 && opts[0] === 'capture')
? TRUE
: x`{ ${opts.map(opt => p`${opt}: true`)} }`);
} else if (block.renderer.options.dev) {
args.push(FALSE);
}
if (block.renderer.options.dev) {
args.push(handler.modifiers.has('stopPropagation') ? TRUE : FALSE);
args.push(handler.modifiers.has('preventDefault') ? TRUE : FALSE);
}
block.event_listeners.push(
x`@listen(${target}, "${handler.name}", ${snippet}, ${args})`
);
});
handlers.forEach(handler => handler.render(block, target));
}

@ -1,7 +1,7 @@
export default function get_name_from_filename(filename: string) {
if (!filename) return null;
// eslint-disable-next-line no-useless-escape
const parts = filename.split(/[\/\\]/);
const parts = filename.split(/[/\\]/).map(encodeURI);
if (parts.length > 1) {
const index_match = parts[parts.length - 1].match(/^index(\.\w+)/);
@ -12,6 +12,7 @@ export default function get_name_from_filename(filename: string) {
}
const base = parts.pop()
.replace(/%/g, 'u')
.replace(/\.[^.]+$/, "")
.replace(/[^a-zA-Z_$0-9]+/g, '_')
.replace(/^_/, '')

@ -1,156 +1,8 @@
import { walk } from 'estree-walker';
import is_reference from 'is-reference';
import { Node, VariableDeclaration, ClassDeclaration, VariableDeclarator, ObjectPattern, Property, RestElement, ArrayPattern, Identifier } from 'estree';
import get_object from './get_object';
import { Node } from 'estree';
import { analyze, Scope, extract_names, extract_identifiers } from 'periscopic';
// TODO replace this with periscopic?
export function create_scopes(expression: Node) {
const map = new WeakMap();
const globals: Map<string, Node> = new Map();
let scope = new Scope(null, false);
walk(expression, {
enter(node, parent) {
if (node.type === 'ImportDeclaration') {
node.specifiers.forEach(specifier => {
scope.declarations.set(specifier.local.name, specifier);
});
} else if (node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression' || node.type === 'ArrowFunctionExpression') {
if (node.type === 'FunctionDeclaration') {
scope.declarations.set(node.id.name, node);
scope = new Scope(scope, false);
map.set(node, scope);
} else {
scope = new Scope(scope, false);
map.set(node, scope);
if (node.type === 'FunctionExpression' && node.id) {
scope.declarations.set(node.id.name, node);
}
}
node.params.forEach((param) => {
extract_names(param).forEach(name => {
scope.declarations.set(name, node);
});
});
} else if (/For(?:In|Of)?Statement/.test(node.type)) {
scope = new Scope(scope, true);
map.set(node, scope);
} else if (node.type === 'BlockStatement') {
scope = new Scope(scope, true);
map.set(node, scope);
} else if (node.type === 'ClassDeclaration' || node.type === 'VariableDeclaration') {
scope.add_declaration(node);
} else if (node.type === 'CatchClause') {
scope = new Scope(scope, true);
map.set(node, scope);
extract_names(node.param).forEach(name => {
scope.declarations.set(name, node.param);
});
} else if (node.type === 'Identifier' && is_reference(node as Node, parent as Node)) {
if (!scope.has(node.name) && !globals.has(node.name)) {
globals.set(node.name, node);
}
}
},
leave(node: Node) {
if (map.has(node)) {
scope = scope.parent;
}
}
});
scope.declarations.forEach((_node, name) => {
globals.delete(name);
});
return { map, scope, globals };
return analyze(expression);
}
export class Scope {
parent: Scope;
block: boolean;
declarations: Map<string, Node> = new Map();
initialised_declarations: Set<string> = new Set();
constructor(parent: Scope, block: boolean) {
this.parent = parent;
this.block = block;
}
add_declaration(node: VariableDeclaration | ClassDeclaration) {
if (node.type === 'VariableDeclaration') {
if (node.kind === 'var' && this.block && this.parent) {
this.parent.add_declaration(node);
} else {
node.declarations.forEach((declarator: VariableDeclarator) => {
extract_names(declarator.id).forEach(name => {
this.declarations.set(name, node);
if (declarator.init) this.initialised_declarations.add(name);
});
});
}
} else {
this.declarations.set(node.id.name, node);
}
}
find_owner(name: string): Scope {
if (this.declarations.has(name)) return this;
return this.parent && this.parent.find_owner(name);
}
has(name: string): boolean {
return (
this.declarations.has(name) || (this.parent && this.parent.has(name))
);
}
}
export function extract_names(param: Node): string[] {
return extract_identifiers(param).map((node: any) => node.name);
}
export function extract_identifiers(param: Node): Identifier[] {
const nodes: Identifier[] = [];
extractors[param.type] && extractors[param.type](nodes, param);
return nodes;
}
const extractors = {
Identifier(nodes: Node[], param: Node) {
nodes.push(param);
},
MemberExpression(nodes: Node[], param: Node) {
nodes.push(get_object(param));
},
ObjectPattern(nodes: Node[], param: ObjectPattern) {
param.properties.forEach((prop: Property | RestElement) => {
if (prop.type === 'RestElement') {
nodes.push(prop.argument);
} else {
extractors[prop.value.type](nodes, prop.value);
}
});
},
ArrayPattern(nodes: Node[], param: ArrayPattern) {
param.elements.forEach((element: Node) => {
if (element) extractors[element.type](nodes, element);
});
},
RestElement(nodes: Node[], param: any) {
extractors[param.argument.type](nodes, param.argument);
},
AssignmentPattern(nodes: Node[], param: any) {
extractors[param.left.type](nodes, param.left);
}
};
export { Scope, extract_names, extract_identifiers };

@ -12,13 +12,15 @@ export function escape(data: string, { only_escape_at_symbol = false } = {}) {
}
const escaped = {
'"': '&quot;',
"'": '&#39;',
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
};
export function escape_html(html) {
return String(html).replace(/[&<>]/g, match => escaped[match]);
return String(html).replace(/["'&<>]/g, match => escaped[match]);
}
export function escape_template(str) {

@ -4,6 +4,21 @@ import { blank_object, is_function, run, run_all, noop, has_prop } from './utils
import { children } from './dom';
import { transition_in } from './transitions';
interface Fragment {
key: string|null;
first: null;
/* create */ c: () => void;
/* claim */ l: (nodes: any) => void;
/* hydrate */ h: () => void;
/* mount */ m: (target: HTMLElement, anchor: any) => void;
/* update */ p: (changed: any, ctx: any) => void;
/* measure */ r: () => void;
/* fix */ f: () => void;
/* animate */ a: () => void;
/* intro */ i: (local: any) => void;
/* outro */ o: (local: any) => void;
/* destroy */ d: (detaching: 0|1) => void;
}
// eslint-disable-next-line @typescript-eslint/class-name-casing
interface T$$ {
dirty: null;
@ -13,7 +28,7 @@ interface T$$ {
callbacks: any;
after_update: any[];
props: Record<string, 0 | string>;
fragment: null|any;
fragment: null|false|Fragment;
not_equal: any;
before_update: any[];
context: Map<any, any>;
@ -29,10 +44,18 @@ export function bind(component, name, callback) {
}
}
export function create_component(block) {
block && block.c();
}
export function claim_component(block, parent_nodes) {
block && block.l(parent_nodes);
}
export function mount_component(component, target, anchor) {
const { fragment, on_mount, on_destroy, after_update } = component.$$;
fragment.m(target, anchor);
fragment && fragment.m(target, anchor);
// onMount happens before the initial afterUpdate
add_render_callback(() => {
@ -51,15 +74,16 @@ export function mount_component(component, target, anchor) {
}
export function destroy_component(component, detaching) {
if (component.$$.fragment) {
run_all(component.$$.on_destroy);
const $$ = component.$$;
if ($$.fragment !== null) {
run_all($$.on_destroy);
component.$$.fragment.d(detaching);
$$.fragment && $$.fragment.d(detaching);
// TODO null out other refs, including component.$$ (but need to
// preserve final state?)
component.$$.on_destroy = component.$$.fragment = null;
component.$$.ctx = {};
$$.on_destroy = $$.fragment = null;
$$.ctx = {};
}
}
@ -115,15 +139,17 @@ export function init(component, options, instance, create_fragment, not_equal, p
$$.update();
ready = true;
run_all($$.before_update);
$$.fragment = create_fragment($$.ctx);
// `false` as a special case of no DOM component
$$.fragment = create_fragment ? create_fragment($$.ctx) : false;
if (options.target) {
if (options.hydrate) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
$$.fragment!.l(children(options.target));
$$.fragment && $$.fragment!.l(children(options.target));
} else {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
$$.fragment!.c();
$$.fragment && $$.fragment!.c();
}
if (options.intro) transition_in(component.$$.fragment);

@ -70,10 +70,10 @@ export function flush() {
}
function update($$) {
if ($$.fragment) {
if ($$.fragment !== null) {
$$.update($$.dirty);
run_all($$.before_update);
$$.fragment.p($$.dirty, $$.ctx);
$$.fragment && $$.fragment.p($$.dirty, $$.ctx);
$$.dirty = null;
$$.after_update.forEach(add_render_callback);

@ -1,4 +1,4 @@
import { cubicOut, cubicInOut } from 'svelte/easing';
import { cubicOut, cubicInOut, linear } from 'svelte/easing';
import { assign, is_function } from 'svelte/internal';
type EasingFunction = (t: number) => number;
@ -43,17 +43,20 @@ export function blur(node: Element, {
interface FadeParams {
delay: number;
duration: number;
easing: EasingFunction;
}
export function fade(node: Element, {
delay = 0,
duration = 400
duration = 400,
easing = linear
}: FadeParams): TransitionConfig {
const o = +getComputedStyle(node).opacity;
return {
delay,
duration,
easing,
css: t => `opacity: ${t * o}`
};
}

@ -0,0 +1,143 @@
export default {
warnings: [
{
code: 'css-unused-selector',
message: 'Unused CSS selector',
frame:
` 9: <style>
10: .foo {color: red;}
11: .fooaa {color: red;}
^
12: .foobb {color: red;}
13: .foocc {color: red;}`,
start: { line: 11, column: 2, character: 206 },
end: { line: 11, column: 8, character: 212 },
pos: 206,
},
{
code: 'css-unused-selector',
message: 'Unused CSS selector',
frame:
`10: .foo {color: red;}
11: .fooaa {color: red;}
12: .foobb {color: red;}
^
13: .foocc {color: red;}
14: .foodd {color: red;}`,
start: { line: 12, column: 2, character: 229 },
end: { line: 12, column: 8, character: 235 },
pos: 229,
},
{
code: 'css-unused-selector',
message: 'Unused CSS selector',
frame:
`12: .foobb {color: red;}
13: .foocc {color: red;}
14: .foodd {color: red;}
^
15: .aa {color: red;}
16: .bb {color: red;}`,
start: { line: 14, column: 2, character: 275 },
end: { line: 14, column: 8, character: 281 },
pos: 275,
},
{
code: 'css-unused-selector',
message: 'Unused CSS selector',
frame:
`18: .dd {color: red;}
19: .aabar {color: red;}
20: .bbbar {color: red;}
^
21: .ccbar {color: red;}
22: .ddbar {color: red;}`,
start: { line: 20, column: 2, character: 401 },
end: { line: 20, column: 8, character: 407 },
pos: 401,
},
{
code: 'css-unused-selector',
message: 'Unused CSS selector',
frame:
`19: .aabar {color: red;}
20: .bbbar {color: red;}
21: .ccbar {color: red;}
^
22: .ddbar {color: red;}
23: .fooaabar {color: red;}`,
start: { line: 21, column: 2, character: 424 },
end: { line: 21, column: 8, character: 430 },
pos: 424,
},
{
code: 'css-unused-selector',
message: 'Unused CSS selector',
frame:
`20: .bbbar {color: red;}
21: .ccbar {color: red;}
22: .ddbar {color: red;}
^
23: .fooaabar {color: red;}
24: .foobbbar {color: red;}`,
start: { line: 22, column: 2, character: 447 },
end: { line: 22, column: 8, character: 453 },
pos: 447,
},
{
code: 'css-unused-selector',
message: 'Unused CSS selector',
frame:
`21: .ccbar {color: red;}
22: .ddbar {color: red;}
23: .fooaabar {color: red;}
^
24: .foobbbar {color: red;}
25: .fooccbar {color: red;}`,
start: { line: 23, column: 2, character: 470 },
end: { line: 23, column: 11, character: 479 },
pos: 470,
},
{
code: 'css-unused-selector',
message: 'Unused CSS selector',
frame:
`22: .ddbar {color: red;}
23: .fooaabar {color: red;}
24: .foobbbar {color: red;}
^
25: .fooccbar {color: red;}
26: .fooddbar {color: red;}`,
start: { line: 24, column: 2, character: 496 },
end: { line: 24, column: 11, character: 505 },
pos: 496,
},
{
code: 'css-unused-selector',
message: 'Unused CSS selector',
frame:
`23: .fooaabar {color: red;}
24: .foobbbar {color: red;}
25: .fooccbar {color: red;}
^
26: .fooddbar {color: red;}
27: .baz {color: red;}`,
start: { line: 25, column: 2, character: 522 },
end: { line: 25, column: 11, character: 531 },
pos: 522,
},
{
code: 'css-unused-selector',
message: 'Unused CSS selector',
frame:
`26: .fooddbar {color: red;}
27: .baz {color: red;}
28: .unused {color: red;}
^
29: </style>`,
start: { line: 28, column: 2, character: 595 },
end: { line: 28, column: 9, character: 602 },
pos: 595,
},
],
};

@ -0,0 +1 @@
.foo.svelte-xyz{color:red}.foocc.svelte-xyz{color:red}.aa.svelte-xyz{color:red}.bb.svelte-xyz{color:red}.cc.svelte-xyz{color:red}.dd.svelte-xyz{color:red}.aabar.svelte-xyz{color:red}.fooddbar.svelte-xyz{color:red}.baz.svelte-xyz{color:red}

@ -0,0 +1,29 @@
<script>
export let a, b, c;
</script>
<div class="foo{a ? ' aa' : b ? ' bb ' : c ? 'cc ' : 'dd'}bar baz {a ? ' aa' : b ? ' bb ' : c ? 'cc ' : 'dd'}">
some stuff
</div>
<style>
.foo {color: red;}
.fooaa {color: red;}
.foobb {color: red;}
.foocc {color: red;}
.foodd {color: red;}
.aa {color: red;}
.bb {color: red;}
.cc {color: red;}
.dd {color: red;}
.aabar {color: red;}
.bbbar {color: red;}
.ccbar {color: red;}
.ddbar {color: red;}
.fooaabar {color: red;}
.foobbbar {color: red;}
.fooccbar {color: red;}
.fooddbar {color: red;}
.baz {color: red;}
.unused {color: red;}
</style>

@ -0,0 +1,3 @@
export default {
warnings: [],
};

@ -0,0 +1 @@
.thing.svelte-xyz{color:blue}.active.svelte-xyz{color:blue}.thing.active.svelte-xyz{color:blue}.hover.svelte-xyz{color:blue}.hover.unused.svelte-xyz{color:blue}.unused.svelte-xyz{color:blue}

@ -0,0 +1,18 @@
<script>
export let active;
export let hover;
</script>
<div class="thing {active ? 'active' : hover}">
some stuff
</div>
<style>
.thing {color: blue;}
.active {color: blue;}
.thing.active {color: blue;}
.hover { color: blue; }
.hover.unused { color: blue; }
.unused {color: blue;}
</style>

@ -0,0 +1,25 @@
export default {
warnings: [
{
code: 'css-unused-selector',
end: {
character: 205,
column: 9,
line: 14,
},
frame: `
12: .thing.active {color: blue;}
13:
14: .unused {color: blue;}
^
15: </style>`,
message: 'Unused CSS selector',
pos: 198,
start: {
character: 198,
column: 2,
line: 14,
},
},
],
};

@ -0,0 +1 @@
.thing.svelte-xyz{color:blue}.active.svelte-xyz{color:blue}.thing.active.svelte-xyz{color:blue}

@ -0,0 +1,15 @@
<script>
export let active;
</script>
<div class="thing {active ? 'active' : ''}">
some stuff
</div>
<style>
.thing {color: blue;}
.active {color: blue;}
.thing.active {color: blue;}
.unused {color: blue;}
</style>

@ -0,0 +1,31 @@
export default {
warnings: [
{
code: 'css-unused-selector',
message: 'Unused CSS selector',
frame: `
13: .thing.active {color: blue;}
14: .hover { color: blue; }
15: .hover.unused { color: blue; }
^
16:
17: .unused {color: blue;}`,
start: { line: 15, column: 2, character: 261 },
end: { line: 15, column: 15, character: 274 },
pos: 261,
},
{
code: 'css-unused-selector',
message: 'Unused CSS selector',
frame: `
15: .hover.unused { color: blue; }
16:
17: .unused {color: blue;}
^
18: </style>`,
start: { line: 17, column: 2, character: 295 },
end: { line: 17, column: 9, character: 302 },
pos: 295,
},
],
};

@ -0,0 +1 @@
.thing.svelte-xyz{color:blue}.active.svelte-xyz{color:blue}.thing.active.svelte-xyz{color:blue}.hover.svelte-xyz{color:blue}

@ -0,0 +1,18 @@
<script>
export let active;
export let hover;
</script>
<div class="thing {active ? 'active' : hover ? 'hover' : ''}">
some stuff
</div>
<style>
.thing {color: blue;}
.active {color: blue;}
.thing.active {color: blue;}
.hover { color: blue; }
.hover.unused { color: blue; }
.unused {color: blue;}
</style>

@ -0,0 +1,82 @@
import {
SvelteComponent,
attr,
detach,
element,
init,
insert,
listen,
noop,
run_all,
safe_not_equal,
space
} from "svelte/internal";
function create_fragment(ctx) {
let input0;
let t;
let input1;
let dispose;
return {
c() {
input0 = element("input");
t = space();
input1 = element("input");
attr(input0, "type", "file");
attr(input1, "type", "file");
dispose = [
listen(input0, "change", ctx.input0_change_handler),
listen(input1, "change", ctx.input1_change_handler)
];
},
m(target, anchor) {
insert(target, input0, anchor);
insert(target, t, anchor);
insert(target, input1, anchor);
},
p: noop,
i: noop,
o: noop,
d(detaching) {
if (detaching) detach(input0);
if (detaching) detach(t);
if (detaching) detach(input1);
run_all(dispose);
}
};
}
function instance($$self, $$props, $$invalidate) {
let { files } = $$props;
function input0_change_handler() {
files = this.files;
$$invalidate("files", files);
}
function input1_change_handler() {
files = this.files;
$$invalidate("files", files);
}
$$self.$set = $$props => {
if ("files" in $$props) $$invalidate("files", files = $$props.files);
};
return {
files,
input0_change_handler,
input1_change_handler
};
}
class Component extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance, create_fragment, safe_not_equal, { files: 0 });
}
}
export default Component;

@ -0,0 +1,6 @@
<script>
export let files;
</script>
<input type="file" bind:files>
<input bind:files type="file">

@ -1,5 +1,6 @@
import {
SvelteComponent,
create_component,
destroy_component,
init,
mount_component,
@ -15,7 +16,7 @@ function create_fragment(ctx) {
return {
c() {
nested.$$.fragment.c();
create_component(nested.$$.fragment);
},
m(target, anchor) {
mount_component(nested, target, anchor);

@ -1,5 +1,6 @@
import {
SvelteComponent,
create_component,
destroy_component,
init,
mount_component,
@ -15,7 +16,7 @@ function create_fragment(ctx) {
return {
c() {
nested.$$.fragment.c();
create_component(nested.$$.fragment);
},
m(target, anchor) {
mount_component(nested, target, anchor);

@ -1,5 +1,6 @@
import {
SvelteComponent,
create_component,
destroy_component,
init,
mount_component,
@ -15,7 +16,7 @@ function create_fragment(ctx) {
return {
c() {
nested.$$.fragment.c();
create_component(nested.$$.fragment);
},
m(target, anchor) {
mount_component(nested, target, anchor);

@ -1,5 +1,6 @@
import {
SvelteComponent,
create_component,
destroy_component,
detach,
element,
@ -28,9 +29,9 @@ function create_fragment(ctx) {
return {
c() {
foo.$$.fragment.c();
create_component(foo.$$.fragment);
t0 = space();
bar.$$.fragment.c();
create_component(bar.$$.fragment);
t1 = space();
input = element("input");
dispose = listen(input, "input", ctx.input_input_handler);

@ -1,5 +1,6 @@
import {
SvelteComponent,
create_component,
destroy_component,
init,
mount_component,
@ -15,7 +16,7 @@ function create_fragment(ctx) {
return {
c() {
nested.$$.fragment.c();
create_component(nested.$$.fragment);
},
m(target, anchor) {
mount_component(nested, target, anchor);

@ -2,24 +2,12 @@ import {
SvelteComponent,
component_subscribe,
init,
noop,
safe_not_equal,
set_store_value
} from "svelte/internal";
import { count } from "./store.js";
function create_fragment(ctx) {
return {
c: noop,
m: noop,
p: noop,
i: noop,
o: noop,
d: noop
};
}
function instance($$self, $$props, $$invalidate) {
let $count;
component_subscribe($$self, count, $$value => $$invalidate("$count", $count = $$value));
@ -34,7 +22,7 @@ function instance($$self, $$props, $$invalidate) {
class Component extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance, create_fragment, safe_not_equal, { increment: 0 });
init(this, options, instance, null, safe_not_equal, { increment: 0 });
}
get increment() {

@ -1,15 +1,4 @@
import { SvelteComponent, init, noop, safe_not_equal } from "svelte/internal";
function create_fragment(ctx) {
return {
c: noop,
m: noop,
p: noop,
i: noop,
o: noop,
d: noop
};
}
import { SvelteComponent, init, safe_not_equal } from "svelte/internal";
function instance($$self, $$props, $$invalidate) {
let { x } = $$props;
@ -32,7 +21,7 @@ function instance($$self, $$props, $$invalidate) {
class Component extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance, create_fragment, safe_not_equal, { x: 0, a: 0, b: 0 });
init(this, options, instance, null, safe_not_equal, { x: 0, a: 0, b: 0 });
}
get a() {

@ -1,17 +1,6 @@
import { SvelteComponent, init, noop, safe_not_equal } from "svelte/internal";
import { SvelteComponent, init, safe_not_equal } from "svelte/internal";
import { onMount } from "svelte";
function create_fragment(ctx) {
return {
c: noop,
m: noop,
p: noop,
i: noop,
o: noop,
d: noop
};
}
function instance($$self, $$props, $$invalidate) {
let { foo = "bar" } = $$props;
@ -29,7 +18,7 @@ function instance($$self, $$props, $$invalidate) {
class Component extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance, create_fragment, safe_not_equal, { foo: 0 });
init(this, options, instance, null, safe_not_equal, { foo: 0 });
}
}

@ -1,5 +1,6 @@
import {
SvelteComponent,
create_component,
destroy_component,
init,
mount_component,
@ -17,7 +18,7 @@ function create_fragment(ctx) {
return {
c() {
lazyload.$$.fragment.c();
create_component(lazyload.$$.fragment);
},
m(target, anchor) {
mount_component(lazyload, target, anchor);

@ -0,0 +1,15 @@
import { SvelteComponent, init, safe_not_equal } from "svelte/internal";
function instance($$self) {
const a = 1 + 2;
return {};
}
class Component extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance, null, safe_not_equal, {});
}
}
export default Component;

@ -0,0 +1,3 @@
<script>
const a = 1 + 2;
</script>

@ -0,0 +1,107 @@
import {
SvelteComponent,
append,
detach,
element,
init,
insert,
listen,
noop,
run_all,
safe_not_equal,
set_data,
space,
text
} from "svelte/internal";
function create_fragment(ctx) {
let p0;
let button0;
let t1;
let button1;
let t3;
let p1;
let t4;
let t5;
let button2;
let dispose;
return {
c() {
p0 = element("p");
button0 = element("button");
button0.textContent = "set handler 1";
t1 = space();
button1 = element("button");
button1.textContent = "set handler 2";
t3 = space();
p1 = element("p");
t4 = text(ctx.number);
t5 = space();
button2 = element("button");
button2.textContent = "click";
dispose = [
listen(button0, "click", ctx.updateHandler1),
listen(button1, "click", ctx.updateHandler2),
listen(button2, "click", function () {
ctx.clickHandler.apply(this, arguments);
})
];
},
m(target, anchor) {
insert(target, p0, anchor);
append(p0, button0);
append(p0, t1);
append(p0, button1);
insert(target, t3, anchor);
insert(target, p1, anchor);
append(p1, t4);
insert(target, t5, anchor);
insert(target, button2, anchor);
},
p(changed, new_ctx) {
ctx = new_ctx;
if (changed.number) set_data(t4, ctx.number);
},
i: noop,
o: noop,
d(detaching) {
if (detaching) detach(p0);
if (detaching) detach(t3);
if (detaching) detach(p1);
if (detaching) detach(t5);
if (detaching) detach(button2);
run_all(dispose);
}
};
}
function instance($$self, $$props, $$invalidate) {
let clickHandler;
let number = 0;
function updateHandler1() {
$$invalidate("clickHandler", clickHandler = () => $$invalidate("number", number = 1));
}
function updateHandler2() {
$$invalidate("clickHandler", clickHandler = () => $$invalidate("number", number = 2));
}
return {
clickHandler,
number,
updateHandler1,
updateHandler2
};
}
class Component extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance, create_fragment, safe_not_equal, {});
}
}
export default Component;

@ -0,0 +1,23 @@
<script>
let clickHandler;
let number = 0;
function updateHandler1(){
clickHandler = () => number = 1;
}
function updateHandler2(){
clickHandler = () => number = 2;
}
</script>
<p>
<button on:click={updateHandler1}>set handler 1</button>
<button on:click={updateHandler2}>set handler 2</button>
</p>
<p>{ number }</p>
<button on:click={clickHandler}>click</button>

@ -1,5 +1,6 @@
import {
SvelteComponent,
create_component,
destroy_component,
detach,
init,
@ -22,9 +23,9 @@ function create_fragment(ctx) {
return {
c() {
imported.$$.fragment.c();
create_component(imported.$$.fragment);
t = space();
nonimported.$$.fragment.c();
create_component(nonimported.$$.fragment);
},
m(target, anchor) {
mount_component(imported, target, anchor);

@ -1,15 +1,4 @@
import { SvelteComponent, init, noop, safe_not_equal } from "svelte/internal";
function create_fragment(ctx) {
return {
c: noop,
m: noop,
p: noop,
i: noop,
o: noop,
d: noop
};
}
import { SvelteComponent, init, safe_not_equal } from "svelte/internal";
function instance($$self, $$props, $$invalidate) {
let { x } = $$props;
@ -36,7 +25,7 @@ function instance($$self, $$props, $$invalidate) {
class Component extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance, create_fragment, safe_not_equal, { x: 0 });
init(this, options, instance, null, safe_not_equal, { x: 0 });
}
}

@ -1,15 +1,4 @@
import { SvelteComponent, init, noop, safe_not_equal } from "svelte/internal";
function create_fragment(ctx) {
return {
c: noop,
m: noop,
p: noop,
i: noop,
o: noop,
d: noop
};
}
import { SvelteComponent, init, safe_not_equal } from "svelte/internal";
function instance($$self, $$props, $$invalidate) {
let { a = 1 } = $$props;
@ -32,7 +21,7 @@ function instance($$self, $$props, $$invalidate) {
class Component extends SvelteComponent {
constructor(options) {
super();
init(this, options, instance, create_fragment, safe_not_equal, { a: 0, b: 0 });
init(this, options, instance, null, safe_not_equal, { a: 0, b: 0 });
}
}

@ -1,16 +1,4 @@
import { SvelteComponent, init, noop, safe_not_equal } from "svelte/internal";
function create_fragment(ctx) {
return {
c: noop,
m: noop,
p: noop,
i: noop,
o: noop,
d: noop
};
}
import { SvelteComponent, init, safe_not_equal } from "svelte/internal";
const SOME_CONSTANT = 42;
function foo(bar) {
@ -20,7 +8,7 @@ function foo(bar) {
class Component extends SvelteComponent {
constructor(options) {
super();
init(this, options, null, create_fragment, safe_not_equal, { foo: 0 });
init(this, options, null, null, safe_not_equal, { foo: 0 });
}
get foo() {

@ -1,3 +1,8 @@
export default {
html: `<span title='"foo"'>foo</span>`
html: `
<span title='"foo"'>
foo
<span title='"bar"'>bar</span>
</span>
`
};

@ -1 +1,4 @@
<span title='"foo"'>foo</span>
<span title='"foo"'>
foo
<span title='"bar"'>bar</span>
</span>

@ -0,0 +1,18 @@
export default {
html: `
<button>update handler</button>
<button>0</button>
`,
async test({ assert, component, target, window }) {
const [updateButton, button] = target.querySelectorAll('button');
const event = new window.MouseEvent('click');
await button.dispatchEvent(event);
assert.equal(component.count, 1);
await updateButton.dispatchEvent(event);
await button.dispatchEvent(event);
assert.equal(component.count, 11);
}
};

@ -0,0 +1,11 @@
<script>
import Button from './Button.svelte';
export let count = 0;
let clickHandler = () => count += 1;
function updateHandler(){
clickHandler = () => count += 10;
}
</script>
<button on:click={updateHandler}>update handler</button>
<Button on:click={clickHandler}>{count}</Button>

@ -0,0 +1,18 @@
export default {
html: `
<button>update handler</button>
<button>0</button>
`,
async test({ assert, component, target, window }) {
const [updateButton, button] = target.querySelectorAll('button');
const event = new window.MouseEvent('click');
await updateButton.dispatchEvent(event);
await button.dispatchEvent(event);
assert.equal(component.count, 10);
await button.dispatchEvent(event);
assert.equal(component.count, 10);
}
};

@ -0,0 +1,11 @@
<script>
import Button from './Button.svelte';
export let count = 0;
let clickHandler = () => count += 1;
function updateHandler(){
clickHandler = () => count += 10;
}
</script>
<button on:click={updateHandler}>update handler</button>
<Button on:click|once={clickHandler}>{count}</Button>

@ -0,0 +1,3 @@
export default {
html: '',
};

@ -0,0 +1,3 @@
<script>
const a = 1 + 2;
</script>

@ -0,0 +1,50 @@
export default {
html: `
<p>
<button>set handler 1</button>
<button>set handler 2</button>
</p>
<p>0</p>
<button>click</button>
`,
async test({ assert, component, target, window }) {
const [updateButton1, updateButton2, button] = target.querySelectorAll(
'button'
);
const event = new window.MouseEvent('click');
await button.dispatchEvent(event);
assert.htmlEqual(target.innerHTML, `
<p>
<button>set handler 1</button>
<button>set handler 2</button>
</p>
<p>0</p>
<button>click</button>
`);
await updateButton1.dispatchEvent(event);
await button.dispatchEvent(event);
assert.htmlEqual(target.innerHTML, `
<p>
<button>set handler 1</button>
<button>set handler 2</button>
</p>
<p>1</p>
<button>click</button>
`);
await updateButton2.dispatchEvent(event);
await button.dispatchEvent(event);
assert.htmlEqual(target.innerHTML, `
<p>
<button>set handler 1</button>
<button>set handler 2</button>
</p>
<p>2</p>
<button>click</button>
`);
},
};

@ -0,0 +1,23 @@
<script>
let clickHandler;
let number = 0;
function updateHandler1(){
clickHandler = () => number = 1;
}
function updateHandler2(){
clickHandler = () => number = 2;
}
</script>
<p>
<button on:click={updateHandler1}>set handler 1</button>
<button on:click={updateHandler2}>set handler 2</button>
</p>
<p>{ number }</p>
<button on:click={clickHandler}>click</button>
Loading…
Cancel
Save