From fdc89ebb6287747a0141347ed0f398a796e1ecfd Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Sun, 16 Feb 2020 01:33:33 +0800 Subject: [PATCH 001/158] warn if component is expected to be reactive (#4409) --- CHANGELOG.md | 1 + .../wrappers/InlineComponent/index.ts | 17 +++++++ test/validator/index.js | 4 +- .../samples/component-dynamic/input.svelte | 18 +++++++ .../samples/component-dynamic/options.json | 3 ++ .../samples/component-dynamic/warnings.json | 47 +++++++++++++++++++ 6 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 test/validator/samples/component-dynamic/input.svelte create mode 100644 test/validator/samples/component-dynamic/options.json create mode 100644 test/validator/samples/component-dynamic/warnings.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 406f2a591ad7..759aabfd7dc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased * Fix indirect bindings involving elements with spreads ([#3680](https://github.com/sveltejs/svelte/issues/3680)) +* Warn when using `` and `Foo` is dynamic ([#4331](https://github.com/sveltejs/svelte/issues/4331)) * Fix unneeded updating of keyed each blocks ([#4373](https://github.com/sveltejs/svelte/issues/4373)) ## 3.18.2 diff --git a/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts b/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts index 631c172576d9..f1c57ed09415 100644 --- a/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts +++ b/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts @@ -106,11 +106,28 @@ export default class InlineComponentWrapper extends Wrapper { block.add_outro(); } + warn_if_reactive() { + const { name } = this.node; + const variable = this.renderer.component.var_lookup.get(name); + if (!variable) { + return; + } + + if (variable.reassigned || variable.export_name || variable.is_reactive_dependency) { + this.renderer.component.warn(this.node, { + code: 'reactive-component', + message: `<${name}/> will not be reactive if ${name} changes. Use if you want this reactivity.`, + }); + } + } + render( block: Block, parent_node: Identifier, parent_nodes: Identifier ) { + this.warn_if_reactive(); + const { renderer } = this; const { component } = renderer; diff --git a/test/validator/index.js b/test/validator/index.js index 8bf0400d7c53..9bce5e149b4a 100644 --- a/test/validator/index.js +++ b/test/validator/index.js @@ -20,6 +20,7 @@ describe("validate", () => { const input = fs.readFileSync(`${__dirname}/samples/${dir}/input.svelte`, "utf-8").replace(/\s+$/, ""); const expected_warnings = tryToLoadJson(`${__dirname}/samples/${dir}/warnings.json`) || []; const expected_errors = tryToLoadJson(`${__dirname}/samples/${dir}/errors.json`); + const options = tryToLoadJson(`${__dirname}/samples/${dir}/options.json`); let error; @@ -28,7 +29,8 @@ describe("validate", () => { dev: config.dev, legacy: config.legacy, generate: false, - customElement: config.customElement + customElement: config.customElement, + ...options, }); assert.deepEqual(warnings.map(w => ({ diff --git a/test/validator/samples/component-dynamic/input.svelte b/test/validator/samples/component-dynamic/input.svelte new file mode 100644 index 000000000000..f591a84fe14c --- /dev/null +++ b/test/validator/samples/component-dynamic/input.svelte @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/test/validator/samples/component-dynamic/options.json b/test/validator/samples/component-dynamic/options.json new file mode 100644 index 000000000000..3a50892ebab1 --- /dev/null +++ b/test/validator/samples/component-dynamic/options.json @@ -0,0 +1,3 @@ +{ + "generate": true +} \ No newline at end of file diff --git a/test/validator/samples/component-dynamic/warnings.json b/test/validator/samples/component-dynamic/warnings.json new file mode 100644 index 000000000000..457ef11a1ed7 --- /dev/null +++ b/test/validator/samples/component-dynamic/warnings.json @@ -0,0 +1,47 @@ +[ + { + "code": "reactive-component", + "message": " will not be reactive if Let changes. Use if you want this reactivity.", + "pos": 190, + "end": { + "character": 197, + "column": 7, + "line": 15 + }, + "start": { + "character": 190, + "column": 0, + "line": 15 + } + }, + { + "message": " will not be reactive if ExportLet changes. Use if you want this reactivity.", + "code": "reactive-component", + "pos": 198, + "end": { + "character": 211, + "column": 13, + "line": 16 + }, + "start": { + "character": 198, + "column": 0, + "line": 16 + } + }, + { + "message": " will not be reactive if Reactive changes. Use if you want this reactivity.", + "code": "reactive-component", + "pos": 212, + "end": { + "character": 224, + "column": 12, + "line": 17 + }, + "start": { + "character": 212, + "column": 0, + "line": 17 + } + } +] From 2b3c2daafb854d04100e0648910083d493bcb1d7 Mon Sep 17 00:00:00 2001 From: Kevin Tewouda Date: Sat, 15 Feb 2020 18:35:54 +0100 Subject: [PATCH 002/158] blog: svelte-for-new-developers: list commands for Windows (#4391) --- site/content/blog/2019-04-16-svelte-for-new-developers.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/content/blog/2019-04-16-svelte-for-new-developers.md b/site/content/blog/2019-04-16-svelte-for-new-developers.md index fc8e993e8824..796a6c11abbb 100644 --- a/site/content/blog/2019-04-16-svelte-for-new-developers.md +++ b/site/content/blog/2019-04-16-svelte-for-new-developers.md @@ -18,7 +18,7 @@ You'll be using the *command line*, also known as the terminal. On Windows, you The command line is a way to interact with your computer (or another computer! but that's a topic for another time) with more power and control than the GUI (graphical user interface) that most people use day-to-day. -Once on the command line, you can navigate the filesystem using `ls` to list the contents of your current directory, and `cd` to change the current directory. For example, if you had a `Development` directory of your projects inside your home directory, you would type +Once on the command line, you can navigate the filesystem using `ls` (`dir` on Windows) to list the contents of your current directory, and `cd` to change the current directory. For example, if you had a `Development` directory of your projects inside your home directory, you would type ```bash cd Development @@ -34,7 +34,7 @@ cd svelte-projects A full introduction to the command line is out of the scope of this guide, but here are a few more useful commands: * `cd ..` — navigates to the parent of the current directory -* `cat my-file.txt` — on Mac/Linux, lists the contents of `my-file.txt` +* `cat my-file.txt` — on Mac/Linux (`type my-file.txt` on Windows), lists the contents of `my-file.txt` * `open .` (or `start .` on Windows) — opens the current directory in Finder or File Explorer From ad139bfb630ce00ffd95b7a07c25f901bb6b5a50 Mon Sep 17 00:00:00 2001 From: PKlknr <60601481+PKlknr@users.noreply.github.com> Date: Tue, 18 Feb 2020 09:31:04 +0100 Subject: [PATCH 003/158] Log warnings in svelte/register when in dev-mode (#4365) --- register.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/register.js b/register.js index 3278c1cbf5cb..25f8aa430974 100644 --- a/register.js +++ b/register.js @@ -36,7 +36,15 @@ function registerExtension(extension) { format: 'cjs' }); - const { js } = compile(fs.readFileSync(filename, 'utf-8'), options); + const { js, warnings } = compile(fs.readFileSync(filename, 'utf-8'), options); + + if (options.dev) { + warnings.forEach(warning => { + console.warn(`\nSvelte Warning in ${warning.filename}:`); + console.warn(warning.message); + console.warn(warning.frame); + }) + } return module._compile(js.code, filename); }; From 30b09f31820529eb718fb6c5abb8c3fc15431cd0 Mon Sep 17 00:00:00 2001 From: Conduitry Date: Tue, 18 Feb 2020 03:32:42 -0500 Subject: [PATCH 004/158] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 759aabfd7dc1..fb8cada5e5d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Fix indirect bindings involving elements with spreads ([#3680](https://github.com/sveltejs/svelte/issues/3680)) * Warn when using `` and `Foo` is dynamic ([#4331](https://github.com/sveltejs/svelte/issues/4331)) +* Display compilation warnings in `svelte/register` in dev mode ([#4364](https://github.com/sveltejs/svelte/issues/4364)) * Fix unneeded updating of keyed each blocks ([#4373](https://github.com/sveltejs/svelte/issues/4373)) ## 3.18.2 From 3fbafe33c21184d090710d35a44aabf84744dc50 Mon Sep 17 00:00:00 2001 From: swyx Date: Tue, 18 Feb 2020 01:49:40 -0800 Subject: [PATCH 005/158] implement Dev mode validation of {#each} block argument (#4419) --- src/compiler/compile/render_dom/wrappers/EachBlock.ts | 5 +++++ src/runtime/internal/dev.ts | 10 ++++++++++ test/js/samples/debug-foo-bar-baz-things/expected.js | 5 ++++- test/js/samples/debug-foo/expected.js | 5 ++++- test/js/samples/debug-no-dependencies/expected.js | 5 ++++- .../dev-warning-each-block-no-sets-maps/_config.js | 6 ++++++ .../dev-warning-each-block-no-sets-maps/main.svelte | 7 +++++++ .../_config.js | 6 ++++++ .../main.svelte | 3 +++ 9 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 test/runtime/samples/dev-warning-each-block-no-sets-maps/_config.js create mode 100644 test/runtime/samples/dev-warning-each-block-no-sets-maps/main.svelte create mode 100644 test/runtime/samples/dev-warning-each-block-require-arraylike/_config.js create mode 100644 test/runtime/samples/dev-warning-each-block-require-arraylike/main.svelte diff --git a/src/compiler/compile/render_dom/wrappers/EachBlock.ts b/src/compiler/compile/render_dom/wrappers/EachBlock.ts index 8f8fe2956460..f0dfa5fbcc43 100644 --- a/src/compiler/compile/render_dom/wrappers/EachBlock.ts +++ b/src/compiler/compile/render_dom/wrappers/EachBlock.ts @@ -204,6 +204,9 @@ export default class EachBlockWrapper extends Wrapper { const snippet = this.node.expression.manipulate(block); block.chunks.init.push(b`let ${this.vars.each_block_value} = ${snippet};`); + if (this.renderer.options.dev) { + block.chunks.init.push(b`@validate_each_argument(${this.vars.each_block_value});`); + } // TODO which is better — Object.create(array) or array.slice()? renderer.blocks.push(b` @@ -421,6 +424,7 @@ export default class EachBlockWrapper extends Wrapper { block.chunks.update.push(b` if (${block.renderer.dirty(Array.from(all_dependencies))}) { const ${this.vars.each_block_value} = ${snippet}; + ${this.renderer.options.dev && b`@validate_each_argument(${this.vars.each_block_value});`} ${this.block.has_outros && b`@group_outros();`} ${this.node.has_animation && b`for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].r();`} @@ -572,6 +576,7 @@ export default class EachBlockWrapper extends Wrapper { const update = b` ${!this.block.has_update_method && b`const #old_length = ${this.vars.each_block_value}.length;`} ${this.vars.each_block_value} = ${snippet}; + ${this.renderer.options.dev && b`@validate_each_argument(${this.vars.each_block_value});`} let #i; for (#i = ${start}; #i < ${data_length}; #i += 1) { diff --git a/src/runtime/internal/dev.ts b/src/runtime/internal/dev.ts index 1829225ad952..7f4b52eb3b1d 100644 --- a/src/runtime/internal/dev.ts +++ b/src/runtime/internal/dev.ts @@ -79,6 +79,16 @@ export function set_data_dev(text, data) { text.data = data; } +export function validate_each_argument(arg) { + if (!arg || !('length' in arg)) { + let msg = '{#each} only iterates over array-like objects.'; + if (typeof Symbol === 'function' && arg && Symbol.iterator in arg) { + msg += ' You can use a spread to convert this iterable into an array.'; + } + throw new Error(msg); + } +} + type Props = Record; export interface SvelteComponentDev { diff --git a/test/js/samples/debug-foo-bar-baz-things/expected.js b/test/js/samples/debug-foo-bar-baz-things/expected.js index fc65c59edaa2..3209afe8a298 100644 --- a/test/js/samples/debug-foo-bar-baz-things/expected.js +++ b/test/js/samples/debug-foo-bar-baz-things/expected.js @@ -13,7 +13,8 @@ import { safe_not_equal, set_data_dev, space, - text + text, + validate_each_argument } from "svelte/internal"; const file = undefined; @@ -88,6 +89,7 @@ function create_fragment(ctx) { let t1; let t2; let each_value = /*things*/ ctx[0]; + validate_each_argument(each_value); let each_blocks = []; for (let i = 0; i < each_value.length; i += 1) { @@ -122,6 +124,7 @@ function create_fragment(ctx) { p: function update(ctx, [dirty]) { if (dirty & /*things*/ 1) { each_value = /*things*/ ctx[0]; + validate_each_argument(each_value); let i; for (i = 0; i < each_value.length; i += 1) { diff --git a/test/js/samples/debug-foo/expected.js b/test/js/samples/debug-foo/expected.js index 710d6b223285..4b08be44d92d 100644 --- a/test/js/samples/debug-foo/expected.js +++ b/test/js/samples/debug-foo/expected.js @@ -13,7 +13,8 @@ import { safe_not_equal, set_data_dev, space, - text + text, + validate_each_argument } from "svelte/internal"; const file = undefined; @@ -82,6 +83,7 @@ function create_fragment(ctx) { let t1; let t2; let each_value = /*things*/ ctx[0]; + validate_each_argument(each_value); let each_blocks = []; for (let i = 0; i < each_value.length; i += 1) { @@ -116,6 +118,7 @@ function create_fragment(ctx) { p: function update(ctx, [dirty]) { if (dirty & /*things*/ 1) { each_value = /*things*/ ctx[0]; + validate_each_argument(each_value); let i; for (i = 0; i < each_value.length; i += 1) { diff --git a/test/js/samples/debug-no-dependencies/expected.js b/test/js/samples/debug-no-dependencies/expected.js index 054dda795328..9985c814a2ae 100644 --- a/test/js/samples/debug-no-dependencies/expected.js +++ b/test/js/samples/debug-no-dependencies/expected.js @@ -10,7 +10,8 @@ import { noop, safe_not_equal, space, - text + text, + validate_each_argument } from "svelte/internal"; const file = undefined; @@ -64,6 +65,7 @@ function create_each_block(ctx) { function create_fragment(ctx) { let each_1_anchor; let each_value = things; + validate_each_argument(each_value); let each_blocks = []; for (let i = 0; i < each_value.length; i += 1) { @@ -91,6 +93,7 @@ function create_fragment(ctx) { p: function update(ctx, [dirty]) { if (dirty & /*things*/ 0) { each_value = things; + validate_each_argument(each_value); let i; for (i = 0; i < each_value.length; i += 1) { diff --git a/test/runtime/samples/dev-warning-each-block-no-sets-maps/_config.js b/test/runtime/samples/dev-warning-each-block-no-sets-maps/_config.js new file mode 100644 index 000000000000..83481d9ebebf --- /dev/null +++ b/test/runtime/samples/dev-warning-each-block-no-sets-maps/_config.js @@ -0,0 +1,6 @@ +export default { + compileOptions: { + dev: true + }, + error: `{#each} only iterates over array-like objects. You can use a spread to convert this iterable into an array.` +}; diff --git a/test/runtime/samples/dev-warning-each-block-no-sets-maps/main.svelte b/test/runtime/samples/dev-warning-each-block-no-sets-maps/main.svelte new file mode 100644 index 000000000000..e1aae26d129a --- /dev/null +++ b/test/runtime/samples/dev-warning-each-block-no-sets-maps/main.svelte @@ -0,0 +1,7 @@ + + +{#each foo as item} +
{item}
+{/each} \ No newline at end of file diff --git a/test/runtime/samples/dev-warning-each-block-require-arraylike/_config.js b/test/runtime/samples/dev-warning-each-block-require-arraylike/_config.js new file mode 100644 index 000000000000..62e5fc209b54 --- /dev/null +++ b/test/runtime/samples/dev-warning-each-block-require-arraylike/_config.js @@ -0,0 +1,6 @@ +export default { + compileOptions: { + dev: true + }, + error: `{#each} only iterates over array-like objects.` +}; diff --git a/test/runtime/samples/dev-warning-each-block-require-arraylike/main.svelte b/test/runtime/samples/dev-warning-each-block-require-arraylike/main.svelte new file mode 100644 index 000000000000..f85df8d84bd7 --- /dev/null +++ b/test/runtime/samples/dev-warning-each-block-require-arraylike/main.svelte @@ -0,0 +1,3 @@ +{#each {} as item} +
{item}
+{/each} \ No newline at end of file From 423d1fe14ece0defb2f68fd3709a77991890aa28 Mon Sep 17 00:00:00 2001 From: Conduitry Date: Tue, 18 Feb 2020 04:52:37 -0500 Subject: [PATCH 006/158] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb8cada5e5d5..922bc08c923b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * Warn when using `` and `Foo` is dynamic ([#4331](https://github.com/sveltejs/svelte/issues/4331)) * Display compilation warnings in `svelte/register` in dev mode ([#4364](https://github.com/sveltejs/svelte/issues/4364)) * Fix unneeded updating of keyed each blocks ([#4373](https://github.com/sveltejs/svelte/issues/4373)) +* Throw runtime error in dev mode for non-array-like values in `{#each}` blocks ([#4408](https://github.com/sveltejs/svelte/issues/4408)) ## 3.18.2 From c992f7a2d2351dcd754d03c66e0b191e96c60511 Mon Sep 17 00:00:00 2001 From: Jesse Skinner Date: Thu, 20 Feb 2020 08:49:34 -0500 Subject: [PATCH 007/158] docs: reword to avoid "outroing" (#4434) --- site/content/docs/02-template-syntax.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/content/docs/02-template-syntax.md b/site/content/docs/02-template-syntax.md index 0a4ca2ee1a1d..1d71dfe9a20e 100644 --- a/site/content/docs/02-template-syntax.md +++ b/site/content/docs/02-template-syntax.md @@ -795,7 +795,7 @@ transition = (node: HTMLElement, params: any) => { A transition is triggered by an element entering or leaving the DOM as a result of a state change. -Elements inside an *outroing* block are kept in the DOM until all current transitions have completed. +When a block is transitioning out, elements inside the block are kept in the DOM until all current transitions have completed. The `transition:` directive indicates a *bidirectional* transition, which means it can be smoothly reversed while the transition is in progress. From 1772c3f7f14fbca8d75f8c76bdeeb440fb85ac54 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Fri, 21 Feb 2020 08:55:38 -0500 Subject: [PATCH 008/158] Remove CI badge (#4438) --- README.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/README.md b/README.md index e05154bd7c92..3a437256372f 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,6 @@ npm version - - build status - - license From 9a747e3b5abcc1c8ec357634e52cdb1dd9f9314d Mon Sep 17 00:00:00 2001 From: Alexandre CANTIN Date: Sun, 23 Feb 2020 05:37:21 +0100 Subject: [PATCH 009/158] site: fix loading REPL with filename containing multiple '.'s (#4441) --- site/src/routes/repl/[id]/index.svelte | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/site/src/routes/repl/[id]/index.svelte b/site/src/routes/repl/[id]/index.svelte index 4d05ac28ea35..b237e1996794 100644 --- a/site/src/routes/repl/[id]/index.svelte +++ b/site/src/routes/repl/[id]/index.svelte @@ -57,7 +57,10 @@ is_relaxed_gist = data.relaxed; const components = data.files.map(file => { - let [name, type] = file.name.split('.'); + const dot = file.name.lastIndexOf("."); + let name = file.name.slice(0, dot); + let type = file.name.slice(dot + 1); + if (type === 'html') type = 'svelte'; // TODO do this on the server return { name, type, source: file.source }; }); From a53da7e4b062a12f7cf6003416bdf383e087eb36 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Sat, 22 Feb 2020 20:40:07 -0800 Subject: [PATCH 010/158] site: clearer examples for (#4125) --- site/content/docs/02-template-syntax.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/site/content/docs/02-template-syntax.md b/site/content/docs/02-template-syntax.md index 1d71dfe9a20e..55b913ca947e 100644 --- a/site/content/docs/02-template-syntax.md +++ b/site/content/docs/02-template-syntax.md @@ -1249,15 +1249,15 @@ The usual shorthand rules apply — `let:item` is equivalent to `let:item={item} ```html - -
{item.text}
+ +
{thing.text}
    {#each items as item}
  • - +
  • {/each}
@@ -1270,7 +1270,7 @@ Named slots can also expose values. The `let:` directive goes on the element wit ```html -
{item.text}
+
{item.text}

Copyright (c) 2019 Svelte Industries

@@ -1278,7 +1278,7 @@ Named slots can also expose values. The `let:` directive goes on the element wit
    {#each items as item}
  • - +
  • {/each}
From cb64fb2ac94b3f0a579f75abbbbbe4f4d4a6eef3 Mon Sep 17 00:00:00 2001 From: rixo Date: Sun, 23 Feb 2020 05:13:59 -0800 Subject: [PATCH 011/158] make $capture_state/$inject_state act on entire state (#3822) Previously, these methods only applied to exported props. Also, add $$inject option to constructor, which injects state before running the update loop. --- src/compiler/compile/render_dom/index.ts | 61 ++++-- src/runtime/internal/dev.ts | 4 + .../samples/capture-inject-state/_config.js | 5 + .../samples/capture-inject-state/expected.js | 197 ++++++++++++++++++ .../samples/capture-inject-state/input.svelte | 23 ++ test/js/samples/debug-empty/expected.js | 8 +- .../debug-foo-bar-baz-things/expected.js | 8 +- test/js/samples/debug-foo/expected.js | 8 +- test/js/samples/debug-hoisted/expected.js | 11 +- .../expected.js | 8 +- test/js/samples/loop-protect/expected.js | 8 +- 11 files changed, 298 insertions(+), 43 deletions(-) create mode 100644 test/js/samples/capture-inject-state/_config.js create mode 100644 test/js/samples/capture-inject-state/expected.js create mode 100644 test/js/samples/capture-inject-state/input.svelte diff --git a/src/compiler/compile/render_dom/index.ts b/src/compiler/compile/render_dom/index.ts index a7a55b884317..17e5eaf750b3 100644 --- a/src/compiler/compile/render_dom/index.ts +++ b/src/compiler/compile/render_dom/index.ts @@ -91,7 +91,10 @@ export default function dom( const accessors = []; const not_equal = component.component_options.immutable ? x`@not_equal` : x`@safe_not_equal`; - let dev_props_check; let inject_state; let capture_state; + let dev_props_check: Node[] | Node; + let inject_state: Expression; + let capture_state: Expression; + let props_inject: Node[] | Node; props.forEach(prop => { const variable = component.var_lookup.get(prop.name); @@ -164,27 +167,30 @@ export default function dom( `; } - capture_state = (uses_props || writable_props.length > 0) ? x` - () => { - return { ${component.vars.filter(prop => prop.writable).map(prop => p`${prop.name}`)} }; - } - ` : x` - () => { - return {}; - } - `; + const capturable_vars = component.vars.filter(v => !v.internal && !v.name.startsWith('$$')); - const writable_vars = component.vars.filter(variable => !variable.module && variable.writable); - inject_state = (uses_props || writable_vars.length > 0) ? x` - ${$$props} => { - ${uses_props && renderer.invalidate('$$props', x`$$props = @assign(@assign({}, $$props), $$new_props)`)} - ${writable_vars.map(prop => b` - if ('${prop.name}' in $$props) ${renderer.invalidate(prop.name, x`${prop.name} = ${$$props}.${prop.name}`)}; - `)} - } - ` : x` - ${$$props} => {} - `; + if (capturable_vars.length > 0) { + capture_state = x`() => ({ ${capturable_vars.map(prop => p`${prop.name}`)} })`; + } + + const injectable_vars = capturable_vars.filter(v => !v.module && v.writable && v.name[0] !== '$'); + + if (uses_props || injectable_vars.length > 0) { + inject_state = x` + ${$$props} => { + ${uses_props && renderer.invalidate('$$props', x`$$props = @assign(@assign({}, $$props), $$new_props)`)} + ${injectable_vars.map( + v => b`if ('${v.name}' in $$props) ${renderer.invalidate(v.name, x`${v.name} = ${$$props}.${v.name}`)};` + )} + } + `; + + props_inject = b` + if ($$props && "$$inject" in $$props) { + $$self.$inject_state($$props.$$inject); + } + `; + } } // instrument assignments @@ -246,7 +252,12 @@ export default function dom( } const args = [x`$$self`]; - if (props.length > 0 || component.has_reactive_assignments || component.slots.size > 0) { + const has_invalidate = props.length > 0 || + component.has_reactive_assignments || + component.slots.size > 0 || + capture_state || + inject_state; + if (has_invalidate) { args.push(x`$$props`, x`$$invalidate`); } @@ -294,7 +305,9 @@ export default function dom( uses_props || component.partly_hoisted.length > 0 || initial_context.length > 0 || - component.reactive_declarations.length > 0 + component.reactive_declarations.length > 0 || + capture_state || + inject_state ); const definition = has_definition @@ -409,6 +422,8 @@ export default function dom( ${injected.map(name => b`let ${name};`)} + ${/* before reactive declarations */ props_inject} + ${reactive_declarations.length > 0 && b` $$self.$$.update = () => { ${reactive_declarations} diff --git a/src/runtime/internal/dev.ts b/src/runtime/internal/dev.ts index 7f4b52eb3b1d..2d60ffb98529 100644 --- a/src/runtime/internal/dev.ts +++ b/src/runtime/internal/dev.ts @@ -120,6 +120,10 @@ export class SvelteComponentDev extends SvelteComponent { console.warn(`Component was already destroyed`); // eslint-disable-line no-console }; } + + $capture_state() {} + + $inject_state() {} } export function loop_guard(timeout) { diff --git a/test/js/samples/capture-inject-state/_config.js b/test/js/samples/capture-inject-state/_config.js new file mode 100644 index 000000000000..414b026a97d6 --- /dev/null +++ b/test/js/samples/capture-inject-state/_config.js @@ -0,0 +1,5 @@ +export default { + options: { + dev: true + } +}; diff --git a/test/js/samples/capture-inject-state/expected.js b/test/js/samples/capture-inject-state/expected.js new file mode 100644 index 000000000000..859314556580 --- /dev/null +++ b/test/js/samples/capture-inject-state/expected.js @@ -0,0 +1,197 @@ +/* generated by Svelte vX.Y.Z */ +import { + SvelteComponentDev, + add_location, + append_dev, + detach_dev, + dispatch_dev, + element, + init, + insert_dev, + noop, + safe_not_equal, + set_data_dev, + space, + subscribe, + text, + validate_store +} from "svelte/internal"; + +const file = undefined; + +function create_fragment(ctx) { + let p; + let t0; + let t1; + let t2; + let t3; + let t4; + let t5; + let t6; + let t7; + let t8; + let t9; + let t10; + + const block = { + c: function create() { + p = element("p"); + t0 = text(/*prop*/ ctx[0]); + t1 = space(); + t2 = text(/*realName*/ ctx[1]); + t3 = space(); + t4 = text(/*local*/ ctx[3]); + t5 = space(); + t6 = text(priv); + t7 = space(); + t8 = text(/*$prop*/ ctx[2]); + t9 = space(); + t10 = text(/*shadowedByModule*/ ctx[4]); + add_location(p, file, 22, 0, 430); + }, + l: function claim(nodes) { + throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option"); + }, + m: function mount(target, anchor) { + insert_dev(target, p, anchor); + append_dev(p, t0); + append_dev(p, t1); + append_dev(p, t2); + append_dev(p, t3); + append_dev(p, t4); + append_dev(p, t5); + append_dev(p, t6); + append_dev(p, t7); + append_dev(p, t8); + append_dev(p, t9); + append_dev(p, t10); + }, + p: function update(ctx, [dirty]) { + if (dirty & /*prop*/ 1) set_data_dev(t0, /*prop*/ ctx[0]); + if (dirty & /*realName*/ 2) set_data_dev(t2, /*realName*/ ctx[1]); + if (dirty & /*$prop*/ 4) set_data_dev(t8, /*$prop*/ ctx[2]); + }, + i: noop, + o: noop, + d: function destroy(detaching) { + if (detaching) detach_dev(p); + } + }; + + dispatch_dev("SvelteRegisterBlock", { + block, + id: create_fragment.name, + type: "component", + source: "", + ctx + }); + + return block; +} + +let moduleLiveBinding; +const moduleContantProps = 4; +let moduleLet; +const moduleConst = 2; +let shadowedByModule; +const priv = "priv"; + +function instance($$self, $$props, $$invalidate) { + let $prop, + $$unsubscribe_prop = noop, + $$subscribe_prop = () => ($$unsubscribe_prop(), $$unsubscribe_prop = subscribe(prop, $$value => $$invalidate(2, $prop = $$value)), prop); + + $$self.$$.on_destroy.push(() => $$unsubscribe_prop()); + let { prop } = $$props; + validate_store(prop, "prop"); + $$subscribe_prop(); + let { alias: realName } = $$props; + let local; + let shadowedByModule; + const writable_props = ["prop", "alias"]; + + Object.keys($$props).forEach(key => { + if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(` was created with unknown prop '${key}'`); + }); + + $$self.$set = $$props => { + if ("prop" in $$props) $$subscribe_prop($$invalidate(0, prop = $$props.prop)); + if ("alias" in $$props) $$invalidate(1, realName = $$props.alias); + }; + + $$self.$capture_state = () => ({ + moduleLiveBinding, + moduleContantProps, + moduleLet, + moduleConst, + shadowedByModule, + prop, + realName, + local, + priv, + shadowedByModule, + computed, + $prop + }); + + $$self.$inject_state = $$props => { + if ("prop" in $$props) $$subscribe_prop($$invalidate(0, prop = $$props.prop)); + if ("realName" in $$props) $$invalidate(1, realName = $$props.realName); + if ("local" in $$props) $$invalidate(3, local = $$props.local); + if ("shadowedByModule" in $$props) $$invalidate(4, shadowedByModule = $$props.shadowedByModule); + if ("computed" in $$props) computed = $$props.computed; + }; + + let computed; + + if ($$props && "$$inject" in $$props) { + $$self.$inject_state($$props.$$inject); + } + + $: computed = local * 2; + return [prop, realName, $prop, local, shadowedByModule]; +} + +class Component extends SvelteComponentDev { + constructor(options) { + super(options); + init(this, options, instance, create_fragment, safe_not_equal, { prop: 0, alias: 1 }); + + dispatch_dev("SvelteRegisterComponent", { + component: this, + tagName: "Component", + options, + id: create_fragment.name + }); + + const { ctx } = this.$$; + const props = options.props || {}; + + if (/*prop*/ ctx[0] === undefined && !("prop" in props)) { + console.warn(" was created without expected prop 'prop'"); + } + + if (/*realName*/ ctx[1] === undefined && !("alias" in props)) { + console.warn(" was created without expected prop 'alias'"); + } + } + + get prop() { + throw new Error(": Props cannot be read directly from the component instance unless compiling with 'accessors: true' or ''"); + } + + set prop(value) { + throw new Error(": Props cannot be set directly on the component instance unless compiling with 'accessors: true' or ''"); + } + + get alias() { + throw new Error(": Props cannot be read directly from the component instance unless compiling with 'accessors: true' or ''"); + } + + set alias(value) { + throw new Error(": Props cannot be set directly on the component instance unless compiling with 'accessors: true' or ''"); + } +} + +export default Component; +export { moduleLiveBinding, moduleContantProps }; \ No newline at end of file diff --git a/test/js/samples/capture-inject-state/input.svelte b/test/js/samples/capture-inject-state/input.svelte new file mode 100644 index 000000000000..a1051bc1470c --- /dev/null +++ b/test/js/samples/capture-inject-state/input.svelte @@ -0,0 +1,23 @@ + + + +

{prop} {realName} {local} {priv} {$prop} {shadowedByModule}

diff --git a/test/js/samples/debug-empty/expected.js b/test/js/samples/debug-empty/expected.js index 358363c661bf..87d78bd69821 100644 --- a/test/js/samples/debug-empty/expected.js +++ b/test/js/samples/debug-empty/expected.js @@ -79,14 +79,16 @@ function instance($$self, $$props, $$invalidate) { if ("name" in $$props) $$invalidate(0, name = $$props.name); }; - $$self.$capture_state = () => { - return { name }; - }; + $$self.$capture_state = () => ({ name }); $$self.$inject_state = $$props => { if ("name" in $$props) $$invalidate(0, name = $$props.name); }; + if ($$props && "$$inject" in $$props) { + $$self.$inject_state($$props.$$inject); + } + return [name]; } diff --git a/test/js/samples/debug-foo-bar-baz-things/expected.js b/test/js/samples/debug-foo-bar-baz-things/expected.js index 3209afe8a298..589c4a783288 100644 --- a/test/js/samples/debug-foo-bar-baz-things/expected.js +++ b/test/js/samples/debug-foo-bar-baz-things/expected.js @@ -186,9 +186,7 @@ function instance($$self, $$props, $$invalidate) { if ("baz" in $$props) $$invalidate(3, baz = $$props.baz); }; - $$self.$capture_state = () => { - return { things, foo, bar, baz }; - }; + $$self.$capture_state = () => ({ things, foo, bar, baz }); $$self.$inject_state = $$props => { if ("things" in $$props) $$invalidate(0, things = $$props.things); @@ -197,6 +195,10 @@ function instance($$self, $$props, $$invalidate) { if ("baz" in $$props) $$invalidate(3, baz = $$props.baz); }; + if ($$props && "$$inject" in $$props) { + $$self.$inject_state($$props.$$inject); + } + return [things, foo, bar, baz]; } diff --git a/test/js/samples/debug-foo/expected.js b/test/js/samples/debug-foo/expected.js index 4b08be44d92d..10129e1b2837 100644 --- a/test/js/samples/debug-foo/expected.js +++ b/test/js/samples/debug-foo/expected.js @@ -176,15 +176,17 @@ function instance($$self, $$props, $$invalidate) { if ("foo" in $$props) $$invalidate(1, foo = $$props.foo); }; - $$self.$capture_state = () => { - return { things, foo }; - }; + $$self.$capture_state = () => ({ things, foo }); $$self.$inject_state = $$props => { if ("things" in $$props) $$invalidate(0, things = $$props.things); if ("foo" in $$props) $$invalidate(1, foo = $$props.foo); }; + if ($$props && "$$inject" in $$props) { + $$self.$inject_state($$props.$$inject); + } + return [things, foo]; } diff --git a/test/js/samples/debug-hoisted/expected.js b/test/js/samples/debug-hoisted/expected.js index eeb946549965..c77168ef4f6d 100644 --- a/test/js/samples/debug-hoisted/expected.js +++ b/test/js/samples/debug-hoisted/expected.js @@ -47,19 +47,20 @@ function create_fragment(ctx) { return block; } -function instance($$self) { +function instance($$self, $$props, $$invalidate) { let obj = { x: 5 }; let kobzol = 5; - - $$self.$capture_state = () => { - return {}; - }; + $$self.$capture_state = () => ({ obj, kobzol }); $$self.$inject_state = $$props => { if ("obj" in $$props) $$invalidate(0, obj = $$props.obj); if ("kobzol" in $$props) $$invalidate(1, kobzol = $$props.kobzol); }; + if ($$props && "$$inject" in $$props) { + $$self.$inject_state($$props.$$inject); + } + return [obj, kobzol]; } diff --git a/test/js/samples/dev-warning-missing-data-computed/expected.js b/test/js/samples/dev-warning-missing-data-computed/expected.js index cc16de67e66c..9c28e0406450 100644 --- a/test/js/samples/dev-warning-missing-data-computed/expected.js +++ b/test/js/samples/dev-warning-missing-data-computed/expected.js @@ -76,15 +76,17 @@ function instance($$self, $$props, $$invalidate) { if ("foo" in $$props) $$invalidate(0, foo = $$props.foo); }; - $$self.$capture_state = () => { - return { foo, bar }; - }; + $$self.$capture_state = () => ({ foo, bar }); $$self.$inject_state = $$props => { if ("foo" in $$props) $$invalidate(0, foo = $$props.foo); if ("bar" in $$props) $$invalidate(1, bar = $$props.bar); }; + if ($$props && "$$inject" in $$props) { + $$self.$inject_state($$props.$$inject); + } + $$self.$$.update = () => { if ($$self.$$.dirty & /*foo*/ 1) { $: $$invalidate(1, bar = foo * 2); diff --git a/test/js/samples/loop-protect/expected.js b/test/js/samples/loop-protect/expected.js index 554ccf23b15f..127addf1d117 100644 --- a/test/js/samples/loop-protect/expected.js +++ b/test/js/samples/loop-protect/expected.js @@ -108,14 +108,16 @@ function instance($$self, $$props, $$invalidate) { }); } - $$self.$capture_state = () => { - return {}; - }; + $$self.$capture_state = () => ({ node, foo, console }); $$self.$inject_state = $$props => { if ("node" in $$props) $$invalidate(0, node = $$props.node); }; + if ($$props && "$$inject" in $$props) { + $$self.$inject_state($$props.$$inject); + } + $: { const guard_4 = loop_guard(100); From a7ffceefdd007a933eedd93dae53aed55b6290b9 Mon Sep 17 00:00:00 2001 From: Conduitry Date: Sun, 23 Feb 2020 08:16:27 -0500 Subject: [PATCH 012/158] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 922bc08c923b..05468d73687d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased * Fix indirect bindings involving elements with spreads ([#3680](https://github.com/sveltejs/svelte/issues/3680)) +* `$capture_state`/`$inject_state` now act on the component's entire state, rather than its props ([#3822](https://github.com/sveltejs/svelte/pull/3822)) * Warn when using `` and `Foo` is dynamic ([#4331](https://github.com/sveltejs/svelte/issues/4331)) * Display compilation warnings in `svelte/register` in dev mode ([#4364](https://github.com/sveltejs/svelte/issues/4364)) * Fix unneeded updating of keyed each blocks ([#4373](https://github.com/sveltejs/svelte/issues/4373)) From a972a47e14b110c50ca31993fae28e8ddf677a4b Mon Sep 17 00:00:00 2001 From: Conduitry Date: Sun, 23 Feb 2020 08:41:22 -0500 Subject: [PATCH 013/158] -> v3.19.0 --- CHANGELOG.md | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05468d73687d..f81b19815480 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Svelte changelog -## Unreleased +## 3.19.0 * Fix indirect bindings involving elements with spreads ([#3680](https://github.com/sveltejs/svelte/issues/3680)) * `$capture_state`/`$inject_state` now act on the component's entire state, rather than its props ([#3822](https://github.com/sveltejs/svelte/pull/3822)) diff --git a/package-lock.json b/package-lock.json index 8f0b7469f887..2454010c0d25 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.18.2", + "version": "3.19.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 6000e9d1c47c..1cb0d10eeb83 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.18.2", + "version": "3.19.0", "description": "Cybernetically enhanced web apps", "module": "index.mjs", "main": "index", From 138213ca3c1ca91998461e961933d630aeb45b15 Mon Sep 17 00:00:00 2001 From: Conduitry Date: Sun, 23 Feb 2020 16:35:25 -0500 Subject: [PATCH 014/158] fix dev mode each block validation when using strings (#4451) --- CHANGELOG.md | 4 ++++ src/runtime/internal/dev.ts | 2 +- test/runtime/samples/each-block-string/_config.js | 10 ++++++++++ test/runtime/samples/each-block-string/main.svelte | 3 +++ 4 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 test/runtime/samples/each-block-string/_config.js create mode 100644 test/runtime/samples/each-block-string/main.svelte diff --git a/CHANGELOG.md b/CHANGELOG.md index f81b19815480..3f4460cde48e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Svelte changelog +## Unreleased + +* Fix dev mode validation of `{#each}` blocks using strings ([#4450](https://github.com/sveltejs/svelte/issues/4450)) + ## 3.19.0 * Fix indirect bindings involving elements with spreads ([#3680](https://github.com/sveltejs/svelte/issues/3680)) diff --git a/src/runtime/internal/dev.ts b/src/runtime/internal/dev.ts index 2d60ffb98529..8aefc88ba7b0 100644 --- a/src/runtime/internal/dev.ts +++ b/src/runtime/internal/dev.ts @@ -80,7 +80,7 @@ export function set_data_dev(text, data) { } export function validate_each_argument(arg) { - if (!arg || !('length' in arg)) { + if (typeof arg !== 'string' && !(arg && typeof arg === 'object' && 'length' in arg)) { let msg = '{#each} only iterates over array-like objects.'; if (typeof Symbol === 'function' && arg && Symbol.iterator in arg) { msg += ' You can use a spread to convert this iterable into an array.'; diff --git a/test/runtime/samples/each-block-string/_config.js b/test/runtime/samples/each-block-string/_config.js new file mode 100644 index 000000000000..7366c964ebb1 --- /dev/null +++ b/test/runtime/samples/each-block-string/_config.js @@ -0,0 +1,10 @@ +export default { + compileOptions: { + dev: true + }, + html: ` +
f
+
o
+
o
+ ` +}; diff --git a/test/runtime/samples/each-block-string/main.svelte b/test/runtime/samples/each-block-string/main.svelte new file mode 100644 index 000000000000..ae60f0f6b32f --- /dev/null +++ b/test/runtime/samples/each-block-string/main.svelte @@ -0,0 +1,3 @@ +{#each 'foo' as c} +
{c}
+{/each} From 3bfa0e5cd6219ce6408a7bfa6689b3afa1945388 Mon Sep 17 00:00:00 2001 From: Conduitry Date: Sun, 23 Feb 2020 17:50:57 -0500 Subject: [PATCH 015/158] deconflict `value` parameter in contextual bindings (#4452) --- CHANGELOG.md | 1 + .../render_dom/wrappers/InlineComponent/index.ts | 13 ++++++------- .../deconflict-contextual-bind/Widget.svelte | 3 +++ .../samples/deconflict-contextual-bind/_config.js | 3 +++ .../samples/deconflict-contextual-bind/main.svelte | 8 ++++++++ 5 files changed, 21 insertions(+), 7 deletions(-) create mode 100644 test/runtime/samples/deconflict-contextual-bind/Widget.svelte create mode 100644 test/runtime/samples/deconflict-contextual-bind/_config.js create mode 100644 test/runtime/samples/deconflict-contextual-bind/main.svelte diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f4460cde48e..2166ca4c9c96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased +* Deconflict `value` parameter name used in contextual bindings ([#4445](https://github.com/sveltejs/svelte/issues/4445)) * Fix dev mode validation of `{#each}` blocks using strings ([#4450](https://github.com/sveltejs/svelte/issues/4450)) ## 3.19.0 diff --git a/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts b/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts index f1c57ed09415..28b3c938f9d3 100644 --- a/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts +++ b/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts @@ -332,8 +332,7 @@ export default class InlineComponentWrapper extends Wrapper { contextual_dependencies.push(object.name, property.name); } - const value = block.get_unique_name('value'); - const params: any[] = [value]; + const params = [x`#value`]; if (contextual_dependencies.length > 0) { const args = []; @@ -349,23 +348,23 @@ export default class InlineComponentWrapper extends Wrapper { block.chunks.init.push(b` - function ${id}(${value}) { - ${callee}.call(null, ${value}, ${args}); + function ${id}(#value) { + ${callee}.call(null, #value, ${args}); } `); block.maintain_context = true; // TODO put this somewhere more logical } else { block.chunks.init.push(b` - function ${id}(${value}) { - ${callee}.call(null, ${value}); + function ${id}(#value) { + ${callee}.call(null, #value); } `); } const body = b` function ${id}(${params}) { - ${lhs} = ${value}; + ${lhs} = #value; ${renderer.invalidate(dependencies[0])}; } `; diff --git a/test/runtime/samples/deconflict-contextual-bind/Widget.svelte b/test/runtime/samples/deconflict-contextual-bind/Widget.svelte new file mode 100644 index 000000000000..3aaa59b74757 --- /dev/null +++ b/test/runtime/samples/deconflict-contextual-bind/Widget.svelte @@ -0,0 +1,3 @@ + diff --git a/test/runtime/samples/deconflict-contextual-bind/_config.js b/test/runtime/samples/deconflict-contextual-bind/_config.js new file mode 100644 index 000000000000..7602cde02323 --- /dev/null +++ b/test/runtime/samples/deconflict-contextual-bind/_config.js @@ -0,0 +1,3 @@ +export default { + preserveIdentifiers: true +}; diff --git a/test/runtime/samples/deconflict-contextual-bind/main.svelte b/test/runtime/samples/deconflict-contextual-bind/main.svelte new file mode 100644 index 000000000000..fe91deca17f1 --- /dev/null +++ b/test/runtime/samples/deconflict-contextual-bind/main.svelte @@ -0,0 +1,8 @@ + + +{#each values as value} + +{/each} From 19f1c9cb7c4818fdb10e56b650465e1b2f40c6bc Mon Sep 17 00:00:00 2001 From: Conduitry Date: Sun, 23 Feb 2020 18:19:06 -0500 Subject: [PATCH 016/158] don't treat $$-names as stores during invalidation (#4453) --- CHANGELOG.md | 1 + src/compiler/compile/render_dom/invalidate.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2166ca4c9c96..d3687b3d2ac9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased +* Do not treat modifications to `$$props` as updates to a store called `$props` ([#4368](https://github.com/sveltejs/svelte/issues/4368)) * Deconflict `value` parameter name used in contextual bindings ([#4445](https://github.com/sveltejs/svelte/issues/4445)) * Fix dev mode validation of `{#each}` blocks using strings ([#4450](https://github.com/sveltejs/svelte/issues/4450)) diff --git a/src/compiler/compile/render_dom/invalidate.ts b/src/compiler/compile/render_dom/invalidate.ts index 20aff05d1e19..28e4f37e3fd1 100644 --- a/src/compiler/compile/render_dom/invalidate.ts +++ b/src/compiler/compile/render_dom/invalidate.ts @@ -43,7 +43,7 @@ export function invalidate(renderer: Renderer, scope: Scope, node: Node, names: if (node.type === 'AssignmentExpression' && node.operator === '=' && nodes_match(node.left, node.right) && tail.length === 0) { return get_invalidated(head, node); } else { - const is_store_value = head.name[0] === '$'; + const is_store_value = head.name[0] === '$' && head.name[1] !== '$'; const extra_args = tail.map(variable => get_invalidated(variable)); const pass_value = ( From b8bf3643d4590fee3afe5aae733e2ccc4547c110 Mon Sep 17 00:00:00 2001 From: Conduitry Date: Sun, 23 Feb 2020 18:28:30 -0500 Subject: [PATCH 017/158] -> v3.19.1 --- CHANGELOG.md | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d3687b3d2ac9..28c24fa066df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Svelte changelog -## Unreleased +## 3.19.1 * Do not treat modifications to `$$props` as updates to a store called `$props` ([#4368](https://github.com/sveltejs/svelte/issues/4368)) * Deconflict `value` parameter name used in contextual bindings ([#4445](https://github.com/sveltejs/svelte/issues/4445)) diff --git a/package-lock.json b/package-lock.json index 2454010c0d25..3b275078ec9f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.19.0", + "version": "3.19.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 1cb0d10eeb83..7a02f1da108e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.19.0", + "version": "3.19.1", "description": "Cybernetically enhanced web apps", "module": "index.mjs", "main": "index", From 0786d2858decb4f71cd98fc2b2ad28b0de7f00ac Mon Sep 17 00:00:00 2001 From: rixo Date: Wed, 26 Feb 2020 23:05:33 +0100 Subject: [PATCH 018/158] exclude global variables from $capture_state (#4475) --- src/compiler/compile/render_dom/index.ts | 2 +- test/js/samples/loop-protect/expected.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/compiler/compile/render_dom/index.ts b/src/compiler/compile/render_dom/index.ts index 17e5eaf750b3..71e868164602 100644 --- a/src/compiler/compile/render_dom/index.ts +++ b/src/compiler/compile/render_dom/index.ts @@ -167,7 +167,7 @@ export default function dom( `; } - const capturable_vars = component.vars.filter(v => !v.internal && !v.name.startsWith('$$')); + const capturable_vars = component.vars.filter(v => !v.internal && !v.global && !v.name.startsWith('$$')); if (capturable_vars.length > 0) { capture_state = x`() => ({ ${capturable_vars.map(prop => p`${prop.name}`)} })`; diff --git a/test/js/samples/loop-protect/expected.js b/test/js/samples/loop-protect/expected.js index 127addf1d117..4eccaae7cb79 100644 --- a/test/js/samples/loop-protect/expected.js +++ b/test/js/samples/loop-protect/expected.js @@ -108,7 +108,7 @@ function instance($$self, $$props, $$invalidate) { }); } - $$self.$capture_state = () => ({ node, foo, console }); + $$self.$capture_state = () => ({ node, foo }); $$self.$inject_state = $$props => { if ("node" in $$props) $$invalidate(0, node = $$props.node); @@ -153,4 +153,4 @@ class Component extends SvelteComponentDev { } } -export default Component; \ No newline at end of file +export default Component; From dc3e9c4bedb58342737c2ca792ef341a2278275d Mon Sep 17 00:00:00 2001 From: Conduitry Date: Wed, 26 Feb 2020 17:06:53 -0500 Subject: [PATCH 019/158] update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 28c24fa066df..ef5ba2307fd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Svelte changelog +## Unreleased + +* Exclude global variables from `$capture_state` ([#4463](https://github.com/sveltejs/svelte/issues/4463)) + ## 3.19.1 * Do not treat modifications to `$$props` as updates to a store called `$props` ([#4368](https://github.com/sveltejs/svelte/issues/4368)) From 7831766fa0da53aa7f5d188ffb9e15efd0106d66 Mon Sep 17 00:00:00 2001 From: Antony Jones Date: Thu, 27 Feb 2020 11:40:42 +0000 Subject: [PATCH 020/158] site: turn fancybutton into custombutton (#4476) --- .../05-dom-event-forwarding/App.svelte | 4 ++-- .../CustomButton.svelte | 22 ++++++++++++++++++ .../FancyButton.svelte | 15 ------------ .../06-dom-event-forwarding/app-a/App.svelte | 4 ++-- .../app-a/CustomButton.svelte | 22 ++++++++++++++++++ .../app-a/FancyButton.svelte | 15 ------------ .../06-dom-event-forwarding/app-b/App.svelte | 4 ++-- .../app-b/CustomButton.svelte | 22 ++++++++++++++++++ .../app-b/FancyButton.svelte | 15 ------------ .../05-events/06-dom-event-forwarding/text.md | 2 +- .../thumbnails/dom-event-forwarding.jpg | Bin 4128 -> 2409 bytes .../samples/extended-builtin/_config.js | 8 +++---- .../samples/extended-builtin/custom-button.js | 2 ++ .../samples/extended-builtin/fancy-button.js | 2 -- .../samples/extended-builtin/main.svelte | 4 ++-- .../samples/extended-builtin/test.js | 2 +- 16 files changed, 82 insertions(+), 61 deletions(-) create mode 100644 site/content/examples/04-events/05-dom-event-forwarding/CustomButton.svelte delete mode 100644 site/content/examples/04-events/05-dom-event-forwarding/FancyButton.svelte create mode 100644 site/content/tutorial/05-events/06-dom-event-forwarding/app-a/CustomButton.svelte delete mode 100644 site/content/tutorial/05-events/06-dom-event-forwarding/app-a/FancyButton.svelte create mode 100644 site/content/tutorial/05-events/06-dom-event-forwarding/app-b/CustomButton.svelte delete mode 100644 site/content/tutorial/05-events/06-dom-event-forwarding/app-b/FancyButton.svelte create mode 100644 test/custom-elements/samples/extended-builtin/custom-button.js delete mode 100644 test/custom-elements/samples/extended-builtin/fancy-button.js diff --git a/site/content/examples/04-events/05-dom-event-forwarding/App.svelte b/site/content/examples/04-events/05-dom-event-forwarding/App.svelte index 1429cae207d8..e75c78106ac3 100644 --- a/site/content/examples/04-events/05-dom-event-forwarding/App.svelte +++ b/site/content/examples/04-events/05-dom-event-forwarding/App.svelte @@ -1,9 +1,9 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/site/content/examples/04-events/05-dom-event-forwarding/CustomButton.svelte b/site/content/examples/04-events/05-dom-event-forwarding/CustomButton.svelte new file mode 100644 index 000000000000..f521c1f4713a --- /dev/null +++ b/site/content/examples/04-events/05-dom-event-forwarding/CustomButton.svelte @@ -0,0 +1,22 @@ + + + \ No newline at end of file diff --git a/site/content/examples/04-events/05-dom-event-forwarding/FancyButton.svelte b/site/content/examples/04-events/05-dom-event-forwarding/FancyButton.svelte deleted file mode 100644 index 68dcc68636a9..000000000000 --- a/site/content/examples/04-events/05-dom-event-forwarding/FancyButton.svelte +++ /dev/null @@ -1,15 +0,0 @@ - - - \ No newline at end of file diff --git a/site/content/tutorial/05-events/06-dom-event-forwarding/app-a/App.svelte b/site/content/tutorial/05-events/06-dom-event-forwarding/app-a/App.svelte index 1429cae207d8..e75c78106ac3 100644 --- a/site/content/tutorial/05-events/06-dom-event-forwarding/app-a/App.svelte +++ b/site/content/tutorial/05-events/06-dom-event-forwarding/app-a/App.svelte @@ -1,9 +1,9 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/site/content/tutorial/05-events/06-dom-event-forwarding/app-a/CustomButton.svelte b/site/content/tutorial/05-events/06-dom-event-forwarding/app-a/CustomButton.svelte new file mode 100644 index 000000000000..0955930b5d59 --- /dev/null +++ b/site/content/tutorial/05-events/06-dom-event-forwarding/app-a/CustomButton.svelte @@ -0,0 +1,22 @@ + + + \ No newline at end of file diff --git a/site/content/tutorial/05-events/06-dom-event-forwarding/app-a/FancyButton.svelte b/site/content/tutorial/05-events/06-dom-event-forwarding/app-a/FancyButton.svelte deleted file mode 100644 index b75f19a1f25c..000000000000 --- a/site/content/tutorial/05-events/06-dom-event-forwarding/app-a/FancyButton.svelte +++ /dev/null @@ -1,15 +0,0 @@ - - - \ No newline at end of file diff --git a/site/content/tutorial/05-events/06-dom-event-forwarding/app-b/App.svelte b/site/content/tutorial/05-events/06-dom-event-forwarding/app-b/App.svelte index 1429cae207d8..e75c78106ac3 100644 --- a/site/content/tutorial/05-events/06-dom-event-forwarding/app-b/App.svelte +++ b/site/content/tutorial/05-events/06-dom-event-forwarding/app-b/App.svelte @@ -1,9 +1,9 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/site/content/tutorial/05-events/06-dom-event-forwarding/app-b/CustomButton.svelte b/site/content/tutorial/05-events/06-dom-event-forwarding/app-b/CustomButton.svelte new file mode 100644 index 000000000000..f521c1f4713a --- /dev/null +++ b/site/content/tutorial/05-events/06-dom-event-forwarding/app-b/CustomButton.svelte @@ -0,0 +1,22 @@ + + + \ No newline at end of file diff --git a/site/content/tutorial/05-events/06-dom-event-forwarding/app-b/FancyButton.svelte b/site/content/tutorial/05-events/06-dom-event-forwarding/app-b/FancyButton.svelte deleted file mode 100644 index 68dcc68636a9..000000000000 --- a/site/content/tutorial/05-events/06-dom-event-forwarding/app-b/FancyButton.svelte +++ /dev/null @@ -1,15 +0,0 @@ - - - \ No newline at end of file diff --git a/site/content/tutorial/05-events/06-dom-event-forwarding/text.md b/site/content/tutorial/05-events/06-dom-event-forwarding/text.md index 0959e1d98b17..be9ae77f8912 100644 --- a/site/content/tutorial/05-events/06-dom-event-forwarding/text.md +++ b/site/content/tutorial/05-events/06-dom-event-forwarding/text.md @@ -4,7 +4,7 @@ title: DOM event forwarding Event forwarding works for DOM events too. -We want to get notified of clicks on our `` — to do that, we just need to forward `click` events on the ` \ No newline at end of file + \ No newline at end of file diff --git a/test/custom-elements/samples/extended-builtin/test.js b/test/custom-elements/samples/extended-builtin/test.js index d676fd137b53..3886ae11498f 100644 --- a/test/custom-elements/samples/extended-builtin/test.js +++ b/test/custom-elements/samples/extended-builtin/test.js @@ -11,5 +11,5 @@ export default function (target) { const el = target.querySelector('custom-element'); const button = el.shadowRoot.querySelector('button'); - assert.ok(button instanceof customElements.get('fancy-button')); + assert.ok(button instanceof customElements.get('custom-button')); } \ No newline at end of file From 20e079007cfecc80f130271400a3d3f368709f60 Mon Sep 17 00:00:00 2001 From: Jesse Skinner Date: Fri, 28 Feb 2020 08:47:21 -0500 Subject: [PATCH 021/158] docs: clarify default prop behaviour (#4460) --- site/content/docs/01-component-format.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/site/content/docs/01-component-format.md b/site/content/docs/01-component-format.md index 026a2da5b39d..07a59c69f8ce 100644 --- a/site/content/docs/01-component-format.md +++ b/site/content/docs/01-component-format.md @@ -42,13 +42,13 @@ Svelte uses the `export` keyword to mark a variable declaration as a *property* --- -You can specify a default value, which will be used if the component's consumer doesn't specify a prop. +You can specify a default initial value for a prop. It will be used if the component's consumer doesn't specify the prop on the component (or if its initial value is `undefined`) when instantiating the component. Note that whenever a prop is removed by the consumer, its value is set to `undefined` rather than the initial value. -In development mode (see the [compiler options](docs#svelte_compile)), a warning will be printed if no default is provided and the consumer does not specify a value. To squelch this warning, ensure that a default is specified, even if it is `undefined`. +In development mode (see the [compiler options](docs#svelte_compile)), a warning will be printed if no default initial value is provided and the consumer does not specify a value. To squelch this warning, ensure that a default initial value is specified, even if it is `undefined`. ```html ``` From f244b80f7a80df54aa07f85c35720fa6ca880318 Mon Sep 17 00:00:00 2001 From: Conduitry Date: Fri, 28 Feb 2020 23:07:34 -0500 Subject: [PATCH 022/158] docs: referenced_from_script var value (#4486) --- site/content/docs/04-compile-time.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/site/content/docs/04-compile-time.md b/site/content/docs/04-compile-time.md index 0cb2ac3caf75..f9bfa772fec1 100644 --- a/site/content/docs/04-compile-time.md +++ b/site/content/docs/04-compile-time.md @@ -113,7 +113,8 @@ const { * `module` is `true` if the value is declared in a `context="module"` script * `mutated` is `true` if the value's properties are assigned to inside the component * `reassigned` is `true` if the value is reassigned inside the component - * `referenced` is `true` if the value is used outside the declaration + * `referenced` is `true` if the value is used in the template + * `referenced_from_script` is `true` if the value is used in the ` + \ No newline at end of file From 8feb85a61fe32ec164ea0358e5966338c5c69e1d Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Sun, 1 Mar 2020 00:32:11 +0800 Subject: [PATCH 024/158] fix bitmask overflow for slot (#4485) --- CHANGELOG.md | 1 + src/runtime/internal/utils.ts | 6 ++- .../bitmask-overflow-slot-3/Echo.svelte | 9 ++++ .../bitmask-overflow-slot-3/_config.js | 30 ++++++++++++ .../bitmask-overflow-slot-3/main.svelte | 11 +++++ .../bitmask-overflow-slot-4/Echo.svelte | 11 +++++ .../bitmask-overflow-slot-4/_config.js | 41 ++++++++++++++++ .../bitmask-overflow-slot-4/main.svelte | 12 +++++ .../bitmask-overflow-slot-5/Echo.svelte | 13 +++++ .../bitmask-overflow-slot-5/_config.js | 49 +++++++++++++++++++ .../bitmask-overflow-slot-5/main.svelte | 13 +++++ 11 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 test/runtime/samples/bitmask-overflow-slot-3/Echo.svelte create mode 100644 test/runtime/samples/bitmask-overflow-slot-3/_config.js create mode 100644 test/runtime/samples/bitmask-overflow-slot-3/main.svelte create mode 100644 test/runtime/samples/bitmask-overflow-slot-4/Echo.svelte create mode 100644 test/runtime/samples/bitmask-overflow-slot-4/_config.js create mode 100644 test/runtime/samples/bitmask-overflow-slot-4/main.svelte create mode 100644 test/runtime/samples/bitmask-overflow-slot-5/Echo.svelte create mode 100644 test/runtime/samples/bitmask-overflow-slot-5/_config.js create mode 100644 test/runtime/samples/bitmask-overflow-slot-5/main.svelte diff --git a/CHANGELOG.md b/CHANGELOG.md index 60553037e44f..8197888f57de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * In `vars` array, correctly indicate whether `module` variables are `mutated` or `reassigned` ([#3215](https://github.com/sveltejs/svelte/issues/3215)) * Exclude global variables from `$capture_state` ([#4463](https://github.com/sveltejs/svelte/issues/4463)) +* Fix bitmask overflow for slots ([#4481](https://github.com/sveltejs/svelte/issues/4481)) ## 3.19.1 diff --git a/src/runtime/internal/utils.ts b/src/runtime/internal/utils.ts index 4ba7e18c153a..acb88c766945 100644 --- a/src/runtime/internal/utils.ts +++ b/src/runtime/internal/utils.ts @@ -83,7 +83,11 @@ export function get_slot_changes(definition, $$scope, dirty, fn) { if (definition[2] && fn) { const lets = definition[2](fn(dirty)); - if (typeof $$scope.dirty === 'object') { + if ($$scope.dirty === undefined) { + return lets; + } + + if (typeof lets === 'object') { const merged = []; const len = Math.max($$scope.dirty.length, lets.length); for (let i = 0; i < len; i += 1) { diff --git a/test/runtime/samples/bitmask-overflow-slot-3/Echo.svelte b/test/runtime/samples/bitmask-overflow-slot-3/Echo.svelte new file mode 100644 index 000000000000..d3ecf142c924 --- /dev/null +++ b/test/runtime/samples/bitmask-overflow-slot-3/Echo.svelte @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/test/runtime/samples/bitmask-overflow-slot-3/_config.js b/test/runtime/samples/bitmask-overflow-slot-3/_config.js new file mode 100644 index 000000000000..93e548e5f7ef --- /dev/null +++ b/test/runtime/samples/bitmask-overflow-slot-3/_config.js @@ -0,0 +1,30 @@ +export default { + + html: ` +

_0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_19_20_21_22_23_24_25_26_27_28_29_30_31_32_33_34_35_36_37_38_39_40

+

0

+ + `, + + async test({ assert, component, target, window }) { + // change from inside + const button = target.querySelector('button'); + await button.dispatchEvent(new window.MouseEvent('click')); + + assert.htmlEqual(target.innerHTML, ` +

_0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_19_20_21_22_23_24_25_26_27_28_29_30_31_32_33_34_35_36_37_38_39_40

+

1

+ + `); + + // change from outside + component._0 = 'a'; + component._40 = 'b'; + + assert.htmlEqual(target.innerHTML, ` +

a_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_19_20_21_22_23_24_25_26_27_28_29_30_31_32_33_34_35_36_37_38_39b

+

1

+ + `); + } +}; \ No newline at end of file diff --git a/test/runtime/samples/bitmask-overflow-slot-3/main.svelte b/test/runtime/samples/bitmask-overflow-slot-3/main.svelte new file mode 100644 index 000000000000..ae798e4aeeb5 --- /dev/null +++ b/test/runtime/samples/bitmask-overflow-slot-3/main.svelte @@ -0,0 +1,11 @@ + + + +

{_0}{_1}{_2}{_3}{_4}{_5}{_6}{_7}{_8}{_9}{_10}{_11}{_12}{_13}{_14}{_15}{_16}{_17}{_18}{_19}{_20}{_21}{_22}{_23}{_24}{_25}{_26}{_27}{_28}{_29}{_30}{_31}{_32}{_33}{_34}{_35}{_36}{_37}{_38}{_39}{_40}

+

{dummy}

+
+ diff --git a/test/runtime/samples/bitmask-overflow-slot-4/Echo.svelte b/test/runtime/samples/bitmask-overflow-slot-4/Echo.svelte new file mode 100644 index 000000000000..2e1beda492d9 --- /dev/null +++ b/test/runtime/samples/bitmask-overflow-slot-4/Echo.svelte @@ -0,0 +1,11 @@ + + +

{_0}{_1}{_2}{_3}{_4}{_5}{_6}{_7}{_8}{_9}{_10}{_11}{_12}{_13}{_14}{_15}{_16}{_17}{_18}{_19}{_20}{_21}{_22}{_23}{_24}{_25}{_26}{_27}{_28}{_29}{_30}{_31}{_32}{_33}{_34}{_35}{_36}{_37}{_38}{_39}{_40}

+ + \ No newline at end of file diff --git a/test/runtime/samples/bitmask-overflow-slot-4/_config.js b/test/runtime/samples/bitmask-overflow-slot-4/_config.js new file mode 100644 index 000000000000..cdaa5de77fa6 --- /dev/null +++ b/test/runtime/samples/bitmask-overflow-slot-4/_config.js @@ -0,0 +1,41 @@ +export default { + html: ` +

_0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_19_20_21_22_23_24_25_26_27_28_29_30_31_32_33_34_35_36_37_38_39_40

+

0

+

0

+ + `, + + async test({ assert, component, target, window }) { + // change from inside + const button = target.querySelector('button'); + await button.dispatchEvent(new window.MouseEvent('click')); + + assert.htmlEqual(target.innerHTML, ` +

_0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_19_20_21_22_23_24_25_26_27_28_29_30_31_32_33_34_35_36_37_38_39_40

+

0

+

1

+ + `); + + // change from outside + component._0 = 'a'; + + assert.htmlEqual(target.innerHTML, ` +

_0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_19_20_21_22_23_24_25_26_27_28_29_30_31_32_33_34_35_36_37_38_39_40

+

a

+

1

+ + `); + + // change from outside through props + component._40 = 'b'; + + assert.htmlEqual(target.innerHTML, ` +

_0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_19_20_21_22_23_24_25_26_27_28_29_30_31_32_33_34_35_36_37_38_39b

+

a

+

1

+ + `); + } +}; \ No newline at end of file diff --git a/test/runtime/samples/bitmask-overflow-slot-4/main.svelte b/test/runtime/samples/bitmask-overflow-slot-4/main.svelte new file mode 100644 index 000000000000..7e02487a305d --- /dev/null +++ b/test/runtime/samples/bitmask-overflow-slot-4/main.svelte @@ -0,0 +1,12 @@ + + + +

{_0}

+

{dummy}

+
+ diff --git a/test/runtime/samples/bitmask-overflow-slot-5/Echo.svelte b/test/runtime/samples/bitmask-overflow-slot-5/Echo.svelte new file mode 100644 index 000000000000..dddb3f76428f --- /dev/null +++ b/test/runtime/samples/bitmask-overflow-slot-5/Echo.svelte @@ -0,0 +1,13 @@ + + +

{_0}{_1}{_2}{_3}{_4}{_5}{_6}{_7}{_8}{_9}{_10}{_11}{_12}{_13}{_14}{_15}{_16}{_17}{_18}{_19}{_20}{_21}{_22}{_23}{_24}{_25}{_26}{_27}{_28}{_29}{_30}{_31}{_32}{_33}{_34}{_35}{_36}{_37}{_38}{_39}{_40}

+

{b}

+ + \ No newline at end of file diff --git a/test/runtime/samples/bitmask-overflow-slot-5/_config.js b/test/runtime/samples/bitmask-overflow-slot-5/_config.js new file mode 100644 index 000000000000..7dedb8f7ebde --- /dev/null +++ b/test/runtime/samples/bitmask-overflow-slot-5/_config.js @@ -0,0 +1,49 @@ +export default { + html: ` +

_0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_19_20_21_22_23_24_25_26_27_28_29_30_31_32_33_34_35_36_37_38_39_40

+

b

+

-0-1-2-3-4-5-6-7-8-9-10-11-12-13-14-15-16-17-18-19-20-21-22-23-24-25-26-27-28-29-30-31-32-33-34-35-36-37-38-39-40

+

0

+

0

+ + `, + + async test({ assert, component, target, window }) { + // change from inside + const button = target.querySelector('button'); + await button.dispatchEvent(new window.MouseEvent('click')); + + assert.htmlEqual(target.innerHTML, ` +

_0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_19_20_21_22_23_24_25_26_27_28_29_30_31_32_33_34_35_36_37_38_39_40

+

b

+

-0-1-2-3-4-5-6-7-8-9-10-11-12-13-14-15-16-17-18-19-20-21-22-23-24-25-26-27-28-29-30-31-32-33-34-35-36-37-38-39-40

+

0

+

1

+ + `); + + // change from outside + component.a = 'AA'; + + assert.htmlEqual(target.innerHTML, ` +

_0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_19_20_21_22_23_24_25_26_27_28_29_30_31_32_33_34_35_36_37_38_39_40

+

b

+

-0-1-2-3-4-5-6-7-8-9-10-11-12-13-14-15-16-17-18-19-20-21-22-23-24-25-26-27-28-29-30-31-32-33-34-35-36-37-38-39-40

+

AA

+

1

+ + `); + + // change from outside through props + component.b = 'BB'; + + assert.htmlEqual(target.innerHTML, ` +

_0_1_2_3_4_5_6_7_8_9_10_11_12_13_14_15_16_17_18_19_20_21_22_23_24_25_26_27_28_29_30_31_32_33_34_35_36_37_38_39_40

+

BB

+

-0-1-2-3-4-5-6-7-8-9-10-11-12-13-14-15-16-17-18-19-20-21-22-23-24-25-26-27-28-29-30-31-32-33-34-35-36-37-38-39-40

+

AA

+

1

+ + `); + } +}; \ No newline at end of file diff --git a/test/runtime/samples/bitmask-overflow-slot-5/main.svelte b/test/runtime/samples/bitmask-overflow-slot-5/main.svelte new file mode 100644 index 000000000000..b17d6f7baef8 --- /dev/null +++ b/test/runtime/samples/bitmask-overflow-slot-5/main.svelte @@ -0,0 +1,13 @@ + + + +

{_0}{_1}{_2}{_3}{_4}{_5}{_6}{_7}{_8}{_9}{_10}{_11}{_12}{_13}{_14}{_15}{_16}{_17}{_18}{_19}{_20}{_21}{_22}{_23}{_24}{_25}{_26}{_27}{_28}{_29}{_30}{_31}{_32}{_33}{_34}{_35}{_36}{_37}{_38}{_39}{_40}

+

{a}

+

{dummy}

+
+ From 37a2d6c6eada0c4e893fb90f3d8faa6eb3036f6f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 29 Feb 2020 11:34:18 -0500 Subject: [PATCH 025/158] Bump codecov from 3.5.0 to 3.6.5 (#4433) Bumps [codecov](https://github.com/codecov/codecov-node) from 3.5.0 to 3.6.5. - [Release notes](https://github.com/codecov/codecov-node/releases) - [Commits](https://github.com/codecov/codecov-node/commits) Signed-off-by: dependabot[bot] --- package-lock.json | 111 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 96 insertions(+), 15 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3b275078ec9f..f0f4e1742246 100644 --- a/package-lock.json +++ b/package-lock.json @@ -137,6 +137,12 @@ } } }, + "@tootallnate/once": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.0.0.tgz", + "integrity": "sha512-KYyTT/T6ALPkIRd2Ge080X/BsXvy9O0hcWTtMWkPvwAwF99+vn6Dv4GzrFT/Nn1LePr+FFDbRXXlqmsy9lw2zA==", + "dev": true + }, "@types/eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", @@ -609,16 +615,16 @@ } }, "codecov": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.5.0.tgz", - "integrity": "sha512-/OsWOfIHaQIr7aeZ4pY0UC1PZT6kimoKFOFYFNb6wxo3iw12nRrh+mNGH72rnXxNsq6SGfesVPizm/6Q3XqcFQ==", + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.6.5.tgz", + "integrity": "sha512-v48WuDMUug6JXwmmfsMzhCHRnhUf8O3duqXvltaYJKrO1OekZWpB/eH6iIoaxMl8Qli0+u3OxptdsBOYiD7VAQ==", "dev": true, "requires": { - "argv": "^0.0.2", - "ignore-walk": "^3.0.1", - "js-yaml": "^3.13.1", - "teeny-request": "^3.11.3", - "urlgrey": "^0.4.4" + "argv": "0.0.2", + "ignore-walk": "3.0.3", + "js-yaml": "3.13.1", + "teeny-request": "6.0.1", + "urlgrey": "0.4.4" } }, "color-convert": { @@ -1670,6 +1676,37 @@ "whatwg-encoding": "^1.0.1" } }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "agent-base": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.0.tgz", + "integrity": "sha512-j1Q7cSCqN+AwrmDd+pzgqc0/NpC655x2bUf5ZjRIO77DcNBFmh+OgRNzF6OKdCC9RSCb19fGd99+bhXFdkRNqw==", + "dev": true, + "requires": { + "debug": "4" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -1707,9 +1744,9 @@ "dev": true }, "ignore-walk": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", - "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", "dev": true, "requires": { "minimatch": "^3.0.4" @@ -3362,6 +3399,15 @@ "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", "dev": true }, + "stream-events": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", + "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", + "dev": true, + "requires": { + "stubs": "^3.0.0" + } + }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -3409,6 +3455,12 @@ "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", "dev": true }, + "stubs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", + "integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls=", + "dev": true + }, "sucrase": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.10.1.tgz", @@ -3449,14 +3501,43 @@ } }, "teeny-request": { - "version": "3.11.3", - "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-3.11.3.tgz", - "integrity": "sha512-CKncqSF7sH6p4rzCgkb/z/Pcos5efl0DmolzvlqRQUNcpRIruOhY9+T1FsIlyEbfWd7MsFpodROOwHYh2BaXzw==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-6.0.1.tgz", + "integrity": "sha512-TAK0c9a00ELOqLrZ49cFxvPVogMUFaWY8dUsQc/0CuQPGF+BOxOQzXfE413BAk2kLomwNplvdtMpeaeGWmoc2g==", "dev": true, "requires": { - "https-proxy-agent": "^2.2.1", + "http-proxy-agent": "^4.0.0", + "https-proxy-agent": "^4.0.0", "node-fetch": "^2.2.0", + "stream-events": "^1.0.5", "uuid": "^3.3.2" + }, + "dependencies": { + "agent-base": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", + "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==", + "dev": true + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "https-proxy-agent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", + "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", + "dev": true, + "requires": { + "agent-base": "5", + "debug": "4" + } + } } }, "test-exclude": { From b6aaa44880892a64712f629bff40f1433d92dfdb Mon Sep 17 00:00:00 2001 From: pushkin Date: Sat, 29 Feb 2020 18:43:53 +0100 Subject: [PATCH 026/158] check for unknown props even if component doesn't have writable props (#4454) --- src/compiler/compile/render_dom/index.ts | 6 +++++- test/js/samples/debug-hoisted/expected.js | 6 ++++++ test/js/samples/debug-no-dependencies/expected.js | 12 +++++++++++- test/js/samples/loop-protect/expected.js | 8 ++++++++ .../samples/dev-warning-unknown-props-2/Foo.svelte | 1 + .../samples/dev-warning-unknown-props-2/_config.js | 9 +++++++++ .../samples/dev-warning-unknown-props-2/main.svelte | 5 +++++ 7 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 test/runtime/samples/dev-warning-unknown-props-2/Foo.svelte create mode 100644 test/runtime/samples/dev-warning-unknown-props-2/_config.js create mode 100644 test/runtime/samples/dev-warning-unknown-props-2/main.svelte diff --git a/src/compiler/compile/render_dom/index.ts b/src/compiler/compile/render_dom/index.ts index 71e868164602..3d1870ccaa77 100644 --- a/src/compiler/compile/render_dom/index.ts +++ b/src/compiler/compile/render_dom/index.ts @@ -259,6 +259,9 @@ export default function dom( inject_state; if (has_invalidate) { args.push(x`$$props`, x`$$invalidate`); + } else if (component.compile_options.dev) { + // $$props arg is still needed for unknown prop check + args.push(x`$$props`); } const has_create_fragment = block.has_content(); @@ -300,6 +303,7 @@ export default function dom( const initial_context = renderer.context.slice(0, i + 1); const has_definition = ( + component.compile_options.dev || (instance_javascript && instance_javascript.length > 0) || filtered_props.length > 0 || uses_props || @@ -379,7 +383,7 @@ export default function dom( }); let unknown_props_check; - if (component.compile_options.dev && !component.var_lookup.has('$$props') && writable_props.length) { + if (component.compile_options.dev && !component.var_lookup.has('$$props')) { unknown_props_check = b` const writable_props = [${writable_props.map(prop => x`'${prop.export_name}'`)}]; @_Object.keys($$props).forEach(key => { diff --git a/test/js/samples/debug-hoisted/expected.js b/test/js/samples/debug-hoisted/expected.js index c77168ef4f6d..190ff12c50ee 100644 --- a/test/js/samples/debug-hoisted/expected.js +++ b/test/js/samples/debug-hoisted/expected.js @@ -50,6 +50,12 @@ function create_fragment(ctx) { function instance($$self, $$props, $$invalidate) { let obj = { x: 5 }; let kobzol = 5; + const writable_props = []; + + Object.keys($$props).forEach(key => { + if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(` was created with unknown prop '${key}'`); + }); + $$self.$capture_state = () => ({ obj, kobzol }); $$self.$inject_state = $$props => { diff --git a/test/js/samples/debug-no-dependencies/expected.js b/test/js/samples/debug-no-dependencies/expected.js index 9985c814a2ae..a097869e747b 100644 --- a/test/js/samples/debug-no-dependencies/expected.js +++ b/test/js/samples/debug-no-dependencies/expected.js @@ -134,10 +134,20 @@ function create_fragment(ctx) { return block; } +function instance($$self, $$props) { + const writable_props = []; + + Object.keys($$props).forEach(key => { + if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(` was created with unknown prop '${key}'`); + }); + + return []; +} + class Component extends SvelteComponentDev { constructor(options) { super(options); - init(this, options, null, create_fragment, safe_not_equal, {}); + init(this, options, instance, create_fragment, safe_not_equal, {}); dispatch_dev("SvelteRegisterComponent", { component: this, diff --git a/test/js/samples/loop-protect/expected.js b/test/js/samples/loop-protect/expected.js index 4eccaae7cb79..f433bd61a962 100644 --- a/test/js/samples/loop-protect/expected.js +++ b/test/js/samples/loop-protect/expected.js @@ -6,6 +6,7 @@ import { detach_dev, dispatch_dev, element, + globals, init, insert_dev, loop_guard, @@ -13,6 +14,7 @@ import { safe_not_equal } from "svelte/internal"; +const { console: console_1 } = globals; const file = undefined; function create_fragment(ctx) { @@ -102,6 +104,12 @@ function instance($$self, $$props, $$invalidate) { } while (true); } + const writable_props = []; + + Object.keys($$props).forEach(key => { + if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console_1.warn(` was created with unknown prop '${key}'`); + }); + function div_binding($$value) { binding_callbacks[$$value ? "unshift" : "push"](() => { $$invalidate(0, node = $$value); diff --git a/test/runtime/samples/dev-warning-unknown-props-2/Foo.svelte b/test/runtime/samples/dev-warning-unknown-props-2/Foo.svelte new file mode 100644 index 000000000000..bc56c4d89448 --- /dev/null +++ b/test/runtime/samples/dev-warning-unknown-props-2/Foo.svelte @@ -0,0 +1 @@ +Foo diff --git a/test/runtime/samples/dev-warning-unknown-props-2/_config.js b/test/runtime/samples/dev-warning-unknown-props-2/_config.js new file mode 100644 index 000000000000..9bff4a2a741b --- /dev/null +++ b/test/runtime/samples/dev-warning-unknown-props-2/_config.js @@ -0,0 +1,9 @@ +export default { + compileOptions: { + dev: true + }, + + warnings: [ + ` was created with unknown prop 'fo'` + ] +}; diff --git a/test/runtime/samples/dev-warning-unknown-props-2/main.svelte b/test/runtime/samples/dev-warning-unknown-props-2/main.svelte new file mode 100644 index 000000000000..1566cf3e41e7 --- /dev/null +++ b/test/runtime/samples/dev-warning-unknown-props-2/main.svelte @@ -0,0 +1,5 @@ + + + From 3f647a84f6c295334ac8309caa9724a3fa137ace Mon Sep 17 00:00:00 2001 From: Conduitry Date: Sat, 29 Feb 2020 12:44:54 -0500 Subject: [PATCH 027/158] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8197888f57de..3dd0aadf8b64 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased * In `vars` array, correctly indicate whether `module` variables are `mutated` or `reassigned` ([#3215](https://github.com/sveltejs/svelte/issues/3215)) +* In `dev` mode, check for unknown props even if the component has no writable props ([#4323](https://github.com/sveltejs/svelte/issues/4323)) * Exclude global variables from `$capture_state` ([#4463](https://github.com/sveltejs/svelte/issues/4463)) * Fix bitmask overflow for slots ([#4481](https://github.com/sveltejs/svelte/issues/4481)) From 3a37de364bfbe75202d8e9fcef9e76b9ce6faaa2 Mon Sep 17 00:00:00 2001 From: Brian Takita Date: Sat, 29 Feb 2020 12:50:54 -0500 Subject: [PATCH 028/158] chore: more specific typings, and add README note about Yarn (#4483) --- README.md | 2 ++ src/compiler/compile/Component.ts | 26 +++++++++---------- src/compiler/compile/nodes/Let.ts | 12 ++++----- .../compile/nodes/shared/Expression.ts | 4 +-- src/compiler/compile/render_dom/index.ts | 4 +-- 5 files changed, 25 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 3a437256372f..fa725804a984 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,8 @@ cd svelte npm install ``` +> Do not use Yarn to install the dependencies, as the specific package versions in `package-lock.json` are used to build and test Svelte. + > Many tests depend on newlines being preserved as ``. On Windows, you can ensure this by cloning with: > ```bash > git -c core.autocrlf=false clone https://github.com/sveltejs/svelte.git diff --git a/src/compiler/compile/Component.ts b/src/compiler/compile/Component.ts index 25698204648f..a7fe2992d18c 100644 --- a/src/compiler/compile/Component.ts +++ b/src/compiler/compile/Component.ts @@ -239,7 +239,7 @@ export default class Component { const program: any = { type: 'Program', body: result.js }; walk(program, { - enter: (node, parent, key) => { + enter: (node: Node, parent: Node, key) => { if (node.type === 'Identifier') { if (node.name[0] === '@') { if (node.name[1] === '_') { @@ -526,7 +526,7 @@ export default class Component { if (!script) return; walk(script.content, { - enter(node) { + enter(node: Node) { if (node.type === 'LabeledStatement' && node.label.name === '$') { component.warn(node as any, { code: 'module-script-reactive-declaration', @@ -715,7 +715,7 @@ export default class Component { let scope_updated = false; walk(content, { - enter(node, parent, prop, index) { + enter(node: Node, parent, prop, index) { if (map.has(node)) { scope = map.get(node); } @@ -741,7 +741,7 @@ export default class Component { component.warn_on_undefined_store_value_references(node, parent, scope); }, - leave(node) { + leave(node: Node) { // do it on leave, to prevent infinite loop if (component.compile_options.dev && component.compile_options.loopGuardTimeout > 0) { const to_replace_for_loop_protect = component.loop_protect(node, scope, component.compile_options.loopGuardTimeout); @@ -785,7 +785,7 @@ export default class Component { let scope = instance_scope; walk(content, { - enter(node, parent) { + enter(node: Node, parent: Node) { if (map.has(node)) { scope = map.get(node); } @@ -818,7 +818,7 @@ export default class Component { } }, - leave(node) { + leave(node: Node) { if (map.has(node)) { scope = scope.parent; } @@ -886,7 +886,7 @@ export default class Component { let scope = instance_scope; walk(this.ast.instance.content, { - enter(node, parent, key, index) { + enter(node: Node, parent, key, index) { if (/Function/.test(node.type)) { return this.skip(); } @@ -963,7 +963,7 @@ export default class Component { } }, - leave(node, parent, _key, index) { + leave(node: Node, parent, _key, index) { if (map.has(node)) { scope = scope.parent; } @@ -1064,7 +1064,7 @@ export default class Component { walking.add(fn_declaration); walk(fn_declaration, { - enter(node, parent) { + enter(node: Node, parent) { if (!hoistable) return this.skip(); if (map.has(node)) { @@ -1112,7 +1112,7 @@ export default class Component { } }, - leave(node) { + leave(node: Node) { if (map.has(node)) { scope = scope.parent; } @@ -1155,7 +1155,7 @@ export default class Component { const map = this.instance_scope_map; walk(node.body, { - enter(node, parent) { + enter(node: Node, parent) { if (map.has(node)) { scope = map.get(node); } @@ -1195,7 +1195,7 @@ export default class Component { } }, - leave(node) { + leave(node: Node) { if (map.has(node)) { scope = scope.parent; } @@ -1455,4 +1455,4 @@ function get_relative_path(from: string, to: string) { } return from_parts.concat(to_parts).join('/'); -} \ No newline at end of file +} diff --git a/src/compiler/compile/nodes/Let.ts b/src/compiler/compile/nodes/Let.ts index 7b92c5ce7085..ef38cd36a877 100644 --- a/src/compiler/compile/nodes/Let.ts +++ b/src/compiler/compile/nodes/Let.ts @@ -1,7 +1,7 @@ import Node from './shared/Node'; import Component from '../Component'; import { walk } from 'estree-walker'; -import { Identifier } from 'estree'; +import { BasePattern, Identifier } from 'estree'; const applicable = new Set(['Identifier', 'ObjectExpression', 'ArrayExpression', 'Property']); @@ -22,7 +22,7 @@ export default class Let extends Node { this.value = info.expression; walk(info.expression, { - enter(node) { + enter(node: Identifier|BasePattern) { if (!applicable.has(node.type)) { component.error(node as any, { code: 'invalid-let', @@ -31,16 +31,16 @@ export default class Let extends Node { } if (node.type === 'Identifier') { - names.push(node.name); + names.push((node as Identifier).name); } // slightly unfortunate hack if (node.type === 'ArrayExpression') { - (node as any).type = 'ArrayPattern'; + node.type = 'ArrayPattern'; } if (node.type === 'ObjectExpression') { - (node as any).type = 'ObjectPattern'; + node.type = 'ObjectPattern'; } } }); @@ -48,4 +48,4 @@ export default class Let extends Node { names.push(this.name.name); } } -} \ No newline at end of file +} diff --git a/src/compiler/compile/nodes/shared/Expression.ts b/src/compiler/compile/nodes/shared/Expression.ts index 1882c19267cd..db0908c3f4bd 100644 --- a/src/compiler/compile/nodes/shared/Expression.ts +++ b/src/compiler/compile/nodes/shared/Expression.ts @@ -143,7 +143,7 @@ export default class Expression { } }, - leave(node) { + leave(node: Node) { if (map.has(node)) { scope = scope.parent; } @@ -338,7 +338,7 @@ export default class Expression { }); } - return (this.manipulated = node); + return (this.manipulated = node as Node); } } diff --git a/src/compiler/compile/render_dom/index.ts b/src/compiler/compile/render_dom/index.ts index 3d1870ccaa77..d6da6142768c 100644 --- a/src/compiler/compile/render_dom/index.ts +++ b/src/compiler/compile/render_dom/index.ts @@ -200,7 +200,7 @@ export default function dom( let execution_context: Node | null = null; walk(component.ast.instance.content, { - enter(node) { + enter(node: Node) { if (map.has(node)) { scope = map.get(node) as Scope; @@ -212,7 +212,7 @@ export default function dom( } }, - leave(node) { + leave(node: Node) { if (map.has(node)) { scope = scope.parent; } From d802c3b266be31a509cb69f3a81666b20842f3ef Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Sun, 1 Mar 2020 11:47:50 +0800 Subject: [PATCH 029/158] in spread, distinguish never-updating and always-updating props (#4487) --- CHANGELOG.md | 1 + .../wrappers/InlineComponent/index.ts | 15 +++- .../samples/spread-component-2/Widget.svelte | 13 ++++ .../samples/spread-component-2/_config.js | 76 +++++++++++++++++++ .../samples/spread-component-2/main.svelte | 12 +++ 5 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 test/runtime/samples/spread-component-2/Widget.svelte create mode 100644 test/runtime/samples/spread-component-2/_config.js create mode 100644 test/runtime/samples/spread-component-2/main.svelte diff --git a/CHANGELOG.md b/CHANGELOG.md index 3dd0aadf8b64..8cdc334868a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased * In `vars` array, correctly indicate whether `module` variables are `mutated` or `reassigned` ([#3215](https://github.com/sveltejs/svelte/issues/3215)) +* Fix spread props not updating in certain situations ([#3521](https://github.com/sveltejs/svelte/issues/3521), [#4480](https://github.com/sveltejs/svelte/issues/4480)) * In `dev` mode, check for unknown props even if the component has no writable props ([#4323](https://github.com/sveltejs/svelte/issues/4323)) * Exclude global variables from `$capture_state` ([#4463](https://github.com/sveltejs/svelte/issues/4463)) * Fix bitmask overflow for slots ([#4481](https://github.com/sveltejs/svelte/issues/4481)) diff --git a/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts b/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts index 28b3c938f9d3..8088bbac91a8 100644 --- a/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts +++ b/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts @@ -224,7 +224,9 @@ export default class InlineComponentWrapper extends Wrapper { const condition = dependencies.size > 0 && (dependencies.size !== all_dependencies.size) ? renderer.dirty(Array.from(dependencies)) : null; + const unchanged = dependencies.size === 0; + let change_object; if (attr.is_spread) { const value = attr.expression.manipulate(block); initial_props.push(value); @@ -233,13 +235,20 @@ export default class InlineComponentWrapper extends Wrapper { if (attr.expression.node.type !== 'ObjectExpression') { value_object = x`@get_spread_object(${value})`; } - changes.push(condition ? x`${condition} && ${value_object}` : value_object); + change_object = value_object; } else { const obj = x`{ ${name}: ${attr.get_value(block)} }`; initial_props.push(obj); - - changes.push(condition ? x`${condition} && ${obj}` : x`${levels}[${i}]`); + change_object = obj; } + + changes.push( + unchanged + ? x`${levels}[${i}]` + : condition + ? x`${condition} && ${change_object}` + : change_object + ); }); block.chunks.init.push(b` diff --git a/test/runtime/samples/spread-component-2/Widget.svelte b/test/runtime/samples/spread-component-2/Widget.svelte new file mode 100644 index 000000000000..ae27aeb5e531 --- /dev/null +++ b/test/runtime/samples/spread-component-2/Widget.svelte @@ -0,0 +1,13 @@ + + +

foo: {foo}

+

baz: {baz} ({typeof baz})

+

qux: {qux}

+

quux: {quux}

+

selected: {selected}

diff --git a/test/runtime/samples/spread-component-2/_config.js b/test/runtime/samples/spread-component-2/_config.js new file mode 100644 index 000000000000..6d36e8e60dfb --- /dev/null +++ b/test/runtime/samples/spread-component-2/_config.js @@ -0,0 +1,76 @@ +export default { + props: { + list: [{ + foo: 'lol', + baz: 40 + 2, + qux: 5, + quux: 'core' + }, { + foo: 'lolzz', + baz: 50 + 2, + qux: 1, + quux: 'quuxx' + }], + }, + + html: ` +
+

foo: lol

+

baz: 42 (number)

+

qux: 0

+

quux: core

+

selected: true

+

foo: lolzz

+

baz: 52 (number)

+

qux: 0

+

quux: quuxx

+

selected: false

+
+ `, + + test({ assert, component, target }) { + component.list = [{ + foo: 'lol', + baz: 40 + 3, + qux: 8, + quux: 'heart' + }, { + foo: 'lolzz', + baz: 50 + 3, + qux: 8, + quux: 'heartxx' + }]; + + assert.htmlEqual(target.innerHTML, ` +
+

foo: lol

+

baz: 43 (number)

+

qux: 0

+

quux: heart

+

selected: true

+

foo: lolzz

+

baz: 53 (number)

+

qux: 0

+

quux: heartxx

+

selected: false

+
+ `); + + component.qux = 1; + + assert.htmlEqual(target.innerHTML, ` +
+

foo: lol

+

baz: 43 (number)

+

qux: 1

+

quux: heart

+

selected: false

+

foo: lolzz

+

baz: 53 (number)

+

qux: 1

+

quux: heartxx

+

selected: true

+
+ `); + } +}; diff --git a/test/runtime/samples/spread-component-2/main.svelte b/test/runtime/samples/spread-component-2/main.svelte new file mode 100644 index 000000000000..436e11f9c50d --- /dev/null +++ b/test/runtime/samples/spread-component-2/main.svelte @@ -0,0 +1,12 @@ + + +
+ {#each list as item, index (item.foo)} + + {/each} +
From addea43e4f6c16e19083a78163210d7903543583 Mon Sep 17 00:00:00 2001 From: Conduitry Date: Mon, 2 Mar 2020 09:01:00 -0500 Subject: [PATCH 030/158] docs: describe falsy and nullish attribute behavior (#4498) --- site/content/docs/02-template-syntax.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/site/content/docs/02-template-syntax.md b/site/content/docs/02-template-syntax.md index 55b913ca947e..d25b348254db 100644 --- a/site/content/docs/02-template-syntax.md +++ b/site/content/docs/02-template-syntax.md @@ -58,6 +58,17 @@ Or they can *be* JavaScript expressions. --- +Boolean attributes are included on the element if their value is [truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy) and excluded if it's [falsy](https://developer.mozilla.org/en-US/docs/Glossary/Falsy). + +All other attributes are included unless their value is [nullish](https://developer.mozilla.org/en-US/docs/Glossary/Nullish) (`null` or `undefined`). + +```html + +
This div has no title attribute
+``` + +--- + An expression might include characters that would cause syntax highlighting to fail in regular HTML, so quoting the value is permitted. The quotes do not affect how the value is parsed: ```html From 926a2aebd8915c53cf81b0b1e4038c2b1952e297 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Wed, 4 Mar 2020 18:37:48 +0800 Subject: [PATCH 031/158] fix render fallback slot content due to whitespace (#4500) --- CHANGELOG.md | 1 + src/compiler/compile/nodes/Text.ts | 29 ++++++++ .../compile/render_dom/wrappers/Fragment.ts | 6 +- .../wrappers/InlineComponent/index.ts | 25 ++++--- .../compile/render_dom/wrappers/Text.ts | 32 +------- .../compile/render_ssr/handlers/Element.ts | 11 ++- .../render_ssr/handlers/InlineComponent.ts | 23 ++++-- .../utils/remove_whitespace_children.ts | 73 +++++++++++++++++++ src/compiler/utils/link.ts | 4 + .../Nested.svelte | 4 + .../component-slot-fallback-empty/_config.js | 13 ++++ .../component-slot-fallback-empty/main.svelte | 10 +++ 12 files changed, 178 insertions(+), 53 deletions(-) create mode 100644 src/compiler/compile/render_ssr/handlers/utils/remove_whitespace_children.ts create mode 100644 src/compiler/utils/link.ts create mode 100644 test/runtime/samples/component-slot-fallback-empty/Nested.svelte create mode 100644 test/runtime/samples/component-slot-fallback-empty/_config.js create mode 100644 test/runtime/samples/component-slot-fallback-empty/main.svelte diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cdc334868a3..b0672d790ea4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * In `vars` array, correctly indicate whether `module` variables are `mutated` or `reassigned` ([#3215](https://github.com/sveltejs/svelte/issues/3215)) * Fix spread props not updating in certain situations ([#3521](https://github.com/sveltejs/svelte/issues/3521), [#4480](https://github.com/sveltejs/svelte/issues/4480)) +* Use the fallback content for slots if they are passed only whitespace ([#4092](https://github.com/sveltejs/svelte/issues/4092)) * In `dev` mode, check for unknown props even if the component has no writable props ([#4323](https://github.com/sveltejs/svelte/issues/4323)) * Exclude global variables from `$capture_state` ([#4463](https://github.com/sveltejs/svelte/issues/4463)) * Fix bitmask overflow for slots ([#4481](https://github.com/sveltejs/svelte/issues/4481)) diff --git a/src/compiler/compile/nodes/Text.ts b/src/compiler/compile/nodes/Text.ts index bfd28a507309..6b7432c22f39 100644 --- a/src/compiler/compile/nodes/Text.ts +++ b/src/compiler/compile/nodes/Text.ts @@ -3,6 +3,18 @@ import Component from '../Component'; import TemplateScope from './shared/TemplateScope'; import { INode } from './interfaces'; +// Whitespace inside one of these elements will not result in +// a whitespace node being created in any circumstances. (This +// list is almost certainly very incomplete) +const elements_without_text = new Set([ + 'audio', + 'datalist', + 'dl', + 'optgroup', + 'select', + 'video', +]); + export default class Text extends Node { type: 'Text'; data: string; @@ -13,4 +25,21 @@ export default class Text extends Node { this.data = info.data; this.synthetic = info.synthetic || false; } + + should_skip() { + if (/\S/.test(this.data)) return false; + + const parent_element = this.find_nearest(/(?:Element|InlineComponent|Head)/); + if (!parent_element) return false; + + if (parent_element.type === 'Head') return true; + if (parent_element.type === 'InlineComponent') return parent_element.children.length === 1 && this === parent_element.children[0]; + + // svg namespace exclusions + if (/svg$/.test(parent_element.namespace)) { + if (this.prev && this.prev.type === "Element" && this.prev.name === "tspan") return false; + } + + return parent_element.namespace || elements_without_text.has(parent_element.name); + } } diff --git a/src/compiler/compile/render_dom/wrappers/Fragment.ts b/src/compiler/compile/render_dom/wrappers/Fragment.ts index 224b17d43f9d..a0984b69b920 100644 --- a/src/compiler/compile/render_dom/wrappers/Fragment.ts +++ b/src/compiler/compile/render_dom/wrappers/Fragment.ts @@ -17,6 +17,7 @@ import { INode } from '../../nodes/interfaces'; import Renderer from '../Renderer'; import Block from '../Block'; import { trim_start, trim_end } from '../../../utils/trim'; +import { link } from '../../../utils/link'; import { Identifier } from 'estree'; const wrappers = { @@ -38,11 +39,6 @@ const wrappers = { Window }; -function link(next: Wrapper, prev: Wrapper) { - prev.next = next; - if (next) next.prev = prev; -} - function trimmable_at(child: INode, next_sibling: Wrapper): boolean { // Whitespace is trimmable if one of the following is true: // The child and its sibling share a common nearest each block (not at an each block boundary) diff --git a/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts b/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts index 8088bbac91a8..8c8bd706962e 100644 --- a/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts +++ b/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts @@ -138,11 +138,27 @@ export default class InlineComponentWrapper extends Wrapper { const statements: Array = []; const updates: Array = []; + if (this.fragment) { + this.renderer.add_to_context('$$scope', true); + const default_slot = this.slots.get('default'); + + this.fragment.nodes.forEach((child) => { + child.render(default_slot.block, null, x`#nodes` as unknown as Identifier); + }); + } + let props; const name_changes = block.get_unique_name(`${name.name}_changes`); const uses_spread = !!this.node.attributes.find(a => a.is_spread); + // removing empty slot + for (const slot of this.slots.keys()) { + if (!this.slots.get(slot).block.has_content()) { + this.slots.delete(slot); + } + } + const initial_props = this.slots.size > 0 ? [ p`$$slots: { @@ -172,15 +188,6 @@ export default class InlineComponentWrapper extends Wrapper { } } - if (this.fragment) { - this.renderer.add_to_context('$$scope', true); - const default_slot = this.slots.get('default'); - - this.fragment.nodes.forEach((child) => { - child.render(default_slot.block, null, x`#nodes` as unknown as Identifier); - }); - } - if (component.compile_options.dev) { // TODO this is a terrible hack, but without it the component // will complain that options.target is missing. This would diff --git a/src/compiler/compile/render_dom/wrappers/Text.ts b/src/compiler/compile/render_dom/wrappers/Text.ts index 1978cba0d7d0..7ef8aebd7011 100644 --- a/src/compiler/compile/render_dom/wrappers/Text.ts +++ b/src/compiler/compile/render_dom/wrappers/Text.ts @@ -5,36 +5,6 @@ import Wrapper from './shared/Wrapper'; import { x } from 'code-red'; import { Identifier } from 'estree'; -// Whitespace inside one of these elements will not result in -// a whitespace node being created in any circumstances. (This -// list is almost certainly very incomplete) -const elements_without_text = new Set([ - 'audio', - 'datalist', - 'dl', - 'optgroup', - 'select', - 'video', -]); - -// TODO this should probably be in Fragment -function should_skip(node: Text) { - if (/\S/.test(node.data)) return false; - - const parent_element = node.find_nearest(/(?:Element|InlineComponent|Head)/); - if (!parent_element) return false; - - if (parent_element.type === 'Head') return true; - if (parent_element.type === 'InlineComponent') return parent_element.children.length === 1 && node === parent_element.children[0]; - - // svg namespace exclusions - if (/svg$/.test(parent_element.namespace)) { - if (node.prev && node.prev.type === "Element" && node.prev.name === "tspan") return false; - } - - return parent_element.namespace || elements_without_text.has(parent_element.name); -} - export default class TextWrapper extends Wrapper { node: Text; data: string; @@ -50,7 +20,7 @@ export default class TextWrapper extends Wrapper { ) { super(renderer, block, parent, node); - this.skip = should_skip(this.node); + this.skip = this.node.should_skip(); this.data = data; this.var = (this.skip ? null : x`t`) as unknown as Identifier; } diff --git a/src/compiler/compile/render_ssr/handlers/Element.ts b/src/compiler/compile/render_ssr/handlers/Element.ts index 6e6a61974a29..ad5c421bc421 100644 --- a/src/compiler/compile/render_ssr/handlers/Element.ts +++ b/src/compiler/compile/render_ssr/handlers/Element.ts @@ -6,10 +6,14 @@ import Renderer, { RenderOptions } from '../Renderer'; import Element from '../../nodes/Element'; import { x } from 'code-red'; import Expression from '../../nodes/shared/Expression'; +import remove_whitespace_children from './utils/remove_whitespace_children'; export default function(node: Element, renderer: Renderer, options: RenderOptions & { slot_scopes: Map; }) { + + const children = remove_whitespace_children(node.children, node.next); + // awkward special case let node_contents; @@ -133,7 +137,7 @@ export default function(node: Element, renderer: Renderer, options: RenderOption if (node_contents !== undefined) { if (contenteditable) { renderer.push(); - renderer.render(node.children, options); + renderer.render(children, options); const result = renderer.pop(); renderer.add_expression(x`($$value => $$value === void 0 ? ${result} : $$value)(${node_contents})`); @@ -145,7 +149,7 @@ export default function(node: Element, renderer: Renderer, options: RenderOption renderer.add_string(``); } } else if (slot && nearest_inline_component) { - renderer.render(node.children, options); + renderer.render(children, options); if (!is_void(node.name)) { renderer.add_string(``); @@ -163,10 +167,11 @@ export default function(node: Element, renderer: Renderer, options: RenderOption output: renderer.pop() }); } else { - renderer.render(node.children, options); + renderer.render(children, options); if (!is_void(node.name)) { renderer.add_string(``); } } } + diff --git a/src/compiler/compile/render_ssr/handlers/InlineComponent.ts b/src/compiler/compile/render_ssr/handlers/InlineComponent.ts index 5c4d9c73b8a8..37f05a941c42 100644 --- a/src/compiler/compile/render_ssr/handlers/InlineComponent.ts +++ b/src/compiler/compile/render_ssr/handlers/InlineComponent.ts @@ -2,6 +2,7 @@ import { string_literal } from '../../utils/stringify'; import Renderer, { RenderOptions } from '../Renderer'; import { get_slot_scope } from './shared/get_slot_scope'; import InlineComponent from '../../nodes/InlineComponent'; +import remove_whitespace_children from './utils/remove_whitespace_children'; import { p, x } from 'code-red'; function get_prop_value(attribute) { @@ -67,12 +68,14 @@ export default function(node: InlineComponent, renderer: Renderer, options: Rend const slot_fns = []; - if (node.children.length) { + const children = remove_whitespace_children(node.children, node.next); + + if (children.length) { const slot_scopes = new Map(); renderer.push(); - renderer.render(node.children, Object.assign({}, options, { + renderer.render(children, Object.assign({}, options, { slot_scopes })); @@ -82,9 +85,11 @@ export default function(node: InlineComponent, renderer: Renderer, options: Rend }); slot_scopes.forEach(({ input, output }, name) => { - slot_fns.push( - p`${name}: (${input}) => ${output}` - ); + if (!is_empty_template_literal(output)) { + slot_fns.push( + p`${name}: (${input}) => ${output}` + ); + } }); } @@ -94,3 +99,11 @@ export default function(node: InlineComponent, renderer: Renderer, options: Rend renderer.add_expression(x`@validate_component(${expression}, "${node.name}").$$render($$result, ${props}, ${bindings}, ${slots})`); } + +function is_empty_template_literal(template_literal) { + return ( + template_literal.expressions.length === 0 && + template_literal.quasis.length === 1 && + template_literal.quasis[0].value.raw === "" + ); +} \ No newline at end of file diff --git a/src/compiler/compile/render_ssr/handlers/utils/remove_whitespace_children.ts b/src/compiler/compile/render_ssr/handlers/utils/remove_whitespace_children.ts new file mode 100644 index 000000000000..b6c1bf493a76 --- /dev/null +++ b/src/compiler/compile/render_ssr/handlers/utils/remove_whitespace_children.ts @@ -0,0 +1,73 @@ +import { INode } from '../../../nodes/interfaces'; +import { trim_end, trim_start } from '../../../../utils/trim'; +import { link } from '../../../../utils/link'; + +// similar logic from `compile/render_dom/wrappers/Fragment` +// We want to remove trailing whitespace inside an element/component/block, +// *unless* there is no whitespace between this node and its next sibling +export default function remove_whitespace_children(children: INode[], next?: INode): INode[] { + const nodes: INode[] = []; + let last_child: INode; + let i = children.length; + while (i--) { + const child = children[i]; + + if (child.type === 'Text') { + if (child.should_skip()) { + continue; + } + + let { data } = child; + + if (nodes.length === 0) { + const should_trim = next + ? next.type === 'Text' && + /^\s/.test(next.data) && + trimmable_at(child, next) + : !child.has_ancestor('EachBlock'); + + if (should_trim) { + data = trim_end(data); + if (!data) continue; + } + } + + // glue text nodes (which could e.g. be separated by comments) together + if (last_child && last_child.type === 'Text') { + last_child.data = data + last_child.data; + continue; + } + + nodes.unshift(child); + link(last_child, last_child = child); + } else { + nodes.unshift(child); + link(last_child, last_child = child); + } + } + + const first = nodes[0]; + if (first && first.type === 'Text') { + first.data = trim_start(first.data); + if (!first.data) { + first.var = null; + nodes.shift(); + + if (nodes[0]) { + nodes[0].prev = null; + } + } + } + + return nodes; +} + +function trimmable_at(child: INode, next_sibling: INode): boolean { + // Whitespace is trimmable if one of the following is true: + // The child and its sibling share a common nearest each block (not at an each block boundary) + // The next sibling's previous node is an each block + return ( + next_sibling.find_nearest(/EachBlock/) === + child.find_nearest(/EachBlock/) || next_sibling.prev.type === 'EachBlock' + ); +} diff --git a/src/compiler/utils/link.ts b/src/compiler/utils/link.ts new file mode 100644 index 000000000000..7cdef75d94a0 --- /dev/null +++ b/src/compiler/utils/link.ts @@ -0,0 +1,4 @@ +export function link(next: T, prev: T) { + prev.next = next; + if (next) next.prev = prev; +} diff --git a/test/runtime/samples/component-slot-fallback-empty/Nested.svelte b/test/runtime/samples/component-slot-fallback-empty/Nested.svelte new file mode 100644 index 000000000000..9e6683feb77a --- /dev/null +++ b/test/runtime/samples/component-slot-fallback-empty/Nested.svelte @@ -0,0 +1,4 @@ +
+

default fallback content

+ bar fallback +
\ No newline at end of file diff --git a/test/runtime/samples/component-slot-fallback-empty/_config.js b/test/runtime/samples/component-slot-fallback-empty/_config.js new file mode 100644 index 000000000000..2e153d24db01 --- /dev/null +++ b/test/runtime/samples/component-slot-fallback-empty/_config.js @@ -0,0 +1,13 @@ +export default { + html: ` +
+

default fallback content

+ +
+ +
+

default fallback content

+ bar fallback +
+ ` +}; diff --git a/test/runtime/samples/component-slot-fallback-empty/main.svelte b/test/runtime/samples/component-slot-fallback-empty/main.svelte new file mode 100644 index 000000000000..7ae5f4c5d778 --- /dev/null +++ b/test/runtime/samples/component-slot-fallback-empty/main.svelte @@ -0,0 +1,10 @@ + + + + + + + + From f2ee7efb942d68e22881fb042ff6870473c2d82e Mon Sep 17 00:00:00 2001 From: Conduitry Date: Wed, 4 Mar 2020 19:56:13 -0500 Subject: [PATCH 032/158] add dev runtime warning for unknown slot names (#4501) --- CHANGELOG.md | 1 + src/compiler/compile/render_dom/Block.ts | 3 +-- src/compiler/compile/render_dom/index.ts | 5 +++-- src/runtime/internal/dev.ts | 7 +++++++ test/js/samples/capture-inject-state/expected.js | 4 ++++ test/js/samples/debug-empty/expected.js | 6 +++++- test/js/samples/debug-foo-bar-baz-things/expected.js | 6 +++++- test/js/samples/debug-foo/expected.js | 6 +++++- test/js/samples/debug-hoisted/expected.js | 5 ++++- test/js/samples/debug-no-dependencies/expected.js | 5 ++++- .../dev-warning-missing-data-computed/expected.js | 6 +++++- test/js/samples/loop-protect/expected.js | 8 ++++++-- .../runtime/samples/component-slot-warning/Nested.svelte | 1 + test/runtime/samples/component-slot-warning/_config.js | 9 +++++++++ test/runtime/samples/component-slot-warning/main.svelte | 7 +++++++ 15 files changed, 67 insertions(+), 12 deletions(-) create mode 100644 test/runtime/samples/component-slot-warning/Nested.svelte create mode 100644 test/runtime/samples/component-slot-warning/_config.js create mode 100644 test/runtime/samples/component-slot-warning/main.svelte diff --git a/CHANGELOG.md b/CHANGELOG.md index b0672d790ea4..f39308e5ffa3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased +* In `dev` mode, display a runtime warning when a component is passed an unexpected slot ([#1020](https://github.com/sveltejs/svelte/issues/1020), [#1447](https://github.com/sveltejs/svelte/issues/1447)) * In `vars` array, correctly indicate whether `module` variables are `mutated` or `reassigned` ([#3215](https://github.com/sveltejs/svelte/issues/3215)) * Fix spread props not updating in certain situations ([#3521](https://github.com/sveltejs/svelte/issues/3521), [#4480](https://github.com/sveltejs/svelte/issues/4480)) * Use the fallback content for slots if they are passed only whitespace ([#4092](https://github.com/sveltejs/svelte/issues/4092)) diff --git a/src/compiler/compile/render_dom/Block.ts b/src/compiler/compile/render_dom/Block.ts index 62bdc5bdd9af..2da77d3fbf52 100644 --- a/src/compiler/compile/render_dom/Block.ts +++ b/src/compiler/compile/render_dom/Block.ts @@ -412,8 +412,7 @@ export default class Block { } has_content() { - return this.renderer.options.dev || - this.first || + return this.first || this.event_listeners.length > 0 || this.chunks.intro.length > 0 || this.chunks.outro.length > 0 || diff --git a/src/compiler/compile/render_dom/index.ts b/src/compiler/compile/render_dom/index.ts index d6da6142768c..fc3c94a2be19 100644 --- a/src/compiler/compile/render_dom/index.ts +++ b/src/compiler/compile/render_dom/index.ts @@ -264,7 +264,7 @@ export default function dom( args.push(x`$$props`); } - const has_create_fragment = block.has_content(); + const has_create_fragment = component.compile_options.dev || block.has_content(); if (has_create_fragment) { body.push(b` function create_fragment(#ctx) { @@ -412,7 +412,8 @@ export default function dom( ${unknown_props_check} - ${component.slots.size ? b`let { $$slots = {}, $$scope } = $$props;` : null} + ${component.slots.size || component.compile_options.dev ? b`let { $$slots = {}, $$scope } = $$props;` : null} + ${component.compile_options.dev && b`@validate_slots('${component.tag}', $$slots, [${[...component.slots.keys()].map(key => `'${key}'`).join(',')}]);`} ${renderer.binding_groups.length > 0 && b`const $$binding_groups = [${renderer.binding_groups.map(_ => x`[]`)}];`} diff --git a/src/runtime/internal/dev.ts b/src/runtime/internal/dev.ts index 8aefc88ba7b0..751f1f802bc0 100644 --- a/src/runtime/internal/dev.ts +++ b/src/runtime/internal/dev.ts @@ -89,6 +89,13 @@ export function validate_each_argument(arg) { } } +export function validate_slots(name, slot, keys) { + for (const slot_key of Object.keys(slot)) { + if (!~keys.indexOf(slot_key)) { + console.warn(`<${name}> received an unexpected slot "${slot_key}".`); + } + } +} type Props = Record; export interface SvelteComponentDev { diff --git a/test/js/samples/capture-inject-state/expected.js b/test/js/samples/capture-inject-state/expected.js index 859314556580..cd719ac5d25f 100644 --- a/test/js/samples/capture-inject-state/expected.js +++ b/test/js/samples/capture-inject-state/expected.js @@ -14,6 +14,7 @@ import { space, subscribe, text, + validate_slots, validate_store } from "svelte/internal"; @@ -114,6 +115,9 @@ function instance($$self, $$props, $$invalidate) { if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(` was created with unknown prop '${key}'`); }); + let { $$slots = {}, $$scope } = $$props; + validate_slots("Component", $$slots, []); + $$self.$set = $$props => { if ("prop" in $$props) $$subscribe_prop($$invalidate(0, prop = $$props.prop)); if ("alias" in $$props) $$invalidate(1, realName = $$props.alias); diff --git a/test/js/samples/debug-empty/expected.js b/test/js/samples/debug-empty/expected.js index 87d78bd69821..dd142adb26b2 100644 --- a/test/js/samples/debug-empty/expected.js +++ b/test/js/samples/debug-empty/expected.js @@ -12,7 +12,8 @@ import { safe_not_equal, set_data_dev, space, - text + text, + validate_slots } from "svelte/internal"; const file = undefined; @@ -75,6 +76,9 @@ function instance($$self, $$props, $$invalidate) { if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(` was created with unknown prop '${key}'`); }); + let { $$slots = {}, $$scope } = $$props; + validate_slots("Component", $$slots, []); + $$self.$set = $$props => { if ("name" in $$props) $$invalidate(0, name = $$props.name); }; diff --git a/test/js/samples/debug-foo-bar-baz-things/expected.js b/test/js/samples/debug-foo-bar-baz-things/expected.js index 589c4a783288..977702b99f5c 100644 --- a/test/js/samples/debug-foo-bar-baz-things/expected.js +++ b/test/js/samples/debug-foo-bar-baz-things/expected.js @@ -14,7 +14,8 @@ import { set_data_dev, space, text, - validate_each_argument + validate_each_argument, + validate_slots } from "svelte/internal"; const file = undefined; @@ -179,6 +180,9 @@ function instance($$self, $$props, $$invalidate) { if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(` was created with unknown prop '${key}'`); }); + let { $$slots = {}, $$scope } = $$props; + validate_slots("Component", $$slots, []); + $$self.$set = $$props => { if ("things" in $$props) $$invalidate(0, things = $$props.things); if ("foo" in $$props) $$invalidate(1, foo = $$props.foo); diff --git a/test/js/samples/debug-foo/expected.js b/test/js/samples/debug-foo/expected.js index 10129e1b2837..fe62ff77bfb1 100644 --- a/test/js/samples/debug-foo/expected.js +++ b/test/js/samples/debug-foo/expected.js @@ -14,7 +14,8 @@ import { set_data_dev, space, text, - validate_each_argument + validate_each_argument, + validate_slots } from "svelte/internal"; const file = undefined; @@ -171,6 +172,9 @@ function instance($$self, $$props, $$invalidate) { if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(` was created with unknown prop '${key}'`); }); + let { $$slots = {}, $$scope } = $$props; + validate_slots("Component", $$slots, []); + $$self.$set = $$props => { if ("things" in $$props) $$invalidate(0, things = $$props.things); if ("foo" in $$props) $$invalidate(1, foo = $$props.foo); diff --git a/test/js/samples/debug-hoisted/expected.js b/test/js/samples/debug-hoisted/expected.js index 190ff12c50ee..0e634297f08f 100644 --- a/test/js/samples/debug-hoisted/expected.js +++ b/test/js/samples/debug-hoisted/expected.js @@ -4,7 +4,8 @@ import { dispatch_dev, init, noop, - safe_not_equal + safe_not_equal, + validate_slots } from "svelte/internal"; const file = undefined; @@ -56,6 +57,8 @@ function instance($$self, $$props, $$invalidate) { if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(` was created with unknown prop '${key}'`); }); + let { $$slots = {}, $$scope } = $$props; + validate_slots("Component", $$slots, []); $$self.$capture_state = () => ({ obj, kobzol }); $$self.$inject_state = $$props => { diff --git a/test/js/samples/debug-no-dependencies/expected.js b/test/js/samples/debug-no-dependencies/expected.js index a097869e747b..76068e8cf464 100644 --- a/test/js/samples/debug-no-dependencies/expected.js +++ b/test/js/samples/debug-no-dependencies/expected.js @@ -11,7 +11,8 @@ import { safe_not_equal, space, text, - validate_each_argument + validate_each_argument, + validate_slots } from "svelte/internal"; const file = undefined; @@ -141,6 +142,8 @@ function instance($$self, $$props) { if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(` was created with unknown prop '${key}'`); }); + let { $$slots = {}, $$scope } = $$props; + validate_slots("Component", $$slots, []); return []; } diff --git a/test/js/samples/dev-warning-missing-data-computed/expected.js b/test/js/samples/dev-warning-missing-data-computed/expected.js index 9c28e0406450..0a50e2cd970a 100644 --- a/test/js/samples/dev-warning-missing-data-computed/expected.js +++ b/test/js/samples/dev-warning-missing-data-computed/expected.js @@ -12,7 +12,8 @@ import { safe_not_equal, set_data_dev, space, - text + text, + validate_slots } from "svelte/internal"; const file = undefined; @@ -72,6 +73,9 @@ function instance($$self, $$props, $$invalidate) { if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console.warn(` was created with unknown prop '${key}'`); }); + let { $$slots = {}, $$scope } = $$props; + validate_slots("Component", $$slots, []); + $$self.$set = $$props => { if ("foo" in $$props) $$invalidate(0, foo = $$props.foo); }; diff --git a/test/js/samples/loop-protect/expected.js b/test/js/samples/loop-protect/expected.js index f433bd61a962..c52d9df437e5 100644 --- a/test/js/samples/loop-protect/expected.js +++ b/test/js/samples/loop-protect/expected.js @@ -11,7 +11,8 @@ import { insert_dev, loop_guard, noop, - safe_not_equal + safe_not_equal, + validate_slots } from "svelte/internal"; const { console: console_1 } = globals; @@ -110,6 +111,9 @@ function instance($$self, $$props, $$invalidate) { if (!~writable_props.indexOf(key) && key.slice(0, 2) !== "$$") console_1.warn(` was created with unknown prop '${key}'`); }); + let { $$slots = {}, $$scope } = $$props; + validate_slots("Component", $$slots, []); + function div_binding($$value) { binding_callbacks[$$value ? "unshift" : "push"](() => { $$invalidate(0, node = $$value); @@ -161,4 +165,4 @@ class Component extends SvelteComponentDev { } } -export default Component; +export default Component; \ No newline at end of file diff --git a/test/runtime/samples/component-slot-warning/Nested.svelte b/test/runtime/samples/component-slot-warning/Nested.svelte new file mode 100644 index 000000000000..c6f086d96c19 --- /dev/null +++ b/test/runtime/samples/component-slot-warning/Nested.svelte @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/runtime/samples/component-slot-warning/_config.js b/test/runtime/samples/component-slot-warning/_config.js new file mode 100644 index 000000000000..6ffe624782e0 --- /dev/null +++ b/test/runtime/samples/component-slot-warning/_config.js @@ -0,0 +1,9 @@ +export default { + compileOptions: { + dev: true + }, + warnings: [ + ' received an unexpected slot "default".', + ' received an unexpected slot "slot1".' + ] +}; diff --git a/test/runtime/samples/component-slot-warning/main.svelte b/test/runtime/samples/component-slot-warning/main.svelte new file mode 100644 index 000000000000..c29ef3e85be2 --- /dev/null +++ b/test/runtime/samples/component-slot-warning/main.svelte @@ -0,0 +1,7 @@ + + + + + From a8291227ce6ebf959749ae5d6f86b017a140d4af Mon Sep 17 00:00:00 2001 From: Conduitry Date: Wed, 4 Mar 2020 20:28:19 -0500 Subject: [PATCH 033/158] fit bitmask overflow initial dirty value in 'if' blocks (#4507) --- CHANGELOG.md | 1 + src/compiler/compile/render_dom/Renderer.ts | 1 + .../compile/render_dom/wrappers/IfBlock.ts | 20 +++++- .../wrappers/shared/get_slot_definition.ts | 2 +- .../samples/bitmask-overflow-if/_config.js | 24 +++++++ .../samples/bitmask-overflow-if/main.svelte | 62 +++++++++++++++++++ 6 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 test/runtime/samples/bitmask-overflow-if/_config.js create mode 100644 test/runtime/samples/bitmask-overflow-if/main.svelte diff --git a/CHANGELOG.md b/CHANGELOG.md index f39308e5ffa3..e58b9b6e0679 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * In `vars` array, correctly indicate whether `module` variables are `mutated` or `reassigned` ([#3215](https://github.com/sveltejs/svelte/issues/3215)) * Fix spread props not updating in certain situations ([#3521](https://github.com/sveltejs/svelte/issues/3521), [#4480](https://github.com/sveltejs/svelte/issues/4480)) * Use the fallback content for slots if they are passed only whitespace ([#4092](https://github.com/sveltejs/svelte/issues/4092)) +* Fix bitmask overflow for `{#if}` blocks ([#4263](https://github.com/sveltejs/svelte/issues/4263)) * In `dev` mode, check for unknown props even if the component has no writable props ([#4323](https://github.com/sveltejs/svelte/issues/4323)) * Exclude global variables from `$capture_state` ([#4463](https://github.com/sveltejs/svelte/issues/4463)) * Fix bitmask overflow for slots ([#4481](https://github.com/sveltejs/svelte/issues/4481)) diff --git a/src/compiler/compile/render_dom/Renderer.ts b/src/compiler/compile/render_dom/Renderer.ts index fbb0c76d7d5d..25012792143e 100644 --- a/src/compiler/compile/render_dom/Renderer.ts +++ b/src/compiler/compile/render_dom/Renderer.ts @@ -230,6 +230,7 @@ export default class Renderer { return bitmask; }; + // TODO: context-overflow make it less gross return { // Using a ParenthesizedExpression allows us to create // the expression lazily. TODO would be better if diff --git a/src/compiler/compile/render_dom/wrappers/IfBlock.ts b/src/compiler/compile/render_dom/wrappers/IfBlock.ts index dfc2228bc5e7..0506c943f92f 100644 --- a/src/compiler/compile/render_dom/wrappers/IfBlock.ts +++ b/src/compiler/compile/render_dom/wrappers/IfBlock.ts @@ -288,7 +288,7 @@ export default class IfBlockWrapper extends Wrapper { } block.chunks.init.push(b` - let ${current_block_type} = ${select_block_type}(#ctx, -1); + let ${current_block_type} = ${select_block_type}(#ctx, ${this.get_initial_dirty_bit()}); let ${name} = ${get_block}; `); @@ -407,12 +407,12 @@ export default class IfBlockWrapper extends Wrapper { if (has_else) { block.chunks.init.push(b` - ${current_block_type_index} = ${select_block_type}(#ctx, -1); + ${current_block_type_index} = ${select_block_type}(#ctx, ${this.get_initial_dirty_bit()}); ${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#ctx); `); } else { block.chunks.init.push(b` - if (~(${current_block_type_index} = ${select_block_type}(#ctx, -1))) { + if (~(${current_block_type_index} = ${select_block_type}(#ctx, ${this.get_initial_dirty_bit()}))) { ${name} = ${if_blocks}[${current_block_type_index}] = ${if_block_creators}[${current_block_type_index}](#ctx); } `); @@ -587,4 +587,18 @@ export default class IfBlockWrapper extends Wrapper { `); } } + + get_initial_dirty_bit() { + const _this = this; + // TODO: context-overflow make it less gross + + const val = x`-1`; + return { + ...val, + elements: [val], + get type() { + return _this.renderer.context_overflow ? 'ArrayExpression' : 'UnaryExpression'; + }, + }; + } } diff --git a/src/compiler/compile/render_dom/wrappers/shared/get_slot_definition.ts b/src/compiler/compile/render_dom/wrappers/shared/get_slot_definition.ts index 9ab48dd035e8..0f28689df312 100644 --- a/src/compiler/compile/render_dom/wrappers/shared/get_slot_definition.ts +++ b/src/compiler/compile/render_dom/wrappers/shared/get_slot_definition.ts @@ -63,7 +63,7 @@ export function get_slot_definition(block: Block, scope: TemplateScope, lets: Le const { context_lookup } = block.renderer; // i am well aware that this code is gross - // TODO make it less gross + // TODO: context-overflow make it less gross const changes = { type: 'ParenthesizedExpression', get expression() { diff --git a/test/runtime/samples/bitmask-overflow-if/_config.js b/test/runtime/samples/bitmask-overflow-if/_config.js new file mode 100644 index 000000000000..74bc70d4144f --- /dev/null +++ b/test/runtime/samples/bitmask-overflow-if/_config.js @@ -0,0 +1,24 @@ +export default { + html: ` + 012345678910111213141516171819202122232425262728293031323334353637383940 + expected: true + if: true + + `, + + async test({ assert, component, target, window }) { + const button = target.querySelector("button"); + await button.dispatchEvent(new window.MouseEvent("click")); + + assert.htmlEqual( + target.innerHTML, + ` + 112345678910111213141516171819202122232425262728293031323334353637383940 + expected: false + if: false +
+ + ` + ); + } +}; diff --git a/test/runtime/samples/bitmask-overflow-if/main.svelte b/test/runtime/samples/bitmask-overflow-if/main.svelte new file mode 100644 index 000000000000..2c1c4530914f --- /dev/null +++ b/test/runtime/samples/bitmask-overflow-if/main.svelte @@ -0,0 +1,62 @@ + + + +{_0}{_1}{_2}{_3}{_4}{_5}{_6}{_7}{_8}{_9}{_10}{_11}{_12}{_13}{_14}{_15}{_16}{_17}{_18}{_19}{_20}{_21}{_22}{_23}{_24}{_25}{_26}{_27}{_28}{_29}{_30}{_31}{_32}{_33}{_34}{_35}{_36}{_37}{_38}{_39}{_40} + +expected: {_a.indexOf(_0) && _0 === '0' && _1 === '1'} +{#if _a.indexOf(_0) && _0 === '0' && _1 === '1'} +if: true +{:else} +if: false +
+{/if} + + \ No newline at end of file From 345d5f27ee2ed5fdd3f0bf2bea84c9f0f57b038e Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Thu, 5 Mar 2020 10:12:30 +0800 Subject: [PATCH 034/158] fix lazy code breaks in build --- src/compiler/compile/render_dom/wrappers/IfBlock.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/compiler/compile/render_dom/wrappers/IfBlock.ts b/src/compiler/compile/render_dom/wrappers/IfBlock.ts index 0506c943f92f..207e1e349ed2 100644 --- a/src/compiler/compile/render_dom/wrappers/IfBlock.ts +++ b/src/compiler/compile/render_dom/wrappers/IfBlock.ts @@ -9,7 +9,7 @@ import FragmentWrapper from './Fragment'; import { b, x } from 'code-red'; import { walk } from 'estree-walker'; import { is_head } from './shared/is_head'; -import { Identifier, Node } from 'estree'; +import { Identifier, Node, UnaryExpression } from 'estree'; function is_else_if(node: ElseBlock) { return ( @@ -591,14 +591,17 @@ export default class IfBlockWrapper extends Wrapper { get_initial_dirty_bit() { const _this = this; // TODO: context-overflow make it less gross - - const val = x`-1`; + const val: UnaryExpression = x`-1` as UnaryExpression; return { - ...val, - elements: [val], get type() { return _this.renderer.context_overflow ? 'ArrayExpression' : 'UnaryExpression'; }, + // as [-1] + elements: [val], + // as -1 + operator: val.operator, + prefix: val.prefix, + argument: val.argument, }; } } From fd378f2d37463a1b9f3aba03a08c6693dea98d78 Mon Sep 17 00:00:00 2001 From: Conduitry Date: Wed, 4 Mar 2020 21:31:38 -0500 Subject: [PATCH 035/158] -> v3.19.2 --- CHANGELOG.md | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e58b9b6e0679..f1564848b561 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Svelte changelog -## Unreleased +## 3.19.2 * In `dev` mode, display a runtime warning when a component is passed an unexpected slot ([#1020](https://github.com/sveltejs/svelte/issues/1020), [#1447](https://github.com/sveltejs/svelte/issues/1447)) * In `vars` array, correctly indicate whether `module` variables are `mutated` or `reassigned` ([#3215](https://github.com/sveltejs/svelte/issues/3215)) diff --git a/package-lock.json b/package-lock.json index f0f4e1742246..014348f37eef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.19.1", + "version": "3.19.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 7a02f1da108e..009e5143a925 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.19.1", + "version": "3.19.2", "description": "Cybernetically enhanced web apps", "module": "index.mjs", "main": "index", From 48721520bdb9fa28f19e6940c67fd6e1f6396813 Mon Sep 17 00:00:00 2001 From: keke Date: Sun, 8 Mar 2020 21:36:11 +0800 Subject: [PATCH 036/158] docs: fix self-closing tag (#4524) --- site/content/docs/03-run-time.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/content/docs/03-run-time.md b/site/content/docs/03-run-time.md index c75ec694d932..0bbae2418574 100644 --- a/site/content/docs/03-run-time.md +++ b/site/content/docs/03-run-time.md @@ -974,7 +974,7 @@ app.count += 1; Svelte components can also be compiled to custom elements (aka web components) using the `customElement: true` compiler option. You should specify a tag name for the component using the `` [element](docs#svelte_options). ```html - + +
Length: {length}
+
Values: {values.join(',')}
+ +
\ No newline at end of file diff --git a/test/runtime/samples/$$rest-without-props/_config.js b/test/runtime/samples/$$rest-without-props/_config.js new file mode 100644 index 000000000000..017f9df5611a --- /dev/null +++ b/test/runtime/samples/$$rest-without-props/_config.js @@ -0,0 +1,54 @@ +export default { + props: { + a: 3, + b: 4, + c: 5, + d: 6 + }, + html: ` +
Length: 3
+
Values: 4,5,1
+
+ + `, + async test({ assert, target, window, }) { + const [btn1, btn2, btn3, btn4] = target.querySelectorAll('button'); + const clickEvent = new window.MouseEvent('click'); + + await btn1.dispatchEvent(clickEvent); + + assert.htmlEqual(target.innerHTML, ` +
Length: 3
+
Values: 4,5,1
+
+ + `); + + await btn2.dispatchEvent(clickEvent); + + assert.htmlEqual(target.innerHTML, ` +
Length: 3
+
Values: 34,5,1
+
+ + `); + + await btn3.dispatchEvent(clickEvent); + + assert.htmlEqual(target.innerHTML, ` +
Length: 3
+
Values: 34,5,31
+
+ + `); + + await btn4.dispatchEvent(clickEvent); + + assert.htmlEqual(target.innerHTML, ` +
Length: 4
+
Values: 34,5,31,2
+
+ + `); + } +}; diff --git a/test/runtime/samples/$$rest-without-props/main.svelte b/test/runtime/samples/$$rest-without-props/main.svelte new file mode 100644 index 000000000000..21b2690584ef --- /dev/null +++ b/test/runtime/samples/$$rest-without-props/main.svelte @@ -0,0 +1,25 @@ + + + + + + + \ No newline at end of file diff --git a/test/runtime/samples/$$rest/App.svelte b/test/runtime/samples/$$rest/App.svelte new file mode 100644 index 000000000000..875372f67050 --- /dev/null +++ b/test/runtime/samples/$$rest/App.svelte @@ -0,0 +1,13 @@ + +
Length: {length}
+
Values: {values.join(',')}
+ +
+
\ No newline at end of file diff --git a/test/runtime/samples/$$rest/_config.js b/test/runtime/samples/$$rest/_config.js new file mode 100644 index 000000000000..255927f354b3 --- /dev/null +++ b/test/runtime/samples/$$rest/_config.js @@ -0,0 +1,60 @@ +export default { + props: { + a: 3, + b: 4, + c: 5, + d: 6 + }, + html: ` +
Length: 3
+
Values: 4,5,1
+
+
+ + `, + + async test({ assert, target, window, }) { + const [btn1, btn2, btn3, btn4] = target.querySelectorAll('button'); + const clickEvent = new window.MouseEvent('click'); + + await btn1.dispatchEvent(clickEvent); + + assert.htmlEqual(target.innerHTML, ` +
Length: 3
+
Values: 4,5,1
+
+
+ + `); + + await btn2.dispatchEvent(clickEvent); + + assert.htmlEqual(target.innerHTML, ` +
Length: 3
+
Values: 34,5,1
+
+
+ + `); + + await btn3.dispatchEvent(clickEvent); + + assert.htmlEqual(target.innerHTML, ` +
Length: 3
+
Values: 34,5,31
+
+
+ + `); + + await btn4.dispatchEvent(clickEvent); + + assert.htmlEqual(target.innerHTML, ` +
Length: 4
+
Values: 34,5,31,2
+
+
+ + `); + } +}; diff --git a/test/runtime/samples/$$rest/main.svelte b/test/runtime/samples/$$rest/main.svelte new file mode 100644 index 000000000000..21b2690584ef --- /dev/null +++ b/test/runtime/samples/$$rest/main.svelte @@ -0,0 +1,25 @@ + + + + + + + \ No newline at end of file diff --git a/test/runtime/samples/dev-warning-unknown-props-with-$$props/Foo.svelte b/test/runtime/samples/dev-warning-unknown-props-with-$$props/Foo.svelte index 9e5c62339d98..375b1a6a0a0b 100644 --- a/test/runtime/samples/dev-warning-unknown-props-with-$$props/Foo.svelte +++ b/test/runtime/samples/dev-warning-unknown-props-with-$$props/Foo.svelte @@ -4,4 +4,4 @@
{foo}
-
{JSON.stringify($$props)}
+
{JSON.stringify($$restProps)}
diff --git a/test/runtime/samples/dev-warning-unknown-props-with-$$rest/Foo.svelte b/test/runtime/samples/dev-warning-unknown-props-with-$$rest/Foo.svelte new file mode 100644 index 000000000000..9e5c62339d98 --- /dev/null +++ b/test/runtime/samples/dev-warning-unknown-props-with-$$rest/Foo.svelte @@ -0,0 +1,7 @@ + + +
{foo}
+
{JSON.stringify($$props)}
diff --git a/test/runtime/samples/dev-warning-unknown-props-with-$$rest/_config.js b/test/runtime/samples/dev-warning-unknown-props-with-$$rest/_config.js new file mode 100644 index 000000000000..62ad08624d9d --- /dev/null +++ b/test/runtime/samples/dev-warning-unknown-props-with-$$rest/_config.js @@ -0,0 +1,7 @@ +export default { + compileOptions: { + dev: true + }, + + warnings: [] +}; diff --git a/test/runtime/samples/dev-warning-unknown-props-with-$$rest/main.svelte b/test/runtime/samples/dev-warning-unknown-props-with-$$rest/main.svelte new file mode 100644 index 000000000000..1566cf3e41e7 --- /dev/null +++ b/test/runtime/samples/dev-warning-unknown-props-with-$$rest/main.svelte @@ -0,0 +1,5 @@ + + + From a66437b3c15e735139f9afb2ec25e3e1c612cd82 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Thu, 12 Mar 2020 19:51:59 +0800 Subject: [PATCH 038/158] allow to be part of a slot (#4532) --- CHANGELOG.md | 1 + src/compiler/parse/state/tag.ts | 4 ++-- test/parser/samples/error-self-reference/error.json | 2 +- .../samples/self-reference-component/Countdown.svelte | 7 +++++++ .../samples/self-reference-component/_config.js | 3 +++ .../samples/self-reference-component/main.svelte | 10 ++++++++++ 6 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 test/runtime/samples/self-reference-component/Countdown.svelte create mode 100644 test/runtime/samples/self-reference-component/_config.js create mode 100644 test/runtime/samples/self-reference-component/main.svelte diff --git a/CHANGELOG.md b/CHANGELOG.md index 7848af35be72..451fc58ca628 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased +* Allow `` to be used in a slot ([#2798](https://github.com/sveltejs/svelte/issues/2798)) * Expose object of unknown props in `$$restProps` ([#2930](https://github.com/sveltejs/svelte/issues/2930)) ## 3.19.2 diff --git a/src/compiler/parse/state/tag.ts b/src/compiler/parse/state/tag.ts index 40bb01de9bee..ce8a0a9aa727 100644 --- a/src/compiler/parse/state/tag.ts +++ b/src/compiler/parse/state/tag.ts @@ -241,7 +241,7 @@ function read_tag_name(parser: Parser) { while (i--) { const fragment = parser.stack[i]; - if (fragment.type === 'IfBlock' || fragment.type === 'EachBlock') { + if (fragment.type === 'IfBlock' || fragment.type === 'EachBlock' || fragment.type === 'InlineComponent') { legal = true; break; } @@ -250,7 +250,7 @@ function read_tag_name(parser: Parser) { if (!legal) { parser.error({ code: `invalid-self-placement`, - message: ` components can only exist inside if-blocks or each-blocks` + message: ` components can only exist inside {#if} blocks, {#each} blocks, or slots passed to components` }, start); } diff --git a/test/parser/samples/error-self-reference/error.json b/test/parser/samples/error-self-reference/error.json index 798b5cb30099..31ecab2b1258 100644 --- a/test/parser/samples/error-self-reference/error.json +++ b/test/parser/samples/error-self-reference/error.json @@ -1,6 +1,6 @@ { "code": "invalid-self-placement", - "message": " components can only exist inside if-blocks or each-blocks", + "message": " components can only exist inside {#if} blocks, {#each} blocks, or slots passed to components", "start": { "line": 1, "column": 1, diff --git a/test/runtime/samples/self-reference-component/Countdown.svelte b/test/runtime/samples/self-reference-component/Countdown.svelte new file mode 100644 index 000000000000..21178f25676a --- /dev/null +++ b/test/runtime/samples/self-reference-component/Countdown.svelte @@ -0,0 +1,7 @@ + + +{#if count > 0} + +{/if} \ No newline at end of file diff --git a/test/runtime/samples/self-reference-component/_config.js b/test/runtime/samples/self-reference-component/_config.js new file mode 100644 index 000000000000..e3e0ad3a4f2a --- /dev/null +++ b/test/runtime/samples/self-reference-component/_config.js @@ -0,0 +1,3 @@ +export default { + html: '5 4 3 2 1 0', +}; \ No newline at end of file diff --git a/test/runtime/samples/self-reference-component/main.svelte b/test/runtime/samples/self-reference-component/main.svelte new file mode 100644 index 000000000000..fd28ec4e40aa --- /dev/null +++ b/test/runtime/samples/self-reference-component/main.svelte @@ -0,0 +1,10 @@ + + +{count} + + + + \ No newline at end of file From ec3589e31425c54cda3c5f6a80b89eb3aaa7bd52 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Sun, 15 Mar 2020 02:15:24 +0800 Subject: [PATCH 039/158] fix hydration of top-level content (#4550) --- CHANGELOG.md | 1 + src/runtime/internal/Component.ts | 6 ++++-- test/hydration/samples/top-level-cleanup-2/_after.html | 1 + test/hydration/samples/top-level-cleanup-2/_before.html | 2 ++ test/hydration/samples/top-level-cleanup-2/_config.js | 1 + test/hydration/samples/top-level-cleanup-2/main.svelte | 1 + test/hydration/samples/top-level-cleanup/_after.html | 1 + test/hydration/samples/top-level-cleanup/_before.html | 1 + test/hydration/samples/top-level-cleanup/_config.js | 1 + test/hydration/samples/top-level-cleanup/main.svelte | 1 + 10 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 test/hydration/samples/top-level-cleanup-2/_after.html create mode 100644 test/hydration/samples/top-level-cleanup-2/_before.html create mode 100644 test/hydration/samples/top-level-cleanup-2/_config.js create mode 100644 test/hydration/samples/top-level-cleanup-2/main.svelte create mode 100644 test/hydration/samples/top-level-cleanup/_after.html create mode 100644 test/hydration/samples/top-level-cleanup/_before.html create mode 100644 test/hydration/samples/top-level-cleanup/_config.js create mode 100644 test/hydration/samples/top-level-cleanup/main.svelte diff --git a/CHANGELOG.md b/CHANGELOG.md index 451fc58ca628..084a90029559 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Allow `` to be used in a slot ([#2798](https://github.com/sveltejs/svelte/issues/2798)) * Expose object of unknown props in `$$restProps` ([#2930](https://github.com/sveltejs/svelte/issues/2930)) +* Fix hydration of top-level content ([#4542](https://github.com/sveltejs/svelte/issues/4542)) ## 3.19.2 diff --git a/src/runtime/internal/Component.ts b/src/runtime/internal/Component.ts index 10588a08046b..7d2a92fa1bce 100644 --- a/src/runtime/internal/Component.ts +++ b/src/runtime/internal/Component.ts @@ -1,7 +1,7 @@ import { add_render_callback, flush, schedule_update, dirty_components } from './scheduler'; import { current_component, set_current_component } from './lifecycle'; import { blank_object, is_function, run, run_all, noop } from './utils'; -import { children } from './dom'; +import { children, detach } from './dom'; import { transition_in } from './transitions'; interface Fragment { @@ -146,8 +146,10 @@ export function init(component, options, instance, create_fragment, not_equal, p if (options.target) { if (options.hydrate) { + const nodes = children(options.target); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - $$.fragment && $$.fragment!.l(children(options.target)); + $$.fragment && $$.fragment!.l(nodes); + nodes.forEach(detach); } else { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion $$.fragment && $$.fragment!.c(); diff --git a/test/hydration/samples/top-level-cleanup-2/_after.html b/test/hydration/samples/top-level-cleanup-2/_after.html new file mode 100644 index 000000000000..8dca56dd88ab --- /dev/null +++ b/test/hydration/samples/top-level-cleanup-2/_after.html @@ -0,0 +1 @@ +
Hello world
\ No newline at end of file diff --git a/test/hydration/samples/top-level-cleanup-2/_before.html b/test/hydration/samples/top-level-cleanup-2/_before.html new file mode 100644 index 000000000000..fdc2379f635a --- /dev/null +++ b/test/hydration/samples/top-level-cleanup-2/_before.html @@ -0,0 +1,2 @@ +
This should be thrown away
+
hello
\ No newline at end of file diff --git a/test/hydration/samples/top-level-cleanup-2/_config.js b/test/hydration/samples/top-level-cleanup-2/_config.js new file mode 100644 index 000000000000..ff8b4c56321a --- /dev/null +++ b/test/hydration/samples/top-level-cleanup-2/_config.js @@ -0,0 +1 @@ +export default {}; diff --git a/test/hydration/samples/top-level-cleanup-2/main.svelte b/test/hydration/samples/top-level-cleanup-2/main.svelte new file mode 100644 index 000000000000..8dca56dd88ab --- /dev/null +++ b/test/hydration/samples/top-level-cleanup-2/main.svelte @@ -0,0 +1 @@ +
Hello world
\ No newline at end of file diff --git a/test/hydration/samples/top-level-cleanup/_after.html b/test/hydration/samples/top-level-cleanup/_after.html new file mode 100644 index 000000000000..8dca56dd88ab --- /dev/null +++ b/test/hydration/samples/top-level-cleanup/_after.html @@ -0,0 +1 @@ +
Hello world
\ No newline at end of file diff --git a/test/hydration/samples/top-level-cleanup/_before.html b/test/hydration/samples/top-level-cleanup/_before.html new file mode 100644 index 000000000000..c7e4bba2331a --- /dev/null +++ b/test/hydration/samples/top-level-cleanup/_before.html @@ -0,0 +1 @@ +
This should be thrown away
\ No newline at end of file diff --git a/test/hydration/samples/top-level-cleanup/_config.js b/test/hydration/samples/top-level-cleanup/_config.js new file mode 100644 index 000000000000..ff8b4c56321a --- /dev/null +++ b/test/hydration/samples/top-level-cleanup/_config.js @@ -0,0 +1 @@ +export default {}; diff --git a/test/hydration/samples/top-level-cleanup/main.svelte b/test/hydration/samples/top-level-cleanup/main.svelte new file mode 100644 index 000000000000..8dca56dd88ab --- /dev/null +++ b/test/hydration/samples/top-level-cleanup/main.svelte @@ -0,0 +1 @@ +
Hello world
\ No newline at end of file From 404ed3dbfe84e2d16c2a3658257536e194c33463 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Sun, 15 Mar 2020 02:27:39 +0800 Subject: [PATCH 040/158] fix else-block update in keyed each-block (#4558) Co-authored-by: Benjamin W. Broersma --- CHANGELOG.md | 1 + .../compile/render_dom/wrappers/EachBlock.ts | 60 +++++++++---------- .../samples/each-block-keyed-else/_config.js | 37 ++++++++++++ .../samples/each-block-keyed-else/main.svelte | 12 ++++ .../each-block-unkeyed-else-2/_config.js | 37 ++++++++++++ .../each-block-unkeyed-else-2/main.svelte | 12 ++++ 6 files changed, 129 insertions(+), 30 deletions(-) create mode 100644 test/runtime/samples/each-block-keyed-else/_config.js create mode 100644 test/runtime/samples/each-block-keyed-else/main.svelte create mode 100644 test/runtime/samples/each-block-unkeyed-else-2/_config.js create mode 100644 test/runtime/samples/each-block-unkeyed-else-2/main.svelte diff --git a/CHANGELOG.md b/CHANGELOG.md index 084a90029559..1e9024c318c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Allow `` to be used in a slot ([#2798](https://github.com/sveltejs/svelte/issues/2798)) * Expose object of unknown props in `$$restProps` ([#2930](https://github.com/sveltejs/svelte/issues/2930)) +* Fix updating keyed `{#each}` blocks with `{:else}` ([#4536](https://github.com/sveltejs/svelte/issues/4536), [#4549](https://github.com/sveltejs/svelte/issues/4549)) * Fix hydration of top-level content ([#4542](https://github.com/sveltejs/svelte/issues/4542)) ## 3.19.2 diff --git a/src/compiler/compile/render_dom/wrappers/EachBlock.ts b/src/compiler/compile/render_dom/wrappers/EachBlock.ts index f0dfa5fbcc43..43a0f754f968 100644 --- a/src/compiler/compile/render_dom/wrappers/EachBlock.ts +++ b/src/compiler/compile/render_dom/wrappers/EachBlock.ts @@ -62,6 +62,8 @@ export default class EachBlockWrapper extends Wrapper { context_props: Array; index_name: Identifier; + updates: Array = []; + dependencies: Set; var: Identifier = { type: 'Identifier', name: 'each' }; @@ -235,6 +237,12 @@ export default class EachBlockWrapper extends Wrapper { update_mount_node }; + const all_dependencies = new Set(this.block.dependencies); // TODO should be dynamic deps only + this.node.expression.dynamic_dependencies().forEach((dependency: string) => { + all_dependencies.add(dependency); + }); + this.dependencies = all_dependencies; + if (this.node.key) { this.render_keyed(args); } else { @@ -291,7 +299,7 @@ export default class EachBlockWrapper extends Wrapper { `); if (this.else.block.has_update_method) { - block.chunks.update.push(b` + this.updates.push(b` if (!${this.vars.data_length} && ${each_block_else}) { ${each_block_else}.p(#ctx, #dirty); } else if (!${this.vars.data_length}) { @@ -304,7 +312,7 @@ export default class EachBlockWrapper extends Wrapper { } `); } else { - block.chunks.update.push(b` + this.updates.push(b` if (${this.vars.data_length}) { if (${each_block_else}) { ${each_block_else}.d(1); @@ -323,6 +331,14 @@ export default class EachBlockWrapper extends Wrapper { `); } + if (this.updates.length) { + block.chunks.update.push(b` + if (${block.renderer.dirty(Array.from(all_dependencies))}) { + ${this.updates} + } + `); + } + this.fragment.render(this.block, null, x`#nodes` as Identifier); if (this.else) { @@ -415,24 +431,17 @@ export default class EachBlockWrapper extends Wrapper { ? `@outro_and_destroy_block` : `@destroy_block`; - const all_dependencies = new Set(this.block.dependencies); // TODO should be dynamic deps only - this.node.expression.dynamic_dependencies().forEach((dependency: string) => { - all_dependencies.add(dependency); - }); + if (this.dependencies.size) { + this.updates.push(b` + const ${this.vars.each_block_value} = ${snippet}; + ${this.renderer.options.dev && b`@validate_each_argument(${this.vars.each_block_value});`} - if (all_dependencies.size) { - block.chunks.update.push(b` - if (${block.renderer.dirty(Array.from(all_dependencies))}) { - const ${this.vars.each_block_value} = ${snippet}; - ${this.renderer.options.dev && b`@validate_each_argument(${this.vars.each_block_value});`} - - ${this.block.has_outros && b`@group_outros();`} - ${this.node.has_animation && b`for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].r();`} - ${this.renderer.options.dev && b`@validate_each_keys(#ctx, ${this.vars.each_block_value}, ${this.vars.get_each_context}, ${get_key});`} - ${iterations} = @update_keyed_each(${iterations}, #dirty, ${get_key}, ${dynamic ? 1 : 0}, #ctx, ${this.vars.each_block_value}, ${lookup}, ${update_mount_node}, ${destroy}, ${create_each_block}, ${update_anchor_node}, ${this.vars.get_each_context}); - ${this.node.has_animation && b`for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].a();`} - ${this.block.has_outros && b`@check_outros();`} - } + ${this.block.has_outros && b`@group_outros();`} + ${this.node.has_animation && b`for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].r();`} + ${this.renderer.options.dev && b`@validate_each_keys(#ctx, ${this.vars.each_block_value}, ${this.vars.get_each_context}, ${get_key});`} + ${iterations} = @update_keyed_each(${iterations}, #dirty, ${get_key}, ${dynamic ? 1 : 0}, #ctx, ${this.vars.each_block_value}, ${lookup}, ${update_mount_node}, ${destroy}, ${create_each_block}, ${update_anchor_node}, ${this.vars.get_each_context}); + ${this.node.has_animation && b`for (let #i = 0; #i < ${view_length}; #i += 1) ${iterations}[#i].a();`} + ${this.block.has_outros && b`@check_outros();`} `); } @@ -504,12 +513,7 @@ export default class EachBlockWrapper extends Wrapper { } `); - const all_dependencies = new Set(this.block.dependencies); // TODO should be dynamic deps only - this.node.expression.dynamic_dependencies().forEach((dependency: string) => { - all_dependencies.add(dependency); - }); - - if (all_dependencies.size) { + if (this.dependencies.size) { const has_transitions = !!(this.block.has_intro_method || this.block.has_outro_method); const for_loop_body = this.block.has_update_method @@ -588,11 +592,7 @@ export default class EachBlockWrapper extends Wrapper { ${remove_old_blocks} `; - block.chunks.update.push(b` - if (${block.renderer.dirty(Array.from(all_dependencies))}) { - ${update} - } - `); + this.updates.push(update); } if (this.block.has_outros) { diff --git a/test/runtime/samples/each-block-keyed-else/_config.js b/test/runtime/samples/each-block-keyed-else/_config.js new file mode 100644 index 000000000000..a5bf722a809d --- /dev/null +++ b/test/runtime/samples/each-block-keyed-else/_config.js @@ -0,0 +1,37 @@ +export default { + props: { + animals: ['alpaca', 'baboon', 'capybara'], + foo: 'something else' + }, + + html: ` + before +

alpaca

+

baboon

+

capybara

+ after + `, + + test({ assert, component, target }) { + component.animals = []; + assert.htmlEqual(target.innerHTML, ` + before +

no animals, but rather something else

+ after + `); + + component.foo = 'something other'; + assert.htmlEqual(target.innerHTML, ` + before +

no animals, but rather something other

+ after + `); + + component.animals = ['wombat']; + assert.htmlEqual(target.innerHTML, ` + before +

wombat

+ after + `); + } +}; diff --git a/test/runtime/samples/each-block-keyed-else/main.svelte b/test/runtime/samples/each-block-keyed-else/main.svelte new file mode 100644 index 000000000000..2a82653ff16a --- /dev/null +++ b/test/runtime/samples/each-block-keyed-else/main.svelte @@ -0,0 +1,12 @@ + + +before +{#each animals as animal (animal)} +

{animal}

+{:else} +

no animals, but rather {foo}

+{/each} +after diff --git a/test/runtime/samples/each-block-unkeyed-else-2/_config.js b/test/runtime/samples/each-block-unkeyed-else-2/_config.js new file mode 100644 index 000000000000..a5bf722a809d --- /dev/null +++ b/test/runtime/samples/each-block-unkeyed-else-2/_config.js @@ -0,0 +1,37 @@ +export default { + props: { + animals: ['alpaca', 'baboon', 'capybara'], + foo: 'something else' + }, + + html: ` + before +

alpaca

+

baboon

+

capybara

+ after + `, + + test({ assert, component, target }) { + component.animals = []; + assert.htmlEqual(target.innerHTML, ` + before +

no animals, but rather something else

+ after + `); + + component.foo = 'something other'; + assert.htmlEqual(target.innerHTML, ` + before +

no animals, but rather something other

+ after + `); + + component.animals = ['wombat']; + assert.htmlEqual(target.innerHTML, ` + before +

wombat

+ after + `); + } +}; diff --git a/test/runtime/samples/each-block-unkeyed-else-2/main.svelte b/test/runtime/samples/each-block-unkeyed-else-2/main.svelte new file mode 100644 index 000000000000..3275cb1f83de --- /dev/null +++ b/test/runtime/samples/each-block-unkeyed-else-2/main.svelte @@ -0,0 +1,12 @@ + + +before +{#each animals as animal} +

{animal}

+{:else} +

no animals, but rather {foo}

+{/each} +after From ef791cc61644e013ea9bf8af4791d737b2241835 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 14 Mar 2020 16:10:38 -0400 Subject: [PATCH 041/158] Bump acorn from 7.1.0 to 7.1.1 (#4553) Bumps [acorn](https://github.com/acornjs/acorn) from 7.1.0 to 7.1.1. - [Release notes](https://github.com/acornjs/acorn/releases) - [Commits](https://github.com/acornjs/acorn/compare/7.1.0...7.1.1) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 014348f37eef..858d90fd1b94 100644 --- a/package-lock.json +++ b/package-lock.json @@ -280,9 +280,9 @@ "dev": true }, "acorn": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", - "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz", + "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==", "dev": true }, "acorn-globals": { From 0ccdca21da697bed429e6fda7d57e1e6e02af970 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 14 Mar 2020 16:10:57 -0400 Subject: [PATCH 042/158] Bump acorn from 7.0.0 to 7.1.1 in /site (#4554) Bumps [acorn](https://github.com/acornjs/acorn) from 7.0.0 to 7.1.1. - [Release notes](https://github.com/acornjs/acorn/releases) - [Commits](https://github.com/acornjs/acorn/compare/7.0.0...7.1.1) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- site/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index 646ca0ce5366..5ce377c88cd5 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -1358,9 +1358,9 @@ } }, "acorn": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.0.0.tgz", - "integrity": "sha512-PaF/MduxijYYt7unVGRuds1vBC9bFxbNf+VWqhOClfdgy7RlVkQqt610ig1/yxTgsDIfW1cWDel5EBbOy3jdtQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz", + "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==", "dev": true }, "ansi-colors": { From e06a900b2331e70f8b057dcbd36f6bd304f4c7dc Mon Sep 17 00:00:00 2001 From: vlasy Date: Sat, 14 Mar 2020 21:15:37 +0100 Subject: [PATCH 043/158] throw compiler error when binding directly to const variables (#4506) --- src/compiler/compile/nodes/Binding.ts | 5 +++++ .../samples/binding-const-field/errors.json | 1 + .../samples/binding-const-field/input.svelte | 7 +++++++ test/validator/samples/binding-const/errors.json | 15 +++++++++++++++ test/validator/samples/binding-const/input.svelte | 5 +++++ 5 files changed, 33 insertions(+) create mode 100644 test/validator/samples/binding-const-field/errors.json create mode 100644 test/validator/samples/binding-const-field/input.svelte create mode 100644 test/validator/samples/binding-const/errors.json create mode 100644 test/validator/samples/binding-const/input.svelte diff --git a/src/compiler/compile/nodes/Binding.ts b/src/compiler/compile/nodes/Binding.ts index 7d6fad0a816a..2f199709c86f 100644 --- a/src/compiler/compile/nodes/Binding.ts +++ b/src/compiler/compile/nodes/Binding.ts @@ -72,6 +72,11 @@ export default class Binding extends Node { }); variable[this.expression.node.type === 'MemberExpression' ? 'mutated' : 'reassigned'] = true; + + if (info.expression.type === 'Identifier' && !variable.writable) component.error(this.expression.node, { + code: 'invalid-binding', + message: 'Cannot bind to a variable which is not writable', + }); } const type = parent.get_static_attribute_value('type'); diff --git a/test/validator/samples/binding-const-field/errors.json b/test/validator/samples/binding-const-field/errors.json new file mode 100644 index 000000000000..fe51488c7066 --- /dev/null +++ b/test/validator/samples/binding-const-field/errors.json @@ -0,0 +1 @@ +[] diff --git a/test/validator/samples/binding-const-field/input.svelte b/test/validator/samples/binding-const-field/input.svelte new file mode 100644 index 000000000000..055a16438d2d --- /dev/null +++ b/test/validator/samples/binding-const-field/input.svelte @@ -0,0 +1,7 @@ + + + diff --git a/test/validator/samples/binding-const/errors.json b/test/validator/samples/binding-const/errors.json new file mode 100644 index 000000000000..6d48af9c4ec1 --- /dev/null +++ b/test/validator/samples/binding-const/errors.json @@ -0,0 +1,15 @@ +[{ + "code": "invalid-binding", + "message": "Cannot bind to a variable which is not writable", + "pos": 61, + "start": { + "line": 5, + "column": 19, + "character": 61 + }, + "end": { + "line": 5, + "column": 24, + "character": 66 + } +}] \ No newline at end of file diff --git a/test/validator/samples/binding-const/input.svelte b/test/validator/samples/binding-const/input.svelte new file mode 100644 index 000000000000..1857a1932cd5 --- /dev/null +++ b/test/validator/samples/binding-const/input.svelte @@ -0,0 +1,5 @@ + + + From c46b3727f11132cf765028522d97f3fedf91c051 Mon Sep 17 00:00:00 2001 From: Conduitry Date: Sat, 14 Mar 2020 16:17:12 -0400 Subject: [PATCH 044/158] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e9024c318c8..6b9d08ea2a32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Allow `` to be used in a slot ([#2798](https://github.com/sveltejs/svelte/issues/2798)) * Expose object of unknown props in `$$restProps` ([#2930](https://github.com/sveltejs/svelte/issues/2930)) +* Disallow binding directly to `const` variables ([#4479](https://github.com/sveltejs/svelte/issues/4479)) * Fix updating keyed `{#each}` blocks with `{:else}` ([#4536](https://github.com/sveltejs/svelte/issues/4536), [#4549](https://github.com/sveltejs/svelte/issues/4549)) * Fix hydration of top-level content ([#4542](https://github.com/sveltejs/svelte/issues/4542)) From 966aae3420ed6474fee296ddb120aa4b68fb75e1 Mon Sep 17 00:00:00 2001 From: Jacob Wright Date: Sat, 14 Mar 2020 14:37:27 -0600 Subject: [PATCH 045/158] allow transitions and animations to work within iframes (#3625) --- CHANGELOG.md | 1 + src/runtime/internal/style_manager.ts | 48 ++++++++------- .../samples/transition-css-iframe/Foo.svelte | 16 +++++ .../transition-css-iframe/Frame.svelte | 58 +++++++++++++++++++ .../samples/transition-css-iframe/_config.js | 18 ++++++ .../samples/transition-css-iframe/main.svelte | 8 +++ 6 files changed, 129 insertions(+), 20 deletions(-) create mode 100644 test/runtime/samples/transition-css-iframe/Foo.svelte create mode 100644 test/runtime/samples/transition-css-iframe/Frame.svelte create mode 100644 test/runtime/samples/transition-css-iframe/_config.js create mode 100644 test/runtime/samples/transition-css-iframe/main.svelte diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b9d08ea2a32..0fe0fa338118 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Allow `` to be used in a slot ([#2798](https://github.com/sveltejs/svelte/issues/2798)) * Expose object of unknown props in `$$restProps` ([#2930](https://github.com/sveltejs/svelte/issues/2930)) +* Allow transitions and animations to work within iframes ([#3624](https://github.com/sveltejs/svelte/issues/3624)) * Disallow binding directly to `const` variables ([#4479](https://github.com/sveltejs/svelte/issues/4479)) * Fix updating keyed `{#each}` blocks with `{:else}` ([#4536](https://github.com/sveltejs/svelte/issues/4536), [#4549](https://github.com/sveltejs/svelte/issues/4549)) * Fix hydration of top-level content ([#4542](https://github.com/sveltejs/svelte/issues/4542)) diff --git a/src/runtime/internal/style_manager.ts b/src/runtime/internal/style_manager.ts index d9264e3c0843..31d7573a769e 100644 --- a/src/runtime/internal/style_manager.ts +++ b/src/runtime/internal/style_manager.ts @@ -1,9 +1,13 @@ import { element } from './dom'; import { raf } from './environment'; -let stylesheet; +interface ExtendedDoc extends Document { + __svelte_stylesheet: CSSStyleSheet; + __svelte_rules: Record; +} + +const active_docs = new Set(); let active = 0; -let current_rules = {}; // https://github.com/darkskyapp/string-hash/blob/master/index.js function hash(str: string) { @@ -25,14 +29,12 @@ export function create_rule(node: Element & ElementCSSInlineStyle, a: number, b: const rule = keyframes + `100% {${fn(b, 1 - b)}}\n}`; const name = `__svelte_${hash(rule)}_${uid}`; + const doc = node.ownerDocument as ExtendedDoc; + active_docs.add(doc); + const stylesheet = doc.__svelte_stylesheet || (doc.__svelte_stylesheet = doc.head.appendChild(element('style') as HTMLStyleElement).sheet as CSSStyleSheet); + const current_rules = doc.__svelte_rules || (doc.__svelte_rules = {}); if (!current_rules[name]) { - if (!stylesheet) { - const style = element('style'); - document.head.appendChild(style); - stylesheet = style.sheet; - } - current_rules[name] = true; stylesheet.insertRule(`@keyframes ${name} ${rule}`, stylesheet.cssRules.length); } @@ -45,22 +47,28 @@ export function create_rule(node: Element & ElementCSSInlineStyle, a: number, b: } export function delete_rule(node: Element & ElementCSSInlineStyle, name?: string) { - node.style.animation = (node.style.animation || '') - .split(', ') - .filter(name - ? anim => anim.indexOf(name) < 0 // remove specific animation - : anim => anim.indexOf('__svelte') === -1 // remove all Svelte animations - ) - .join(', '); - - if (name && !--active) clear_rules(); + const previous = (node.style.animation || '').split(', '); + const next = previous.filter(name + ? anim => anim.indexOf(name) < 0 // remove specific animation + : anim => anim.indexOf('__svelte') === -1 // remove all Svelte animations + ); + const deleted = previous.length - next.length; + if (deleted) { + node.style.animation = next.join(', '); + active -= deleted; + if (!active) clear_rules(); + } } export function clear_rules() { raf(() => { if (active) return; - let i = stylesheet.cssRules.length; - while (i--) stylesheet.deleteRule(i); - current_rules = {}; + active_docs.forEach(doc => { + const stylesheet = doc.__svelte_stylesheet; + let i = stylesheet.cssRules.length; + while (i--) stylesheet.deleteRule(i); + doc.__svelte_rules = {}; + }); + active_docs.clear(); }); } diff --git a/test/runtime/samples/transition-css-iframe/Foo.svelte b/test/runtime/samples/transition-css-iframe/Foo.svelte new file mode 100644 index 000000000000..c79672f21b15 --- /dev/null +++ b/test/runtime/samples/transition-css-iframe/Foo.svelte @@ -0,0 +1,16 @@ + + +{#if visible} +
+{/if} \ No newline at end of file diff --git a/test/runtime/samples/transition-css-iframe/Frame.svelte b/test/runtime/samples/transition-css-iframe/Frame.svelte new file mode 100644 index 000000000000..c7ac9cf76f81 --- /dev/null +++ b/test/runtime/samples/transition-css-iframe/Frame.svelte @@ -0,0 +1,58 @@ + + + + + diff --git a/test/runtime/samples/transition-css-iframe/_config.js b/test/runtime/samples/transition-css-iframe/_config.js new file mode 100644 index 000000000000..507efe44f4f5 --- /dev/null +++ b/test/runtime/samples/transition-css-iframe/_config.js @@ -0,0 +1,18 @@ +export default { + skip_if_ssr: true, + + async test({ assert, component, target, window, raf }) { + const frame = target.querySelector('iframe'); + await Promise.resolve(); + + component.visible = true; + const div = frame.contentDocument.querySelector('div'); + + raf.tick(25); + + component.visible = false; + + raf.tick(26); + assert.ok(~div.style.animation.indexOf('25ms')); + }, +}; diff --git a/test/runtime/samples/transition-css-iframe/main.svelte b/test/runtime/samples/transition-css-iframe/main.svelte new file mode 100644 index 000000000000..b1686ff15e7f --- /dev/null +++ b/test/runtime/samples/transition-css-iframe/main.svelte @@ -0,0 +1,8 @@ + + + \ No newline at end of file From 0cde17a4adf32bc91032d2b7ebba20472f38f2a1 Mon Sep 17 00:00:00 2001 From: Victor Guyard <19635051+FlipFloop@users.noreply.github.com> Date: Sat, 14 Mar 2020 16:43:41 -0400 Subject: [PATCH 046/158] site: lossless image optimization (#4503) --- banner.png | Bin 47395 -> 0 bytes .../thumbnails/dom-event-forwarding.jpg | Bin 2409 -> 2156 bytes site/static/favicon.png | Bin 2010 -> 1373 bytes site/static/icons/arrow-right.svg | 8 +------ site/static/icons/check.svg | 5 +---- site/static/icons/chevron.svg | 5 +---- site/static/icons/collapse.svg | 5 +---- site/static/icons/download.svg | 5 +---- site/static/icons/dropdown.svg | 5 +---- site/static/icons/edit.svg | 8 +------ site/static/icons/expand.svg | 5 +---- site/static/icons/flip.svg | 5 +---- site/static/icons/fork.svg | 5 +---- site/static/icons/link.svg | 9 +------- site/static/icons/save.svg | 5 +---- .../static/images/svelte-apple-touch-icon.png | Bin 1588 -> 1586 bytes site/static/images/twitter-card.png | Bin 5858 -> 3381 bytes site/static/svelte-logo-mask.svg | 17 +------------- site/static/svelte-logo-outline.svg | 21 +----------------- site/static/svelte-logo-vertical.svg | 5 +---- site/static/svelte-logo.svg | 21 +----------------- site/static/tutorial/icons/email.svg | 5 +---- site/static/tutorial/icons/folder-open.svg | 5 +---- site/static/tutorial/icons/folder.svg | 5 +---- site/static/tutorial/icons/gif.svg | 5 +---- site/static/tutorial/icons/map-marker.svg | 5 +---- site/static/tutorial/icons/md.svg | 5 +---- site/static/tutorial/icons/xlsx.svg | 5 +---- site/static/tutorial/kitten.png | Bin 113450 -> 110587 bytes 29 files changed, 23 insertions(+), 146 deletions(-) delete mode 100644 banner.png diff --git a/banner.png b/banner.png deleted file mode 100644 index 0d117c3c09d434d441b1b546722774f6dac34928..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47395 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 diff --git a/site/static/examples/thumbnails/dom-event-forwarding.jpg b/site/static/examples/thumbnails/dom-event-forwarding.jpg index 0992aef1fdca6eb4d786b03e988307aa9c423c02..4c23217bbafb1a5efa32619c7793a632d698c9ce 100644 GIT binary patch literal 2156 zcmc&$c`(~)AOA(7p<*lOE=4ttrb1NEb@R5a5tem?MO6`Jir1NS_uaN}tm-C?#ZcoY zQbNTMq^e%`mAXq^)pb;mma4iUZ)W#x=bird{!^pv0w6bcm<7CH@+6orY1z@)_`&Pd9glRqzaPFD7Uk~;E& zf|{bN>?Iu)H4TimwzfP{&q!C(P+dz~6C^Aw3=@G#iHb^TB4iPo|2KHg0k{xg1tfz( za6kYK0>eSPE`Y)h2nO*1d;v)C6j%TP6$3zE5JVUZ0e^l234q}c!EZ-TiDRxfI7Lv3 z5p^9B3Rmqly~x-20(_Y-8vH>33;_x9oj@QkR7CKL178FJ7f0ATgprHKBqT9fR~^GC z9ivN{+W)GfdkHG=UI8$^qW~NX2TTBN>-Muv2EIBil6-x2<6 zp3#bI%*#x_?7|4!elyD?C3X!Z>rv+hZ|P>d&Y&!AVuI&8O}zc|hHY2fy}C3ktwQ&t znm9{Eby~8k6%ptsZ=@8<7)LO7;y+(Z=Ve4Vw&YBQ!Qf-=ToRhu?7wN#`4-ynX`w@!M}%^qOAj_aE^WBwyO`zjxKw^ z(o63S29mb#l z5t-;@%2``_!14M>aNpG`r$6Cyu?mk-C1{C2*|2WXaZAP==P3&1P)YUlv={CP+Gmag z)=<8$%qoSfAj2)i+Z9fy{c4U?L5zHMoeRiWBf2j1;p?NapIYyy;!kqfAAN0eL#6ah zP>4?v?|VOK95&JprN>==0WOO}!pR&;!o%p{ph3mW$umoqtN z@IR}1trt1ASngZ-Eb0-I^w2DYkiE@XL*wj?`fvW&&}F|9+SpSpeTOVcJN^BAZ=-xVL7g7!a4))lDw|TP3e%GhK1tbB z6x3ZJt_<1KamS1X&89q@xcPyv!X}rgRb%T3sjEETMtm>Qc4Gw@eLY!s=A#lp6-z_e zz6@C1EwrwEyTDPcfQ8%ZE1|>DN?680>@8Dm+N77gW40mvFno7on7Fp%R%u>7(W-B! zo^hX$zlFz@55(p;G%ZT+42mS%y6<=-tdp}Qp8wNA5oDe!AH3_a(G%k0enmR7}2h?)K z%$SoXb+Rh&+}LiaPf!IQZYWgnwbqGJw*u;5aaBflGjnui5$i(OV57FME)yNLkLc+! zdXBxspg>QWLCu1vGB)(=C$Y31x^rojn|&Z-f|*HGwLvw8|9hMV$Pf^ce@J0fR*e#z z6=x1Y$0vxpzRqr=rO>lHpwfz2znBzK{sS&UIm!Ixc@>%KlU7%rEgw6MG>s0vQkz8d zF9qWV=$pjQ3t0%IiQ0j<91Ck2uB6cg7uaZG8DLNKqyBRGF!b`h!;0oYtDchJr&Tem z?-Y?f1r26y)Tq`h_GqVITw6$B_9!KN9N)D}z?*x}N|MS54h1yr$I4{y_773Lfx{M> zb`4pvN}^b9A2&#Hf^J*AQ9=GespvJkGE1@0fK`)s7B`&deqh1gJV{gA)1{hYS(zS; zs>Yi6?s{6nmfidKiUuD55ba3~Ax0H$lB{)H-MiXTa_rVKYMq_d|7>uHJkbP}6mh1? zZLzrUO7`u~efaMkqHP_)tbT{rbZs42P(C)JC)q^B(kpCq(&gl{#r`aRZi3qs7q(tq z{S_4)R^nbb?;nSt3{N?4Uw)&UdFWF$Nlu(|TxhCXN&9K~zTe~0jU$}Iy@07Gm9lqM zzQK_?Cx%P9%}Zq5ovnhd^WjokvG5PZpeVz4{(T*LEblXVu;@0SgCd~yA+dh>=8-=J zT0kN{VuC5_6UKY!1z5dRTwHKc* ze{1!^hu?Y$BMRq-u3#b0f_Bbz2e5l?}PY)UHagSVf`>QqZ Je-^x%{{X<8$l?G1 literal 2409 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 N07(Z$PDHLkV1lI2b@BiJ delta 1944 zcmV;J2WR-*3fd2l92x)^000SaNLh0L01FZT01FZU(%pXiks&{SRv`akF#m2q z|9epXhhYDcaQ~lx|ErMyx1j&Su>a4%|J%_2=-~hK@c;k+{^8<-0000GbW%=J01zNB zKu}(NDy3|Z zPx`mDoR_VAF|KuZHT(&+_wzsifS0z=*<}YAEIFqSq$1_Whq`SgFpS zo9#9*xLY%*E7h%I%3y06002Z?({@nI6#Q>G^>UoKJk(Q&y^cYlll3~BRV}dP_OIW# z#|6Prwbby%&YHb{lag@SvogGfF((3Q&GFM({opda&&EZ{r{z(q(}SI;b17x-k*$<3 zQ<(rz4CC8=Dgl^`o#A)$2RBVcW(GE$Hk-omYM5!}otbk?ftAb_0f0zb#k~4fV(DR6 znKl!e9+Xwa$OlRPItM#LJq=gT{pq19s+Z+%`y&_I!43d_0E)UG!{&s#0UlF(w)``% z|7*sGdd>Z;7`q3PE*_(gfYZ@w^cfghRCT0&t$5j3O;k^1>$2vfdcmYd-<8p+#AtBG z`_k~2HY!n)r=UfcM!&VuV=#Afegzl-7&cyFYMaF>Cj;ogO z{^`LdR*Pm^&G>}-MUv?}l`OzEjxab(Xq}xE4h+B^fCY0Op^LO51wg9cVV+q9S=^wjI z!yVn(t~E;~iKKX2RQ%9^m%);ETsOw1WbPU^hBo$)? zRz7H+3pqt+FfYH6m{7YV26#kNTvF2+lsMvQ7@T&~V>q=ULUSxS6Qv9L1qSQ6Z8$1= z-x<>)6v}ewHH_(~w)QK?W{TaoHh3DnE_VKT49wKlEKZ0mL%1p`MIb> zKKL5x${@jpXLgFE95KN*-JR`;XR2#c>3c=1MkM44&Z@22gsATc9nKnqS%?a+5h2N- z*7Eri>)#NCaj$Pu6U(Q&C75PJbDNcDL@c%}@hs3dz{D%QYqV;_V`nioe=uARzZ0T;@dh0;j$#yRLq$uzsqahrJ zfj8}>scZ;sC+(UOCtM$Tdiv9>A`4Lxf1v?X_S<<`nN zxjcF1nsxlfvJu-Q2(Q%auZ7v|0}X!(=-CVDNbLqc*b{aaZ|Ols^J%wr`e()T5;BqG zH4E;kLoJssJODgvdZ91!gxw!uWA_{Y(uSTr1E6mRy!}D4eN!T%!@W(J&VYS?VD2J- zbv{?pk&dQakyl#;Fc0@gr?2_`WZojjlP&`2^-d7VFNH%5d{$N_@HPON?+W2uhm*wj z(vBX06&G+T$e}3f^1IIdOpBr@iagznOZHsOFF9vZyps~cB@Z4r0X*u$Yvufg2@C=B zj3+8DG~ika?@U%z@;Xx&h&tqddZ>HmlVF(uh`eCHt0l%iYkaV0MoL8X{v7`jOE;Nh^+)$}~sxRn*Y}bX9@q&kc7_c&+nfbjD zk#SeYvU1XI^Um;ZDyC!XVuEl>twS8P@{Pmm>dDc%&IiZ?VS_pbd&a)bWZ+NH-@(s^aHq{#mKA=pm)wM9Al z*eS_r#q77w9$6h?uh}nOI52ZO82auF@AIM_;#2T#I+4djkJB%nR33h=(RgSR-Ok5f eKP3I5uh2guB=Kbaq#O(Y0000 - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/site/static/icons/check.svg b/site/static/icons/check.svg index 5679642c7f2e..c3e46a42b616 100644 --- a/site/static/icons/check.svg +++ b/site/static/icons/check.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/site/static/icons/chevron.svg b/site/static/icons/chevron.svg index 3706f5327881..9d582fa803f0 100644 --- a/site/static/icons/chevron.svg +++ b/site/static/icons/chevron.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/site/static/icons/collapse.svg b/site/static/icons/collapse.svg index 13ff9dee82e5..795939aec874 100644 --- a/site/static/icons/collapse.svg +++ b/site/static/icons/collapse.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/site/static/icons/download.svg b/site/static/icons/download.svg index 8d255ff74b4d..b286a882fe47 100644 --- a/site/static/icons/download.svg +++ b/site/static/icons/download.svg @@ -1,4 +1 @@ - - - - + \ No newline at end of file diff --git a/site/static/icons/dropdown.svg b/site/static/icons/dropdown.svg index b3fcdbe7950f..69435856b4f0 100644 --- a/site/static/icons/dropdown.svg +++ b/site/static/icons/dropdown.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/site/static/icons/edit.svg b/site/static/icons/edit.svg index 5e7b182086ac..760321cd2f0a 100644 --- a/site/static/icons/edit.svg +++ b/site/static/icons/edit.svg @@ -1,7 +1 @@ - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/site/static/icons/expand.svg b/site/static/icons/expand.svg index b429cb53c811..a026808da37e 100644 --- a/site/static/icons/expand.svg +++ b/site/static/icons/expand.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/site/static/icons/flip.svg b/site/static/icons/flip.svg index 09326b1e6b5d..3a18d5ffa109 100644 --- a/site/static/icons/flip.svg +++ b/site/static/icons/flip.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/site/static/icons/fork.svg b/site/static/icons/fork.svg index 57ad61bb2f34..3e2188549535 100644 --- a/site/static/icons/fork.svg +++ b/site/static/icons/fork.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/site/static/icons/link.svg b/site/static/icons/link.svg index 3b36b03cab38..3345bdd0ba89 100644 --- a/site/static/icons/link.svg +++ b/site/static/icons/link.svg @@ -1,8 +1 @@ - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/site/static/icons/save.svg b/site/static/icons/save.svg index 4bde5edde568..a8a5fa161896 100644 --- a/site/static/icons/save.svg +++ b/site/static/icons/save.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/site/static/images/svelte-apple-touch-icon.png b/site/static/images/svelte-apple-touch-icon.png index 94c9f12f03a7fb51dd9d8d3fa81fdde22b820c28..5600445b1c2b89ba79696144ae48153d3517b9e2 100644 GIT binary patch delta 1511 zcmV5@vghv;~pHLvVTogVn<*8RlagZ6QM37p)N(VE!l+@v2Cz}qJ^k* zyTzB22iGLpgp@ql;(;Ys^5&GiyVTEwpyK!H^GXFIGW?Ikri}T&trR^($xDEx zb%9p6clBcIeZA`1!B*gO^qcq{&6aL!KbTi9n5#}fR)1hvw?@&&D%1+%YK-wzxD^;S zTwSrktzfIFTO^4bO$At?ZRihfF8hss;kyQvXa#W}GtI;gEUpu3g=%{E1pIGxP_vPO zRqBumWQm?DLhF2Q0&}e#Om^fNR=kdx&$i zkeGj5>tO}q%Uz@1;%&~WH8?n0hAU^k6A$n^>^-a??Xhp@0Ipyk(>^VALteNWZ_2W0 z8GHV)JgguvIB`a(*bAP5^41g5`fYQpi9YibO9N`V%>sbP0 z8qHAs!5Hn}cPPiY`=lDn_Q$Ip1g)tIjirUon0@iF-V9lXj6~c!IAQwj5v)LC$(wO` zn_o@9!-8YU&A(t?Rp7Bk9t#)=4x#7Pa>+v@!7^WAW-Rd+l60|Pl>@MZS#i@F&8#$CvUMGAh^0$biLyBI> ztt&_s@)nQMt{GOT@(GggWm z6_k$N8>>(Y4_4&ne*$6w_d|5$H|OfnSVCnnG%x+OcQlV{*Ne3mr^b&ReP!wjCS3PR^1L4Tc|AfydaYXlaaAQp?pu45LVuF54_kV^w zal`VK3@)v%t{icoTY~Hp=IDWsd-f#^ocyP81RmT+xaumT(Nu<j7IfPOyTI3T%7C?WGf};4wQbR*V&J9|$-+ z$79JO!NExfE8(#;cpr$d4{4}7X@BTq?BeDh@26QTUNv{0gM#V~osBWhV(-#9;Fe(M z4}JFXNp*JzZV3v0mxz~4C`(P`nhLN26DfXzj#0XhRE(q8uX~LI!BmWc+=I#(xAyN$ z3krE$@_it+k04HXb#W^&PH}{>mj)c574R3xCpO$&fE9#C1>bgS5Gyd$A%6;?AjS}G z1@IA_s1Bwp=J8*YWLA$U{y zUWHPCK!L&TWV#=j22JZ*0h-P`-J7ziZpP?|7{J#u^y?#>V-~H?j%08v;Oq&9TVdN= zxD{{`MIyKraN;Wg;8qC#nP70Z6@oY@zzQ2s N002ovPDHLkV1jWL?r8u3 delta 1513 zcmVvGC|A%1zlW_l^fd8wI|F@w3!?6F)!2jFO z|LEZV^zi@x|Ni0Pg8%>k5Oh*bQveVkFhEdXaDb4Yu)xsZ@KoTa$N&HZa7jc#RCwC$ zoWYu^IuL{f5mCW(AV5GMy#G_)b9du3+N7d*zVrF7XHh1dN`JZ%X7{i1<;$0Sa>)KC zO_Jy@QFOc%^b?hz4jKtz@Dmv3DwiR|%v=WtV zxA=1M;F@fsDkD#}7_j6@-W1WhOZ`L$YX4sQyb^{wym6>5gp+>W6*klr=M+ftc~{t` z?vsL^Vr)OSd4HbWaI@yIu|`|Eg6Z9S$E~4dF59_6GtC@lH7#-6$Q8^uFXLKTK*d|Q zg6`(Wj1_V64P2p~=4ZGDcQ4!(^lg@~#JIlM6&g3o^w22>cZG78S7CY8zwuaQ-Mo?p zs4mbIs&QV8t6o=K2iO%jBmHLoj%LeDvmeY?&zM&gL4U5maQYQRzgK~-Ag{(ft_pSq zjtjT0y~16=4a2y~Byv<0;0jYif6zDM?sa~3XHOIk5^(Iung<@88=M=x|trG zAx^6|L;iD}hbsu1yFq=6w>i(&V5eyvx?kKAkMJC}9{tZOK@#GYM%20MPp6bWbI@!hbfIGyS3yTmb+mtw?kS?g}^;_y8zm z3CwzH+YNuP)@XbVMOl@Ps=A-9-&(hGmI| zaru}(l+a+|vV`Vea9$PTvT801hy*+N-a548p-8X~%D?#mqU50q6bbf1!TWALjz@Y> zB!AfQiVtb1`4Ss76bTxi4Uut?k6WWbB0;A^?(Q;PT%4gbrV&KR3`QuA*YA~LAr*L#Qr3FDe_~ge5yZ&ecM)my!B+H;UVd^A zbdks~rnR;Mn_nd@N8Oe1s3zL_#2gVhwB?HyMm+&XnVxtrS@Xn;j#?)9*B{KG}NOMx_?-=y7|ZZX(o$TP33b@FjUap7~>@NE~5rs35I^? zlgc;MV+Fht6#QLczb2vV4UujJ#1*)a;y36By$(>txd{EbMO=a;X|Et_}(b7-*-G_+}*(LwsoR{n%l=+rKNs=Vd?%(ChmoNVTe2NX;V5(e> P00000NkvXXu0mjfmoDgV diff --git a/site/static/images/twitter-card.png b/site/static/images/twitter-card.png index 1e8271f655f75fdd12e76e1677e3eeecf57de3a2..7a66e94003775de13d3798fca9c328dbe56e9e42 100644 GIT binary patch literal 3381 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 - - - - + \ No newline at end of file diff --git a/site/static/svelte-logo-outline.svg b/site/static/svelte-logo-outline.svg index 9aac72c95791..d93d71c593f8 100644 --- a/site/static/svelte-logo-outline.svg +++ b/site/static/svelte-logo-outline.svg @@ -1,20 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/site/static/svelte-logo-vertical.svg b/site/static/svelte-logo-vertical.svg index b019147f35ba..7e2888234d62 100644 --- a/site/static/svelte-logo-vertical.svg +++ b/site/static/svelte-logo-vertical.svg @@ -1,4 +1 @@ - - - - + \ No newline at end of file diff --git a/site/static/svelte-logo.svg b/site/static/svelte-logo.svg index 4bf279659a93..d8b477bee13e 100644 --- a/site/static/svelte-logo.svg +++ b/site/static/svelte-logo.svg @@ -1,20 +1 @@ - - - - - - - + \ No newline at end of file diff --git a/site/static/tutorial/icons/email.svg b/site/static/tutorial/icons/email.svg index db656054ffa0..70d92ca4300f 100644 --- a/site/static/tutorial/icons/email.svg +++ b/site/static/tutorial/icons/email.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/site/static/tutorial/icons/folder-open.svg b/site/static/tutorial/icons/folder-open.svg index 9dac0ef9e967..b2a58e743241 100644 --- a/site/static/tutorial/icons/folder-open.svg +++ b/site/static/tutorial/icons/folder-open.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/site/static/tutorial/icons/folder.svg b/site/static/tutorial/icons/folder.svg index 7d4a03f1d2ef..2e1246a7f993 100644 --- a/site/static/tutorial/icons/folder.svg +++ b/site/static/tutorial/icons/folder.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/site/static/tutorial/icons/gif.svg b/site/static/tutorial/icons/gif.svg index 315860a2471b..4b28abcecd16 100644 --- a/site/static/tutorial/icons/gif.svg +++ b/site/static/tutorial/icons/gif.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/site/static/tutorial/icons/map-marker.svg b/site/static/tutorial/icons/map-marker.svg index 4e9466c7bdda..40a702db9db2 100644 --- a/site/static/tutorial/icons/map-marker.svg +++ b/site/static/tutorial/icons/map-marker.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/site/static/tutorial/icons/md.svg b/site/static/tutorial/icons/md.svg index 60bc36f4a7ef..582204d3b763 100644 --- a/site/static/tutorial/icons/md.svg +++ b/site/static/tutorial/icons/md.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/site/static/tutorial/icons/xlsx.svg b/site/static/tutorial/icons/xlsx.svg index 6ee32e943dfb..1a51093a973c 100644 --- a/site/static/tutorial/icons/xlsx.svg +++ b/site/static/tutorial/icons/xlsx.svg @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/site/static/tutorial/kitten.png b/site/static/tutorial/kitten.png index 6b0cedc945fdfd0ab936b03c1d88928b4c1d36c3..f1a0ecca192e13c96108b01297e739af6c94f604 100644 GIT binary patch literal 110587 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�~9_d7B=e}j>z1!LSdn2V|}Sy{clSC@K1c&82;`Zx(f>L!#R(~PoNYpdW8tJ z;x~@c8AJbX1%ot?9HX>#+}zRO(pDTF>A_?x;q?Ig8bSBXo}O4tQ5M$++MihGiGvlb zaP{mGszl@^0(5*R>@H6C_Z*8{y`^2TsWz0z_=`()$CFsp9G=k;!d8-gtd(JxRMYw; zq1tWvb=U62`|8xewHGk;hBOR7W1c!*^Nu55#^&%0D4C?pk_&?`wucL}%@+Ongr;g~ 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
+
+
+
+
+ diff --git a/test/runtime/samples/component-slot-nested-error-3/Nested.svelte b/test/runtime/samples/component-slot-nested-error-3/Nested.svelte new file mode 100644 index 000000000000..c6f086d96c19 --- /dev/null +++ b/test/runtime/samples/component-slot-nested-error-3/Nested.svelte @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/runtime/samples/component-slot-nested-error-3/_config.js b/test/runtime/samples/component-slot-nested-error-3/_config.js new file mode 100644 index 000000000000..98a9f1cab00d --- /dev/null +++ b/test/runtime/samples/component-slot-nested-error-3/_config.js @@ -0,0 +1,3 @@ +export default { + error: [`Element with a slot='...' attribute must be a child of a component or a descendant of a custom element`] +}; diff --git a/test/runtime/samples/component-slot-nested-error-3/main.svelte b/test/runtime/samples/component-slot-nested-error-3/main.svelte new file mode 100644 index 000000000000..a63b1defdee6 --- /dev/null +++ b/test/runtime/samples/component-slot-nested-error-3/main.svelte @@ -0,0 +1,11 @@ + + + +
+
+
+
+
+ diff --git a/test/runtime/samples/component-slot-nested-error/Nested.svelte b/test/runtime/samples/component-slot-nested-error/Nested.svelte new file mode 100644 index 000000000000..c6f086d96c19 --- /dev/null +++ b/test/runtime/samples/component-slot-nested-error/Nested.svelte @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/runtime/samples/component-slot-nested-error/_config.js b/test/runtime/samples/component-slot-nested-error/_config.js new file mode 100644 index 000000000000..98a9f1cab00d --- /dev/null +++ b/test/runtime/samples/component-slot-nested-error/_config.js @@ -0,0 +1,3 @@ +export default { + error: [`Element with a slot='...' attribute must be a child of a component or a descendant of a custom element`] +}; diff --git a/test/runtime/samples/component-slot-nested-error/main.svelte b/test/runtime/samples/component-slot-nested-error/main.svelte new file mode 100644 index 000000000000..531c96f08c2d --- /dev/null +++ b/test/runtime/samples/component-slot-nested-error/main.svelte @@ -0,0 +1,9 @@ + + + +
+
+
+ diff --git a/test/validator/samples/component-slotted-custom-element-2/errors.json b/test/validator/samples/component-slotted-custom-element-2/errors.json new file mode 100644 index 000000000000..06be51d72d09 --- /dev/null +++ b/test/validator/samples/component-slotted-custom-element-2/errors.json @@ -0,0 +1,9 @@ +[ + { + "code": "invalid-slotted-content", + "message": "Element with a slot='...' attribute must be a child of a component or a descendant of a custom element", + "start": { "line": 10, "column": 9, "character": 138 }, + "end": { "line": 10, "column": 19, "character": 148 }, + "pos": 138 + } +] diff --git a/test/validator/samples/component-slotted-custom-element-2/input.svelte b/test/validator/samples/component-slotted-custom-element-2/input.svelte new file mode 100644 index 000000000000..221659ca4d94 --- /dev/null +++ b/test/validator/samples/component-slotted-custom-element-2/input.svelte @@ -0,0 +1,14 @@ + + + + + {#if thing} +
+
+
+ {/if} + + \ No newline at end of file diff --git a/test/validator/samples/component-slotted-custom-element/errors.json b/test/validator/samples/component-slotted-custom-element/errors.json new file mode 100644 index 000000000000..0637a088a01e --- /dev/null +++ b/test/validator/samples/component-slotted-custom-element/errors.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/test/validator/samples/component-slotted-custom-element/input.svelte b/test/validator/samples/component-slotted-custom-element/input.svelte new file mode 100644 index 000000000000..e0e27834c10e --- /dev/null +++ b/test/validator/samples/component-slotted-custom-element/input.svelte @@ -0,0 +1,15 @@ + + + + +
+
+
+ {#if thing} +
+ {/if} + + \ No newline at end of file diff --git a/test/validator/samples/component-slotted-each-block/errors.json b/test/validator/samples/component-slotted-each-block/errors.json index 89f394bca438..2944acae1717 100644 --- a/test/validator/samples/component-slotted-each-block/errors.json +++ b/test/validator/samples/component-slotted-each-block/errors.json @@ -1,6 +1,6 @@ [{ "code": "invalid-slotted-content", - "message": "Cannot place slotted elements inside an each-block", + "message": "Element with a slot='...' attribute must be a child of a component or a descendant of a custom element", "start": { "line": 7, "column": 7, diff --git a/test/validator/samples/component-slotted-if-block/errors.json b/test/validator/samples/component-slotted-if-block/errors.json index ab35a77fcebc..3ae07c1b3b90 100644 --- a/test/validator/samples/component-slotted-if-block/errors.json +++ b/test/validator/samples/component-slotted-if-block/errors.json @@ -1,6 +1,6 @@ [{ "code": "invalid-slotted-content", - "message": "Cannot place slotted elements inside an if-block", + "message": "Element with a slot='...' attribute must be a child of a component or a descendant of a custom element", "start": { "line": 7, "column": 7, diff --git a/test/validator/samples/slot-attribute-invalid/errors.json b/test/validator/samples/slot-attribute-invalid/errors.json index fc01fa979224..a75fdc065c26 100644 --- a/test/validator/samples/slot-attribute-invalid/errors.json +++ b/test/validator/samples/slot-attribute-invalid/errors.json @@ -1,6 +1,6 @@ [{ "code": "invalid-slotted-content", - "message": "Element with a slot='...' attribute must be a descendant of a component or custom element", + "message": "Element with a slot='...' attribute must be a child of a component or a descendant of a custom element", "start": { "line": 1, "column": 5, From 7d1e4e82ffb5825bee254113cbba360aea0745f0 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Sun, 15 Mar 2020 18:12:52 +0800 Subject: [PATCH 049/158] support destructuring in await (#4548) --- CHANGELOG.md | 1 + src/compiler/compile/nodes/AwaitBlock.ts | 28 ++++++-- src/compiler/compile/nodes/CatchBlock.ts | 11 +++- src/compiler/compile/nodes/ThenBlock.ts | 11 +++- src/compiler/compile/render_dom/Block.ts | 4 ++ .../compile/render_dom/wrappers/AwaitBlock.ts | 65 ++++++++++++++----- .../compile/render_ssr/handlers/AwaitBlock.ts | 2 +- .../utils/traverse_destructure_pattern.ts | 35 ++++++++++ src/compiler/parse/index.ts | 48 ++++++++++++++ src/compiler/parse/state/mustache.ts | 4 +- src/compiler/parse/utils/bracket.ts | 28 ++++++++ src/compiler/utils/error.ts | 2 +- test/parser/samples/await-catch/output.json | 5 +- .../samples/await-then-catch/output.json | 10 ++- .../no-error-if-before-closing/output.json | 10 ++- .../await-then-destruct-array/_config.js | 61 +++++++++++++++++ .../await-then-destruct-array/main.svelte | 14 ++++ .../await-then-destruct-default/_config.js | 23 +++++++ .../await-then-destruct-default/main.svelte | 34 ++++++++++ .../await-then-destruct-object/_config.js | 63 ++++++++++++++++++ .../await-then-destruct-object/main.svelte | 13 ++++ .../await-then-destruct-rest/_config.js | 21 ++++++ .../await-then-destruct-rest/main.svelte | 32 +++++++++ 23 files changed, 489 insertions(+), 36 deletions(-) create mode 100644 src/compiler/compile/utils/traverse_destructure_pattern.ts create mode 100644 src/compiler/parse/utils/bracket.ts create mode 100644 test/runtime/samples/await-then-destruct-array/_config.js create mode 100644 test/runtime/samples/await-then-destruct-array/main.svelte create mode 100644 test/runtime/samples/await-then-destruct-default/_config.js create mode 100644 test/runtime/samples/await-then-destruct-default/main.svelte create mode 100644 test/runtime/samples/await-then-destruct-object/_config.js create mode 100644 test/runtime/samples/await-then-destruct-object/main.svelte create mode 100644 test/runtime/samples/await-then-destruct-rest/_config.js create mode 100644 test/runtime/samples/await-then-destruct-rest/main.svelte diff --git a/CHANGELOG.md b/CHANGELOG.md index b85ec4ba16de..a24223e5bcf7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased +* Allow destructuring in `{#await}` blocks ([#1851](https://github.com/sveltejs/svelte/issues/1851)) * Allow `` to be used in a slot ([#2798](https://github.com/sveltejs/svelte/issues/2798)) * Expose object of unknown props in `$$restProps` ([#2930](https://github.com/sveltejs/svelte/issues/2930)) * Prevent passing named slots other than from the top level within a component ([#3385](https://github.com/sveltejs/svelte/issues/3385)) diff --git a/src/compiler/compile/nodes/AwaitBlock.ts b/src/compiler/compile/nodes/AwaitBlock.ts index cd57750d292e..a7b8fb815e4e 100644 --- a/src/compiler/compile/nodes/AwaitBlock.ts +++ b/src/compiler/compile/nodes/AwaitBlock.ts @@ -3,27 +3,45 @@ import PendingBlock from './PendingBlock'; import ThenBlock from './ThenBlock'; import CatchBlock from './CatchBlock'; import Expression from './shared/Expression'; +import { Pattern } from 'estree'; +import Component from '../Component'; +import TemplateScope from './shared/TemplateScope'; +import { TemplateNode } from '../../interfaces'; +import traverse_destructure_pattern from '../utils/traverse_destructure_pattern'; export default class AwaitBlock extends Node { type: 'AwaitBlock'; expression: Expression; - value: string; - error: string; + value: DestructurePattern; + error: DestructurePattern; pending: PendingBlock; then: ThenBlock; catch: CatchBlock; - constructor(component, parent, scope, info) { + constructor(component: Component, parent, scope: TemplateScope, info: TemplateNode) { super(component, parent, scope, info); this.expression = new Expression(component, this, scope, info.expression); - this.value = info.value; - this.error = info.error; + this.value = info.value && new DestructurePattern(info.value); + this.error = info.error && new DestructurePattern(info.error); this.pending = new PendingBlock(component, this, scope, info.pending); this.then = new ThenBlock(component, this, scope, info.then); this.catch = new CatchBlock(component, this, scope, info.catch); } } + +export class DestructurePattern { + pattern: Pattern; + expressions: string[]; + identifier_name: string | undefined; + + constructor(pattern: Pattern) { + this.pattern = pattern; + this.expressions = []; + traverse_destructure_pattern(pattern, (node) => this.expressions.push(node.name)); + this.identifier_name = this.pattern.type === 'Identifier' ? this.pattern.name : undefined; + } +} diff --git a/src/compiler/compile/nodes/CatchBlock.ts b/src/compiler/compile/nodes/CatchBlock.ts index 0edc0f76d82c..8b3736a2b990 100644 --- a/src/compiler/compile/nodes/CatchBlock.ts +++ b/src/compiler/compile/nodes/CatchBlock.ts @@ -1,16 +1,23 @@ import map_children from './shared/map_children'; import TemplateScope from './shared/TemplateScope'; import AbstractBlock from './shared/AbstractBlock'; +import AwaitBlock from './AwaitBlock'; +import Component from '../Component'; +import { TemplateNode } from '../../interfaces'; export default class CatchBlock extends AbstractBlock { type: 'CatchBlock'; scope: TemplateScope; - constructor(component, parent, scope, info) { + constructor(component: Component, parent: AwaitBlock, scope: TemplateScope, info: TemplateNode) { super(component, parent, scope, info); this.scope = scope.child(); - this.scope.add(parent.error, parent.expression.dependencies, this); + if (parent.error) { + parent.error.expressions.forEach(expression => { + this.scope.add(expression, parent.expression.dependencies, this); + }); + } this.children = map_children(component, parent, this.scope, info.children); if (!info.skip) { diff --git a/src/compiler/compile/nodes/ThenBlock.ts b/src/compiler/compile/nodes/ThenBlock.ts index 7f9bbde0f0a2..7eefe2e6fb59 100644 --- a/src/compiler/compile/nodes/ThenBlock.ts +++ b/src/compiler/compile/nodes/ThenBlock.ts @@ -1,16 +1,23 @@ import map_children from './shared/map_children'; import TemplateScope from './shared/TemplateScope'; import AbstractBlock from './shared/AbstractBlock'; +import AwaitBlock from './AwaitBlock'; +import Component from '../Component'; +import { TemplateNode } from '../../interfaces'; export default class ThenBlock extends AbstractBlock { type: 'ThenBlock'; scope: TemplateScope; - constructor(component, parent, scope, info) { + constructor(component: Component, parent: AwaitBlock, scope: TemplateScope, info: TemplateNode) { super(component, parent, scope, info); this.scope = scope.child(); - this.scope.add(parent.value, parent.expression.dependencies, this); + if (parent.value) { + parent.value.expressions.forEach(expression => { + this.scope.add(expression, parent.expression.dependencies, this); + }); + } this.children = map_children(component, parent, this.scope, info.children); if (!info.skip) { diff --git a/src/compiler/compile/render_dom/Block.ts b/src/compiler/compile/render_dom/Block.ts index 2da77d3fbf52..3deba786b4f7 100644 --- a/src/compiler/compile/render_dom/Block.ts +++ b/src/compiler/compile/render_dom/Block.ts @@ -46,6 +46,7 @@ export default class Block { }>; chunks: { + declarations: Array; init: Array; create: Array; claim: Array; @@ -93,6 +94,7 @@ export default class Block { this.bindings = options.bindings; this.chunks = { + declarations: [], init: [], create: [], claim: [], @@ -384,6 +386,8 @@ export default class Block { const block = dev && this.get_unique_name('block'); const body = b` + ${this.chunks.declarations} + ${Array.from(this.variables.values()).map(({ id, init }) => { return init ? b`let ${id} = ${init}` diff --git a/src/compiler/compile/render_dom/wrappers/AwaitBlock.ts b/src/compiler/compile/render_dom/wrappers/AwaitBlock.ts index 12b7fc2cef8f..d6ac17f0ced4 100644 --- a/src/compiler/compile/render_dom/wrappers/AwaitBlock.ts +++ b/src/compiler/compile/render_dom/wrappers/AwaitBlock.ts @@ -9,6 +9,7 @@ import PendingBlock from '../../nodes/PendingBlock'; import ThenBlock from '../../nodes/ThenBlock'; import CatchBlock from '../../nodes/CatchBlock'; import { Identifier } from 'estree'; +import traverse_destructure_pattern from '../../utils/traverse_destructure_pattern'; class AwaitBlockBranch extends Wrapper { node: PendingBlock | ThenBlock | CatchBlock; @@ -46,6 +47,23 @@ class AwaitBlockBranch extends Wrapper { this.is_dynamic = this.block.dependencies.size > 0; } + + render(block: Block, parent_node: Identifier, parent_nodes: Identifier) { + this.fragment.render(block, parent_node, parent_nodes); + } + + render_destructure(block: Block, value, node, index) { + if (value && node.pattern.type !== 'Identifier') { + traverse_destructure_pattern(node.pattern, (node, parent, index) => { + parent[index] = x`#ctx[${block.renderer.context_lookup.get(node.name).index}]`; + }); + + this.block.chunks.declarations.push(b`(${node.pattern} = #ctx[${index}])`); + if (this.block.has_update_method) { + this.block.chunks.update.push(b`(${node.pattern} = #ctx[${index}])`); + } + } + } } export default class AwaitBlockWrapper extends Wrapper { @@ -55,6 +73,9 @@ export default class AwaitBlockWrapper extends Wrapper { then: AwaitBlockBranch; catch: AwaitBlockBranch; + value: string; + error: string; + var: Identifier = { type: 'Identifier', name: 'await_block' }; constructor( @@ -71,8 +92,20 @@ export default class AwaitBlockWrapper extends Wrapper { this.not_static_content(); block.add_dependencies(this.node.expression.dependencies); - if (this.node.value) block.renderer.add_to_context(this.node.value, true); - if (this.node.error) block.renderer.add_to_context(this.node.error, true); + if (this.node.value) { + for (const ctx of this.node.value.expressions) { + block.renderer.add_to_context(ctx, true); + } + this.value = this.node.value.identifier_name || block.get_unique_name('value').name; + block.renderer.add_to_context(this.value, true); + } + if (this.node.error) { + for (const ctx of this.node.error.expressions) { + block.renderer.add_to_context(ctx, true); + } + this.error = this.node.error.identifier_name || block.get_unique_name('error').name; + block.renderer.add_to_context(this.error, true); + } let is_dynamic = false; let has_intros = false; @@ -105,17 +138,11 @@ export default class AwaitBlockWrapper extends Wrapper { this[status] = branch; }); - this.pending.block.has_update_method = is_dynamic; - this.then.block.has_update_method = is_dynamic; - this.catch.block.has_update_method = is_dynamic; - - this.pending.block.has_intro_method = has_intros; - this.then.block.has_intro_method = has_intros; - this.catch.block.has_intro_method = has_intros; - - this.pending.block.has_outro_method = has_outros; - this.then.block.has_outro_method = has_outros; - this.catch.block.has_outro_method = has_outros; + ['pending', 'then', 'catch'].forEach(status => { + this[status].block.has_update_method = is_dynamic; + this[status].block.has_intro_method = has_intros; + this[status].block.has_outro_method = has_outros; + }); if (has_outros) { block.add_outro(); @@ -139,8 +166,8 @@ export default class AwaitBlockWrapper extends Wrapper { block.maintain_context = true; - const value_index = this.node.value && block.renderer.context_lookup.get(this.node.value).index; - const error_index = this.node.error && block.renderer.context_lookup.get(this.node.error).index; + const value_index = this.value && block.renderer.context_lookup.get(this.value).index; + const error_index = this.error && block.renderer.context_lookup.get(this.error).index; const info_props: any = x`{ ctx: #ctx, @@ -205,7 +232,7 @@ export default class AwaitBlockWrapper extends Wrapper { } else { const #child_ctx = #ctx.slice(); - ${this.node.value && b`#child_ctx[${value_index}] = ${info}.resolved;`} + ${this.value && b`#child_ctx[${value_index}] = ${info}.resolved;`} ${info}.block.p(#child_ctx, #dirty); } `); @@ -219,7 +246,7 @@ export default class AwaitBlockWrapper extends Wrapper { block.chunks.update.push(b` { const #child_ctx = #ctx.slice(); - ${this.node.value && b`#child_ctx[${value_index}] = ${info}.resolved;`} + ${this.value && b`#child_ctx[${value_index}] = ${info}.resolved;`} ${info}.block.p(#child_ctx, #dirty); } `); @@ -242,7 +269,9 @@ export default class AwaitBlockWrapper extends Wrapper { `); [this.pending, this.then, this.catch].forEach(branch => { - branch.fragment.render(branch.block, null, x`#nodes` as Identifier); + branch.render(branch.block, null, x`#nodes` as Identifier); }); + this.then.render_destructure(block, this.value, this.node.value, value_index); + this.catch.render_destructure(block, this.error, this.node.error, error_index); } } diff --git a/src/compiler/compile/render_ssr/handlers/AwaitBlock.ts b/src/compiler/compile/render_ssr/handlers/AwaitBlock.ts index f63782628045..d6bb86f1a4d3 100644 --- a/src/compiler/compile/render_ssr/handlers/AwaitBlock.ts +++ b/src/compiler/compile/render_ssr/handlers/AwaitBlock.ts @@ -14,7 +14,7 @@ export default function(node: AwaitBlock, renderer: Renderer, options: RenderOpt renderer.add_expression(x` function(__value) { if (@is_promise(__value)) return ${pending}; - return (function(${node.value}) { return ${then}; }(__value)); + return (function(${node.value ? node.value.pattern : ''}) { return ${then}; }(__value)); }(${node.expression.node}) `); } diff --git a/src/compiler/compile/utils/traverse_destructure_pattern.ts b/src/compiler/compile/utils/traverse_destructure_pattern.ts new file mode 100644 index 000000000000..6c918c28c07f --- /dev/null +++ b/src/compiler/compile/utils/traverse_destructure_pattern.ts @@ -0,0 +1,35 @@ +import { Pattern, Identifier, RestElement } from "estree"; +import { Node } from "acorn"; + +export default function traverse_destructure_pattern( + node: Pattern, + callback: (node: Identifier, parent: Node, key: string | number) => void +) { + function traverse(node: Pattern, parent, key) { + switch (node.type) { + case "Identifier": + return callback(node, parent, key); + case "ArrayPattern": + for (let i = 0; i < node.elements.length; i++) { + const element = node.elements[i]; + traverse(element, node.elements, i); + } + break; + case "ObjectPattern": + for (let i = 0; i < node.properties.length; i++) { + const property = node.properties[i]; + if (property.type === "Property") { + traverse(property.value, property, "value"); + } else { + traverse((property as any) as RestElement, node.properties, i); + } + } + break; + case "RestElement": + return traverse(node.argument, node, 'argument'); + case "AssignmentPattern": + return traverse(node.left, node, 'left'); + } + } + traverse(node, null, null); +} diff --git a/src/compiler/parse/index.ts b/src/compiler/parse/index.ts index a809eeebeb31..c21e6d6f7968 100644 --- a/src/compiler/parse/index.ts +++ b/src/compiler/parse/index.ts @@ -5,6 +5,9 @@ import { reserved } from '../utils/names'; import full_char_code_at from '../utils/full_char_code_at'; import { TemplateNode, Ast, ParserOptions, Fragment, Style, Script } from '../interfaces'; import error from '../utils/error'; +import { is_bracket_open, is_bracket_close, is_bracket_pair, get_bracket_close } from './utils/bracket'; +import { parse_expression_at } from './acorn'; +import { Pattern } from 'estree'; type ParserState = (parser: Parser) => (ParserState | void); @@ -170,6 +173,51 @@ export class Parser { return identifier; } + read_destructure_pattern(): Pattern { + const start = this.index; + let i = this.index; + + const code = full_char_code_at(this.template, i); + if (isIdentifierStart(code, true)) { + return { type: 'Identifier', name: this.read_identifier() }; + } + + if (!is_bracket_open(code)) { + this.error({ + code: 'unexpected-token', + message: 'Expected identifier or destructure pattern', + }); + } + + const bracket_stack = [code]; + i += code <= 0xffff ? 1 : 2; + + while (i < this.template.length) { + const code = full_char_code_at(this.template, i); + if (is_bracket_open(code)) { + bracket_stack.push(code); + } else if (is_bracket_close(code)) { + if (!is_bracket_pair(bracket_stack[bracket_stack.length - 1], code)) { + this.error({ + code: 'unexpected-token', + message: `Expected ${String.fromCharCode(get_bracket_close(bracket_stack[bracket_stack.length - 1]))}` + }); + } + bracket_stack.pop(); + if (bracket_stack.length === 0) { + i += code <= 0xffff ? 1 : 2; + break; + } + } + i += code <= 0xffff ? 1 : 2; + } + + this.index = i; + + const pattern_string = this.template.slice(start, i); + return (parse_expression_at(`(${pattern_string} = 1)`, 0) as any).left as Pattern; + } + read_until(pattern: RegExp) { if (this.index >= this.template.length) this.error({ diff --git a/src/compiler/parse/state/mustache.ts b/src/compiler/parse/state/mustache.ts index e5e365dddfaf..28ef853f8e1d 100644 --- a/src/compiler/parse/state/mustache.ts +++ b/src/compiler/parse/state/mustache.ts @@ -196,7 +196,7 @@ export default function mustache(parser: Parser) { if (!parser.eat('}')) { parser.require_whitespace(); - await_block[is_then ? 'value': 'error'] = parser.read_identifier(); + await_block[is_then ? 'value': 'error'] = parser.read_destructure_pattern(); parser.allow_whitespace(); parser.eat('}', true); } @@ -305,7 +305,7 @@ export default function mustache(parser: Parser) { const await_block_shorthand = type === 'AwaitBlock' && parser.eat('then'); if (await_block_shorthand) { parser.require_whitespace(); - block.value = parser.read_identifier(); + block.value = parser.read_destructure_pattern(); parser.allow_whitespace(); } diff --git a/src/compiler/parse/utils/bracket.ts b/src/compiler/parse/utils/bracket.ts new file mode 100644 index 000000000000..ffbb9e49521b --- /dev/null +++ b/src/compiler/parse/utils/bracket.ts @@ -0,0 +1,28 @@ +const SQUARE_BRACKET_OPEN = "[".charCodeAt(0); +const SQUARE_BRACKET_CLOSE = "]".charCodeAt(0); +const CURLY_BRACKET_OPEN = "{".charCodeAt(0); +const CURLY_BRACKET_CLOSE = "}".charCodeAt(0); + +export function is_bracket_open(code) { + return code === SQUARE_BRACKET_OPEN || code === CURLY_BRACKET_OPEN; +} + +export function is_bracket_close(code) { + return code === SQUARE_BRACKET_CLOSE || code === CURLY_BRACKET_CLOSE; +} + +export function is_bracket_pair(open, close) { + return ( + (open === SQUARE_BRACKET_OPEN && close === SQUARE_BRACKET_CLOSE) || + (open === CURLY_BRACKET_OPEN && close === CURLY_BRACKET_CLOSE) + ); +} + +export function get_bracket_close(open) { + if (open === SQUARE_BRACKET_OPEN) { + return SQUARE_BRACKET_CLOSE; + } + if (open === CURLY_BRACKET_OPEN) { + return CURLY_BRACKET_CLOSE; + } +} \ No newline at end of file diff --git a/src/compiler/utils/error.ts b/src/compiler/utils/error.ts index d13222578aa6..e05ea66df1c1 100644 --- a/src/compiler/utils/error.ts +++ b/src/compiler/utils/error.ts @@ -21,7 +21,7 @@ export default function error(message: string, props: { filename: string; start: number; end?: number; -}) { +}): never { const error = new CompileError(message); error.name = props.name; diff --git a/test/parser/samples/await-catch/output.json b/test/parser/samples/await-catch/output.json index 2461f467f264..d47d27e4cb93 100644 --- a/test/parser/samples/await-catch/output.json +++ b/test/parser/samples/await-catch/output.json @@ -25,7 +25,10 @@ "name": "thePromise" }, "value": null, - "error": "theError", + "error": { + "type": "Identifier", + "name": "theError" + }, "pending": { "start": 19, "end": 39, diff --git a/test/parser/samples/await-then-catch/output.json b/test/parser/samples/await-then-catch/output.json index d9defb69329d..01dc89f3f904 100644 --- a/test/parser/samples/await-then-catch/output.json +++ b/test/parser/samples/await-then-catch/output.json @@ -24,8 +24,14 @@ }, "name": "thePromise" }, - "value": "theValue", - "error": "theError", + "value": { + "type": "Identifier", + "name": "theValue" + }, + "error": { + "type": "Identifier", + "name": "theError" + }, "pending": { "start": 19, "end": 39, diff --git a/test/parser/samples/no-error-if-before-closing/output.json b/test/parser/samples/no-error-if-before-closing/output.json index 251cefc0ca81..e30c302e0f95 100644 --- a/test/parser/samples/no-error-if-before-closing/output.json +++ b/test/parser/samples/no-error-if-before-closing/output.json @@ -115,7 +115,10 @@ "value": true, "raw": "true" }, - "value": "f", + "value": { + "type": "Identifier", + "name": "f" + }, "error": null, "pending": { "start": 80, @@ -198,7 +201,10 @@ "value": true, "raw": "true" }, - "value": "f", + "value": { + "type": "Identifier", + "name": "f" + }, "error": null, "pending": { "start": 123, diff --git a/test/runtime/samples/await-then-destruct-array/_config.js b/test/runtime/samples/await-then-destruct-array/_config.js new file mode 100644 index 000000000000..55c48481e0d0 --- /dev/null +++ b/test/runtime/samples/await-then-destruct-array/_config.js @@ -0,0 +1,61 @@ +export default { + props: { + thePromise: new Promise(resolve => {}) + }, + + html: ` + loading... + `, + + async test({ assert, component, target }) { + await (component.thePromise = Promise.resolve([1, 2])); + + assert.htmlEqual( + target.innerHTML, + ` +

a: 1

+

b: 2

+ ` + ); + + await (component.thePromise = Promise.resolve([4, 5])); + + assert.htmlEqual( + target.innerHTML, + ` +

a: 4

+

b: 5

+ ` + ); + + try { + await (component.thePromise = Promise.reject(['a', [6, 7]])); + } catch (e) { + // do nothing + } + + assert.htmlEqual( + target.innerHTML, + ` +

c: a

+

d: 6

+

e: 7

+ ` + ); + + try { + await (component.thePromise = Promise.reject(['b', [8, 9]])); + } catch (e) { + // do nothing + } + + assert.htmlEqual( + target.innerHTML, + ` +

c: b

+

d: 8

+

e: 9

+ ` + ); + } +}; diff --git a/test/runtime/samples/await-then-destruct-array/main.svelte b/test/runtime/samples/await-then-destruct-array/main.svelte new file mode 100644 index 000000000000..cc0d217f7984 --- /dev/null +++ b/test/runtime/samples/await-then-destruct-array/main.svelte @@ -0,0 +1,14 @@ + + +{#await thePromise} + loading... +{:then [ a, b ]} +

a: {a}

+

b: {b}

+{:catch [c, [d, e]]} +

c: {c}

+

d: {d}

+

e: {e}

+{/await} \ No newline at end of file diff --git a/test/runtime/samples/await-then-destruct-default/_config.js b/test/runtime/samples/await-then-destruct-default/_config.js new file mode 100644 index 000000000000..d0e5a49f28cd --- /dev/null +++ b/test/runtime/samples/await-then-destruct-default/_config.js @@ -0,0 +1,23 @@ +export default { + async test({ assert, component, target }) { + await Promise.resolve(); + + assert.htmlEqual( + target.innerHTML, + ` +

a: 3

+

b: 2

+

c: 3

+

a: 1

+

b: 2

+

c: 3

+

a: 3

+

b: 2

+

c: 3

+

a: 1

+

b: 2

+

c: 3

+ ` + ); + } +}; diff --git a/test/runtime/samples/await-then-destruct-default/main.svelte b/test/runtime/samples/await-then-destruct-default/main.svelte new file mode 100644 index 000000000000..d559aadab163 --- /dev/null +++ b/test/runtime/samples/await-then-destruct-default/main.svelte @@ -0,0 +1,34 @@ + + +{#await object then { a = 3, b = 4, c }} +

a: {a}

+

b: {b}

+

c: {c}

+{/await} + +{#await array then [a, b, c = 3]} +

a: {a}

+

b: {b}

+

c: {c}

+{/await} + +{#await objectReject then value} + resolved +{:catch { a = 3, b = 4, c }} +

a: {a}

+

b: {b}

+

c: {c}

+{/await} + +{#await arrayReject then value} + resolved +{:catch [a, b, c = 3]} +

a: {a}

+

b: {b}

+

c: {c}

+{/await} \ No newline at end of file diff --git a/test/runtime/samples/await-then-destruct-object/_config.js b/test/runtime/samples/await-then-destruct-object/_config.js new file mode 100644 index 000000000000..371462de9799 --- /dev/null +++ b/test/runtime/samples/await-then-destruct-object/_config.js @@ -0,0 +1,63 @@ +export default { + props: { + thePromise: new Promise(resolve => {}) + }, + + html: ` + loading... + `, + + async test({ assert, component, target }) { + await (component.thePromise = Promise.resolve({ error: "error message" })); + + assert.htmlEqual( + target.innerHTML, + ` +

error: error message

+

result: undefined

+ ` + ); + + await (component.thePromise = Promise.resolve({ result: "42" })); + + assert.htmlEqual( + target.innerHTML, + ` +

error: undefined

+

result: 42

+ ` + ); + + try { + await (component.thePromise = Promise.reject({ + error: { message: "oops", code: "123" } + })); + } catch (e) { + // do nothing + } + + assert.htmlEqual( + target.innerHTML, + ` +

message: oops

+

code: 123

+ ` + ); + + try { + await (component.thePromise = Promise.reject({ + error: { message: "timeout", code: "456" } + })); + } catch (e) { + // do nothing + } + + assert.htmlEqual( + target.innerHTML, + ` +

message: timeout

+

code: 456

+ ` + ); + } +}; diff --git a/test/runtime/samples/await-then-destruct-object/main.svelte b/test/runtime/samples/await-then-destruct-object/main.svelte new file mode 100644 index 000000000000..ff574b7be806 --- /dev/null +++ b/test/runtime/samples/await-then-destruct-object/main.svelte @@ -0,0 +1,13 @@ + + +{#await thePromise} + loading... +{:then { result, error }} +

error: {error}

+

result: {result}

+{:catch { error: { message, code } }} +

message: {message}

+

code: {code}

+{/await} \ No newline at end of file diff --git a/test/runtime/samples/await-then-destruct-rest/_config.js b/test/runtime/samples/await-then-destruct-rest/_config.js new file mode 100644 index 000000000000..528568e569bc --- /dev/null +++ b/test/runtime/samples/await-then-destruct-rest/_config.js @@ -0,0 +1,21 @@ +export default { + async test({ assert, component, target }) { + await Promise.resolve(); + + assert.htmlEqual( + target.innerHTML, + ` +

a: 1

+

rest: {"b":2,"c":3}

+

a: 1

+

b: 2

+

rest: [3,4,5,6]

+

a: 1

+

rest: {"b":2,"c":3}

+

a: 1

+

b: 2

+

rest: [3,4,5,6]

+ ` + ); + } +}; diff --git a/test/runtime/samples/await-then-destruct-rest/main.svelte b/test/runtime/samples/await-then-destruct-rest/main.svelte new file mode 100644 index 000000000000..a2d57dabf384 --- /dev/null +++ b/test/runtime/samples/await-then-destruct-rest/main.svelte @@ -0,0 +1,32 @@ + + +{#await object then { a, ...rest }} +

a: {a}

+

rest: {JSON.stringify(rest)}

+{/await} + +{#await array then [a, b, ...rest]} +

a: {a}

+

b: {b}

+

rest: {JSON.stringify(rest)}

+{/await} + +{#await objectReject then value} + resolved +{:catch { a, ...rest }} +

a: {a}

+

rest: {JSON.stringify(rest)}

+{/await} + +{#await arrayReject then value} + resolved +{:catch [a, b, ...rest]} +

a: {a}

+

b: {b}

+

rest: {JSON.stringify(rest)}

+{/await} \ No newline at end of file From b4b57c39a25a736b339b936257220510182895ab Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Sun, 15 Mar 2020 22:18:41 +0800 Subject: [PATCH 050/158] clean up event handlers on re-mount (#4493) --- CHANGELOG.md | 1 + src/compiler/compile/render_dom/Block.ts | 12 +++++- src/runtime/internal/keyed_each.ts | 2 +- .../action-custom-event-handler/expected.js | 3 +- test/js/samples/action/expected.js | 3 +- test/js/samples/bind-online/expected.js | 4 +- test/js/samples/bind-open/expected.js | 3 +- .../bindings-readonly-order/expected.js | 3 +- .../capture-inject-dev-only/expected.js | 3 +- .../samples/component-static-var/expected.js | 3 +- .../expected.js | 3 +- .../samples/dont-invalidate-this/expected.js | 3 +- .../samples/event-handler-dynamic/expected.js | 3 +- .../event-handler-no-passive/expected.js | 3 +- test/js/samples/event-modifiers/expected.js | 3 +- test/js/samples/input-files/expected.js | 3 +- .../input-no-initial-value/expected.js | 3 +- test/js/samples/input-range/expected.js | 3 +- test/js/samples/input-value/expected.js | 3 +- .../input-without-blowback-guard/expected.js | 3 +- .../expected.js | 3 +- .../expected.js | 3 +- .../expected.js | 3 +- .../expected.js | 3 +- test/js/samples/media-bindings/expected.js | 4 +- test/js/samples/video-bindings/expected.js | 3 +- .../samples/window-binding-online/expected.js | 4 +- .../samples/window-binding-scroll/expected.js | 3 +- .../event-handler-each-modifier/_config.js | 42 +++++++++++++++++++ .../event-handler-each-modifier/main.svelte | 37 ++++++++++++++++ 30 files changed, 144 insertions(+), 28 deletions(-) create mode 100644 test/runtime/samples/event-handler-each-modifier/_config.js create mode 100644 test/runtime/samples/event-handler-each-modifier/main.svelte diff --git a/CHANGELOG.md b/CHANGELOG.md index a24223e5bcf7..2d8e6a09ac30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ * Allow transitions and animations to work within iframes ([#3624](https://github.com/sveltejs/svelte/issues/3624)) * Fix initialising slot fallbacks when unnecessary ([#3763](https://github.com/sveltejs/svelte/issues/3763)) * Disallow binding directly to `const` variables ([#4479](https://github.com/sveltejs/svelte/issues/4479)) +* Fix re-attaching event handlers on keyed `{#each}` blocks ([#4491](https://github.com/sveltejs/svelte/issues/4491)) * Fix updating keyed `{#each}` blocks with `{:else}` ([#4536](https://github.com/sveltejs/svelte/issues/4536), [#4549](https://github.com/sveltejs/svelte/issues/4549)) * Fix hydration of top-level content ([#4542](https://github.com/sveltejs/svelte/issues/4542)) diff --git a/src/compiler/compile/render_dom/Block.ts b/src/compiler/compile/render_dom/Block.ts index 3deba786b4f7..c84359459912 100644 --- a/src/compiler/compile/render_dom/Block.ts +++ b/src/compiler/compile/render_dom/Block.ts @@ -294,10 +294,14 @@ export default class Block { if (this.chunks.mount.length === 0) { properties.mount = noop; - } else { + } else if (this.event_listeners.length === 0) { properties.mount = x`function #mount(#target, anchor) { ${this.chunks.mount} }`; + } else { + properties.mount = x`function #mount(#target, anchor, #remount) { + ${this.chunks.mount} + }`; } if (this.has_update_method || this.maintain_context) { @@ -457,7 +461,10 @@ export default class Block { if (this.event_listeners.length === 1) { this.chunks.mount.push( - b`${dispose} = ${this.event_listeners[0]};` + b` + if (#remount) ${dispose}(); + ${dispose} = ${this.event_listeners[0]}; + ` ); this.chunks.destroy.push( @@ -465,6 +472,7 @@ export default class Block { ); } else { this.chunks.mount.push(b` + if (#remount) @run_all(${dispose}); ${dispose} = [ ${this.event_listeners} ]; diff --git a/src/runtime/internal/keyed_each.ts b/src/runtime/internal/keyed_each.ts index b397335c8766..6b56010d46cc 100644 --- a/src/runtime/internal/keyed_each.ts +++ b/src/runtime/internal/keyed_each.ts @@ -56,7 +56,7 @@ export function update_keyed_each(old_blocks, dirty, get_key, dynamic, ctx, list function insert(block) { transition_in(block, 1); - block.m(node, next); + block.m(node, next, lookup.has(block.key)); lookup.set(block.key, block); next = block.first; n--; diff --git a/test/js/samples/action-custom-event-handler/expected.js b/test/js/samples/action-custom-event-handler/expected.js index ead6d90e0639..aa2941f404c8 100644 --- a/test/js/samples/action-custom-event-handler/expected.js +++ b/test/js/samples/action-custom-event-handler/expected.js @@ -21,8 +21,9 @@ function create_fragment(ctx) { button = element("button"); button.textContent = "foo"; }, - m(target, anchor) { + m(target, anchor, remount) { insert(target, button, anchor); + if (remount) dispose(); dispose = action_destroyer(foo_action = foo.call(null, button, /*foo_function*/ ctx[1])); }, p(ctx, [dirty]) { diff --git a/test/js/samples/action/expected.js b/test/js/samples/action/expected.js index 22d9cd939c2c..1b3f5cc94583 100644 --- a/test/js/samples/action/expected.js +++ b/test/js/samples/action/expected.js @@ -22,8 +22,9 @@ function create_fragment(ctx) { a.textContent = "Test"; attr(a, "href", "#"); }, - m(target, anchor) { + m(target, anchor, remount) { insert(target, a, anchor); + if (remount) dispose(); dispose = action_destroyer(link_action = link.call(null, a)); }, p: noop, diff --git a/test/js/samples/bind-online/expected.js b/test/js/samples/bind-online/expected.js index e129e66d7163..fa955e4fd59b 100644 --- a/test/js/samples/bind-online/expected.js +++ b/test/js/samples/bind-online/expected.js @@ -15,7 +15,9 @@ function create_fragment(ctx) { return { c: noop, - m(target, anchor) { + m(target, anchor, remount) { + if (remount) run_all(dispose); + dispose = [ listen(window, "online", /*onlinestatuschanged*/ ctx[1]), listen(window, "offline", /*onlinestatuschanged*/ ctx[1]) diff --git a/test/js/samples/bind-open/expected.js b/test/js/samples/bind-open/expected.js index 7d66145f0ae7..77b68f1b27fc 100644 --- a/test/js/samples/bind-open/expected.js +++ b/test/js/samples/bind-open/expected.js @@ -21,9 +21,10 @@ function create_fragment(ctx) { details.innerHTML = `summarycontent `; }, - m(target, anchor) { + m(target, anchor, remount) { insert(target, details, anchor); details.open = /*open*/ ctx[0]; + if (remount) dispose(); dispose = listen(details, "toggle", /*details_toggle_handler*/ ctx[1]); }, p(ctx, [dirty]) { diff --git a/test/js/samples/bindings-readonly-order/expected.js b/test/js/samples/bindings-readonly-order/expected.js index db0e7cb007ae..00e8a5bf00cc 100644 --- a/test/js/samples/bindings-readonly-order/expected.js +++ b/test/js/samples/bindings-readonly-order/expected.js @@ -27,10 +27,11 @@ function create_fragment(ctx) { attr(input0, "type", "file"); attr(input1, "type", "file"); }, - m(target, anchor) { + m(target, anchor, remount) { insert(target, input0, anchor); insert(target, t, anchor); insert(target, input1, anchor); + if (remount) run_all(dispose); dispose = [ listen(input0, "change", /*input0_change_handler*/ ctx[1]), diff --git a/test/js/samples/capture-inject-dev-only/expected.js b/test/js/samples/capture-inject-dev-only/expected.js index a314b0cff33b..3e355e149186 100644 --- a/test/js/samples/capture-inject-dev-only/expected.js +++ b/test/js/samples/capture-inject-dev-only/expected.js @@ -29,12 +29,13 @@ function create_fragment(ctx) { t1 = space(); input = element("input"); }, - m(target, anchor) { + m(target, anchor, remount) { insert(target, p, anchor); append(p, t0); insert(target, t1, anchor); insert(target, input, anchor); set_input_value(input, /*foo*/ ctx[0]); + if (remount) dispose(); dispose = listen(input, "input", /*input_input_handler*/ ctx[1]); }, p(ctx, [dirty]) { diff --git a/test/js/samples/component-static-var/expected.js b/test/js/samples/component-static-var/expected.js index a65d9186a78e..c032a0636d42 100644 --- a/test/js/samples/component-static-var/expected.js +++ b/test/js/samples/component-static-var/expected.js @@ -36,7 +36,7 @@ function create_fragment(ctx) { t1 = space(); input = element("input"); }, - m(target, anchor) { + m(target, anchor, remount) { mount_component(foo, target, anchor); insert(target, t0, anchor); mount_component(bar, target, anchor); @@ -44,6 +44,7 @@ function create_fragment(ctx) { insert(target, input, anchor); set_input_value(input, /*z*/ ctx[0]); current = true; + if (remount) dispose(); dispose = listen(input, "input", /*input_input_handler*/ ctx[1]); }, p(ctx, [dirty]) { diff --git a/test/js/samples/component-store-reassign-invalidate/expected.js b/test/js/samples/component-store-reassign-invalidate/expected.js index 771b20dec4ea..b33047d8f377 100644 --- a/test/js/samples/component-store-reassign-invalidate/expected.js +++ b/test/js/samples/component-store-reassign-invalidate/expected.js @@ -32,11 +32,12 @@ function create_fragment(ctx) { button = element("button"); button.textContent = "reset"; }, - m(target, anchor) { + m(target, anchor, remount) { insert(target, h1, anchor); append(h1, t0); insert(target, t1, anchor); insert(target, button, anchor); + if (remount) dispose(); dispose = listen(button, "click", /*click_handler*/ ctx[2]); }, p(ctx, [dirty]) { diff --git a/test/js/samples/dont-invalidate-this/expected.js b/test/js/samples/dont-invalidate-this/expected.js index f5f6d078125d..ba9e7152d75c 100644 --- a/test/js/samples/dont-invalidate-this/expected.js +++ b/test/js/samples/dont-invalidate-this/expected.js @@ -18,8 +18,9 @@ function create_fragment(ctx) { c() { input = element("input"); }, - m(target, anchor) { + m(target, anchor, remount) { insert(target, input, anchor); + if (remount) dispose(); dispose = listen(input, "input", make_uppercase); }, p: noop, diff --git a/test/js/samples/event-handler-dynamic/expected.js b/test/js/samples/event-handler-dynamic/expected.js index 16b4a3f6262e..d8f5710023a6 100644 --- a/test/js/samples/event-handler-dynamic/expected.js +++ b/test/js/samples/event-handler-dynamic/expected.js @@ -43,7 +43,7 @@ function create_fragment(ctx) { button2 = element("button"); button2.textContent = "click"; }, - m(target, anchor) { + m(target, anchor, remount) { insert(target, p0, anchor); append(p0, button0); append(p0, t1); @@ -53,6 +53,7 @@ function create_fragment(ctx) { append(p1, t4); insert(target, t5, anchor); insert(target, button2, anchor); + if (remount) run_all(dispose); dispose = [ listen(button0, "click", /*updateHandler1*/ ctx[2]), diff --git a/test/js/samples/event-handler-no-passive/expected.js b/test/js/samples/event-handler-no-passive/expected.js index c519fac668f5..8bf2de769371 100644 --- a/test/js/samples/event-handler-no-passive/expected.js +++ b/test/js/samples/event-handler-no-passive/expected.js @@ -21,8 +21,9 @@ function create_fragment(ctx) { a.textContent = "this should not navigate to example.com"; attr(a, "href", "https://example.com"); }, - m(target, anchor) { + m(target, anchor, remount) { insert(target, a, anchor); + if (remount) dispose(); dispose = listen(a, "touchstart", touchstart_handler); }, p: noop, diff --git a/test/js/samples/event-modifiers/expected.js b/test/js/samples/event-modifiers/expected.js index c12c3523a0a1..2eca5f29b89c 100644 --- a/test/js/samples/event-modifiers/expected.js +++ b/test/js/samples/event-modifiers/expected.js @@ -36,13 +36,14 @@ function create_fragment(ctx) { button2 = element("button"); button2.textContent = "or me!"; }, - m(target, anchor) { + m(target, anchor, remount) { insert(target, div, anchor); append(div, button0); append(div, t1); append(div, button1); append(div, t3); append(div, button2); + if (remount) run_all(dispose); dispose = [ listen(button0, "click", stop_propagation(prevent_default(handleClick))), diff --git a/test/js/samples/input-files/expected.js b/test/js/samples/input-files/expected.js index 2a2254fbd754..1c1e57fc9b24 100644 --- a/test/js/samples/input-files/expected.js +++ b/test/js/samples/input-files/expected.js @@ -21,8 +21,9 @@ function create_fragment(ctx) { attr(input, "type", "file"); input.multiple = true; }, - m(target, anchor) { + m(target, anchor, remount) { insert(target, input, anchor); + if (remount) dispose(); dispose = listen(input, "change", /*input_change_handler*/ ctx[1]); }, p: noop, diff --git a/test/js/samples/input-no-initial-value/expected.js b/test/js/samples/input-no-initial-value/expected.js index d588f0bf735a..f72daa22a302 100644 --- a/test/js/samples/input-no-initial-value/expected.js +++ b/test/js/samples/input-no-initial-value/expected.js @@ -32,12 +32,13 @@ function create_fragment(ctx) { attr(input, "type", "text"); input.required = true; }, - m(target, anchor) { + m(target, anchor, remount) { insert(target, form, anchor); append(form, input); set_input_value(input, /*test*/ ctx[0]); append(form, t0); append(form, button); + if (remount) run_all(dispose); dispose = [ listen(input, "input", /*input_input_handler*/ ctx[2]), diff --git a/test/js/samples/input-range/expected.js b/test/js/samples/input-range/expected.js index 12dfd3e90efe..17a806544907 100644 --- a/test/js/samples/input-range/expected.js +++ b/test/js/samples/input-range/expected.js @@ -23,9 +23,10 @@ function create_fragment(ctx) { input = element("input"); attr(input, "type", "range"); }, - m(target, anchor) { + m(target, anchor, remount) { insert(target, input, anchor); set_input_value(input, /*value*/ ctx[0]); + if (remount) run_all(dispose); dispose = [ listen(input, "change", /*input_change_input_handler*/ ctx[1]), diff --git a/test/js/samples/input-value/expected.js b/test/js/samples/input-value/expected.js index 21c7bfc83b9e..31be2895ac0d 100644 --- a/test/js/samples/input-value/expected.js +++ b/test/js/samples/input-value/expected.js @@ -31,12 +31,13 @@ function create_fragment(ctx) { t2 = text("!"); input.value = /*name*/ ctx[0]; }, - m(target, anchor) { + m(target, anchor, remount) { insert(target, input, anchor); insert(target, t0, anchor); insert(target, h1, anchor); append(h1, t1); append(h1, t2); + if (remount) dispose(); dispose = listen(input, "input", /*onInput*/ ctx[1]); }, p(ctx, [dirty]) { diff --git a/test/js/samples/input-without-blowback-guard/expected.js b/test/js/samples/input-without-blowback-guard/expected.js index fefe867e146b..1e379032f3a1 100644 --- a/test/js/samples/input-without-blowback-guard/expected.js +++ b/test/js/samples/input-without-blowback-guard/expected.js @@ -20,9 +20,10 @@ function create_fragment(ctx) { input = element("input"); attr(input, "type", "checkbox"); }, - m(target, anchor) { + m(target, anchor, remount) { insert(target, input, anchor); input.checked = /*foo*/ ctx[0]; + if (remount) dispose(); dispose = listen(input, "change", /*input_change_handler*/ ctx[1]); }, p(ctx, [dirty]) { diff --git a/test/js/samples/instrumentation-script-if-no-block/expected.js b/test/js/samples/instrumentation-script-if-no-block/expected.js index 7634481a2d6a..f45e52aebd3b 100644 --- a/test/js/samples/instrumentation-script-if-no-block/expected.js +++ b/test/js/samples/instrumentation-script-if-no-block/expected.js @@ -31,12 +31,13 @@ function create_fragment(ctx) { t2 = text("x: "); t3 = text(/*x*/ ctx[0]); }, - m(target, anchor) { + m(target, anchor, remount) { insert(target, button, anchor); insert(target, t1, anchor); insert(target, p, anchor); append(p, t2); append(p, t3); + if (remount) dispose(); dispose = listen(button, "click", /*foo*/ ctx[1]); }, p(ctx, [dirty]) { diff --git a/test/js/samples/instrumentation-script-x-equals-x/expected.js b/test/js/samples/instrumentation-script-x-equals-x/expected.js index c154608cd52c..9fe964097829 100644 --- a/test/js/samples/instrumentation-script-x-equals-x/expected.js +++ b/test/js/samples/instrumentation-script-x-equals-x/expected.js @@ -32,12 +32,13 @@ function create_fragment(ctx) { t2 = text("number of things: "); t3 = text(t3_value); }, - m(target, anchor) { + m(target, anchor, remount) { insert(target, button, anchor); insert(target, t1, anchor); insert(target, p, anchor); append(p, t2); append(p, t3); + if (remount) dispose(); dispose = listen(button, "click", /*foo*/ ctx[1]); }, p(ctx, [dirty]) { diff --git a/test/js/samples/instrumentation-template-if-no-block/expected.js b/test/js/samples/instrumentation-template-if-no-block/expected.js index 77780baa99d1..6f3bea4010fc 100644 --- a/test/js/samples/instrumentation-template-if-no-block/expected.js +++ b/test/js/samples/instrumentation-template-if-no-block/expected.js @@ -31,12 +31,13 @@ function create_fragment(ctx) { t2 = text("x: "); t3 = text(/*x*/ ctx[0]); }, - m(target, anchor) { + m(target, anchor, remount) { insert(target, button, anchor); insert(target, t1, anchor); insert(target, p, anchor); append(p, t2); append(p, t3); + if (remount) dispose(); dispose = listen(button, "click", /*click_handler*/ ctx[1]); }, p(ctx, [dirty]) { diff --git a/test/js/samples/instrumentation-template-x-equals-x/expected.js b/test/js/samples/instrumentation-template-x-equals-x/expected.js index 4fe45616c75b..ed095353bd53 100644 --- a/test/js/samples/instrumentation-template-x-equals-x/expected.js +++ b/test/js/samples/instrumentation-template-x-equals-x/expected.js @@ -32,12 +32,13 @@ function create_fragment(ctx) { t2 = text("number of things: "); t3 = text(t3_value); }, - m(target, anchor) { + m(target, anchor, remount) { insert(target, button, anchor); insert(target, t1, anchor); insert(target, p, anchor); append(p, t2); append(p, t3); + if (remount) dispose(); dispose = listen(button, "click", /*click_handler*/ ctx[1]); }, p(ctx, [dirty]) { diff --git a/test/js/samples/media-bindings/expected.js b/test/js/samples/media-bindings/expected.js index 52fef3679246..e58d32cf294d 100644 --- a/test/js/samples/media-bindings/expected.js +++ b/test/js/samples/media-bindings/expected.js @@ -42,7 +42,7 @@ function create_fragment(ctx) { if (/*seeking*/ ctx[8] === void 0) add_render_callback(() => /*audio_seeking_seeked_handler*/ ctx[17].call(audio)); if (/*ended*/ ctx[9] === void 0) add_render_callback(() => /*audio_ended_handler*/ ctx[18].call(audio)); }, - m(target, anchor) { + m(target, anchor, remount) { insert(target, audio, anchor); if (!isNaN(/*volume*/ ctx[6])) { @@ -53,6 +53,8 @@ function create_fragment(ctx) { audio.playbackRate = /*playbackRate*/ ctx[7]; } + if (remount) run_all(dispose); + dispose = [ listen(audio, "progress", /*audio_progress_handler*/ ctx[10]), listen(audio, "loadedmetadata", /*audio_loadedmetadata_handler*/ ctx[11]), diff --git a/test/js/samples/video-bindings/expected.js b/test/js/samples/video-bindings/expected.js index c8cd1d84ce0d..3cad17b34d3e 100644 --- a/test/js/samples/video-bindings/expected.js +++ b/test/js/samples/video-bindings/expected.js @@ -38,9 +38,10 @@ function create_fragment(ctx) { if (/*videoHeight*/ ctx[1] === void 0 || /*videoWidth*/ ctx[2] === void 0) add_render_callback(() => /*video_resize_handler*/ ctx[5].call(video)); add_render_callback(() => /*video_elementresize_handler*/ ctx[6].call(video)); }, - m(target, anchor) { + m(target, anchor, remount) { insert(target, video, anchor); video_resize_listener = add_resize_listener(video, /*video_elementresize_handler*/ ctx[6].bind(video)); + if (remount) run_all(dispose); dispose = [ listen(video, "timeupdate", video_timeupdate_handler), diff --git a/test/js/samples/window-binding-online/expected.js b/test/js/samples/window-binding-online/expected.js index e129e66d7163..fa955e4fd59b 100644 --- a/test/js/samples/window-binding-online/expected.js +++ b/test/js/samples/window-binding-online/expected.js @@ -15,7 +15,9 @@ function create_fragment(ctx) { return { c: noop, - m(target, anchor) { + m(target, anchor, remount) { + if (remount) run_all(dispose); + dispose = [ listen(window, "online", /*onlinestatuschanged*/ ctx[1]), listen(window, "offline", /*onlinestatuschanged*/ ctx[1]) diff --git a/test/js/samples/window-binding-scroll/expected.js b/test/js/samples/window-binding-scroll/expected.js index 70c39eedd20c..30723cc142fc 100644 --- a/test/js/samples/window-binding-scroll/expected.js +++ b/test/js/samples/window-binding-scroll/expected.js @@ -34,10 +34,11 @@ function create_fragment(ctx) { t0 = text("scrolled to "); t1 = text(/*y*/ ctx[0]); }, - m(target, anchor) { + m(target, anchor, remount) { insert(target, p, anchor); append(p, t0); append(p, t1); + if (remount) dispose(); dispose = listen(window, "scroll", () => { scrolling = true; diff --git a/test/runtime/samples/event-handler-each-modifier/_config.js b/test/runtime/samples/event-handler-each-modifier/_config.js new file mode 100644 index 000000000000..702addd3c317 --- /dev/null +++ b/test/runtime/samples/event-handler-each-modifier/_config.js @@ -0,0 +1,42 @@ +export default { + async test({ assert, component, target, window }) { + // set first + await component.lists.update(() => [ + { text: "item1" }, + { text: "item2" }, + { text: "item3" } + ]); + + await component.lists.update(() => [ + { text: "item3" }, + { text: "item2" }, + { text: "item1" } + ]); + + await component.lists.update(() => [ + { text: "item1" }, + { text: "item2" }, + { text: "item3" } + ]); + + assert.equal(component.updated, 4); + + const [item1, item2] = target.childNodes; + const [item1Btn1, item1Btn2] = item1.querySelectorAll('button'); + const [item2Btn1, item2Btn2] = item2.querySelectorAll('button'); + + const clickEvent = new window.MouseEvent('click'); + + await item1Btn1.dispatchEvent(clickEvent); + assert.equal(component.getNormalCount(), 1); + + await item1Btn2.dispatchEvent(clickEvent); + assert.equal(component.getModifierCount(), 1); + + await item2Btn1.dispatchEvent(clickEvent); + assert.equal(component.getNormalCount(), 2); + + await item2Btn2.dispatchEvent(clickEvent); + assert.equal(component.getModifierCount(), 2); + } +}; diff --git a/test/runtime/samples/event-handler-each-modifier/main.svelte b/test/runtime/samples/event-handler-each-modifier/main.svelte new file mode 100644 index 000000000000..ca7447f728f3 --- /dev/null +++ b/test/runtime/samples/event-handler-each-modifier/main.svelte @@ -0,0 +1,37 @@ + + +{#each $lists as item (item.text)} +
+ {item.text} + + +
+{/each} From 40c5df51a2262186d940331b139fb049f2ae93da Mon Sep 17 00:00:00 2001 From: Conduitry Date: Sun, 15 Mar 2020 10:34:13 -0400 Subject: [PATCH 051/158] -> v3.20.0 --- CHANGELOG.md | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d8e6a09ac30..6ace7d81049f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Svelte changelog -## Unreleased +## 3.20.0 * Allow destructuring in `{#await}` blocks ([#1851](https://github.com/sveltejs/svelte/issues/1851)) * Allow `` to be used in a slot ([#2798](https://github.com/sveltejs/svelte/issues/2798)) diff --git a/package-lock.json b/package-lock.json index 858d90fd1b94..6dccee0d65c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.19.2", + "version": "3.20.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 009e5143a925..4e52b15636e3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.19.2", + "version": "3.20.0", "description": "Cybernetically enhanced web apps", "module": "index.mjs", "main": "index", From cdc0270ef1c74c30a5610d8765fc66194ec8ce65 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Tue, 17 Mar 2020 00:10:20 +0800 Subject: [PATCH 052/158] fix deconflicting variable name for slot fallback (#4564) --- src/compiler/compile/render_dom/wrappers/Slot.ts | 2 +- .../samples/component-slot-fallback-3/Inner.svelte | 6 ++++++ .../runtime/samples/component-slot-fallback-3/_config.js | 6 ++++++ .../samples/component-slot-fallback-3/main.svelte | 9 +++++++++ 4 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 test/runtime/samples/component-slot-fallback-3/Inner.svelte create mode 100644 test/runtime/samples/component-slot-fallback-3/_config.js create mode 100644 test/runtime/samples/component-slot-fallback-3/main.svelte diff --git a/src/compiler/compile/render_dom/wrappers/Slot.ts b/src/compiler/compile/render_dom/wrappers/Slot.ts index 37b10c2ea38a..f28719813208 100644 --- a/src/compiler/compile/render_dom/wrappers/Slot.ts +++ b/src/compiler/compile/render_dom/wrappers/Slot.ts @@ -38,6 +38,7 @@ export default class SlotWrapper extends Wrapper { name: this.renderer.component.get_unique_name(`fallback_block`), type: 'fallback' }); + renderer.blocks.push(this.fallback); } this.fragment = new FragmentWrapper( @@ -115,7 +116,6 @@ export default class SlotWrapper extends Wrapper { if (this.fallback) { this.fragment.render(this.fallback, null, x`#nodes` as Identifier); - renderer.blocks.push(this.fallback); } const slot = block.get_unique_name(`${sanitize(slot_name)}_slot`); diff --git a/test/runtime/samples/component-slot-fallback-3/Inner.svelte b/test/runtime/samples/component-slot-fallback-3/Inner.svelte new file mode 100644 index 000000000000..db2af272d2ca --- /dev/null +++ b/test/runtime/samples/component-slot-fallback-3/Inner.svelte @@ -0,0 +1,6 @@ + +
Hello
+
world
+
Bye
+
World
+
diff --git a/test/runtime/samples/component-slot-fallback-3/_config.js b/test/runtime/samples/component-slot-fallback-3/_config.js new file mode 100644 index 000000000000..b5591fb5e07d --- /dev/null +++ b/test/runtime/samples/component-slot-fallback-3/_config.js @@ -0,0 +1,6 @@ +export default { + html: ` +
Hello World
+
Hello
world
Bye
World
+ `, +}; diff --git a/test/runtime/samples/component-slot-fallback-3/main.svelte b/test/runtime/samples/component-slot-fallback-3/main.svelte new file mode 100644 index 000000000000..eda7ea60e4dd --- /dev/null +++ b/test/runtime/samples/component-slot-fallback-3/main.svelte @@ -0,0 +1,9 @@ + + + +
Hello World
+
+ + From e50ad1dcb6d7e9e5ff6d27f566f459369c51beba Mon Sep 17 00:00:00 2001 From: Conduitry Date: Mon, 16 Mar 2020 12:11:53 -0400 Subject: [PATCH 053/158] -> v3.20.1 --- CHANGELOG.md | 4 ++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ace7d81049f..93a8262121ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Svelte changelog +## 3.20.1 + +* Fix compiler regression with slots ([#4562](https://github.com/sveltejs/svelte/issues/4562)) + ## 3.20.0 * Allow destructuring in `{#await}` blocks ([#1851](https://github.com/sveltejs/svelte/issues/1851)) diff --git a/package-lock.json b/package-lock.json index 6dccee0d65c7..7c521bd93da5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.20.0", + "version": "3.20.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 4e52b15636e3..2053ebb76fb1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.20.0", + "version": "3.20.1", "description": "Cybernetically enhanced web apps", "module": "index.mjs", "main": "index", From e247de351b51db6189ca91e63a66f894e4a6699c Mon Sep 17 00:00:00 2001 From: Conduitry Date: Fri, 20 Mar 2020 08:44:24 -0400 Subject: [PATCH 054/158] site: bump sapper --- site/package-lock.json | 6 +++--- site/package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index 5ce377c88cd5..7ac3211a7e18 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -3483,9 +3483,9 @@ } }, "sapper": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/sapper/-/sapper-0.27.8.tgz", - "integrity": "sha512-78K+56yu9nGOEU0B0XjBvNchRuPEv4aHbAKK4D874S4aoapMAkHCT0bHtPK12S3P7JPxvvT8GzHaq/8NetMmbg==", + "version": "0.27.11", + "resolved": "https://registry.npmjs.org/sapper/-/sapper-0.27.11.tgz", + "integrity": "sha512-5EaPZhlc8OnyN3UCI6dRSM1Gz5sxyzLZG/1z5nMvZhg9Ng+rSvEvJx/rW/tSHcnQPa8or7+YcbfvQHKS5oPHiw==", "dev": true, "requires": { "html-minifier": "^4.0.0", diff --git a/site/package.json b/site/package.json index a94d26421781..5ff40e1153ca 100644 --- a/site/package.json +++ b/site/package.json @@ -53,7 +53,7 @@ "rollup-plugin-replace": "^2.2.0", "rollup-plugin-svelte": "^5.1.0", "rollup-plugin-terser": "^5.1.1", - "sapper": "^0.27.8", + "sapper": "^0.27.11", "shelljs": "^0.8.3", "svelte": "^3.12.0" }, From a0749f6adb7f27144e81f3b06a29418411abdc61 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Sun, 22 Mar 2020 20:08:32 +0800 Subject: [PATCH 055/158] fix creating debugging comment for HTML comment (#4567) --- CHANGELOG.md | 4 ++++ .../render_dom/wrappers/shared/create_debugging_comment.ts | 2 +- test/runtime/samples/component-slot-fallback-4/Inner.svelte | 3 +++ test/runtime/samples/component-slot-fallback-4/_config.js | 5 +++++ test/runtime/samples/component-slot-fallback-4/main.svelte | 5 +++++ 5 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 test/runtime/samples/component-slot-fallback-4/Inner.svelte create mode 100644 test/runtime/samples/component-slot-fallback-4/_config.js create mode 100644 test/runtime/samples/component-slot-fallback-4/main.svelte diff --git a/CHANGELOG.md b/CHANGELOG.md index 93a8262121ac..cbab1872dc4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Svelte changelog +## Unreleased + +* Fix attaching of JS debugging comments to HTML comments ([#4565](https://github.com/sveltejs/svelte/issues/4565)) + ## 3.20.1 * Fix compiler regression with slots ([#4562](https://github.com/sveltejs/svelte/issues/4562)) diff --git a/src/compiler/compile/render_dom/wrappers/shared/create_debugging_comment.ts b/src/compiler/compile/render_dom/wrappers/shared/create_debugging_comment.ts index 11f1feb841b9..1bdc473df0db 100644 --- a/src/compiler/compile/render_dom/wrappers/shared/create_debugging_comment.ts +++ b/src/compiler/compile/render_dom/wrappers/shared/create_debugging_comment.ts @@ -24,7 +24,7 @@ export default function create_debugging_comment( while (source[d] !== '>') d += 1; d += 1; } - } else if (node.type === 'Text') { + } else if (node.type === 'Text' || node.type === 'Comment') { d = node.end; } else { // @ts-ignore diff --git a/test/runtime/samples/component-slot-fallback-4/Inner.svelte b/test/runtime/samples/component-slot-fallback-4/Inner.svelte new file mode 100644 index 000000000000..9eb3ef140148 --- /dev/null +++ b/test/runtime/samples/component-slot-fallback-4/Inner.svelte @@ -0,0 +1,3 @@ + + + foobar \ No newline at end of file diff --git a/test/runtime/samples/component-slot-fallback-4/_config.js b/test/runtime/samples/component-slot-fallback-4/_config.js new file mode 100644 index 000000000000..b7c2b63ed6f7 --- /dev/null +++ b/test/runtime/samples/component-slot-fallback-4/_config.js @@ -0,0 +1,5 @@ +export default { + html: ` + foobar + `, +}; diff --git a/test/runtime/samples/component-slot-fallback-4/main.svelte b/test/runtime/samples/component-slot-fallback-4/main.svelte new file mode 100644 index 000000000000..206ce21def76 --- /dev/null +++ b/test/runtime/samples/component-slot-fallback-4/main.svelte @@ -0,0 +1,5 @@ + + + From cc1f2c6c9ec8ea3b2b4878c5a866cfafd7d33172 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Mon, 23 Mar 2020 00:17:14 +0800 Subject: [PATCH 056/158] remove unneeded fragment block (#4568) --- src/compiler/compile/render_dom/Block.ts | 4 ++-- src/compiler/compile/render_dom/Renderer.ts | 4 ++++ .../render_dom/wrappers/InlineComponent/index.ts | 1 + src/compiler/compile/render_dom/wrappers/Slot.ts | 13 +++++++++---- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/compiler/compile/render_dom/Block.ts b/src/compiler/compile/render_dom/Block.ts index c84359459912..f5c4281710fa 100644 --- a/src/compiler/compile/render_dom/Block.ts +++ b/src/compiler/compile/render_dom/Block.ts @@ -419,8 +419,8 @@ export default class Block { return body; } - has_content() { - return this.first || + has_content(): boolean { + return !!this.first || this.event_listeners.length > 0 || this.chunks.intro.length > 0 || this.chunks.outro.length > 0 || diff --git a/src/compiler/compile/render_dom/Renderer.ts b/src/compiler/compile/render_dom/Renderer.ts index e933faf97abd..ca93c51060c9 100644 --- a/src/compiler/compile/render_dom/Renderer.ts +++ b/src/compiler/compile/render_dom/Renderer.ts @@ -284,4 +284,8 @@ export default class Renderer { return node; } + + remove_block(block: Block | Node | Node[]) { + this.blocks.splice(this.blocks.indexOf(block), 1); + } } diff --git a/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts b/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts index 8c8bd706962e..4b1e787cbe92 100644 --- a/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts +++ b/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts @@ -155,6 +155,7 @@ export default class InlineComponentWrapper extends Wrapper { // removing empty slot for (const slot of this.slots.keys()) { if (!this.slots.get(slot).block.has_content()) { + this.renderer.remove_block(this.slots.get(slot).block); this.slots.delete(slot); } } diff --git a/src/compiler/compile/render_dom/wrappers/Slot.ts b/src/compiler/compile/render_dom/wrappers/Slot.ts index f28719813208..1111a7cffe0c 100644 --- a/src/compiler/compile/render_dom/wrappers/Slot.ts +++ b/src/compiler/compile/render_dom/wrappers/Slot.ts @@ -114,18 +114,23 @@ export default class SlotWrapper extends Wrapper { get_slot_context_fn = 'null'; } + let has_fallback = !!this.fallback; if (this.fallback) { this.fragment.render(this.fallback, null, x`#nodes` as Identifier); + has_fallback = this.fallback.has_content(); + if (!has_fallback) { + renderer.remove_block(this.fallback); + } } const slot = block.get_unique_name(`${sanitize(slot_name)}_slot`); const slot_definition = block.get_unique_name(`${sanitize(slot_name)}_slot_template`); - const slot_or_fallback = this.fallback ? block.get_unique_name(`${sanitize(slot_name)}_slot_or_fallback`) : slot; + const slot_or_fallback = has_fallback ? block.get_unique_name(`${sanitize(slot_name)}_slot_or_fallback`) : slot; block.chunks.init.push(b` const ${slot_definition} = ${renderer.reference('$$slots')}.${slot_name}; const ${slot} = @create_slot(${slot_definition}, #ctx, ${renderer.reference('$$scope')}, ${get_slot_context_fn}); - ${this.fallback ? b`const ${slot_or_fallback} = ${slot} || ${this.fallback.name}(#ctx);` : null} + ${has_fallback ? b`const ${slot_or_fallback} = ${slot} || ${this.fallback.name}(#ctx);` : null} `); block.chunks.create.push( @@ -161,7 +166,7 @@ export default class SlotWrapper extends Wrapper { const dynamic_dependencies = Array.from(this.dependencies).filter(is_dependency_dynamic); - const fallback_dynamic_dependencies = this.fallback + const fallback_dynamic_dependencies = has_fallback ? Array.from(this.fallback.dependencies).filter(is_dependency_dynamic) : []; @@ -173,7 +178,7 @@ export default class SlotWrapper extends Wrapper { ); } `; - const fallback_update = this.fallback && fallback_dynamic_dependencies.length > 0 && b` + const fallback_update = has_fallback && fallback_dynamic_dependencies.length > 0 && b` if (${slot_or_fallback} && ${slot_or_fallback}.p && ${renderer.dirty(fallback_dynamic_dependencies)}) { ${slot_or_fallback}.p(#ctx, #dirty); } From aa3dcc06d6b0fcb079ccd993fa6e3455242a2a96 Mon Sep 17 00:00:00 2001 From: Jongkeun Hong Date: Tue, 24 Mar 2020 22:29:19 +0900 Subject: [PATCH 057/158] add .vscode to .gitignore (#4595) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 7a1424492996..f7fac04ebaa9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ .idea .DS_Store .nyc_output +.vscode node_modules *.map /src/compiler/compile/internal_exports.ts From 89f30dae3692fd8d013bd33f0342c7d58f195aea Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Mon, 6 Apr 2020 20:45:27 +1000 Subject: [PATCH 058/158] docs: Fix simple typo, specificy -> specify (#4637) --- site/content/docs/03-run-time.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/content/docs/03-run-time.md b/site/content/docs/03-run-time.md index 0bbae2418574..85661bd3b935 100644 --- a/site/content/docs/03-run-time.md +++ b/site/content/docs/03-run-time.md @@ -804,7 +804,7 @@ You can see a full example on the [animations tutorial](tutorial/animate) ### `svelte/easing` -Easing functions specificy the rate of change over time and are useful when working with Svelte's built-in transitions and animations as well as the tweened and spring utilities. `svelte/easing` contains 31 named exports, a `linear` ease and 3 variants of 10 different easing functions: `in`, `out` and `inOut`. +Easing functions specify the rate of change over time and are useful when working with Svelte's built-in transitions and animations as well as the tweened and spring utilities. `svelte/easing` contains 31 named exports, a `linear` ease and 3 variants of 10 different easing functions: `in`, `out` and `inOut`. You can explore the various eases using the [ease visualiser](examples#easing) in the [examples section](examples). From 085897c799dba914e553fcfac83aa3416ab23bef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=B3=D0=BE=D1=80=D1=8C=20=D0=A4=D1=80=D0=BE=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2?= Date: Mon, 6 Apr 2020 14:01:02 +0300 Subject: [PATCH 059/158] feat(internal): Support globalThis in modern environments (#4628) --- src/runtime/internal/globals.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/runtime/internal/globals.ts b/src/runtime/internal/globals.ts index 664093d2e4fd..b97f81ab9f47 100644 --- a/src/runtime/internal/globals.ts +++ b/src/runtime/internal/globals.ts @@ -1,3 +1,7 @@ declare const global: any; -export const globals = (typeof window !== 'undefined' ? window : global) as unknown as typeof globalThis; +export const globals = (typeof window !== 'undefined' + ? window + : typeof globalThis !== 'undefined' + ? globalThis + : global) as unknown as typeof globalThis; From d7497deaecc043f799ce81bb86298010605d2b99 Mon Sep 17 00:00:00 2001 From: Conduitry Date: Mon, 6 Apr 2020 07:04:40 -0400 Subject: [PATCH 060/158] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cbab1872dc4e..80db122cb621 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased +* Try using `globalThis` rather than `globals` for the benefit of non-Node servers and web workers ([#3561](https://github.com/sveltejs/svelte/issues/3561), [#4545](https://github.com/sveltejs/svelte/issues/4545)) * Fix attaching of JS debugging comments to HTML comments ([#4565](https://github.com/sveltejs/svelte/issues/4565)) ## 3.20.1 From df3ae85b42b6fa2d6a07cdb1073c9ebd8c9f8a71 Mon Sep 17 00:00:00 2001 From: Robin Cussol Date: Tue, 7 Apr 2020 15:30:33 +0200 Subject: [PATCH 061/158] fix(examples): use correct URL for Ask HN posts (#4640) --- .../examples/21-miscellaneous/01-hacker-news/Item.svelte | 6 ++++-- .../examples/21-miscellaneous/01-hacker-news/Summary.svelte | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/site/content/examples/21-miscellaneous/01-hacker-news/Item.svelte b/site/content/examples/21-miscellaneous/01-hacker-news/Item.svelte index e9cd617e96a0..802ab437f717 100644 --- a/site/content/examples/21-miscellaneous/01-hacker-news/Item.svelte +++ b/site/content/examples/21-miscellaneous/01-hacker-news/Item.svelte @@ -3,6 +3,8 @@ export let item; export let returnTo; + + $: url = !item.domain ? `https://news.ycombinator.com/${item.url}` : item.url; - \ No newline at end of file + diff --git a/site/content/examples/10-animations/00-animate/App.svelte b/site/content/examples/10-animations/00-animate/App.svelte index 279821491b27..a90d0ecfb51b 100644 --- a/site/content/examples/10-animations/00-animate/App.svelte +++ b/site/content/examples/10-animations/00-animate/App.svelte @@ -112,7 +112,7 @@
diff --git a/site/content/tutorial/07-lifecycle/03-update/app-a/App.svelte b/site/content/tutorial/07-lifecycle/03-update/app-a/App.svelte index d8c4caabef17..a009b2cc1f0b 100644 --- a/site/content/tutorial/07-lifecycle/03-update/app-a/App.svelte +++ b/site/content/tutorial/07-lifecycle/03-update/app-a/App.svelte @@ -20,7 +20,7 @@ ]; function handleKeydown(event) { - if (event.which === 13) { + if (event.key === 'Enter') { const text = event.target.value; if (!text) return; @@ -104,4 +104,4 @@
-
\ No newline at end of file +
diff --git a/site/content/tutorial/07-lifecycle/03-update/app-b/App.svelte b/site/content/tutorial/07-lifecycle/03-update/app-b/App.svelte index bdf42e28a99b..97caca99d571 100644 --- a/site/content/tutorial/07-lifecycle/03-update/app-b/App.svelte +++ b/site/content/tutorial/07-lifecycle/03-update/app-b/App.svelte @@ -20,7 +20,7 @@ ]; function handleKeydown(event) { - if (event.which === 13) { + if (event.key === 'Enter') { const text = event.target.value; if (!text) return; @@ -104,4 +104,4 @@
-
\ No newline at end of file +
diff --git a/site/content/tutorial/07-lifecycle/04-tick/app-a/App.svelte b/site/content/tutorial/07-lifecycle/04-tick/app-a/App.svelte index 3386ff93dfca..97edefa93540 100644 --- a/site/content/tutorial/07-lifecycle/04-tick/app-a/App.svelte +++ b/site/content/tutorial/07-lifecycle/04-tick/app-a/App.svelte @@ -2,7 +2,7 @@ let text = `Select some text and hit the tab key to toggle uppercase`; async function handleKeydown(event) { - if (event.which !== 9) return; + if (event.key !== 'Tab') return; event.preventDefault(); @@ -32,4 +32,4 @@ } - \ No newline at end of file + diff --git a/site/content/tutorial/07-lifecycle/04-tick/app-b/App.svelte b/site/content/tutorial/07-lifecycle/04-tick/app-b/App.svelte index c9cb6de42089..477b5ffb79db 100644 --- a/site/content/tutorial/07-lifecycle/04-tick/app-b/App.svelte +++ b/site/content/tutorial/07-lifecycle/04-tick/app-b/App.svelte @@ -4,7 +4,7 @@ let text = `Select some text and hit the tab key to toggle uppercase`; async function handleKeydown(event) { - if (event.which !== 9) return; + if (event.key !== 'Tab') return; event.preventDefault(); @@ -34,4 +34,4 @@ } - \ No newline at end of file + diff --git a/site/content/tutorial/10-transitions/08-deferred-transitions/app-a/App.svelte b/site/content/tutorial/10-transitions/08-deferred-transitions/app-a/App.svelte index e86981673078..f05c5813906f 100644 --- a/site/content/tutorial/10-transitions/08-deferred-transitions/app-a/App.svelte +++ b/site/content/tutorial/10-transitions/08-deferred-transitions/app-a/App.svelte @@ -56,7 +56,7 @@
e.which === 13 && add(e.target)} + on:keydown={e => e.key === 'Enter' && add(e.target)} >
@@ -145,4 +145,4 @@ label:hover button { opacity: 1; } - \ No newline at end of file + diff --git a/site/content/tutorial/10-transitions/08-deferred-transitions/app-b/App.svelte b/site/content/tutorial/10-transitions/08-deferred-transitions/app-b/App.svelte index 3cb21a8ed9f0..b7447ca7dede 100644 --- a/site/content/tutorial/10-transitions/08-deferred-transitions/app-b/App.svelte +++ b/site/content/tutorial/10-transitions/08-deferred-transitions/app-b/App.svelte @@ -56,7 +56,7 @@
e.which === 13 && add(e.target)} + on:keydown={e => e.key === 'Enter' && add(e.target)} >
@@ -152,4 +152,4 @@ label:hover button { opacity: 1; } - \ No newline at end of file + diff --git a/site/content/tutorial/11-animations/01-animate/app-a/App.svelte b/site/content/tutorial/11-animations/01-animate/app-a/App.svelte index 3cb21a8ed9f0..b7447ca7dede 100644 --- a/site/content/tutorial/11-animations/01-animate/app-a/App.svelte +++ b/site/content/tutorial/11-animations/01-animate/app-a/App.svelte @@ -56,7 +56,7 @@
e.which === 13 && add(e.target)} + on:keydown={e => e.key === 'Enter' && add(e.target)} >
@@ -152,4 +152,4 @@ label:hover button { opacity: 1; } - \ No newline at end of file + diff --git a/site/content/tutorial/11-animations/01-animate/app-b/App.svelte b/site/content/tutorial/11-animations/01-animate/app-b/App.svelte index 6194dd941efa..0d232bf02b85 100644 --- a/site/content/tutorial/11-animations/01-animate/app-b/App.svelte +++ b/site/content/tutorial/11-animations/01-animate/app-b/App.svelte @@ -57,7 +57,7 @@
e.which === 13 && add(e.target)} + on:keydown={e => e.key === 'Enter' && add(e.target)} >
@@ -155,4 +155,4 @@ label:hover button { opacity: 1; } - \ No newline at end of file + diff --git a/site/src/routes/repl/[id]/_components/AppControls/index.svelte b/site/src/routes/repl/[id]/_components/AppControls/index.svelte index 007dba34615f..10639e91c0a6 100644 --- a/site/src/routes/repl/[id]/_components/AppControls/index.svelte +++ b/site/src/routes/repl/[id]/_components/AppControls/index.svelte @@ -30,7 +30,7 @@ $: canSave = $session.user && gist && gist.owner === $session.user.uid; function handleKeydown(event) { - if (event.which === 83 && (isMac ? event.metaKey : event.ctrlKey)) { + if (event.key === 's' && (isMac ? event.metaKey : event.ctrlKey)) { event.preventDefault(); save(); } diff --git a/test/runtime/samples/action-custom-event-handler-this/_config.js b/test/runtime/samples/action-custom-event-handler-this/_config.js index 194fa08c31ad..88a30232abe5 100644 --- a/test/runtime/samples/action-custom-event-handler-this/_config.js +++ b/test/runtime/samples/action-custom-event-handler-this/_config.js @@ -4,7 +4,7 @@ export default { test({ assert, component, target, window }) { const input = target.querySelector('input'); const event = new window.KeyboardEvent('keydown', { - which: 13 + key: 'Enter' }); let blurred = false; diff --git a/test/runtime/samples/action-custom-event-handler-this/main.svelte b/test/runtime/samples/action-custom-event-handler-this/main.svelte index a7347cdc997f..c3ace108a5a7 100644 --- a/test/runtime/samples/action-custom-event-handler-this/main.svelte +++ b/test/runtime/samples/action-custom-event-handler-this/main.svelte @@ -1,7 +1,7 @@ - \ No newline at end of file + diff --git a/test/runtime/samples/window-event-custom/_config.js b/test/runtime/samples/window-event-custom/_config.js index 207fad1b0b3c..1c1075c0de4c 100644 --- a/test/runtime/samples/window-event-custom/_config.js +++ b/test/runtime/samples/window-event-custom/_config.js @@ -3,7 +3,7 @@ export default { async test({ assert, component, target, window }) { const event = new window.KeyboardEvent('keydown', { - which: 27 + key: 'Escape' }); await window.dispatchEvent(event); diff --git a/test/runtime/samples/window-event-custom/main.svelte b/test/runtime/samples/window-event-custom/main.svelte index ce453d9334fb..ff286f430987 100644 --- a/test/runtime/samples/window-event-custom/main.svelte +++ b/test/runtime/samples/window-event-custom/main.svelte @@ -3,7 +3,7 @@ function esc(node, callback) { function onKeyDown(event) { - if (event.which === 27) callback(event); + if (event.key === 'Escape') callback(event); } node.addEventListener('keydown', onKeyDown); return { @@ -16,4 +16,4 @@ -

escaped: {escaped}

\ No newline at end of file +

escaped: {escaped}

From f111cf6881d6708f0e7d0b7db9653f411dd6bab1 Mon Sep 17 00:00:00 2001 From: Conduitry Date: Sun, 3 May 2020 11:48:24 -0400 Subject: [PATCH 105/158] deconflict `anchor` variable name (#4769) --- CHANGELOG.md | 1 + src/compiler/compile/render_dom/Block.ts | 6 +++--- src/compiler/compile/render_dom/wrappers/AwaitBlock.ts | 2 +- src/compiler/compile/render_dom/wrappers/EachBlock.ts | 2 +- src/compiler/compile/render_dom/wrappers/Element/index.ts | 2 +- src/compiler/compile/render_dom/wrappers/IfBlock.ts | 6 +++--- .../compile/render_dom/wrappers/InlineComponent/index.ts | 4 ++-- src/compiler/compile/render_dom/wrappers/RawMustacheTag.ts | 2 +- src/compiler/compile/render_dom/wrappers/Slot.ts | 2 +- test/runtime/samples/deconflict-anchor/Anchor.svelte | 1 + test/runtime/samples/deconflict-anchor/_config.js | 4 ++++ test/runtime/samples/deconflict-anchor/main.svelte | 5 +++++ 12 files changed, 24 insertions(+), 13 deletions(-) create mode 100644 test/runtime/samples/deconflict-anchor/Anchor.svelte create mode 100644 test/runtime/samples/deconflict-anchor/_config.js create mode 100644 test/runtime/samples/deconflict-anchor/main.svelte diff --git a/CHANGELOG.md b/CHANGELOG.md index 78487a8d1bef..2f977c041ffc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * Do not display a11y warning about missing `href` for `` with `name` or `id` ([#4697](https://github.com/sveltejs/svelte/issues/4697)) * Disable infinite loop guard inside generators ([#4698](https://github.com/sveltejs/svelte/issues/4698)) * Display a11y warning for `href="javascript:..."` ([#4733](https://github.com/sveltejs/svelte/pull/4733)) +* Fix variable name conflict with component called `` ([#4768](https://github.com/sveltejs/svelte/issues/4768)) ## 3.21.0 diff --git a/src/compiler/compile/render_dom/Block.ts b/src/compiler/compile/render_dom/Block.ts index f5c4281710fa..b29b4d4afd95 100644 --- a/src/compiler/compile/render_dom/Block.ts +++ b/src/compiler/compile/render_dom/Block.ts @@ -185,7 +185,7 @@ export default class Block { this.chunks.mount.push(b`@append(${parent_node}, ${id});`); if (is_head(parent_node) && !no_detach) this.chunks.destroy.push(b`@detach(${id});`); } else { - this.chunks.mount.push(b`@insert(#target, ${id}, anchor);`); + this.chunks.mount.push(b`@insert(#target, ${id}, #anchor);`); if (!no_detach) this.chunks.destroy.push(b`if (detaching) @detach(${id});`); } } @@ -295,11 +295,11 @@ export default class Block { if (this.chunks.mount.length === 0) { properties.mount = noop; } else if (this.event_listeners.length === 0) { - properties.mount = x`function #mount(#target, anchor) { + properties.mount = x`function #mount(#target, #anchor) { ${this.chunks.mount} }`; } else { - properties.mount = x`function #mount(#target, anchor, #remount) { + properties.mount = x`function #mount(#target, #anchor, #remount) { ${this.chunks.mount} }`; } diff --git a/src/compiler/compile/render_dom/wrappers/AwaitBlock.ts b/src/compiler/compile/render_dom/wrappers/AwaitBlock.ts index d6ac17f0ced4..1898a840d23b 100644 --- a/src/compiler/compile/render_dom/wrappers/AwaitBlock.ts +++ b/src/compiler/compile/render_dom/wrappers/AwaitBlock.ts @@ -200,7 +200,7 @@ export default class AwaitBlockWrapper extends Wrapper { } const initial_mount_node = parent_node || '#target'; - const anchor_node = parent_node ? 'null' : 'anchor'; + const anchor_node = parent_node ? 'null' : '#anchor'; const has_transitions = this.pending.block.has_intro_method || this.pending.block.has_outro_method; diff --git a/src/compiler/compile/render_dom/wrappers/EachBlock.ts b/src/compiler/compile/render_dom/wrappers/EachBlock.ts index 43a0f754f968..1efadfb90cf2 100644 --- a/src/compiler/compile/render_dom/wrappers/EachBlock.ts +++ b/src/compiler/compile/render_dom/wrappers/EachBlock.ts @@ -219,7 +219,7 @@ export default class EachBlockWrapper extends Wrapper { } `); - const initial_anchor_node: Identifier = { type: 'Identifier', name: parent_node ? 'null' : 'anchor' }; + const initial_anchor_node: Identifier = { type: 'Identifier', name: parent_node ? 'null' : '#anchor' }; const initial_mount_node: Identifier = parent_node || { type: 'Identifier', name: '#target' }; const update_anchor_node = needs_anchor ? block.get_unique_name(`${this.var.name}_anchor`) diff --git a/src/compiler/compile/render_dom/wrappers/Element/index.ts b/src/compiler/compile/render_dom/wrappers/Element/index.ts index 64d02191fb8e..ab802b023d73 100644 --- a/src/compiler/compile/render_dom/wrappers/Element/index.ts +++ b/src/compiler/compile/render_dom/wrappers/Element/index.ts @@ -320,7 +320,7 @@ export default class ElementWrapper extends Wrapper { block.chunks.destroy.push(b`@detach(${node});`); } } else { - block.chunks.mount.push(b`@insert(#target, ${node}, anchor);`); + block.chunks.mount.push(b`@insert(#target, ${node}, #anchor);`); // TODO we eventually need to consider what happens to elements // that belong to the same outgroup as an outroing element... diff --git a/src/compiler/compile/render_dom/wrappers/IfBlock.ts b/src/compiler/compile/render_dom/wrappers/IfBlock.ts index 78b821170f87..e18d9f3b6bc3 100644 --- a/src/compiler/compile/render_dom/wrappers/IfBlock.ts +++ b/src/compiler/compile/render_dom/wrappers/IfBlock.ts @@ -293,7 +293,7 @@ export default class IfBlockWrapper extends Wrapper { `); const initial_mount_node = parent_node || '#target'; - const anchor_node = parent_node ? 'null' : 'anchor'; + const anchor_node = parent_node ? 'null' : '#anchor'; if (if_exists_condition) { block.chunks.mount.push( @@ -423,7 +423,7 @@ export default class IfBlockWrapper extends Wrapper { } const initial_mount_node = parent_node || '#target'; - const anchor_node = parent_node ? 'null' : 'anchor'; + const anchor_node = parent_node ? 'null' : '#anchor'; block.chunks.mount.push( if_current_block_type_index( @@ -519,7 +519,7 @@ export default class IfBlockWrapper extends Wrapper { `); const initial_mount_node = parent_node || '#target'; - const anchor_node = parent_node ? 'null' : 'anchor'; + const anchor_node = parent_node ? 'null' : '#anchor'; block.chunks.mount.push( b`if (${name}) ${name}.m(${initial_mount_node}, ${anchor_node});` diff --git a/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts b/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts index 4b1e787cbe92..00f803bbbd48 100644 --- a/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts +++ b/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts @@ -435,7 +435,7 @@ export default class InlineComponentWrapper extends Wrapper { block.chunks.mount.push(b` if (${name}) { - @mount_component(${name}, ${parent_node || '#target'}, ${parent_node ? 'null' : 'anchor'}); + @mount_component(${name}, ${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'}); } `); @@ -509,7 +509,7 @@ export default class InlineComponentWrapper extends Wrapper { } block.chunks.mount.push( - b`@mount_component(${name}, ${parent_node || '#target'}, ${parent_node ? 'null' : 'anchor'});` + b`@mount_component(${name}, ${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'});` ); block.chunks.intro.push(b` diff --git a/src/compiler/compile/render_dom/wrappers/RawMustacheTag.ts b/src/compiler/compile/render_dom/wrappers/RawMustacheTag.ts index 3b13e6c68a48..63889dd8294f 100644 --- a/src/compiler/compile/render_dom/wrappers/RawMustacheTag.ts +++ b/src/compiler/compile/render_dom/wrappers/RawMustacheTag.ts @@ -54,7 +54,7 @@ export default class RawMustacheTagWrapper extends Tag { const update_anchor = in_head ? 'null' : needs_anchor ? html_anchor : this.next ? this.next.var : 'null'; block.chunks.hydrate.push(b`${html_tag} = new @HtmlTag(${init}, ${update_anchor});`); - block.chunks.mount.push(b`${html_tag}.m(${parent_node || '#target'}, ${parent_node ? null : 'anchor'});`); + block.chunks.mount.push(b`${html_tag}.m(${parent_node || '#target'}, ${parent_node ? null : '#anchor'});`); if (needs_anchor) { block.add_element(html_anchor, x`@empty()`, x`@empty()`, parent_node); diff --git a/src/compiler/compile/render_dom/wrappers/Slot.ts b/src/compiler/compile/render_dom/wrappers/Slot.ts index 492136303a85..55ed031381b6 100644 --- a/src/compiler/compile/render_dom/wrappers/Slot.ts +++ b/src/compiler/compile/render_dom/wrappers/Slot.ts @@ -145,7 +145,7 @@ export default class SlotWrapper extends Wrapper { block.chunks.mount.push(b` if (${slot_or_fallback}) { - ${slot_or_fallback}.m(${parent_node || '#target'}, ${parent_node ? 'null' : 'anchor'}); + ${slot_or_fallback}.m(${parent_node || '#target'}, ${parent_node ? 'null' : '#anchor'}); } `); diff --git a/test/runtime/samples/deconflict-anchor/Anchor.svelte b/test/runtime/samples/deconflict-anchor/Anchor.svelte new file mode 100644 index 000000000000..e758d60056a1 --- /dev/null +++ b/test/runtime/samples/deconflict-anchor/Anchor.svelte @@ -0,0 +1 @@ +

Anchor

diff --git a/test/runtime/samples/deconflict-anchor/_config.js b/test/runtime/samples/deconflict-anchor/_config.js new file mode 100644 index 000000000000..817dd42fcb27 --- /dev/null +++ b/test/runtime/samples/deconflict-anchor/_config.js @@ -0,0 +1,4 @@ +export default { + preserveIdentifiers: true, + html: `

Anchor

` +}; diff --git a/test/runtime/samples/deconflict-anchor/main.svelte b/test/runtime/samples/deconflict-anchor/main.svelte new file mode 100644 index 000000000000..cce6281e49ce --- /dev/null +++ b/test/runtime/samples/deconflict-anchor/main.svelte @@ -0,0 +1,5 @@ + + + From a08a94ac33c9f15025bd571bd8f0fbe54a005b48 Mon Sep 17 00:00:00 2001 From: Pat Cavit Date: Sun, 3 May 2020 08:52:32 -0700 Subject: [PATCH 106/158] make setting tweened with duration=0 instantly update (#4766) --- src/runtime/motion/tweened.ts | 5 +++++ test/motion/index.js | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/src/runtime/motion/tweened.ts b/src/runtime/motion/tweened.ts index e33f0f79f977..abbb3b1aa276 100644 --- a/src/runtime/motion/tweened.ts +++ b/src/runtime/motion/tweened.ts @@ -93,6 +93,11 @@ export function tweened(value?: T, defaults: Options = {}): Tweened { interpolate = get_interpolator } = assign(assign({}, defaults), opts); + if (duration === 0) { + store.set(target_value); + return Promise.resolve(); + } + const start = now() + delay; let fn; diff --git a/test/motion/index.js b/test/motion/index.js index 33489b18e1a0..ec58c6df36e2 100644 --- a/test/motion/index.js +++ b/test/motion/index.js @@ -19,5 +19,12 @@ describe('motion', () => { size.set(100); assert.equal(get(size), 100); }); + + it('sets immediately when duration is 0', () => { + const size = tweened(0); + + size.set(100, { duration : 0 }); + assert.equal(get(size), 100); + }); }); }); From 09115b5256cbe88ae27879f5eac96f11d2366ebb Mon Sep 17 00:00:00 2001 From: Conduitry Date: Sun, 3 May 2020 11:53:47 -0400 Subject: [PATCH 107/158] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f977c041ffc..d3f99af139d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased * Fix misaligned line numbers in source maps ([#3906](https://github.com/sveltejs/svelte/issues/3906)) +* Make setting a `tweened` store using `duration: 0` instantly update the value ([#4399](https://github.com/sveltejs/svelte/issues/4399)) * Fix reactivity with imported values that are then mutated ([#4555](https://github.com/sveltejs/svelte/issues/4555)) * Do not display a11y warning about missing `href` for `
` with `name` or `id` ([#4697](https://github.com/sveltejs/svelte/issues/4697)) * Disable infinite loop guard inside generators ([#4698](https://github.com/sveltejs/svelte/issues/4698)) From 153b128fe28a3283b684fccb051deb66152a6d46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Lins?= Date: Sun, 3 May 2020 13:06:10 -0300 Subject: [PATCH 108/158] a11y: implement img-redundant-alt (#4750) --- src/compiler/compile/nodes/Element.ts | 49 ++++++++++++++----- .../input.svelte | 2 +- .../a11y-figcaption-right-place/input.svelte | 2 +- .../a11y-figcaption-wrong-place/input.svelte | 4 +- .../a11y-figcaption-wrong-place/warnings.json | 12 ++--- .../a11y-img-redundant-alt/input.svelte | 7 +++ .../a11y-img-redundant-alt/warnings.json | 47 ++++++++++++++++++ 7 files changed, 101 insertions(+), 22 deletions(-) create mode 100644 test/validator/samples/a11y-img-redundant-alt/input.svelte create mode 100644 test/validator/samples/a11y-img-redundant-alt/warnings.json diff --git a/src/compiler/compile/nodes/Element.ts b/src/compiler/compile/nodes/Element.ts index f7f3cc55bc9e..93997ae66ece 100644 --- a/src/compiler/compile/nodes/Element.ts +++ b/src/compiler/compile/nodes/Element.ts @@ -272,6 +272,7 @@ export default class Element extends Node { } this.validate_attributes(); + this.validate_special_cases(); this.validate_bindings(); this.validate_content(); this.validate_event_handlers(); @@ -420,8 +421,16 @@ export default class Element extends Node { attribute_map.set(attribute.name, attribute); }); + } + + validate_special_cases() { + const { component,attributes } = this; + const attribute_map = new Map(); + + attributes.forEach(attribute => ( + attribute_map.set(attribute.name, attribute) + )); - // handle special cases if (this.name === 'a') { const href_attribute = attribute_map.get('href') || attribute_map.get('xlink:href'); const id_attribute = attribute_map.get('id'); @@ -447,9 +456,7 @@ export default class Element extends Node { }); } } - } - - else { + } else { const required_attributes = a11y_required_attributes[this.name]; if (required_attributes) { const has_attribute = required_attributes.some(name => attribute_map.has(name)); @@ -458,16 +465,34 @@ export default class Element extends Node { should_have_attribute(this, required_attributes); } } + } - if (this.name === 'input') { - const type = attribute_map.get('type'); - if (type && type.get_static_value() === 'image') { - const required_attributes = ['alt', 'aria-label', 'aria-labelledby']; - const has_attribute = required_attributes.some(name => attribute_map.has(name)); + if (this.name === 'input') { + const type = attribute_map.get('type'); + if (type && type.get_static_value() === 'image') { + const required_attributes = ['alt', 'aria-label', 'aria-labelledby']; + const has_attribute = required_attributes.some(name => attribute_map.has(name)); - if (!has_attribute) { - should_have_attribute(this, required_attributes, 'input type="image"'); - } + if (!has_attribute) { + should_have_attribute(this, required_attributes, 'input type="image"'); + } + } + } + + if (this.name === 'img') { + const alt_attribute = attribute_map.get('alt'); + const aria_hidden_attribute = attribute_map.get('aria-hidden'); + + const aria_hidden_exist = aria_hidden_attribute && aria_hidden_attribute.get_static_value(); + + if (alt_attribute && !aria_hidden_exist) { + const alt_value = alt_attribute.get_static_value(); + + if (alt_value.match(/\b(image|picture|photo)\b/i)) { + component.warn(this, { + code: `a11y-img-redundant-alt`, + message: `A11y: Screenreaders already announce elements as an image.` + }); } } } diff --git a/test/validator/samples/a11y-figcaption-in-non-element-block/input.svelte b/test/validator/samples/a11y-figcaption-in-non-element-block/input.svelte index 9d4b6ded4d9d..33e7a891f009 100644 --- a/test/validator/samples/a11y-figcaption-in-non-element-block/input.svelte +++ b/test/validator/samples/a11y-figcaption-in-non-element-block/input.svelte @@ -3,7 +3,7 @@
- a picture of a foo + a foo {#if caption}
{caption}
{/if} diff --git a/test/validator/samples/a11y-figcaption-right-place/input.svelte b/test/validator/samples/a11y-figcaption-right-place/input.svelte index 808dbee941d6..783219c8f818 100644 --- a/test/validator/samples/a11y-figcaption-right-place/input.svelte +++ b/test/validator/samples/a11y-figcaption-right-place/input.svelte @@ -1,5 +1,5 @@
- a picture of a foo + a foo
a foo in its natural habitat diff --git a/test/validator/samples/a11y-figcaption-wrong-place/input.svelte b/test/validator/samples/a11y-figcaption-wrong-place/input.svelte index ffa7dde65db1..e99d1cc86cfb 100644 --- a/test/validator/samples/a11y-figcaption-wrong-place/input.svelte +++ b/test/validator/samples/a11y-figcaption-wrong-place/input.svelte @@ -1,5 +1,5 @@
- a picture of a foo + a foo
a foo in its natural habitat @@ -9,7 +9,7 @@
- a picture of a foo + a foo
diff --git a/test/validator/samples/a11y-figcaption-wrong-place/warnings.json b/test/validator/samples/a11y-figcaption-wrong-place/warnings.json index ee5a89d3ff45..eba5b6f31eb4 100644 --- a/test/validator/samples/a11y-figcaption-wrong-place/warnings.json +++ b/test/validator/samples/a11y-figcaption-wrong-place/warnings.json @@ -5,14 +5,14 @@ "start": { "line": 4, "column": 1, - "character": 57 + "character": 44 }, "end": { "line": 6, "column": 14, - "character": 115 + "character": 102 }, - "pos": 57 + "pos": 44 }, { "code": "a11y-structure", @@ -20,13 +20,13 @@ "start": { "line": 15, "column": 2, - "character": 252 + "character": 226 }, "end": { "line": 17, "column": 15, - "character": 328 + "character": 302 }, - "pos": 252 + "pos": 226 } ] diff --git a/test/validator/samples/a11y-img-redundant-alt/input.svelte b/test/validator/samples/a11y-img-redundant-alt/input.svelte new file mode 100644 index 000000000000..3ba029844da0 --- /dev/null +++ b/test/validator/samples/a11y-img-redundant-alt/input.svelte @@ -0,0 +1,7 @@ +Foo eating a sandwich. +Picture of me taking a photo of an image +Photo of foo being weird. +Image of me at a bar! +Picture of baz fixing a bug. +Plant doing photosynthesis in the afternoon +Picturesque food \ No newline at end of file diff --git a/test/validator/samples/a11y-img-redundant-alt/warnings.json b/test/validator/samples/a11y-img-redundant-alt/warnings.json new file mode 100644 index 000000000000..44106c23d003 --- /dev/null +++ b/test/validator/samples/a11y-img-redundant-alt/warnings.json @@ -0,0 +1,47 @@ +[ + { + "code": "a11y-img-redundant-alt", + "message": "A11y: Screenreaders already announce elements as an image.", + "end": { + "character": 173, + "column": 49, + "line": 3 + }, + "start": { + "character": 124, + "column": 0, + "line": 3 + }, + "pos": 124 + }, + { + "code": "a11y-img-redundant-alt", + "message": "A11y: Screenreaders already announce elements as an image.", + "end": { + "character": 219, + "column": 45, + "line": 4 + }, + "start": { + "character": 174, + "column": 0, + "line": 4 + }, + "pos": 174 + }, + { + "code": "a11y-img-redundant-alt", + "message": "A11y: Screenreaders already announce elements as an image.", + "end": { + "character": 272, + "column": 52, + "line": 5 + }, + "start": { + "character": 220, + "column": 0, + "line": 5 + }, + "pos": 220 + } +] \ No newline at end of file From 9179c3e99bbd8a79b9000067feb07edf81dd7e96 Mon Sep 17 00:00:00 2001 From: Conduitry Date: Sun, 3 May 2020 12:08:25 -0400 Subject: [PATCH 109/158] update changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d3f99af139d3..ba58df5b82aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,8 @@ * Fix reactivity with imported values that are then mutated ([#4555](https://github.com/sveltejs/svelte/issues/4555)) * Do not display a11y warning about missing `href` for `` with `name` or `id` ([#4697](https://github.com/sveltejs/svelte/issues/4697)) * Disable infinite loop guard inside generators ([#4698](https://github.com/sveltejs/svelte/issues/4698)) -* Display a11y warning for `href="javascript:..."` ([#4733](https://github.com/sveltejs/svelte/pull/4733)) +* Display `a11y-invalid-attribute` warning for `href="javascript:..."` ([#4733](https://github.com/sveltejs/svelte/pull/4733)) +* Implement `a11y-img-redundant-alt` warning ([#4750](https://github.com/sveltejs/svelte/pull/4750)) * Fix variable name conflict with component called `` ([#4768](https://github.com/sveltejs/svelte/issues/4768)) ## 3.21.0 From 5efeeecee83aca2064aeca0d9e7f7ec949410774 Mon Sep 17 00:00:00 2001 From: Joseph Abrahamson Date: Sun, 3 May 2020 12:13:15 -0400 Subject: [PATCH 110/158] docs: clarify store contract type signature (#4539) --- site/content/docs/01-component-format.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/content/docs/01-component-format.md b/site/content/docs/01-component-format.md index 07a59c69f8ce..fa851ccc41e0 100644 --- a/site/content/docs/01-component-format.md +++ b/site/content/docs/01-component-format.md @@ -175,7 +175,7 @@ Local variables (that do not represent store values) must *not* have a `$` prefi ##### Store contract ```js -store = { subscribe: (subscription: (value: any) => void) => () => void, set?: (value: any) => void } +store = { subscribe: (subscription: (value: any) => void) => (() => void), set?: (value: any) => void } ``` You can create your own stores without relying on [`svelte/store`](docs#svelte_store), by implementing the *store contract*: From a73be39a805e8b39adaa4314af38c5a635d56439 Mon Sep 17 00:00:00 2001 From: Th0rN13 Date: Sun, 3 May 2020 21:41:51 +0500 Subject: [PATCH 111/158] fix contextual dynamic bind:this in {#each} (#4759) --- .../render_dom/wrappers/shared/bind_this.ts | 3 +++ .../binding-this-each-object-props/_config.js | 14 ++++++++++++++ .../binding-this-each-object-props/main.svelte | 13 +++++++++++++ .../binding-this-each-object-spread/_config.js | 14 ++++++++++++++ .../binding-this-each-object-spread/main.svelte | 13 +++++++++++++ 5 files changed, 57 insertions(+) create mode 100644 test/runtime/samples/binding-this-each-object-props/_config.js create mode 100644 test/runtime/samples/binding-this-each-object-props/main.svelte create mode 100644 test/runtime/samples/binding-this-each-object-spread/_config.js create mode 100644 test/runtime/samples/binding-this-each-object-spread/main.svelte diff --git a/src/compiler/compile/render_dom/wrappers/shared/bind_this.ts b/src/compiler/compile/render_dom/wrappers/shared/bind_this.ts index 97199a71c2e3..8a9830b01b6b 100644 --- a/src/compiler/compile/render_dom/wrappers/shared/bind_this.ts +++ b/src/compiler/compile/render_dom/wrappers/shared/bind_this.ts @@ -55,6 +55,9 @@ export default function bind_this(component: Component, block: Block, binding: B const args = []; for (const id of contextual_dependencies) { args.push(id); + if (block.variables.has(id.name)) { + if (block.renderer.context_lookup.get(id.name).is_contextual) continue; + } block.add_variable(id, block.renderer.reference(id.name)); } diff --git a/test/runtime/samples/binding-this-each-object-props/_config.js b/test/runtime/samples/binding-this-each-object-props/_config.js new file mode 100644 index 000000000000..5372667b82b6 --- /dev/null +++ b/test/runtime/samples/binding-this-each-object-props/_config.js @@ -0,0 +1,14 @@ +export default { + html: ``, + + async test({ assert, component, target }) { + component.visible = true; + assert.htmlEqual(target.innerHTML, ` +
b
b
c
c
+ `); + assert.equal(component.items1[1], target.querySelector('div')); + assert.equal(component.items2[1], target.querySelector('div:nth-child(2)')); + assert.equal(component.items1[2], target.querySelector('div:nth-child(3)')); + assert.equal(component.items2[2], target.querySelector('div:last-child')); + } +}; diff --git a/test/runtime/samples/binding-this-each-object-props/main.svelte b/test/runtime/samples/binding-this-each-object-props/main.svelte new file mode 100644 index 000000000000..9654a5841818 --- /dev/null +++ b/test/runtime/samples/binding-this-each-object-props/main.svelte @@ -0,0 +1,13 @@ + + +{#each data as item (item.id)} +
{item.text}
+
{item.text}
+{/each} diff --git a/test/runtime/samples/binding-this-each-object-spread/_config.js b/test/runtime/samples/binding-this-each-object-spread/_config.js new file mode 100644 index 000000000000..cecec08db903 --- /dev/null +++ b/test/runtime/samples/binding-this-each-object-spread/_config.js @@ -0,0 +1,14 @@ +export default { + html: ``, + + async test({ assert, component, target }) { + component.visible = true; + assert.htmlEqual(target.innerHTML, ` +
a
a
b
b
+ `); + assert.equal(component.items1[1], target.querySelector('div')); + assert.equal(component.items2[1], target.querySelector('div:nth-child(2)')); + assert.equal(component.items1[2], target.querySelector('div:nth-child(3)')); + assert.equal(component.items2[2], target.querySelector('div:last-child')); + } +}; diff --git a/test/runtime/samples/binding-this-each-object-spread/main.svelte b/test/runtime/samples/binding-this-each-object-spread/main.svelte new file mode 100644 index 000000000000..256ed0ede6e8 --- /dev/null +++ b/test/runtime/samples/binding-this-each-object-spread/main.svelte @@ -0,0 +1,13 @@ + + +{#each data as {id, text} (id)} +
{text}
+
{text}
+{/each} From 3df407447f9641496867bf8fe4c340376fb65f70 Mon Sep 17 00:00:00 2001 From: Conduitry Date: Sun, 3 May 2020 12:43:24 -0400 Subject: [PATCH 112/158] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba58df5b82aa..87fdfdacc74d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Fix misaligned line numbers in source maps ([#3906](https://github.com/sveltejs/svelte/issues/3906)) * Make setting a `tweened` store using `duration: 0` instantly update the value ([#4399](https://github.com/sveltejs/svelte/issues/4399)) * Fix reactivity with imported values that are then mutated ([#4555](https://github.com/sveltejs/svelte/issues/4555)) +* Fix contextual dynamic `bind:this` inside `{#each}` block ([#4686](https://github.com/sveltejs/svelte/issues/4686)) * Do not display a11y warning about missing `href` for `
` with `name` or `id` ([#4697](https://github.com/sveltejs/svelte/issues/4697)) * Disable infinite loop guard inside generators ([#4698](https://github.com/sveltejs/svelte/issues/4698)) * Display `a11y-invalid-attribute` warning for `href="javascript:..."` ([#4733](https://github.com/sveltejs/svelte/pull/4733)) From b9f83fd295168b12d5608c9778c183fcb53abeb6 Mon Sep 17 00:00:00 2001 From: Conduitry Date: Sun, 3 May 2020 13:17:51 -0400 Subject: [PATCH 113/158] -> v3.22.0 --- CHANGELOG.md | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87fdfdacc74d..b53b5bc0f663 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Svelte changelog -## Unreleased +## 3.22.0 * Fix misaligned line numbers in source maps ([#3906](https://github.com/sveltejs/svelte/issues/3906)) * Make setting a `tweened` store using `duration: 0` instantly update the value ([#4399](https://github.com/sveltejs/svelte/issues/4399)) diff --git a/package-lock.json b/package-lock.json index d5adaa34ca2a..91e9b8fad12c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.21.0", + "version": "3.22.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 215a6099e9cc..4e859128e4c0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.21.0", + "version": "3.22.0", "description": "Cybernetically enhanced web apps", "module": "index.mjs", "main": "index", From ba89c29b988740f36ceefbf7631d03882018e70c Mon Sep 17 00:00:00 2001 From: Doga Genc Date: Sun, 3 May 2020 23:28:53 +0300 Subject: [PATCH 114/158] fix img-reduntant-alt bug (#4771) --- src/compiler/compile/nodes/Element.ts | 6 +++--- test/validator/samples/a11y-img-redundant-alt/input.svelte | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/compiler/compile/nodes/Element.ts b/src/compiler/compile/nodes/Element.ts index 93997ae66ece..5cda9919af18 100644 --- a/src/compiler/compile/nodes/Element.ts +++ b/src/compiler/compile/nodes/Element.ts @@ -438,7 +438,7 @@ export default class Element extends Node { if (href_attribute) { const href_value = href_attribute.get_static_value(); - + if (href_value === '' || href_value === '#' || /^\W*javascript:/i.test(href_value)) { component.warn(href_attribute, { code: `a11y-invalid-attribute`, @@ -484,11 +484,11 @@ export default class Element extends Node { const aria_hidden_attribute = attribute_map.get('aria-hidden'); const aria_hidden_exist = aria_hidden_attribute && aria_hidden_attribute.get_static_value(); - + if (alt_attribute && !aria_hidden_exist) { const alt_value = alt_attribute.get_static_value(); - if (alt_value.match(/\b(image|picture|photo)\b/i)) { + if (alt_value && alt_value.match(/\b(image|picture|photo)\b/i)) { component.warn(this, { code: `a11y-img-redundant-alt`, message: `A11y: Screenreaders already announce elements as an image.` diff --git a/test/validator/samples/a11y-img-redundant-alt/input.svelte b/test/validator/samples/a11y-img-redundant-alt/input.svelte index 3ba029844da0..cd942ce2a05f 100644 --- a/test/validator/samples/a11y-img-redundant-alt/input.svelte +++ b/test/validator/samples/a11y-img-redundant-alt/input.svelte @@ -4,4 +4,5 @@ Image of me at a bar! Picture of baz fixing a bug. Plant doing photosynthesis in the afternoon -Picturesque food \ No newline at end of file +Picturesque food +{'baz'} From bb5e2d2f262867ad0e96f7d85f8ab9013c853a3b Mon Sep 17 00:00:00 2001 From: Conduitry Date: Sun, 3 May 2020 16:30:19 -0400 Subject: [PATCH 115/158] -> v3.22.1 --- CHANGELOG.md | 4 ++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b53b5bc0f663..bc36b2eb06f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Svelte changelog +## 3.22.1 + +* Fix compiler exception with `a11y-img-redundant-alt` and dynamic `alt` attribute ([#4770](https://github.com/sveltejs/svelte/issues/4770)) + ## 3.22.0 * Fix misaligned line numbers in source maps ([#3906](https://github.com/sveltejs/svelte/issues/3906)) diff --git a/package-lock.json b/package-lock.json index 91e9b8fad12c..199e237df991 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.22.0", + "version": "3.22.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 4e859128e4c0..990c2643636e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.22.0", + "version": "3.22.1", "description": "Cybernetically enhanced web apps", "module": "index.mjs", "main": "index", From bdabd89f093afe06d5a4bfb8ee0362b0a9634cfc Mon Sep 17 00:00:00 2001 From: Conduitry Date: Mon, 4 May 2020 11:23:04 -0400 Subject: [PATCH 116/158] fix exception with empty alt attribute (#4778) --- CHANGELOG.md | 4 ++++ src/compiler/compile/nodes/Element.ts | 2 +- test/validator/samples/a11y-img-redundant-alt/input.svelte | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc36b2eb06f6..2b43394564ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Svelte changelog +## Unreleased + +* Fix compiler exception with `a11y-img-redundant-alt` and value-less `alt` attribute ([#4777](https://github.com/sveltejs/svelte/issues/4777)) + ## 3.22.1 * Fix compiler exception with `a11y-img-redundant-alt` and dynamic `alt` attribute ([#4770](https://github.com/sveltejs/svelte/issues/4770)) diff --git a/src/compiler/compile/nodes/Element.ts b/src/compiler/compile/nodes/Element.ts index 5cda9919af18..a337eff73ae3 100644 --- a/src/compiler/compile/nodes/Element.ts +++ b/src/compiler/compile/nodes/Element.ts @@ -488,7 +488,7 @@ export default class Element extends Node { if (alt_attribute && !aria_hidden_exist) { const alt_value = alt_attribute.get_static_value(); - if (alt_value && alt_value.match(/\b(image|picture|photo)\b/i)) { + if (/\b(image|picture|photo)\b/i.test(alt_value)) { component.warn(this, { code: `a11y-img-redundant-alt`, message: `A11y: Screenreaders already announce elements as an image.` diff --git a/test/validator/samples/a11y-img-redundant-alt/input.svelte b/test/validator/samples/a11y-img-redundant-alt/input.svelte index cd942ce2a05f..a3528a5c41ec 100644 --- a/test/validator/samples/a11y-img-redundant-alt/input.svelte +++ b/test/validator/samples/a11y-img-redundant-alt/input.svelte @@ -6,3 +6,4 @@ Plant doing photosynthesis in the afternoon Picturesque food {'baz'} + From c743e72a1eaa5710ab510841e9906e27879fc539 Mon Sep 17 00:00:00 2001 From: Conduitry Date: Mon, 4 May 2020 11:23:38 -0400 Subject: [PATCH 117/158] -> v3.22.2 --- CHANGELOG.md | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b43394564ff..4f3d47d73b0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Svelte changelog -## Unreleased +## 3.22.2 * Fix compiler exception with `a11y-img-redundant-alt` and value-less `alt` attribute ([#4777](https://github.com/sveltejs/svelte/issues/4777)) diff --git a/package-lock.json b/package-lock.json index 199e237df991..937f04f5f46c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.22.1", + "version": "3.22.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 990c2643636e..91bf7086763e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.22.1", + "version": "3.22.2", "description": "Cybernetically enhanced web apps", "module": "index.mjs", "main": "index", From 37cc5888f8db1f281a45df0395e8defc9180753a Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Mon, 11 May 2020 23:37:27 +0800 Subject: [PATCH 118/158] dry {#each}/{#await} destructuring (#4596) --- CHANGELOG.md | 4 + src/compiler/compile/nodes/AwaitBlock.ts | 39 +-- src/compiler/compile/nodes/CatchBlock.ts | 6 +- src/compiler/compile/nodes/EachBlock.ts | 52 +--- src/compiler/compile/nodes/ThenBlock.ts | 6 +- src/compiler/compile/nodes/shared/Context.ts | 58 ++++ .../compile/render_dom/wrappers/AwaitBlock.ts | 95 ++++--- .../compile/render_ssr/handlers/AwaitBlock.ts | 2 +- .../utils/traverse_destructure_pattern.ts | 35 --- src/compiler/parse/index.ts | 48 ---- src/compiler/parse/read/context.ts | 260 +++++------------- src/compiler/parse/state/mustache.ts | 6 +- test/parser/samples/await-catch/output.json | 2 + .../samples/await-then-catch/output.json | 4 + .../each-block-destructured/input.svelte | 4 + .../each-block-destructured/output.json | 221 ++++++++++++--- .../no-error-if-before-closing/output.json | 4 + .../_config.js | 22 ++ .../main.svelte | 7 + .../errors.json | 2 +- .../errors.json | 4 +- .../errors.json | 4 +- 22 files changed, 453 insertions(+), 432 deletions(-) create mode 100644 src/compiler/compile/nodes/shared/Context.ts delete mode 100644 src/compiler/compile/utils/traverse_destructure_pattern.ts create mode 100644 test/runtime/samples/each-block-destructured-default/_config.js create mode 100644 test/runtime/samples/each-block-destructured-default/main.svelte diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f3d47d73b0a..cb9bbf6b8f48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Svelte changelog +## Unreleased + +* Support default values and trailing commas in destructuring `{#await}` ([#4560](https://github.com/sveltejs/svelte/issues/4560), [#4810](https://github.com/sveltejs/svelte/issues/4810)) + ## 3.22.2 * Fix compiler exception with `a11y-img-redundant-alt` and value-less `alt` attribute ([#4777](https://github.com/sveltejs/svelte/issues/4777)) diff --git a/src/compiler/compile/nodes/AwaitBlock.ts b/src/compiler/compile/nodes/AwaitBlock.ts index a7b8fb815e4e..66bc15364c48 100644 --- a/src/compiler/compile/nodes/AwaitBlock.ts +++ b/src/compiler/compile/nodes/AwaitBlock.ts @@ -3,17 +3,21 @@ import PendingBlock from './PendingBlock'; import ThenBlock from './ThenBlock'; import CatchBlock from './CatchBlock'; import Expression from './shared/Expression'; -import { Pattern } from 'estree'; import Component from '../Component'; import TemplateScope from './shared/TemplateScope'; import { TemplateNode } from '../../interfaces'; -import traverse_destructure_pattern from '../utils/traverse_destructure_pattern'; +import { Context, unpack_destructuring } from './shared/Context'; +import { Node as ESTreeNode } from 'estree'; export default class AwaitBlock extends Node { type: 'AwaitBlock'; expression: Expression; - value: DestructurePattern; - error: DestructurePattern; + + then_contexts: Context[]; + catch_contexts: Context[]; + + then_node: ESTreeNode | null; + catch_node: ESTreeNode | null; pending: PendingBlock; then: ThenBlock; @@ -24,24 +28,21 @@ export default class AwaitBlock extends Node { this.expression = new Expression(component, this, scope, info.expression); - this.value = info.value && new DestructurePattern(info.value); - this.error = info.error && new DestructurePattern(info.error); + this.then_node = info.value; + this.catch_node = info.error; + + if (this.then_node) { + this.then_contexts = []; + unpack_destructuring(this.then_contexts, info.value, node => node); + } + + if (this.catch_node) { + this.catch_contexts = []; + unpack_destructuring(this.catch_contexts, info.error, node => node); + } this.pending = new PendingBlock(component, this, scope, info.pending); this.then = new ThenBlock(component, this, scope, info.then); this.catch = new CatchBlock(component, this, scope, info.catch); } } - -export class DestructurePattern { - pattern: Pattern; - expressions: string[]; - identifier_name: string | undefined; - - constructor(pattern: Pattern) { - this.pattern = pattern; - this.expressions = []; - traverse_destructure_pattern(pattern, (node) => this.expressions.push(node.name)); - this.identifier_name = this.pattern.type === 'Identifier' ? this.pattern.name : undefined; - } -} diff --git a/src/compiler/compile/nodes/CatchBlock.ts b/src/compiler/compile/nodes/CatchBlock.ts index 8b3736a2b990..1a92f617bbeb 100644 --- a/src/compiler/compile/nodes/CatchBlock.ts +++ b/src/compiler/compile/nodes/CatchBlock.ts @@ -13,9 +13,9 @@ export default class CatchBlock extends AbstractBlock { super(component, parent, scope, info); this.scope = scope.child(); - if (parent.error) { - parent.error.expressions.forEach(expression => { - this.scope.add(expression, parent.expression.dependencies, this); + if (parent.catch_node) { + parent.catch_contexts.forEach(context => { + this.scope.add(context.key.name, parent.expression.dependencies, this); }); } this.children = map_children(component, parent, this.scope, info.children); diff --git a/src/compiler/compile/nodes/EachBlock.ts b/src/compiler/compile/nodes/EachBlock.ts index 31850f874546..6458ea002019 100644 --- a/src/compiler/compile/nodes/EachBlock.ts +++ b/src/compiler/compile/nodes/EachBlock.ts @@ -4,56 +4,8 @@ import map_children from './shared/map_children'; import TemplateScope from './shared/TemplateScope'; import AbstractBlock from './shared/AbstractBlock'; import Element from './Element'; -import { x } from 'code-red'; -import { Node, Identifier, RestElement } from 'estree'; - -interface Context { - key: Identifier; - name?: string; - modifier: (node: Node) => Node; -} - -function unpack_destructuring(contexts: Context[], node: Node, modifier: (node: Node) => Node) { - if (!node) return; - - if (node.type === 'Identifier' || (node as any).type === 'RestIdentifier') { // TODO is this right? not RestElement? - contexts.push({ - key: node as Identifier, - modifier - }); - } else if (node.type === 'ArrayPattern') { - node.elements.forEach((element, i) => { - if (element && (element as any).type === 'RestIdentifier') { - unpack_destructuring(contexts, element, node => x`${modifier(node)}.slice(${i})` as Node); - } else { - unpack_destructuring(contexts, element, node => x`${modifier(node)}[${i}]` as Node); - } - }); - } else if (node.type === 'ObjectPattern') { - const used_properties = []; - - node.properties.forEach((property, i) => { - if ((property as any).kind === 'rest') { // TODO is this right? - const replacement: RestElement = { - type: 'RestElement', - argument: property.key as Identifier - }; - - node.properties[i] = replacement as any; - - unpack_destructuring( - contexts, - property.value, - node => x`@object_without_properties(${modifier(node)}, [${used_properties}])` as Node - ); - } else { - used_properties.push(x`"${(property.key as Identifier).name}"`); - - unpack_destructuring(contexts, property.value, node => x`${modifier(node)}.${(property.key as Identifier).name}` as Node); - } - }); - } -} +import { Context, unpack_destructuring } from './shared/Context'; +import { Node } from 'estree'; export default class EachBlock extends AbstractBlock { type: 'EachBlock'; diff --git a/src/compiler/compile/nodes/ThenBlock.ts b/src/compiler/compile/nodes/ThenBlock.ts index 7eefe2e6fb59..720f88ad786b 100644 --- a/src/compiler/compile/nodes/ThenBlock.ts +++ b/src/compiler/compile/nodes/ThenBlock.ts @@ -13,9 +13,9 @@ export default class ThenBlock extends AbstractBlock { super(component, parent, scope, info); this.scope = scope.child(); - if (parent.value) { - parent.value.expressions.forEach(expression => { - this.scope.add(expression, parent.expression.dependencies, this); + if (parent.then_node) { + parent.then_contexts.forEach(context => { + this.scope.add(context.key.name, parent.expression.dependencies, this); }); } this.children = map_children(component, parent, this.scope, info.children); diff --git a/src/compiler/compile/nodes/shared/Context.ts b/src/compiler/compile/nodes/shared/Context.ts new file mode 100644 index 000000000000..797405b0fe8b --- /dev/null +++ b/src/compiler/compile/nodes/shared/Context.ts @@ -0,0 +1,58 @@ +import { x } from 'code-red'; +import { Node, Identifier, RestElement, Property } from 'estree'; + +export interface Context { + key: Identifier; + name?: string; + modifier: (node: Node) => Node; +} + +export function unpack_destructuring(contexts: Context[], node: Node, modifier: (node: Node) => Node) { + if (!node) return; + + if (node.type === 'Identifier') { + contexts.push({ + key: node as Identifier, + modifier + }); + } else if (node.type === 'RestElement') { + contexts.push({ + key: node.argument as Identifier, + modifier + }); + } else if (node.type === 'ArrayPattern') { + node.elements.forEach((element, i) => { + if (element && element.type === 'RestElement') { + unpack_destructuring(contexts, element, node => x`${modifier(node)}.slice(${i})` as Node); + } else if (element && element.type === 'AssignmentPattern') { + unpack_destructuring(contexts, element.left, node => x`${modifier(node)}[${i}] !== undefined ? ${modifier(node)}[${i}] : ${element.right}` as Node); + } else { + unpack_destructuring(contexts, element, node => x`${modifier(node)}[${i}]` as Node); + } + }); + } else if (node.type === 'ObjectPattern') { + const used_properties = []; + + node.properties.forEach((property) => { + const props: (RestElement | Property) = (property as any); + + if (props.type === 'RestElement') { + unpack_destructuring( + contexts, + props.argument, + node => x`@object_without_properties(${modifier(node)}, [${used_properties}])` as Node + ); + } else { + const key = property.key as Identifier; + const value = property.value; + + used_properties.push(x`"${(key as Identifier).name}"`); + if (value.type === 'AssignmentPattern') { + unpack_destructuring(contexts, value.left, node => x`${modifier(node)}.${key.name} !== undefined ? ${modifier(node)}.${key.name} : ${value.right}` as Node); + } else { + unpack_destructuring(contexts, value, node => x`${modifier(node)}.${key.name}` as Node); + } + } + }); + } +} diff --git a/src/compiler/compile/render_dom/wrappers/AwaitBlock.ts b/src/compiler/compile/render_dom/wrappers/AwaitBlock.ts index 1898a840d23b..ceb898bf7901 100644 --- a/src/compiler/compile/render_dom/wrappers/AwaitBlock.ts +++ b/src/compiler/compile/render_dom/wrappers/AwaitBlock.ts @@ -8,27 +8,37 @@ import FragmentWrapper from './Fragment'; import PendingBlock from '../../nodes/PendingBlock'; import ThenBlock from '../../nodes/ThenBlock'; import CatchBlock from '../../nodes/CatchBlock'; -import { Identifier } from 'estree'; -import traverse_destructure_pattern from '../../utils/traverse_destructure_pattern'; +import { Context } from '../../nodes/shared/Context'; +import { Identifier, Literal, Node } from 'estree'; + +type Status = 'pending' | 'then' | 'catch'; class AwaitBlockBranch extends Wrapper { + parent: AwaitBlockWrapper; node: PendingBlock | ThenBlock | CatchBlock; block: Block; fragment: FragmentWrapper; is_dynamic: boolean; var = null; + status: Status; + + value: string; + value_index: Literal; + value_contexts: Context[]; + is_destructured: boolean; constructor( - status: string, + status: Status, renderer: Renderer, block: Block, - parent: Wrapper, - node: AwaitBlock, + parent: AwaitBlockWrapper, + node: PendingBlock | ThenBlock | CatchBlock, strip_whitespace: boolean, next_sibling: Wrapper ) { super(renderer, block, parent, node); + this.status = status; this.block = block.child({ comment: create_debugging_comment(node, this.renderer.component), @@ -36,6 +46,8 @@ class AwaitBlockBranch extends Wrapper { type: status }); + this.add_context(parent.node[status + '_node'], parent.node[status + '_contexts']); + this.fragment = new FragmentWrapper( renderer, this.block, @@ -48,20 +60,43 @@ class AwaitBlockBranch extends Wrapper { this.is_dynamic = this.block.dependencies.size > 0; } + add_context(node: Node | null, contexts: Context[]) { + if (!node) return; + + if (node.type === 'Identifier') { + this.value = node.name; + this.renderer.add_to_context(this.value, true); + } else { + contexts.forEach(context => { + this.renderer.add_to_context(context.key.name, true); + }); + this.value = this.block.parent.get_unique_name('value').name; + this.value_contexts = contexts; + this.renderer.add_to_context(this.value, true); + this.is_destructured = true; + } + this.value_index = this.renderer.context_lookup.get(this.value).index; + } + render(block: Block, parent_node: Identifier, parent_nodes: Identifier) { this.fragment.render(block, parent_node, parent_nodes); - } - render_destructure(block: Block, value, node, index) { - if (value && node.pattern.type !== 'Identifier') { - traverse_destructure_pattern(node.pattern, (node, parent, index) => { - parent[index] = x`#ctx[${block.renderer.context_lookup.get(node.name).index}]`; - }); + if (this.is_destructured) { + this.render_destructure(); + } + } - this.block.chunks.declarations.push(b`(${node.pattern} = #ctx[${index}])`); - if (this.block.has_update_method) { - this.block.chunks.update.push(b`(${node.pattern} = #ctx[${index}])`); + render_destructure() { + const props = this.value_contexts.map(prop => b`#ctx[${this.block.renderer.context_lookup.get(prop.key.name).index}] = ${prop.modifier(x`#ctx[${this.value_index}]`)};`); + const get_context = this.block.renderer.component.get_unique_name(`get_${this.status}_context`); + this.block.renderer.blocks.push(b` + function ${get_context}(#ctx) { + ${props} } + `); + this.block.chunks.declarations.push(b`${get_context}(#ctx)`); + if (this.block.has_update_method) { + this.block.chunks.update.push(b`${get_context}(#ctx)`); } } } @@ -73,9 +108,6 @@ export default class AwaitBlockWrapper extends Wrapper { then: AwaitBlockBranch; catch: AwaitBlockBranch; - value: string; - error: string; - var: Identifier = { type: 'Identifier', name: 'await_block' }; constructor( @@ -92,26 +124,12 @@ export default class AwaitBlockWrapper extends Wrapper { this.not_static_content(); block.add_dependencies(this.node.expression.dependencies); - if (this.node.value) { - for (const ctx of this.node.value.expressions) { - block.renderer.add_to_context(ctx, true); - } - this.value = this.node.value.identifier_name || block.get_unique_name('value').name; - block.renderer.add_to_context(this.value, true); - } - if (this.node.error) { - for (const ctx of this.node.error.expressions) { - block.renderer.add_to_context(ctx, true); - } - this.error = this.node.error.identifier_name || block.get_unique_name('error').name; - block.renderer.add_to_context(this.error, true); - } let is_dynamic = false; let has_intros = false; let has_outros = false; - ['pending', 'then', 'catch'].forEach(status => { + ['pending', 'then', 'catch'].forEach((status: Status) => { const child = this.node[status]; const branch = new AwaitBlockBranch( @@ -166,9 +184,6 @@ export default class AwaitBlockWrapper extends Wrapper { block.maintain_context = true; - const value_index = this.value && block.renderer.context_lookup.get(this.value).index; - const error_index = this.error && block.renderer.context_lookup.get(this.error).index; - const info_props: any = x`{ ctx: #ctx, current: null, @@ -176,8 +191,8 @@ export default class AwaitBlockWrapper extends Wrapper { pending: ${this.pending.block.name}, then: ${this.then.block.name}, catch: ${this.catch.block.name}, - value: ${value_index}, - error: ${error_index}, + value: ${this.then.value_index}, + error: ${this.catch.value_index}, blocks: ${this.pending.block.has_outro_method && x`[,,,]`} }`; @@ -232,7 +247,7 @@ export default class AwaitBlockWrapper extends Wrapper { } else { const #child_ctx = #ctx.slice(); - ${this.value && b`#child_ctx[${value_index}] = ${info}.resolved;`} + ${this.then.value && b`#child_ctx[${this.then.value_index}] = ${info}.resolved;`} ${info}.block.p(#child_ctx, #dirty); } `); @@ -246,7 +261,7 @@ export default class AwaitBlockWrapper extends Wrapper { block.chunks.update.push(b` { const #child_ctx = #ctx.slice(); - ${this.value && b`#child_ctx[${value_index}] = ${info}.resolved;`} + ${this.then.value && b`#child_ctx[${this.then.value_index}] = ${info}.resolved;`} ${info}.block.p(#child_ctx, #dirty); } `); @@ -271,7 +286,5 @@ export default class AwaitBlockWrapper extends Wrapper { [this.pending, this.then, this.catch].forEach(branch => { branch.render(branch.block, null, x`#nodes` as Identifier); }); - this.then.render_destructure(block, this.value, this.node.value, value_index); - this.catch.render_destructure(block, this.error, this.node.error, error_index); } } diff --git a/src/compiler/compile/render_ssr/handlers/AwaitBlock.ts b/src/compiler/compile/render_ssr/handlers/AwaitBlock.ts index d6bb86f1a4d3..6a62f872bb73 100644 --- a/src/compiler/compile/render_ssr/handlers/AwaitBlock.ts +++ b/src/compiler/compile/render_ssr/handlers/AwaitBlock.ts @@ -14,7 +14,7 @@ export default function(node: AwaitBlock, renderer: Renderer, options: RenderOpt renderer.add_expression(x` function(__value) { if (@is_promise(__value)) return ${pending}; - return (function(${node.value ? node.value.pattern : ''}) { return ${then}; }(__value)); + return (function(${node.then_node ? node.then_node : ''}) { return ${then}; }(__value)); }(${node.expression.node}) `); } diff --git a/src/compiler/compile/utils/traverse_destructure_pattern.ts b/src/compiler/compile/utils/traverse_destructure_pattern.ts deleted file mode 100644 index 6c918c28c07f..000000000000 --- a/src/compiler/compile/utils/traverse_destructure_pattern.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { Pattern, Identifier, RestElement } from "estree"; -import { Node } from "acorn"; - -export default function traverse_destructure_pattern( - node: Pattern, - callback: (node: Identifier, parent: Node, key: string | number) => void -) { - function traverse(node: Pattern, parent, key) { - switch (node.type) { - case "Identifier": - return callback(node, parent, key); - case "ArrayPattern": - for (let i = 0; i < node.elements.length; i++) { - const element = node.elements[i]; - traverse(element, node.elements, i); - } - break; - case "ObjectPattern": - for (let i = 0; i < node.properties.length; i++) { - const property = node.properties[i]; - if (property.type === "Property") { - traverse(property.value, property, "value"); - } else { - traverse((property as any) as RestElement, node.properties, i); - } - } - break; - case "RestElement": - return traverse(node.argument, node, 'argument'); - case "AssignmentPattern": - return traverse(node.left, node, 'left'); - } - } - traverse(node, null, null); -} diff --git a/src/compiler/parse/index.ts b/src/compiler/parse/index.ts index c21e6d6f7968..a809eeebeb31 100644 --- a/src/compiler/parse/index.ts +++ b/src/compiler/parse/index.ts @@ -5,9 +5,6 @@ import { reserved } from '../utils/names'; import full_char_code_at from '../utils/full_char_code_at'; import { TemplateNode, Ast, ParserOptions, Fragment, Style, Script } from '../interfaces'; import error from '../utils/error'; -import { is_bracket_open, is_bracket_close, is_bracket_pair, get_bracket_close } from './utils/bracket'; -import { parse_expression_at } from './acorn'; -import { Pattern } from 'estree'; type ParserState = (parser: Parser) => (ParserState | void); @@ -173,51 +170,6 @@ export class Parser { return identifier; } - read_destructure_pattern(): Pattern { - const start = this.index; - let i = this.index; - - const code = full_char_code_at(this.template, i); - if (isIdentifierStart(code, true)) { - return { type: 'Identifier', name: this.read_identifier() }; - } - - if (!is_bracket_open(code)) { - this.error({ - code: 'unexpected-token', - message: 'Expected identifier or destructure pattern', - }); - } - - const bracket_stack = [code]; - i += code <= 0xffff ? 1 : 2; - - while (i < this.template.length) { - const code = full_char_code_at(this.template, i); - if (is_bracket_open(code)) { - bracket_stack.push(code); - } else if (is_bracket_close(code)) { - if (!is_bracket_pair(bracket_stack[bracket_stack.length - 1], code)) { - this.error({ - code: 'unexpected-token', - message: `Expected ${String.fromCharCode(get_bracket_close(bracket_stack[bracket_stack.length - 1]))}` - }); - } - bracket_stack.pop(); - if (bracket_stack.length === 0) { - i += code <= 0xffff ? 1 : 2; - break; - } - } - i += code <= 0xffff ? 1 : 2; - } - - this.index = i; - - const pattern_string = this.template.slice(start, i); - return (parse_expression_at(`(${pattern_string} = 1)`, 0) as any).left as Pattern; - } - read_until(pattern: RegExp) { if (this.index >= this.template.length) this.error({ diff --git a/src/compiler/parse/read/context.ts b/src/compiler/parse/read/context.ts index fe666467f803..8d28bd20247f 100644 --- a/src/compiler/parse/read/context.ts +++ b/src/compiler/parse/read/context.ts @@ -1,202 +1,82 @@ -import { Parser } from '../index'; -import { reserved } from '../../utils/names'; - -interface Identifier { - start: number; - end: number; - type: 'Identifier'; - name: string; -} - -interface Property { - start: number; - end: number; - type: 'Property'; - kind: 'init' | 'rest'; - shorthand: boolean; - key: Identifier; - value: Context; -} - -interface Context { - start: number; - end: number; - type: 'Identifier' | 'ArrayPattern' | 'ObjectPattern' | 'RestIdentifier'; - name?: string; - elements?: Context[]; - properties?: Property[]; -} +import { Parser } from "../index"; +import { isIdentifierStart } from "acorn"; +import full_char_code_at from "../../utils/full_char_code_at"; +import { + is_bracket_open, + is_bracket_close, + is_bracket_pair, + get_bracket_close +} from "../utils/bracket"; +import { parse_expression_at } from "../acorn"; +import { Pattern } from "estree"; + +export default function read_context( + parser: Parser +): Pattern & { start: number; end: number } { + const start = parser.index; + let i = parser.index; + + const code = full_char_code_at(parser.template, i); + if (isIdentifierStart(code, true)) { + return { + type: "Identifier", + name: parser.read_identifier(), + start, + end: parser.index + }; + } -function error_on_assignment_pattern(parser: Parser) { - if (parser.eat('=')) { + if (!is_bracket_open(code)) { parser.error({ - code: 'invalid-assignment-pattern', - message: 'Assignment patterns are not supported' - }, parser.index - 1); + code: "unexpected-token", + message: "Expected identifier or destructure pattern" + }); } -} - -function error_on_rest_pattern_not_last(parser: Parser) { - parser.error({ - code: 'rest-pattern-not-last', - message: 'Rest destructuring expected to be last' - }, parser.index); -} - -export default function read_context(parser: Parser) { - const context: Context = { - start: parser.index, - end: null, - type: null - }; - if (parser.eat('[')) { - context.type = 'ArrayPattern'; - context.elements = []; - - do { - parser.allow_whitespace(); - - const lastContext = context.elements[context.elements.length - 1]; - if (lastContext && lastContext.type === 'RestIdentifier') { - error_on_rest_pattern_not_last(parser); + const bracket_stack = [code]; + i += code <= 0xffff ? 1 : 2; + + while (i < parser.template.length) { + const code = full_char_code_at(parser.template, i); + if (is_bracket_open(code)) { + bracket_stack.push(code); + } else if (is_bracket_close(code)) { + if (!is_bracket_pair(bracket_stack[bracket_stack.length - 1], code)) { + parser.error({ + code: "unexpected-token", + message: `Expected ${String.fromCharCode( + get_bracket_close(bracket_stack[bracket_stack.length - 1]) + )}` + }); } - - if (parser.template[parser.index] === ',') { - context.elements.push(null); - } else { - context.elements.push(read_context(parser)); - parser.allow_whitespace(); - } - } while (parser.eat(',')); - - error_on_assignment_pattern(parser); - parser.eat(']', true); - context.end = parser.index; - } - - else if (parser.eat('{')) { - context.type = 'ObjectPattern'; - context.properties = []; - - do { - parser.allow_whitespace(); - - if (parser.eat('...')) { - parser.allow_whitespace(); - - const start = parser.index; - const name = parser.read_identifier(); - const key: Identifier = { - start, - end: parser.index, - type: 'Identifier', - name - }; - const property: Property = { - start, - end: parser.index, - type: 'Property', - kind: 'rest', - shorthand: true, - key, - value: key - }; - - context.properties.push(property); - - parser.allow_whitespace(); - - if (parser.eat(',')) { - parser.error({ - code: `comma-after-rest`, - message: `Comma is not permitted after the rest element` - }, parser.index - 1); - } - + bracket_stack.pop(); + if (bracket_stack.length === 0) { + i += code <= 0xffff ? 1 : 2; break; } - - // TODO: DRY this out somehow - // We don't know whether we want to allow reserved words until we see whether there's a ':' after it - // Probably ideally we'd use Acorn to do all of this - const start = parser.index; - const name = parser.read_identifier(true); - const key: Identifier = { - start, - end: parser.index, - type: 'Identifier', - name - }; - parser.allow_whitespace(); - - let value: Context; - if (parser.eat(':')) { - parser.allow_whitespace(); - value = read_context(parser); - } else { - if (reserved.has(name)) { - parser.error({ - code: `unexpected-reserved-word`, - message: `'${name}' is a reserved word in JavaScript and cannot be used here` - }, start); - } - value = key; - } - - const property: Property = { - start, - end: value.end, - type: 'Property', - kind: 'init', - shorthand: value.type === 'Identifier' && value.name === name, - key, - value - }; - - context.properties.push(property); - - parser.allow_whitespace(); - } while (parser.eat(',')); - - error_on_assignment_pattern(parser); - parser.eat('}', true); - context.end = parser.index; - } - - else if (parser.eat('...')) { - const name = parser.read_identifier(); - if (name) { - context.type = 'RestIdentifier'; - context.end = parser.index; - context.name = name; - } - - else { - parser.error({ - code: 'invalid-context', - message: 'Expected a rest pattern' - }); } + i += code <= 0xffff ? 1 : 2; } - else { - const name = parser.read_identifier(); - if (name) { - context.type = 'Identifier'; - context.end = parser.index; - context.name = name; - } - - else { - parser.error({ - code: 'invalid-context', - message: 'Expected a name, array pattern or object pattern' - }); - } - - error_on_assignment_pattern(parser); + parser.index = i; + + const pattern_string = parser.template.slice(start, i); + try { + // the length of the `space_with_newline` has to be start - 1 + // because we added a `(` in front of the pattern_string, + // which shifted the entire string to right by 1 + // so we offset it by removing 1 character in the `space_with_newline` + // to achieve that, we remove the 1st space encountered, + // so it will not affect the `column` of the node + let space_with_newline = parser.template.slice(0, start).replace(/[^\n]/g, ' '); + const first_space = space_with_newline.indexOf(' '); + space_with_newline = space_with_newline.slice(0, first_space) + space_with_newline.slice(first_space + 1); + + return (parse_expression_at( + `${space_with_newline}(${pattern_string} = 1)`, + start - 1 + ) as any).left; + } catch (error) { + parser.acorn_error(error); } - - return context; } diff --git a/src/compiler/parse/state/mustache.ts b/src/compiler/parse/state/mustache.ts index 0f6608f679af..4e1d5c5fd4cc 100644 --- a/src/compiler/parse/state/mustache.ts +++ b/src/compiler/parse/state/mustache.ts @@ -196,7 +196,7 @@ export default function mustache(parser: Parser) { if (!parser.eat('}')) { parser.require_whitespace(); - await_block[is_then ? 'value': 'error'] = parser.read_destructure_pattern(); + await_block[is_then ? 'value': 'error'] = read_context(parser); parser.allow_whitespace(); parser.eat('}', true); } @@ -305,14 +305,14 @@ export default function mustache(parser: Parser) { const await_block_shorthand = type === 'AwaitBlock' && parser.eat('then'); if (await_block_shorthand) { parser.require_whitespace(); - block.value = parser.read_destructure_pattern(); + block.value = read_context(parser); parser.allow_whitespace(); } const await_block_catch_shorthand = !await_block_shorthand && type === 'AwaitBlock' && parser.eat('catch'); if (await_block_catch_shorthand) { parser.require_whitespace(); - block.error = parser.read_destructure_pattern(); + block.error = read_context(parser); parser.allow_whitespace(); } diff --git a/test/parser/samples/await-catch/output.json b/test/parser/samples/await-catch/output.json index d47d27e4cb93..c5435830184b 100644 --- a/test/parser/samples/await-catch/output.json +++ b/test/parser/samples/await-catch/output.json @@ -26,6 +26,8 @@ }, "value": null, "error": { + "start": 47, + "end": 55, "type": "Identifier", "name": "theError" }, diff --git a/test/parser/samples/await-then-catch/output.json b/test/parser/samples/await-then-catch/output.json index 01dc89f3f904..8e4b7a4c32e5 100644 --- a/test/parser/samples/await-then-catch/output.json +++ b/test/parser/samples/await-then-catch/output.json @@ -25,10 +25,14 @@ "name": "thePromise" }, "value": { + "start": 46, + "end": 54, "type": "Identifier", "name": "theValue" }, "error": { + "start": 96, + "end": 104, "type": "Identifier", "name": "theError" }, diff --git a/test/parser/samples/each-block-destructured/input.svelte b/test/parser/samples/each-block-destructured/input.svelte index 09e9885be019..5313050fa0b2 100644 --- a/test/parser/samples/each-block-destructured/input.svelte +++ b/test/parser/samples/each-block-destructured/input.svelte @@ -1,3 +1,7 @@ + + {#each animals as [key, value, ...rest]}

{key}: {value}

{/each} diff --git a/test/parser/samples/each-block-destructured/output.json b/test/parser/samples/each-block-destructured/output.json index 425c609a2ccd..69e165c0a4c4 100644 --- a/test/parser/samples/each-block-destructured/output.json +++ b/test/parser/samples/each-block-destructured/output.json @@ -1,24 +1,31 @@ { "html": { - "start": 0, - "end": 71, + "start": 41, + "end": 112, "type": "Fragment", "children": [ { - "start": 0, - "end": 71, + "start": 39, + "end": 41, + "type": "Text", + "raw": "\n\n", + "data": "\n\n" + }, + { + "start": 41, + "end": 112, "type": "EachBlock", "expression": { "type": "Identifier", - "start": 7, - "end": 14, + "start": 48, + "end": 55, "loc": { "start": { - "line": 1, + "line": 5, "column": 7 }, "end": { - "line": 1, + "line": 5, "column": 14 } }, @@ -26,27 +33,27 @@ }, "children": [ { - "start": 42, - "end": 63, + "start": 83, + "end": 104, "type": "Element", "name": "p", "attributes": [], "children": [ { - "start": 45, - "end": 50, + "start": 86, + "end": 91, "type": "MustacheTag", "expression": { "type": "Identifier", - "start": 46, - "end": 49, + "start": 87, + "end": 90, "loc": { "start": { - "line": 2, + "line": 6, "column": 5 }, "end": { - "line": 2, + "line": 6, "column": 8 } }, @@ -54,27 +61,27 @@ } }, { - "start": 50, - "end": 52, + "start": 91, + "end": 93, "type": "Text", "raw": ": ", "data": ": " }, { - "start": 52, - "end": 59, + "start": 93, + "end": 100, "type": "MustacheTag", "expression": { "type": "Identifier", - "start": 53, - "end": 58, + "start": 94, + "end": 99, "loc": { "start": { - "line": 2, + "line": 6, "column": 12 }, "end": { - "line": 2, + "line": 6, "column": 17 } }, @@ -85,31 +92,177 @@ } ], "context": { - "start": 18, - "end": 39, "type": "ArrayPattern", + "start": 59, + "end": 80, + "loc": { + "start": { + "line": 5, + "column": 19 + }, + "end": { + "line": 5, + "column": 40 + } + }, "elements": [ { - "start": 19, - "end": 22, "type": "Identifier", + "start": 60, + "end": 63, + "loc": { + "start": { + "line": 5, + "column": 20 + }, + "end": { + "line": 5, + "column": 23 + } + }, "name": "key" }, { - "start": 24, - "end": 29, "type": "Identifier", + "start": 65, + "end": 70, + "loc": { + "start": { + "line": 5, + "column": 25 + }, + "end": { + "line": 5, + "column": 30 + } + }, "name": "value" }, { - "start": 31, - "end": 38, - "type": "RestIdentifier", - "name": "rest" + "type": "RestElement", + "start": 72, + "end": 79, + "loc": { + "start": { + "line": 5, + "column": 32 + }, + "end": { + "line": 5, + "column": 39 + } + }, + "argument": { + "type": "Identifier", + "start": 75, + "end": 79, + "loc": { + "start": { + "line": 5, + "column": 35 + }, + "end": { + "line": 5, + "column": 39 + } + }, + "name": "rest" + } } ] } } ] + }, + "instance": { + "type": "Script", + "start": 0, + "end": 39, + "context": "default", + "content": { + "type": "Program", + "start": 8, + "end": 30, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 0 + } + }, + "body": [ + { + "type": "ExportNamedDeclaration", + "start": 10, + "end": 29, + "loc": { + "start": { + "line": 2, + "column": 1 + }, + "end": { + "line": 2, + "column": 20 + } + }, + "declaration": { + "type": "VariableDeclaration", + "start": 17, + "end": 29, + "loc": { + "start": { + "line": 2, + "column": 8 + }, + "end": { + "line": 2, + "column": 20 + } + }, + "declarations": [ + { + "type": "VariableDeclarator", + "start": 21, + "end": 28, + "loc": { + "start": { + "line": 2, + "column": 12 + }, + "end": { + "line": 2, + "column": 19 + } + }, + "id": { + "type": "Identifier", + "start": 21, + "end": 28, + "loc": { + "start": { + "line": 2, + "column": 12 + }, + "end": { + "line": 2, + "column": 19 + } + }, + "name": "animals" + }, + "init": null + } + ], + "kind": "let" + }, + "specifiers": [], + "source": null + } + ], + "sourceType": "module" + } } } \ No newline at end of file diff --git a/test/parser/samples/no-error-if-before-closing/output.json b/test/parser/samples/no-error-if-before-closing/output.json index e30c302e0f95..708128a42eb9 100644 --- a/test/parser/samples/no-error-if-before-closing/output.json +++ b/test/parser/samples/no-error-if-before-closing/output.json @@ -116,6 +116,8 @@ "raw": "true" }, "value": { + "start": 97, + "end": 98, "type": "Identifier", "name": "f" }, @@ -202,6 +204,8 @@ "raw": "true" }, "value": { + "start": 137, + "end": 138, "type": "Identifier", "name": "f" }, diff --git a/test/runtime/samples/each-block-destructured-default/_config.js b/test/runtime/samples/each-block-destructured-default/_config.js new file mode 100644 index 000000000000..133fd685321a --- /dev/null +++ b/test/runtime/samples/each-block-destructured-default/_config.js @@ -0,0 +1,22 @@ +export default { + props: { + animalEntries: [ + { animal: 'raccoon', class: 'mammal', species: 'P. lotor', kilogram: 25 }, + { animal: 'eagle', class: 'bird', kilogram: 5.4 } + ] + }, + + html: ` +

raccoon - P. lotor - 25kg

+

eagle - unknown - 5.4kg

+ `, + + + + test({ assert, component, target }) { + component.animalEntries = [{ animal: 'cow', class: 'mammal', species: '‎B. taurus' }]; + assert.htmlEqual(target.innerHTML, ` +

cow - ‎B. taurus - 50kg

+ `); + }, +}; diff --git a/test/runtime/samples/each-block-destructured-default/main.svelte b/test/runtime/samples/each-block-destructured-default/main.svelte new file mode 100644 index 000000000000..a91b45299e5c --- /dev/null +++ b/test/runtime/samples/each-block-destructured-default/main.svelte @@ -0,0 +1,7 @@ + + +{#each animalEntries as { animal, species = 'unknown', kilogram: weight = 50 , ...props } } +

{animal} - {species} - {weight}kg

+{/each} diff --git a/test/validator/samples/each-block-destructured-object-rest-comma-after/errors.json b/test/validator/samples/each-block-destructured-object-rest-comma-after/errors.json index 549b6960eb33..df899b7702ad 100644 --- a/test/validator/samples/each-block-destructured-object-rest-comma-after/errors.json +++ b/test/validator/samples/each-block-destructured-object-rest-comma-after/errors.json @@ -1,5 +1,5 @@ [{ - "code": "comma-after-rest", + "code": "parse-error", "message": "Comma is not permitted after the rest element", "pos": 100, "start": { diff --git a/test/validator/samples/each-block-invalid-context-destructured-object/errors.json b/test/validator/samples/each-block-invalid-context-destructured-object/errors.json index 085021ff5ac0..c96e3d2c8cc7 100644 --- a/test/validator/samples/each-block-invalid-context-destructured-object/errors.json +++ b/test/validator/samples/each-block-invalid-context-destructured-object/errors.json @@ -1,6 +1,6 @@ [{ - "code": "unexpected-reserved-word", - "message": "'case' is a reserved word in JavaScript and cannot be used here", + "code": "parse-error", + "message": "Unexpected keyword 'case'", "start": { "line": 1, "column": 18, diff --git a/test/validator/samples/each-block-invalid-context-destructured/errors.json b/test/validator/samples/each-block-invalid-context-destructured/errors.json index afe99ee219bc..62d6f62e87c2 100644 --- a/test/validator/samples/each-block-invalid-context-destructured/errors.json +++ b/test/validator/samples/each-block-invalid-context-destructured/errors.json @@ -1,6 +1,6 @@ [{ - "code": "unexpected-reserved-word", - "message": "'case' is a reserved word in JavaScript and cannot be used here", + "code": "parse-error", + "message": "Unexpected token", "start": { "line": 1, "column": 17, From 40d0ea6702c06590c10760869b65e326a44413dd Mon Sep 17 00:00:00 2001 From: Daniel Imfeld Date: Mon, 11 May 2020 06:24:01 -1000 Subject: [PATCH 119/158] set .value while setting .__value during spread (#4809) --- src/runtime/internal/dom.ts | 4 +++- .../_config.js | 15 +++++++++++++++ .../main.svelte | 6 ++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 test/runtime/samples/spread-element-input-bind-group-with-value-attr/_config.js create mode 100644 test/runtime/samples/spread-element-input-bind-group-with-value-attr/main.svelte diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts index bf8fc1f5a036..e447eae36276 100644 --- a/src/runtime/internal/dom.ts +++ b/src/runtime/internal/dom.ts @@ -98,7 +98,9 @@ export function set_attributes(node: Element & ElementCSSInlineStyle, attributes node.removeAttribute(key); } else if (key === 'style') { node.style.cssText = attributes[key]; - } else if (key === '__value' || descriptors[key] && descriptors[key].set) { + } else if (key === '__value') { + (node as any).value = node[key] = attributes[key]; + } else if (descriptors[key] && descriptors[key].set) { node[key] = attributes[key]; } else { attr(node, key, attributes[key]); diff --git a/test/runtime/samples/spread-element-input-bind-group-with-value-attr/_config.js b/test/runtime/samples/spread-element-input-bind-group-with-value-attr/_config.js new file mode 100644 index 000000000000..6e1b89035132 --- /dev/null +++ b/test/runtime/samples/spread-element-input-bind-group-with-value-attr/_config.js @@ -0,0 +1,15 @@ +export default { + props: { + props: { + 'data-foo': 'bar' + } + }, + + html: ``, + + async test({ assert, component, target, window }) { + const input = target.querySelector('input'); + assert.equal(input.value, 'abc'); + assert.equal(input.__value, 'abc'); + } +}; diff --git a/test/runtime/samples/spread-element-input-bind-group-with-value-attr/main.svelte b/test/runtime/samples/spread-element-input-bind-group-with-value-attr/main.svelte new file mode 100644 index 000000000000..ce6b76f0932f --- /dev/null +++ b/test/runtime/samples/spread-element-input-bind-group-with-value-attr/main.svelte @@ -0,0 +1,6 @@ + + + From ee130793ca69c2430d36ecf30359424ab6e2135e Mon Sep 17 00:00:00 2001 From: Conduitry Date: Mon, 11 May 2020 12:25:20 -0400 Subject: [PATCH 120/158] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cb9bbf6b8f48..3743f2d34058 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased * Support default values and trailing commas in destructuring `{#await}` ([#4560](https://github.com/sveltejs/svelte/issues/4560), [#4810](https://github.com/sveltejs/svelte/issues/4810)) +* Fix setting `value` attribute with `bind:group` and attribute spread ([#4803](https://github.com/sveltejs/svelte/issues/4803)) ## 3.22.2 From 9be33104316ba4f111ee7aba9472eb43c546a0a7 Mon Sep 17 00:00:00 2001 From: Antony Jones Date: Wed, 13 May 2020 12:49:25 +0100 Subject: [PATCH 121/158] site: add FAQs page (#4823) --- site/content/faq/100-im-new-to-svelte.md | 7 + .../1000-how-can-i-update-my-v2-components.md | 5 + .../faq/1100-is-svelte-v2-still-availabile.md | 7 + site/content/faq/1200-how-do-i-do-hmr.md | 5 + .../faq/200-are-there-any-video-courses.md | 10 + site/content/faq/300-is-svelte-dev-down.md | 5 + .../400-how-can-i-get-syntax-highlighting.md | 5 + .../faq/500-what-about-typescript-support.md | 5 + site/content/faq/600-does-svelte-scale.md | 5 + .../faq/700-is-there-a-component-library.md | 5 + .../faq/800-how-do-i-test-svelte-apps.md | 6 + site/content/faq/900-is-there-a-router.md | 13 + site/src/routes/blog/[slug].svelte | 30 - site/src/routes/faq.js | 4 - site/src/routes/faq/_faqs.js | 58 ++ site/src/routes/faq/index.json.js | 24 + site/src/routes/faq/index.svelte | 89 +++ site/src/template.html | 1 + site/static/global.css | 513 +----------------- 19 files changed, 272 insertions(+), 525 deletions(-) create mode 100644 site/content/faq/100-im-new-to-svelte.md create mode 100644 site/content/faq/1000-how-can-i-update-my-v2-components.md create mode 100644 site/content/faq/1100-is-svelte-v2-still-availabile.md create mode 100644 site/content/faq/1200-how-do-i-do-hmr.md create mode 100644 site/content/faq/200-are-there-any-video-courses.md create mode 100644 site/content/faq/300-is-svelte-dev-down.md create mode 100644 site/content/faq/400-how-can-i-get-syntax-highlighting.md create mode 100644 site/content/faq/500-what-about-typescript-support.md create mode 100644 site/content/faq/600-does-svelte-scale.md create mode 100644 site/content/faq/700-is-there-a-component-library.md create mode 100644 site/content/faq/800-how-do-i-test-svelte-apps.md create mode 100644 site/content/faq/900-is-there-a-router.md delete mode 100644 site/src/routes/faq.js create mode 100644 site/src/routes/faq/_faqs.js create mode 100644 site/src/routes/faq/index.json.js create mode 100644 site/src/routes/faq/index.svelte diff --git a/site/content/faq/100-im-new-to-svelte.md b/site/content/faq/100-im-new-to-svelte.md new file mode 100644 index 000000000000..18e4b6742f70 --- /dev/null +++ b/site/content/faq/100-im-new-to-svelte.md @@ -0,0 +1,7 @@ +--- +question: I'm new to Svelte. Where should I start? +--- + +We think the best way to get started is playing through the interactive [Tutorial](https://svelte.dev/tutorial). Each step there is mainly focused on one specific aspect and is easy to follow. You'll be editing and running real Svelte components right in your browser. + +Five to ten minutes should be enough to get you up and running. An hour and a half should get you through the entire tutorial. \ No newline at end of file diff --git a/site/content/faq/1000-how-can-i-update-my-v2-components.md b/site/content/faq/1000-how-can-i-update-my-v2-components.md new file mode 100644 index 000000000000..0800dff89b15 --- /dev/null +++ b/site/content/faq/1000-how-can-i-update-my-v2-components.md @@ -0,0 +1,5 @@ +--- +question: How can I update my components written in Svelte v2? +--- + +svelte-upgrade isn't fully working for v2->v3 yet, [but it's close](https://github.com/sveltejs/svelte-upgrade/pull/12). \ No newline at end of file diff --git a/site/content/faq/1100-is-svelte-v2-still-availabile.md b/site/content/faq/1100-is-svelte-v2-still-availabile.md new file mode 100644 index 000000000000..0fbc4c039c75 --- /dev/null +++ b/site/content/faq/1100-is-svelte-v2-still-availabile.md @@ -0,0 +1,7 @@ +--- +question: Is Svelte v2 still available? +--- + +New features aren't being added to it, and bugs will probably only be fixed if they are extremely nasty or present some sort of security vulnerability. + +The documentation is still available [here](https://v2.svelte.dev/guide). \ No newline at end of file diff --git a/site/content/faq/1200-how-do-i-do-hmr.md b/site/content/faq/1200-how-do-i-do-hmr.md new file mode 100644 index 000000000000..88d08b252f3a --- /dev/null +++ b/site/content/faq/1200-how-do-i-do-hmr.md @@ -0,0 +1,5 @@ +--- +question: How do I do hot module reloading? +--- + +Use the community plugins for [rollup](https://github.com/rixo/rollup-plugin-svelte-hot) and [webpack](https://github.com/rixo/svelte-loader-hot). diff --git a/site/content/faq/200-are-there-any-video-courses.md b/site/content/faq/200-are-there-any-video-courses.md new file mode 100644 index 000000000000..0c2c1f680e94 --- /dev/null +++ b/site/content/faq/200-are-there-any-video-courses.md @@ -0,0 +1,10 @@ +--- +question: Are there any video courses? +--- + +There are no official ones, but here are a couple of third-part ones that we know of. + +- [Egghead](https://egghead.io/playlists/getting-started-with-svelte-3-05a8541a) +- [Udemy](https://www.udemy.com/sveltejs-the-complete-guide/) + +Note that Udemy very frequently has discounts over 90%. diff --git a/site/content/faq/300-is-svelte-dev-down.md b/site/content/faq/300-is-svelte-dev-down.md new file mode 100644 index 000000000000..a7ce9984b725 --- /dev/null +++ b/site/content/faq/300-is-svelte-dev-down.md @@ -0,0 +1,5 @@ +--- +question: Is svelte.dev down? +--- + +Probably not, but it's possible. If you can't seem to access any `.dev` sites, check out [this SuperUser question and answer](https://superuser.com/q/1413402). \ No newline at end of file diff --git a/site/content/faq/400-how-can-i-get-syntax-highlighting.md b/site/content/faq/400-how-can-i-get-syntax-highlighting.md new file mode 100644 index 000000000000..90f10b254fcf --- /dev/null +++ b/site/content/faq/400-how-can-i-get-syntax-highlighting.md @@ -0,0 +1,5 @@ +--- +question: How can I get VSCode to syntax-highlight my .svelte files? +--- + +There is an [official VSCode extension for Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode), however it is still in the **beta** testing stage, and not all issues have been ironed out. \ No newline at end of file diff --git a/site/content/faq/500-what-about-typescript-support.md b/site/content/faq/500-what-about-typescript-support.md new file mode 100644 index 000000000000..dae27143ed7a --- /dev/null +++ b/site/content/faq/500-what-about-typescript-support.md @@ -0,0 +1,5 @@ +--- +question: What about Typescript support? +--- + +You need to install a [community supported preprocessor](https://github.com/sveltejs/integrations#preprocessors) such as [svelte-preprocess](https://github.com/kaisermann/svelte-preprocess). Work is ongoing to improve [IDE support](https://github.com/sveltejs/language-tools/issues/83) and build [additional CLI tooling](https://github.com/sveltejs/language-tools/issues/68) \ No newline at end of file diff --git a/site/content/faq/600-does-svelte-scale.md b/site/content/faq/600-does-svelte-scale.md new file mode 100644 index 000000000000..06c9b58a97fa --- /dev/null +++ b/site/content/faq/600-does-svelte-scale.md @@ -0,0 +1,5 @@ +--- +question: Does Svelte scale? +--- + +There will be a blog post about this eventually, but in the meantime, check out [this issue](https://github.com/sveltejs/svelte/issues/2546). diff --git a/site/content/faq/700-is-there-a-component-library.md b/site/content/faq/700-is-there-a-component-library.md new file mode 100644 index 000000000000..fd771eabda53 --- /dev/null +++ b/site/content/faq/700-is-there-a-component-library.md @@ -0,0 +1,5 @@ +--- +question: Is there a UI component library? +--- + +There are several UI component libraries. Find them under the [code section](https://svelte-community.netlify.com/code) of the Svelte Community website. diff --git a/site/content/faq/800-how-do-i-test-svelte-apps.md b/site/content/faq/800-how-do-i-test-svelte-apps.md new file mode 100644 index 000000000000..af67bebf3f2b --- /dev/null +++ b/site/content/faq/800-how-do-i-test-svelte-apps.md @@ -0,0 +1,6 @@ +--- +question: How do I test Svelte apps? +--- + +We don't have a good answer to this yet, but it is a priority. There are a few approaches that people take when testing, but it generally involves compiling the component and mounting it to something and then performing the tests. +You essentially need to create a bundle for each component you're testing (since svelte is a compiler and not a normal library) and then mount them. You can mount to a JSDOM instance, or you can use Puppeteer if you need a real browser, or you can use a tool like Cypress. There is an example of this in the Sapper starter template. diff --git a/site/content/faq/900-is-there-a-router.md b/site/content/faq/900-is-there-a-router.md new file mode 100644 index 000000000000..a78c47894376 --- /dev/null +++ b/site/content/faq/900-is-there-a-router.md @@ -0,0 +1,13 @@ +--- +question: Is there a router? +--- + +You can use any router lib you want. A lot of people use [page.js](https://github.com/visionmedia/page.js). There's also [navaid](https://github.com/lukeed/navaid), which is very similar. + +If you prefer a declarative HTML approach, there's [svelte-routing](https://github.com/EmilTholin/svelte-routing). + +If you need hash-based routing on the client side, check out [svelte-spa-router](https://github.com/ItalyPaleAle/svelte-spa-router), or [abstract-state-router](https://github.com/TehShrike/abstract-state-router/), a mature router for business software. + +For filesystem-based routing, you can take a look at [Routify](https://routify.dev). + +For an official solution, there's nothing that's simply a routing library. There is, however, the official [Sapper](https://sapper.svelte.dev/) framework, a Next.js-style application framework built on Svelte, which includes its own filesystem-based routing. \ No newline at end of file diff --git a/site/src/routes/blog/[slug].svelte b/site/src/routes/blog/[slug].svelte index 610fb6506b0f..d5fd6c067661 100644 --- a/site/src/routes/blog/[slug].svelte +++ b/site/src/routes/blog/[slug].svelte @@ -133,44 +133,14 @@ border: 0.8rem solid var(--second); } - /* headers anchors */ - - .post :global(.offset-anchor) { - position: relative; - display: block; - top: calc(-1 * (var(--nav-h) + var(--top-offset) - 1rem)); - width: 0; - height: 0; - } - .post :global(.anchor) { - position: absolute; - display: block; - background: url(/icons/link.svg) 0 50% no-repeat; - background-size: 1em 1em; - width: 1.4em; - height: 1em; top: calc((var(--h3) - 24px) / 2); - left: -1.4em; - opacity: 0; - transition: opacity 0.2s; - border: none !important; /* TODO get rid of linkify */ } - .post :global(h2):hover :global(.anchor), - .post :global(h3):hover :global(.anchor), - .post :global(h4):hover :global(.anchor), - .post :global(h5):hover :global(.anchor), - .post :global(h6):hover :global(.anchor) { - opacity: 1; - } - - @media (max-width: 768px) { .post :global(.anchor) { transform: scale(0.6); opacity: 1; - top: calc((1em - 0.6 * 24px) / 2); left: -1.0em; } } diff --git a/site/src/routes/faq.js b/site/src/routes/faq.js deleted file mode 100644 index 6263494a4ceb..000000000000 --- a/site/src/routes/faq.js +++ /dev/null @@ -1,4 +0,0 @@ -export function get(req, res) { - res.writeHead(302, { Location: 'https://github.com/sveltejs/svelte/wiki/FAQ' }); - res.end(); -} \ No newline at end of file diff --git a/site/src/routes/faq/_faqs.js b/site/src/routes/faq/_faqs.js new file mode 100644 index 000000000000..fa48e02282e7 --- /dev/null +++ b/site/src/routes/faq/_faqs.js @@ -0,0 +1,58 @@ +import fs from 'fs'; +import path from 'path'; +import { extract_frontmatter, link_renderer } from '@sveltejs/site-kit/utils/markdown.js'; +import marked from 'marked'; +import { makeSlugProcessor } from '../../utils/slug'; +import { highlight } from '../../utils/highlight'; +import { SLUG_PRESERVE_UNICODE } from '../../../config'; + +const makeSlug = makeSlugProcessor(SLUG_PRESERVE_UNICODE); + +export default function get_faqs() { + return fs + .readdirSync('content/faq') + .map(file => { + if (path.extname(file) !== '.md') return; + + const match = /^([0-9]+)-(.+)\.md$/.exec(file); + if (!match) throw new Error(`Invalid filename '${file}'`); + + const [, order, slug] = match; + + const markdown = fs.readFileSync(`content/faq/${file}`, 'utf-8'); + + const { content, metadata } = extract_frontmatter(markdown); + + const renderer = new marked.Renderer(); + + renderer.link = link_renderer; + + renderer.code = highlight; + + renderer.heading = (text, level, rawtext) => { + const fragment = makeSlug(rawtext); + + return ` + + +
+ ${text} + `; + }; + + const answer = marked( + content.replace(/^\t+/gm, match => match.split('\t').join(' ')), + { renderer } + ); + + const fragment = makeSlug(slug); + + return { + fragment, + order, + answer, + metadata + }; + }) + .sort((a, b) => a.order - b.order); +} diff --git a/site/src/routes/faq/index.json.js b/site/src/routes/faq/index.json.js new file mode 100644 index 000000000000..b6810a984e2b --- /dev/null +++ b/site/src/routes/faq/index.json.js @@ -0,0 +1,24 @@ +import send from '@polka/send'; +import get_faqs from './_faqs.js'; + +let json; + +export function get(req, res) { + if (!json || process.env.NODE_ENV !== 'production') { + const faqs = get_faqs() + .map(faq => { + return { + fragment: faq.fragment, + answer: faq.answer, + metadata: faq.metadata + }; + }); + + json = JSON.stringify(faqs); + } + + send(res, 200, json, { + 'Content-Type': 'application/json', + 'Cache-Control': `max-age=${5 * 60 * 1e3}` // 5 minutes + }); +} diff --git a/site/src/routes/faq/index.svelte b/site/src/routes/faq/index.svelte new file mode 100644 index 000000000000..c426f5bf3d78 --- /dev/null +++ b/site/src/routes/faq/index.svelte @@ -0,0 +1,89 @@ + + + + + + Frequently Asked Questions • Svelte + + + + + + +
+ + diff --git a/site/src/template.html b/site/src/template.html index 344684d76669..28ea1910a545 100644 --- a/site/src/template.html +++ b/site/src/template.html @@ -7,6 +7,7 @@ %sapper.base% + diff --git a/site/static/global.css b/site/static/global.css index 14e4e0a0c0b5..7aa0715a9842 100644 --- a/site/static/global.css +++ b/site/static/global.css @@ -1,500 +1,31 @@ -/* ------------------------------------------------ - vars – css custom-properties +/* headers anchors */ - NOTE - - some vars change inside media-queries! - - under normal conditions, there's no need to touch these ------------------------------------------------ -*/ -:root { - --nav-h: 6rem; - --top-offset: 6rem; - --sidebar-w: 30rem; - --sidebar-mid-w: 36rem; - --sidebar-large-w: 48rem; - --main-width: 80rem; - --code-w: 72em; - --side-nav: 3.2rem; - --side-page: var(--side-nav); - - /* easings */ - --in-cubic: cubic-bezier(0.55, 0.055, 0.675, 0.19); - --out-cubic: cubic-bezier(0.215, 0.61, 0.355, 1); - --inout-cubic: cubic-bezier(0.645, 0.045, 0.355, 1); - - --in-back: cubic-bezier(0.6, -0.28, 0.735, 0.045); - --out-back: cubic-bezier(0.175, 0.885, 0.32, 1.275); - --inout-back: cubic-bezier(0.68, -0.55, 0.265, 1.55); -} - -@media screen and (min-width: 768px) { - :root { - --side-page: 14vw; - --top-offset: 10rem; - --side-nav: 4.8rem; - } -} - -/* theme vars */ -.theme-default { - --back: #ffffff; - --back-light: #f6fafd; - --back-api: #eff8ff; - --prime: #ff3e00; - --second: #676778; - --flash: #40b3ff; - --heading: var(--second); - --text: #444; - --sidebar-text: rgba(255, 255, 255, .75); - --border-w: .3rem; /* border-width */ - --border-r: .4rem; /* border-radius */ -} - -/* typo vars */ -.typo-default { - --unit: .8rem; - --code-fs: 1.3rem; - --h6: 1.4rem; - --h5: 1.6rem; - --h4: 1.8rem; /* default font-size */ - --h3: 2.6rem; - --h2: 3rem; - --h1: 3.2rem; - --linemax: 42em; /* max line-length */ - --lh: 1.5; /* base line-height */ -} - -body { - --font: 'Overpass', sans-serif; - --font-mono: 'Fira Mono', monospace; - --font-ui: var(--font-mono); - --font-system: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; -} - - -/* fonts ---------------------------------- */ -/* overpass-300normal - latin */ -@font-face { - font-family: 'Overpass'; - font-style: normal; - font-weight: 300; - font-display: fallback; - src: - local('Overpass Light '), - local('Overpass-Light'), - url('fonts/overpass/overpass-latin-300.woff2') format('woff2'); -} - -/* overpass-600normal - latin */ -@font-face { - font-family: 'Overpass'; - font-style: normal; - font-weight: 600; - font-display: fallback; - src: - local('Overpass Bold '), - local('Overpass-Bold'), - url('fonts/overpass/overpass-latin-600.woff2') format('woff2'); -} - -/* fira-mono-400normal - latin */ -@font-face { - font-family: 'Fira Mono'; - font-style: normal; - font-weight: 400; - font-display: fallback; - src: - local('Fira Mono Regular '), - local('Fira Mono-Regular'), - url('fonts/fira-mono/fira-mono-latin-400.woff2') format('woff2'); -} - -/* base reset ----------------------------- */ -html { - font-size: 62.5%; - -ms-text-size-adjust: 62.5%; - -webkit-text-size-adjust: 62.5%; - -ms-overflow-style: -ms-autohiding-scrollbar; - box-sizing: border-box; - border-collapse: collapse; -} - -html, -body, -#sapper { - width: 100%; - height: 100%; -} - -* { - box-sizing: inherit; - margin: 0; - padding: 0; -} - -/* link reset ----------------------------- */ -a { - text-decoration: none; - cursor: pointer; - color: inherit; -} - -a:hover, a:active { color: var(--flash) } -a:focus { outline: none } - -/* ------------------------------------------------ - global styles ------------------------------------------------ -*/ - -/* typography ----------------------------- */ -body { - font: 300 var(--h4)/var(--lh) var(--font); - background-color: var(--back); - color: var(--text); - - /* default spacing of Overpass is a bit too airy */ - /* letter-spacing: -.013em; */ -} - -h1, h2, h3, h4, h5, h6, blockquote { - position: relative; - margin: 0; - color: var(--heading); -} - -/* h1, h2, h3, h4, h5, h6 { font-weight: 600 } */ -h6 { font-size: var(--h6) } -h5 { font-size: var(--h5) } -h4 { font-size: var(--h4) } -h3 { font-size: var(--h3) } -h2 { font-size: var(--h2) } -h1 { font-size: var(--h1) } - -h1, h2 { - font-family: var(--font); - line-height: 1.25; -} - -h3 { font-weight: 300 } - -p, ol, ul { - margin: 0 0 1em 0; -} - -.b, b, strong { font-weight: 600 } - -tt, code, kbd, samp { - font: 400 var(--code-fs)/1.7 var(--font-mono); -} - -code { - position: relative; - border-radius: .3em; - white-space: nowrap; - color: #444; - -webkit-font-smoothing: initial; -} - -pre code { - top: 0; - white-space: inherit; - background-color: none; -} - -/* sync CodeMirror with prism */ -.CodeMirror { - font-size: var(--code-fs) !important; -} - -::selection { - background: var(--flash); - color: white; -} - -/* opinionated styles --------------------- */ - -li:not(.white) > h2 { - color: var(--second) -} - -blockquote { - position: relative; - margin: 1.6rem 0 2.4rem; - padding: 2rem 2.4rem 1.8rem 2.4rem; - border-radius: var(--border-r); - font-family: var(--font); - max-width: var(--linemax); -} - -blockquote p { - font-size: var(--h5); -} - -blockquote :last-child { - margin: 0; -} - -/* buttons -------------------------------- */ -button { - font-family: inherit; - font-size: inherit; - background-color: transparent; - border: none; - color: currentColor; - cursor: pointer; -} - -button:focus, -.btn:focus { outline: 0 } - -button[disabled], -.btn[disabled], -.btn:hover[disabled] { - opacity: .55; - pointer-events: none; -} - -button > svg, -.btn > svg { - position: relative; - top: -.1rem; - width: 2rem !important; - height: 2rem !important; - stroke: currentColor !important; -} - -/* reset ------- */ -.btn { - --btn-h: 4rem; - --btn-outline: .2rem; - --btn-font: var(--font); - --btn-calc-h: calc(var(--btn-h) - var(--btn-outline) * 2); - --btn-hover: linear-gradient(to top, rgba(0,0,0,.07), rgba(0,0,0,.07)); - - position: relative; - margin: 0 .8rem .8rem 0; - vertical-align: middle; - white-space: nowrap; - display: inline-block; - zoom: 1; - border: none transparent; - font: var(--h4) var(--btn-font); - border-radius: var(--border-r); - color: currentColor; - cursor: pointer; -} - -/* default */ -.btn { - line-height: var(--btn-h); - height: var(--btn-h); - padding: 0 1.6rem; - transition: all .1s; -} - -.btn:hover { - transform: scale(.98); - mix-blend-mode: multiply; - background-image: var(--btn-hover); -} - -/* optional */ -.btn[outline] { - line-height: var(--btn-calc-h); - height: var(--btn-calc-h); - border: var(--btn-outline) solid currentColor; - background-color: white; - color: currentColor; -} - -/* links ------------------------------------- */ -a { - position: relative; - padding: 0 0 1px 0; - border-bottom: 1px solid currentColor; - user-select: none; - color: var(--prime); - transition: color .2s, border .2s, padding .2s; -} - -a:hover { - color: var(--flash); -} - -a:hover { - padding: 0; - border-bottom: 2px solid currentColor; -} - -a.no-underline { - border-bottom: none; - padding: 0; -} - -/* a:hover:not(.disabled) > .icon { stroke: var(--flash) } */ - -/* lists ---------------------------------- */ -.listify ol, -.listify ul { - --list-padding: 2.9rem; - - list-style: none; - color: currentColor; - margin-left: var(--list-padding); -} - -.listify ol > li, -.listify ul > li { - max-width: calc(var(--linemax) - var(--list-padding)); - line-height: 1.5; - margin: 0 0 0.4rem 0; -} - -.listify ul > li:before { - content: ''; - position: absolute; - margin-top: 1.1rem; - margin-left: -1.8rem; - background-color: var(--second); - width: .6rem; - height: .6rem; - border-radius: 2px; - opacity: 0.7; -} - -.listify ol { list-style: decimal } - -/* tables --------------------------------- */ -table { - width: 100%; - font-size: var(--h5); -} - -td, th { - text-align: left; - border-bottom: 1px solid #eee; - padding: 0.4rem 0.8rem 0.4rem 0; -} - -table code, table span { - white-space: pre; -} - -/* grid ----------------------------------- */ -.grid, .grid.half { - display: grid; - grid-gap: 2.4rem; - grid-template-columns: 1fr; - align-items: center; -} - -.grid.stretch { align-items: stretch } - -.grid > .cols-2, -.grid > .cols-3 { grid-column: span 1 } - -@media screen and (min-width: 840px) { - .grid.half, - .grid { grid-template-columns: repeat(2, 1fr) } - .grid > .cols-2, - .grid > .cols-3 { grid-column: span 2 } -} - -@media screen and (min-width: 1100px) { - .grid { grid-template-columns: repeat(3, 1fr) } - .grid > .cols-2 { grid-column: span 2 } - .grid > .cols-3 { grid-column: span 3 } -} - -/* helper styles -------------------------- */ -.flex-auto { flex: 1 0 auto } - -.py0 { - padding-top: 0 !important; - padding-bottom: 0 !important; -} - -.legend, figcaption, .post aside { - max-width: none; - margin: 0 auto; - padding: 1.6rem 0 0 .8rem; - font: 1.2rem/1.6 var(--font-ui); -} - -.filename { - display: inline-block; - padding: 1.6rem 0 0 1rem; - font: var(--h6) var(--font-ui); -} - -.box { - padding: 2.4rem 3.2rem; - border-radius: var(--border-r); -} - -/* theme colors --------------------------- */ -.prime { color: var(--prime) !important } -.second { color: var(--second) !important } -.flash { color: var(--flash) !important } -.black { color: black !important } -.white { color: white !important } - -.back { background-color: var(--back) !important } -.back-light { background-color: var(--back-light) !important } -.bg-prime { background-color: var(--prime) !important } -.bg-second { background-color: var(--second) !important } -.bg-flash { background-color: var(--flash) !important } - -/* inputs --------------------------------- */ -input[type="checkbox"] { - /* display: block; */ +.offset-anchor { position: relative; - height: 1em; - width: calc(100% - 0.6em); - max-width: 2em; - top: -2px; - border-radius: 0.5em; - -webkit-appearance: none; - outline: none; - margin: 0 0.6em 0 0; -} - -input[type="checkbox"]::before { - content: ""; - position: absolute; display: block; - height: 100%; - width: 100%; - padding: 2px; - border-radius: 1em; - top: 0; - left: 0; - background: var(--second); - /* box-sizing: border-box; */ - box-sizing: content-box; + top: calc(-1 * (var(--nav-h) + var(--top-offset)) + 11rem); + width: 0; + height: 0; } -input[type="checkbox"]:checked::before { - background: var(--prime); -} - -input[type="checkbox"]::after { - content: ""; +.anchor { position: absolute; display: block; + background: url(/icons/link.svg) 0 50% no-repeat; + background-size: 1em 1em; + width: 1.4em; height: 1em; - width: 1em; - top: 2px; - left: 2px; - border-radius: 1em; - background: white; - box-shadow: 0 0px 1px rgba(0,0,0,.4), 0 4px 2px rgba(0,0,0,.1); - -webkit-transition: background .2s ease-out, left .2s ease-out; -} - -input[type="checkbox"]:checked::after { - left: calc(100% - 9px); + top: calc(((var(--h3) - 24px) / 2) + 0.6em); + left: -1.4em; + opacity: 0; + transition: opacity 0.2s; + border: none !important; /* TODO get rid of linkify */ +} + +h2:hover .anchor, +h3:hover .anchor, +h4:hover .anchor, +h5:hover .anchor, +h6:hover .anchor { + opacity: 1; } From 5ac8a1d07a86ff5d87dfffe2c3f82011071fc051 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Wed, 13 May 2020 04:53:06 -0700 Subject: [PATCH 122/158] docs: link to list of community preprocessors (#4817) --- site/content/docs/04-compile-time.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/site/content/docs/04-compile-time.md b/site/content/docs/04-compile-time.md index f9bfa772fec1..9fa0f9219505 100644 --- a/site/content/docs/04-compile-time.md +++ b/site/content/docs/04-compile-time.md @@ -183,6 +183,10 @@ const ast = svelte.parse(source, { filename: 'App.svelte' }); ### `svelte.preprocess` +A number of [community-maintained preprocessing plugins](https://github.com/sveltejs/integrations#preprocessors) are available to allow you to use Svelte with tools like TypeScript, PostCSS, SCSS, and Less. + +You can write your own preprocessor using the `svelte.preprocess` API. + ```js result: { code: string, From c9020d35b7ca52b381a9afd9d50206ba42fc13bc Mon Sep 17 00:00:00 2001 From: Conduitry Date: Fri, 15 May 2020 06:19:56 -0400 Subject: [PATCH 123/158] site: bump @sveltejs/svelte-repl --- site/package-lock.json | 12 ++++++------ site/package.json | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/site/package-lock.json b/site/package-lock.json index 68fcf1f2899d..972f8e7ef6d9 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -1291,9 +1291,9 @@ } }, "@sveltejs/svelte-repl": { - "version": "0.1.18", - "resolved": "https://registry.npmjs.org/@sveltejs/svelte-repl/-/svelte-repl-0.1.18.tgz", - "integrity": "sha512-b1psPdlJ9qRqn28l+sPSma6OSfilue0dGK4BcS75MOsfdjZjSvsc0AIAoriQ3q1mB/frCoyUri6nxFGgEKv0iQ==", + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/@sveltejs/svelte-repl/-/svelte-repl-0.1.19.tgz", + "integrity": "sha512-35R94X6uYgy6PHLQnQCsKcZ4zb6rGGQXjBYqjuCkoCykIlSLx8/avq6BGqudmE5pzVWDP3kk4063cHgccy1xYg==", "dev": true, "requires": { "codemirror": "^5.49.2", @@ -1601,9 +1601,9 @@ "dev": true }, "codemirror": { - "version": "5.52.2", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.52.2.tgz", - "integrity": "sha512-WCGCixNUck2HGvY8/ZNI1jYfxPG5cRHv0VjmWuNzbtCLz8qYA5d+je4QhSSCtCaagyeOwMi/HmmPTjBgiTm2lQ==", + "version": "5.53.2", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.53.2.tgz", + "integrity": "sha512-wvSQKS4E+P8Fxn/AQ+tQtJnF1qH5UOlxtugFLpubEZ5jcdH2iXTVinb+Xc/4QjshuOxRm4fUsU2QPF1JJKiyXA==", "dev": true }, "color-convert": { diff --git a/site/package.json b/site/package.json index 057d9f9adf8f..5333acece408 100644 --- a/site/package.json +++ b/site/package.json @@ -36,7 +36,7 @@ "@babel/runtime": "^7.6.0", "@sindresorhus/slugify": "^0.9.1", "@sveltejs/site-kit": "^1.1.4", - "@sveltejs/svelte-repl": "^0.1.18", + "@sveltejs/svelte-repl": "^0.1.19", "degit": "^2.1.4", "dotenv": "^8.1.0", "esm": "^3.2.25", From 81ade59797a25139a811c3cd8bebecf282953a78 Mon Sep 17 00:00:00 2001 From: Daniel Imfeld Date: Sat, 16 May 2020 22:26:35 -1000 Subject: [PATCH 124/158] fix check for uninitialized `condition` (#4841) --- src/compiler/compile/render_dom/wrappers/IfBlock.ts | 2 +- .../RRR.svelte | 1 + .../_config.js | 3 +++ .../main.svelte | 13 +++++++++++++ 4 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 test/runtime/samples/if-block-static-with-elseif-else-and-outros/RRR.svelte create mode 100644 test/runtime/samples/if-block-static-with-elseif-else-and-outros/_config.js create mode 100644 test/runtime/samples/if-block-static-with-elseif-else-and-outros/main.svelte diff --git a/src/compiler/compile/render_dom/wrappers/IfBlock.ts b/src/compiler/compile/render_dom/wrappers/IfBlock.ts index e18d9f3b6bc3..220b52990201 100644 --- a/src/compiler/compile/render_dom/wrappers/IfBlock.ts +++ b/src/compiler/compile/render_dom/wrappers/IfBlock.ts @@ -392,7 +392,7 @@ export default class IfBlockWrapper extends Wrapper { ${snippet && ( dependencies.length > 0 ? b`if (${block.renderer.dirty(dependencies)}) ${condition} = !!${snippet}` - : b`if (${condition} == -1) ${condition} = !!${snippet}` + : b`if (${condition} == null) ${condition} = !!${snippet}` )} if (${condition}) return ${i};` : b`return ${i};`)} diff --git a/test/runtime/samples/if-block-static-with-elseif-else-and-outros/RRR.svelte b/test/runtime/samples/if-block-static-with-elseif-else-and-outros/RRR.svelte new file mode 100644 index 000000000000..724237324909 --- /dev/null +++ b/test/runtime/samples/if-block-static-with-elseif-else-and-outros/RRR.svelte @@ -0,0 +1 @@ +rrr \ No newline at end of file diff --git a/test/runtime/samples/if-block-static-with-elseif-else-and-outros/_config.js b/test/runtime/samples/if-block-static-with-elseif-else-and-outros/_config.js new file mode 100644 index 000000000000..8b2c6d2d6671 --- /dev/null +++ b/test/runtime/samples/if-block-static-with-elseif-else-and-outros/_config.js @@ -0,0 +1,3 @@ +export default { + html: 'eee' +}; diff --git a/test/runtime/samples/if-block-static-with-elseif-else-and-outros/main.svelte b/test/runtime/samples/if-block-static-with-elseif-else-and-outros/main.svelte new file mode 100644 index 000000000000..b60885722e55 --- /dev/null +++ b/test/runtime/samples/if-block-static-with-elseif-else-and-outros/main.svelte @@ -0,0 +1,13 @@ + + +{#if "Eva".startsWith('E')} + eee +{:else if x} + def +{:else} + +{/if} From 283f9ae6cf774332e9c5934fedd1fb9bb432596c Mon Sep 17 00:00:00 2001 From: Conduitry Date: Sun, 17 May 2020 04:29:29 -0400 Subject: [PATCH 125/158] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3743f2d34058..d3371bb6077f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Support default values and trailing commas in destructuring `{#await}` ([#4560](https://github.com/sveltejs/svelte/issues/4560), [#4810](https://github.com/sveltejs/svelte/issues/4810)) * Fix setting `value` attribute with `bind:group` and attribute spread ([#4803](https://github.com/sveltejs/svelte/issues/4803)) +* Fix issue with compound `{#if}` block involving static condition, dynamic condition, and inline component ([#4840](https://github.com/sveltejs/svelte/issues/4840)) ## 3.22.2 From ef2a886c8397a602543d3fa5bbc9bcc2aefca55c Mon Sep 17 00:00:00 2001 From: Pat Cavit Date: Sun, 17 May 2020 01:46:13 -0700 Subject: [PATCH 126/158] fix: cache value & cancel tween for instant-set (#4847) --- src/runtime/motion/tweened.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/runtime/motion/tweened.ts b/src/runtime/motion/tweened.ts index abbb3b1aa276..c802604c0e27 100644 --- a/src/runtime/motion/tweened.ts +++ b/src/runtime/motion/tweened.ts @@ -94,7 +94,12 @@ export function tweened(value?: T, defaults: Options = {}): Tweened { } = assign(assign({}, defaults), opts); if (duration === 0) { - store.set(target_value); + if (previous_task) { + previous_task.abort(); + previous_task = null; + } + + store.set(value = target_value); return Promise.resolve(); } From bdbc73f111ccfdd27e748bc5cd73ed6af6e035f2 Mon Sep 17 00:00:00 2001 From: Conduitry Date: Sun, 17 May 2020 04:47:54 -0400 Subject: [PATCH 127/158] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d3371bb6077f..1ead5c723d59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased * Support default values and trailing commas in destructuring `{#await}` ([#4560](https://github.com/sveltejs/svelte/issues/4560), [#4810](https://github.com/sveltejs/svelte/issues/4810)) +* Fix handling of `tweened` store when set using `duration: 0` ([#4799](https://github.com/sveltejs/svelte/issues/4799), [#4846](https://github.com/sveltejs/svelte/issues/4846)) * Fix setting `value` attribute with `bind:group` and attribute spread ([#4803](https://github.com/sveltejs/svelte/issues/4803)) * Fix issue with compound `{#if}` block involving static condition, dynamic condition, and inline component ([#4840](https://github.com/sveltejs/svelte/issues/4840)) From a9fd168da3f156097221b7fa18de7d98df91310c Mon Sep 17 00:00:00 2001 From: Billy Levin Date: Sun, 17 May 2020 09:51:17 +0100 Subject: [PATCH 128/158] update for ARIA 1.2 working draft (#4845) --- src/compiler/compile/nodes/Element.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/compile/nodes/Element.ts b/src/compiler/compile/nodes/Element.ts index a337eff73ae3..7adf46076d68 100644 --- a/src/compiler/compile/nodes/Element.ts +++ b/src/compiler/compile/nodes/Element.ts @@ -19,10 +19,10 @@ import { INode } from './interfaces'; const svg = /^(?:altGlyph|altGlyphDef|altGlyphItem|animate|animateColor|animateMotion|animateTransform|circle|clipPath|color-profile|cursor|defs|desc|discard|ellipse|feBlend|feColorMatrix|feComponentTransfer|feComposite|feConvolveMatrix|feDiffuseLighting|feDisplacementMap|feDistantLight|feDropShadow|feFlood|feFuncA|feFuncB|feFuncG|feFuncR|feGaussianBlur|feImage|feMerge|feMergeNode|feMorphology|feOffset|fePointLight|feSpecularLighting|feSpotLight|feTile|feTurbulence|filter|font|font-face|font-face-format|font-face-name|font-face-src|font-face-uri|foreignObject|g|glyph|glyphRef|hatch|hatchpath|hkern|image|line|linearGradient|marker|mask|mesh|meshgradient|meshpatch|meshrow|metadata|missing-glyph|mpath|path|pattern|polygon|polyline|radialGradient|rect|set|solidcolor|stop|svg|switch|symbol|text|textPath|tref|tspan|unknown|use|view|vkern)$/; -const aria_attributes = 'activedescendant atomic autocomplete busy checked colindex controls current describedby details disabled dropeffect errormessage expanded flowto grabbed haspopup hidden invalid keyshortcuts label labelledby level live modal multiline multiselectable orientation owns placeholder posinset pressed readonly relevant required roledescription rowindex selected setsize sort valuemax valuemin valuenow valuetext'.split(' '); +const aria_attributes = 'activedescendant atomic autocomplete busy checked colcount colindex colspan controls current describedby details disabled dropeffect errormessage expanded flowto grabbed haspopup hidden invalid keyshortcuts label labelledby level live modal multiline multiselectable orientation owns placeholder posinset pressed readonly relevant required roledescription rowcount rowindex rowspan selected setsize sort valuemax valuemin valuenow valuetext'.split(' '); const aria_attribute_set = new Set(aria_attributes); -const aria_roles = 'alert alertdialog application article banner button cell checkbox columnheader combobox command complementary composite contentinfo definition dialog directory document feed figure form grid gridcell group heading img input landmark link list listbox listitem log main marquee math menu menubar menuitem menuitemcheckbox menuitemradio navigation none note option presentation progressbar radio radiogroup range region roletype row rowgroup rowheader scrollbar search searchbox section sectionhead select separator slider spinbutton status structure switch tab table tablist tabpanel term textbox timer toolbar tooltip tree treegrid treeitem widget window'.split(' '); +const aria_roles = 'alert alertdialog application article banner blockquote button caption cell checkbox code columnheader combobox complementary contentinfo definition deletion dialog directory document emphasis feed figure form generic grid gridcell group heading img link list listbox listitem log main marquee math meter menu menubar menuitem menuitemcheckbox menuitemradio navigation none note option paragraph presentation progressbar radio radiogroup region row rowgroup rowheader scrollbar search searchbox separator slider spinbutton status strong subscript superscript switch tab table tablist tabpanel term textbox time timer toolbar tooltip tree treegrid treeitem'.split(' '); const aria_role_set = new Set(aria_roles); const a11y_required_attributes = { From a1b0295fc395a3742717c1abfafcb8022d3897ff Mon Sep 17 00:00:00 2001 From: Conduitry Date: Sun, 17 May 2020 04:52:42 -0400 Subject: [PATCH 129/158] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ead5c723d59..058f6e29efbe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * Fix handling of `tweened` store when set using `duration: 0` ([#4799](https://github.com/sveltejs/svelte/issues/4799), [#4846](https://github.com/sveltejs/svelte/issues/4846)) * Fix setting `value` attribute with `bind:group` and attribute spread ([#4803](https://github.com/sveltejs/svelte/issues/4803)) * Fix issue with compound `{#if}` block involving static condition, dynamic condition, and inline component ([#4840](https://github.com/sveltejs/svelte/issues/4840)) +* Update a11y warnings per ARIA 1.2 working draft ([#4844](https://github.com/sveltejs/svelte/issues/4844)) ## 3.22.2 From d8fb0bb62c27d2cbb4097ca25953258813c158a7 Mon Sep 17 00:00:00 2001 From: Jeremy Bernier Date: Sun, 17 May 2020 18:43:39 +0900 Subject: [PATCH 130/158] Fix input with bind:value displaying "undefined" There's a bug where when `` and `sampleVar` is updated to undefined (`sampleVar = undefined`), then the input displays "undefined" (despite the input initally showing up correctly empty when initialized to undefined). This issue has been documented since September 14, 2019 https://github.com/sveltejs/svelte/issues/3569 I'm new to Svelte, but this seems to fix this problem. --- src/runtime/internal/dom.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts index e447eae36276..a502cdb6f5bc 100644 --- a/src/runtime/internal/dom.ts +++ b/src/runtime/internal/dom.ts @@ -193,7 +193,7 @@ export function set_data(text, data) { export function set_input_value(input, value) { if (value != null || input.value) { - input.value = value; + input.value = value || ''; } } From 33d8979495e483c769505657c6c981ef869f670f Mon Sep 17 00:00:00 2001 From: Conduitry Date: Sun, 17 May 2020 09:46:54 -0400 Subject: [PATCH 131/158] -> v3.22.3 --- CHANGELOG.md | 2 +- package-lock.json | 2 +- package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 058f6e29efbe..5918d2b7d6a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Svelte changelog -## Unreleased +## 3.22.3 * Support default values and trailing commas in destructuring `{#await}` ([#4560](https://github.com/sveltejs/svelte/issues/4560), [#4810](https://github.com/sveltejs/svelte/issues/4810)) * Fix handling of `tweened` store when set using `duration: 0` ([#4799](https://github.com/sveltejs/svelte/issues/4799), [#4846](https://github.com/sveltejs/svelte/issues/4846)) diff --git a/package-lock.json b/package-lock.json index 937f04f5f46c..06c562e448f2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.22.2", + "version": "3.22.3", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 91bf7086763e..ce4ee88ad36f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.22.2", + "version": "3.22.3", "description": "Cybernetically enhanced web apps", "module": "index.mjs", "main": "index", From 6397588e50196aa006581d3fffb65a39309c8248 Mon Sep 17 00:00:00 2001 From: Richard Harris Date: Sun, 17 May 2020 11:19:58 -0400 Subject: [PATCH 132/158] add test for #3569 and similar situations --- .../binding-input-text-undefined/_config.js | 30 +++++++++++++++++++ .../binding-input-text-undefined/main.svelte | 5 ++++ 2 files changed, 35 insertions(+) create mode 100644 test/runtime/samples/binding-input-text-undefined/_config.js create mode 100644 test/runtime/samples/binding-input-text-undefined/main.svelte diff --git a/test/runtime/samples/binding-input-text-undefined/_config.js b/test/runtime/samples/binding-input-text-undefined/_config.js new file mode 100644 index 000000000000..009e1b37ba8b --- /dev/null +++ b/test/runtime/samples/binding-input-text-undefined/_config.js @@ -0,0 +1,30 @@ +export default { + html: ` + + `, + + ssrHtml: ` + + `, + + async test({ assert, component, target, window }) { + const input = target.querySelector('input'); + assert.equal(input.value, ''); + + component.x = null; + assert.equal(input.value, ''); + + component.x = undefined; + assert.equal(input.value, ''); + + component.x = 'string'; + component.x = undefined; + assert.equal(input.value, ''); + + component.x = 0; + assert.equal(input.value, '0'); + + component.x = undefined; + assert.equal(input.value, ''); + }, +}; diff --git a/test/runtime/samples/binding-input-text-undefined/main.svelte b/test/runtime/samples/binding-input-text-undefined/main.svelte new file mode 100644 index 000000000000..b4c2a84fd21a --- /dev/null +++ b/test/runtime/samples/binding-input-text-undefined/main.svelte @@ -0,0 +1,5 @@ + + + \ No newline at end of file From 081f7cd878a4624cf5c74570ad281193f2434f43 Mon Sep 17 00:00:00 2001 From: Richard Harris Date: Sun, 17 May 2020 11:20:18 -0400 Subject: [PATCH 133/158] dont coerce all falsy values to empty strings --- src/runtime/internal/dom.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts index a502cdb6f5bc..1823cba2737f 100644 --- a/src/runtime/internal/dom.ts +++ b/src/runtime/internal/dom.ts @@ -192,9 +192,7 @@ export function set_data(text, data) { } export function set_input_value(input, value) { - if (value != null || input.value) { - input.value = value || ''; - } + input.value = value == null ? '' : value; } export function set_input_type(input, type) { From 40dca5252beaa669210a4d89512249937691131a Mon Sep 17 00:00:00 2001 From: Pat Cavit Date: Sun, 17 May 2020 08:49:37 -0700 Subject: [PATCH 134/158] WIP: Don't attempt to unsub if the iframe is destroyed (#4782) Fixes #4752 by not attempting to call .removeEventListener if the iframe.contentWindow no longer exists. --- src/runtime/internal/dom.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts index 1823cba2737f..02fd3dc23ecb 100644 --- a/src/runtime/internal/dom.ts +++ b/src/runtime/internal/dom.ts @@ -270,9 +270,11 @@ export function add_resize_listener(node: HTMLElement, fn: () => void) { iframe.setAttribute('aria-hidden', 'true'); iframe.tabIndex = -1; + const crossorigin = is_crossorigin(); + let unsubscribe: () => void; - if (is_crossorigin()) { + if (crossorigin) { iframe.src = `data:text/html,`; unsubscribe = listen(window, 'message', (event: MessageEvent) => { if (event.source === iframe.contentWindow) fn(); @@ -287,8 +289,13 @@ export function add_resize_listener(node: HTMLElement, fn: () => void) { append(node, iframe); return () => { + if (crossorigin) { + unsubscribe(); + } else if (unsubscribe && iframe.contentWindow) { + unsubscribe(); + } + detach(iframe); - if (unsubscribe) unsubscribe(); }; } From f7d1bf35a08a201dae161d54790e59a663830dc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Lins?= Date: Sun, 17 May 2020 12:50:38 -0300 Subject: [PATCH 135/158] A11y rule no-onchange (#4788) * A11y rule no-onchange * Fix message * Fix tests * Removing declarations --- src/compiler/compile/nodes/Element.ts | 21 +++++++++++- .../samples/a11y-no-onchange/input.svelte | 16 ++++++++++ .../samples/a11y-no-onchange/warnings.json | 32 +++++++++++++++++++ 3 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 test/validator/samples/a11y-no-onchange/input.svelte create mode 100644 test/validator/samples/a11y-no-onchange/warnings.json diff --git a/src/compiler/compile/nodes/Element.ts b/src/compiler/compile/nodes/Element.ts index 7adf46076d68..b3503e533f2e 100644 --- a/src/compiler/compile/nodes/Element.ts +++ b/src/compiler/compile/nodes/Element.ts @@ -56,6 +56,11 @@ const a11y_required_content = new Set([ 'h6' ]); +const a11y_no_onchange = new Set([ + 'select', + 'option' +]); + const invisible_elements = new Set(['meta', 'html', 'script', 'style']); const valid_modifiers = new Set([ @@ -424,13 +429,18 @@ export default class Element extends Node { } validate_special_cases() { - const { component,attributes } = this; + const { component, attributes, handlers } = this; const attribute_map = new Map(); + const handlers_map = new Map(); attributes.forEach(attribute => ( attribute_map.set(attribute.name, attribute) )); + handlers.forEach(handler => ( + handlers_map.set(handler.name, handler) + )); + if (this.name === 'a') { const href_attribute = attribute_map.get('href') || attribute_map.get('xlink:href'); const id_attribute = attribute_map.get('id'); @@ -496,6 +506,15 @@ export default class Element extends Node { } } } + + if (a11y_no_onchange.has(this.name)) { + if (handlers_map.has('change') && !handlers_map.has('blur')) { + component.warn(this, { + code: `a11y-no-onchange`, + message: `A11y: on:blur must be used instead of on:change, unless absolutely necessary and it causes no negative consequences for keyboard only or screen reader users.` + }); + } + } } validate_bindings() { diff --git a/test/validator/samples/a11y-no-onchange/input.svelte b/test/validator/samples/a11y-no-onchange/input.svelte new file mode 100644 index 000000000000..af2041f40679 --- /dev/null +++ b/test/validator/samples/a11y-no-onchange/input.svelte @@ -0,0 +1,16 @@ + + + + \ No newline at end of file diff --git a/test/validator/samples/a11y-no-onchange/warnings.json b/test/validator/samples/a11y-no-onchange/warnings.json new file mode 100644 index 000000000000..461f546c0bbd --- /dev/null +++ b/test/validator/samples/a11y-no-onchange/warnings.json @@ -0,0 +1,32 @@ +[ + { + "code": "a11y-no-onchange", + "end": { + "character": 88, + "column": 9, + "line": 4 + }, + "message": "A11y: on:blur must be used instead of on:change, unless absolutely necessary and it causes no negative consequences for keyboard only or screen reader users.", + "pos": 0, + "start": { + "character": 0, + "column": 0, + "line": 1 + } + }, + { + "code": "a11y-no-onchange", + "end": { + "character": 249, + "column": 44, + "line": 10 + }, + "message": "A11y: on:blur must be used instead of on:change, unless absolutely necessary and it causes no negative consequences for keyboard only or screen reader users.", + "pos": 209, + "start": { + "character": 209, + "column": 4, + "line": 10 + } + } +] From d5e95594e9676b9760bde20007c881b0a7f269ae Mon Sep 17 00:00:00 2001 From: pngwn Date: Sun, 17 May 2020 17:03:22 +0100 Subject: [PATCH 136/158] feat(site): add svelte syntax highlighting (#4851) --- site/content/docs/01-component-format.md | 24 ++-- site/content/docs/02-template-syntax.md | 142 +++++++++++------------ site/content/docs/03-run-time.md | 42 +++---- site/package-lock.json | 11 +- site/package.json | 3 +- site/src/utils/highlight.js | 1 + 6 files changed, 115 insertions(+), 108 deletions(-) diff --git a/site/content/docs/01-component-format.md b/site/content/docs/01-component-format.md index fa851ccc41e0..8eac5d3c504a 100644 --- a/site/content/docs/01-component-format.md +++ b/site/content/docs/01-component-format.md @@ -8,7 +8,7 @@ Components are the building blocks of Svelte applications. They are written into All three sections — script, styles and markup — are optional. -```html +```sv @@ -30,7 +30,7 @@ A ` @@ -26,7 +26,7 @@ A lowercase tag, like `
`, denotes a regular HTML element. A capitalised tag By default, attributes work exactly like their HTML counterparts. -```html +```sv
@@ -36,7 +36,7 @@ By default, attributes work exactly like their HTML counterparts. As in HTML, values may be unquoted. -```html +```sv ``` @@ -44,7 +44,7 @@ As in HTML, values may be unquoted. Attribute values can contain JavaScript expressions. -```html +```sv
page {p} ``` @@ -52,7 +52,7 @@ Attribute values can contain JavaScript expressions. Or they can *be* JavaScript expressions. -```html +```sv ``` @@ -71,7 +71,7 @@ All other attributes are included unless their value is [nullish](https://develo An expression might include characters that would cause syntax highlighting to fail in regular HTML, so quoting the value is permitted. The quotes do not affect how the value is parsed: -```html +```sv ``` @@ -79,7 +79,7 @@ An expression might include characters that would cause syntax highlighting to f When the attribute name and value match (`name={name}`), they can be replaced with `{name}`. -```html +```sv @@ -91,7 +91,7 @@ By convention, values passed to components are referred to as *properties* or *p As with elements, `name={name}` can be replaced with the `{name}` shorthand. -```html +```sv ``` @@ -101,7 +101,7 @@ As with elements, `name={name}` can be replaced with the `{name}` shorthand. An element or component can have multiple spread attributes, interspersed with regular ones. -```html +```sv ``` @@ -109,7 +109,7 @@ An element or component can have multiple spread attributes, interspersed with r *`$$props`* references all props that are passed to a component – including ones that are not declared with `export`. It is useful in rare cases, but not generally recommended, as it is difficult for Svelte to optimise. -```html +```sv ``` @@ -133,7 +133,7 @@ An element or component can have multiple spread attributes, interspersed with r Text can also contain JavaScript expressions: -```html +```sv

Hello {name}!

{a} + {b} = {a + b}.

``` @@ -145,7 +145,7 @@ Text can also contain JavaScript expressions: You can use HTML comments inside components. -```html +```sv

Hello world

``` @@ -154,7 +154,7 @@ You can use HTML comments inside components. Comments beginning with `svelte-ignore` disable warnings for the next block of markup. Usually these are accessibility warnings; make sure that you're disabling them for a good reason. -```html +```sv ``` @@ -176,7 +176,7 @@ Comments beginning with `svelte-ignore` disable warnings for the next block of m Content that is conditionally rendered can be wrapped in an if block. -```html +```sv {#if answer === 42}

what was the question?

{/if} @@ -186,7 +186,7 @@ Content that is conditionally rendered can be wrapped in an if block. Additional conditions can be added with `{:else if expression}`, optionally ending in an `{:else}` clause. -```html +```sv {#if porridge.temperature > 100}

too hot!

{:else if 80 > porridge.temperature} @@ -219,7 +219,7 @@ Additional conditions can be added with `{:else if expression}`, optionally endi Iterating over lists of values can be done with an each block. -```html +```sv

Shopping list

    {#each items as item} @@ -234,7 +234,7 @@ You can use each blocks to iterate over any array or array-like value — that i An each block can also specify an *index*, equivalent to the second argument in an `array.map(...)` callback: -```html +```sv {#each items as item, i}
  • {i + 1}: {item.name} x {item.qty}
  • {/each} @@ -244,7 +244,7 @@ An each block can also specify an *index*, equivalent to the second argument in If a *key* expression is provided — which must uniquely identify each list item — Svelte will use it to diff the list when data changes, rather than adding or removing items at the end. The key can be any object, but strings and numbers are recommended since they allow identity to persist when the objects themselves change. -```html +```sv {#each items as item (item.id)}
  • {item.name} x {item.qty}
  • {/each} @@ -259,7 +259,7 @@ If a *key* expression is provided — which must uniquely identify each list ite You can freely use destructuring and rest patterns in each blocks. -```html +```sv {#each items as { id, name, qty }, i (id)}
  • {i + 1}: {name} x {qty}
  • {/each} @@ -277,7 +277,7 @@ You can freely use destructuring and rest patterns in each blocks. An each block can also have an `{:else}` clause, which is rendered if the list is empty. -```html +```sv {#each todos as todo}

    {todo.text}

    {:else} @@ -302,7 +302,7 @@ An each block can also have an `{:else}` clause, which is rendered if the list i Await blocks allow you to branch on the three possible states of a Promise — pending, fulfilled or rejected. -```html +```sv {#await promise}

    waiting for the promise to resolve...

    @@ -319,7 +319,7 @@ Await blocks allow you to branch on the three possible states of a Promise — p The `catch` block can be omitted if you don't need to render anything when the promise rejects (or no error is possible). -```html +```sv {#await promise}

    waiting for the promise to resolve...

    @@ -333,7 +333,7 @@ The `catch` block can be omitted if you don't need to render anything when the p If you don't care about the pending state, you can also omit the initial block. -```html +```sv {#await promise then value}

    The value is {value}

    {/await} @@ -354,7 +354,7 @@ The expression should be valid standalone HTML — `{@html "
    "}content{@html > Svelte does not sanitize expressions before injecting HTML. If the data comes from an untrusted source, you must sanitize it, or you are exposing your users to an XSS vulnerability. -```html +```sv

    {post.title}

    {@html post.content} @@ -377,7 +377,7 @@ The `{@debug ...}` tag offers an alternative to `console.log(...)`. It logs the It accepts a comma-separated list of variable names (not arbitrary expressions). -```html +```sv @@ -1349,7 +1349,7 @@ The `` element renders a component dynamically, using the comp If `this` is falsy, no component is rendered. -```html +```sv ``` @@ -1367,7 +1367,7 @@ If `this` is falsy, no component is rendered. The `` element allows you to add event listeners to the `window` object without worrying about removing them when the component is destroyed, or checking for the existence of `window` when server-side rendering. -```html +```sv @@ -582,7 +582,7 @@ Animates a `blur` filter alongside an element's opacity. * `opacity` (`number`, default 0) - the opacity value to animate out to and in from * `amount` (`number`, default 5) - the size of the blur in pixels -```html +```sv @@ -621,7 +621,7 @@ Animates the x and y positions and the opacity of an element. `in` transitions a You can see the `fly` transition in action in the [transition tutorial](tutorial/adding-parameters-to-transitions). -```html +```sv -

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�vOH)$E7+w=8#`Yv<&3 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 a_7sz From 82dce0c8fcc2d23cc0911ff9d9152ff11a2136a6 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Sun, 15 Mar 2020 17:44:05 +0800 Subject: [PATCH 047/158] do not initialise slot fallback fragment unless necessary (#4514) --- CHANGELOG.md | 1 + .../compile/render_dom/wrappers/Slot.ts | 100 ++++++++++-------- .../shared/create_debugging_comment.ts | 12 ++- .../component-slot-fallback-2/Inner.svelte | 7 ++ .../component-slot-fallback-2/Outer.svelte | 7 ++ .../component-slot-fallback-2/_config.js | 39 +++++++ .../component-slot-fallback-2/main.svelte | 23 ++++ .../component-slot-fallback-2/store.svelte | 23 ++++ 8 files changed, 167 insertions(+), 45 deletions(-) create mode 100644 test/runtime/samples/component-slot-fallback-2/Inner.svelte create mode 100644 test/runtime/samples/component-slot-fallback-2/Outer.svelte create mode 100644 test/runtime/samples/component-slot-fallback-2/_config.js create mode 100644 test/runtime/samples/component-slot-fallback-2/main.svelte create mode 100644 test/runtime/samples/component-slot-fallback-2/store.svelte diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fe0fa338118..11648dbcd801 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Allow `` to be used in a slot ([#2798](https://github.com/sveltejs/svelte/issues/2798)) * Expose object of unknown props in `$$restProps` ([#2930](https://github.com/sveltejs/svelte/issues/2930)) * Allow transitions and animations to work within iframes ([#3624](https://github.com/sveltejs/svelte/issues/3624)) +* Fix initialising slot fallbacks when unnecessary ([#3763](https://github.com/sveltejs/svelte/issues/3763)) * Disallow binding directly to `const` variables ([#4479](https://github.com/sveltejs/svelte/issues/4479)) * Fix updating keyed `{#each}` blocks with `{:else}` ([#4536](https://github.com/sveltejs/svelte/issues/4536), [#4549](https://github.com/sveltejs/svelte/issues/4549)) * Fix hydration of top-level content ([#4542](https://github.com/sveltejs/svelte/issues/4542)) diff --git a/src/compiler/compile/render_dom/wrappers/Slot.ts b/src/compiler/compile/render_dom/wrappers/Slot.ts index 5f2d3318397e..37b10c2ea38a 100644 --- a/src/compiler/compile/render_dom/wrappers/Slot.ts +++ b/src/compiler/compile/render_dom/wrappers/Slot.ts @@ -10,10 +10,12 @@ import get_slot_data from '../../utils/get_slot_data'; import Expression from '../../nodes/shared/Expression'; import is_dynamic from './shared/is_dynamic'; import { Identifier, ObjectExpression } from 'estree'; +import create_debugging_comment from './shared/create_debugging_comment'; export default class SlotWrapper extends Wrapper { node: Slot; fragment: FragmentWrapper; + fallback: Block | null = null; var: Identifier = { type: 'Identifier', name: 'slot' }; dependencies: Set = new Set(['$$scope']); @@ -30,9 +32,17 @@ export default class SlotWrapper extends Wrapper { this.cannot_use_innerhtml(); this.not_static_content(); + if (this.node.children.length) { + this.fallback = block.child({ + comment: create_debugging_comment(this.node.children[0], this.renderer.component), + name: this.renderer.component.get_unique_name(`fallback_block`), + type: 'fallback' + }); + } + this.fragment = new FragmentWrapper( renderer, - block, + this.fallback, node.children, parent, strip_whitespace, @@ -103,86 +113,90 @@ export default class SlotWrapper extends Wrapper { get_slot_context_fn = 'null'; } + if (this.fallback) { + this.fragment.render(this.fallback, null, x`#nodes` as Identifier); + renderer.blocks.push(this.fallback); + } + const slot = block.get_unique_name(`${sanitize(slot_name)}_slot`); const slot_definition = block.get_unique_name(`${sanitize(slot_name)}_slot_template`); + const slot_or_fallback = this.fallback ? block.get_unique_name(`${sanitize(slot_name)}_slot_or_fallback`) : slot; block.chunks.init.push(b` const ${slot_definition} = ${renderer.reference('$$slots')}.${slot_name}; const ${slot} = @create_slot(${slot_definition}, #ctx, ${renderer.reference('$$scope')}, ${get_slot_context_fn}); + ${this.fallback ? b`const ${slot_or_fallback} = ${slot} || ${this.fallback.name}(#ctx);` : null} `); - // TODO this is a dreadful hack! Should probably make this nicer - const { create, claim, hydrate, mount, update, destroy } = block.chunks; - - block.chunks.create = []; - block.chunks.claim = []; - block.chunks.hydrate = []; - block.chunks.mount = []; - block.chunks.update = []; - block.chunks.destroy = []; - - const listeners = block.event_listeners; - block.event_listeners = []; - this.fragment.render(block, parent_node, parent_nodes); - block.render_listeners(`_${slot.name}`); - block.event_listeners = listeners; - - if (block.chunks.create.length) create.push(b`if (!${slot}) { ${block.chunks.create} }`); - if (block.chunks.claim.length) claim.push(b`if (!${slot}) { ${block.chunks.claim} }`); - if (block.chunks.hydrate.length) hydrate.push(b`if (!${slot}) { ${block.chunks.hydrate} }`); - if (block.chunks.mount.length) mount.push(b`if (!${slot}) { ${block.chunks.mount} }`); - if (block.chunks.update.length) update.push(b`if (!${slot}) { ${block.chunks.update} }`); - if (block.chunks.destroy.length) destroy.push(b`if (!${slot}) { ${block.chunks.destroy} }`); - - block.chunks.create = create; - block.chunks.claim = claim; - block.chunks.hydrate = hydrate; - block.chunks.mount = mount; - block.chunks.update = update; - block.chunks.destroy = destroy; - block.chunks.create.push( - b`if (${slot}) ${slot}.c();` + b`if (${slot_or_fallback}) ${slot_or_fallback}.c();` ); if (renderer.options.hydratable) { block.chunks.claim.push( - b`if (${slot}) ${slot}.l(${parent_nodes});` + b`if (${slot_or_fallback}) ${slot_or_fallback}.l(${parent_nodes});` ); } block.chunks.mount.push(b` - if (${slot}) { - ${slot}.m(${parent_node || '#target'}, ${parent_node ? 'null' : 'anchor'}); + if (${slot_or_fallback}) { + ${slot_or_fallback}.m(${parent_node || '#target'}, ${parent_node ? 'null' : 'anchor'}); } `); block.chunks.intro.push( - b`@transition_in(${slot}, #local);` + b`@transition_in(${slot_or_fallback}, #local);` ); block.chunks.outro.push( - b`@transition_out(${slot}, #local);` + b`@transition_out(${slot_or_fallback}, #local);` ); - const dynamic_dependencies = Array.from(this.dependencies).filter(name => { + const is_dependency_dynamic = name => { if (name === '$$scope') return true; if (this.node.scope.is_let(name)) return true; const variable = renderer.component.var_lookup.get(name); return is_dynamic(variable); - }); + }; + + const dynamic_dependencies = Array.from(this.dependencies).filter(is_dependency_dynamic); + + const fallback_dynamic_dependencies = this.fallback + ? Array.from(this.fallback.dependencies).filter(is_dependency_dynamic) + : []; - block.chunks.update.push(b` - if (${slot} && ${slot}.p && ${renderer.dirty(dynamic_dependencies)}) { + const slot_update = b` + if (${slot}.p && ${renderer.dirty(dynamic_dependencies)}) { ${slot}.p( @get_slot_context(${slot_definition}, #ctx, ${renderer.reference('$$scope')}, ${get_slot_context_fn}), @get_slot_changes(${slot_definition}, ${renderer.reference('$$scope')}, #dirty, ${get_slot_changes_fn}) ); } - `); + `; + const fallback_update = this.fallback && fallback_dynamic_dependencies.length > 0 && b` + if (${slot_or_fallback} && ${slot_or_fallback}.p && ${renderer.dirty(fallback_dynamic_dependencies)}) { + ${slot_or_fallback}.p(#ctx, #dirty); + } + `; + + if (fallback_update) { + block.chunks.update.push(b` + if (${slot}) { + ${slot_update} + } else { + ${fallback_update} + } + `); + } else { + block.chunks.update.push(b` + if (${slot}) { + ${slot_update} + } + `); + } block.chunks.destroy.push( - b`if (${slot}) ${slot}.d(detaching);` + b`if (${slot_or_fallback}) ${slot_or_fallback}.d(detaching);` ); } } diff --git a/src/compiler/compile/render_dom/wrappers/shared/create_debugging_comment.ts b/src/compiler/compile/render_dom/wrappers/shared/create_debugging_comment.ts index e2aa0c0b41d2..11f1feb841b9 100644 --- a/src/compiler/compile/render_dom/wrappers/shared/create_debugging_comment.ts +++ b/src/compiler/compile/render_dom/wrappers/shared/create_debugging_comment.ts @@ -16,8 +16,16 @@ export default function create_debugging_comment( let d; if (node.type === 'InlineComponent' || node.type === 'Element') { - d = node.children.length ? node.children[0].start : node.start; - while (source[d - 1] !== '>') d -= 1; + if (node.children.length) { + d = node.children[0].start; + while (source[d - 1] !== '>') d -= 1; + } else { + d = node.start; + while (source[d] !== '>') d += 1; + d += 1; + } + } else if (node.type === 'Text') { + d = node.end; } else { // @ts-ignore d = node.expression ? node.expression.node.end : c; diff --git a/test/runtime/samples/component-slot-fallback-2/Inner.svelte b/test/runtime/samples/component-slot-fallback-2/Inner.svelte new file mode 100644 index 000000000000..d1c247ad35b0 --- /dev/null +++ b/test/runtime/samples/component-slot-fallback-2/Inner.svelte @@ -0,0 +1,7 @@ + + + +{value} \ No newline at end of file diff --git a/test/runtime/samples/component-slot-fallback-2/Outer.svelte b/test/runtime/samples/component-slot-fallback-2/Outer.svelte new file mode 100644 index 000000000000..1e44ba4db722 --- /dev/null +++ b/test/runtime/samples/component-slot-fallback-2/Outer.svelte @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/test/runtime/samples/component-slot-fallback-2/_config.js b/test/runtime/samples/component-slot-fallback-2/_config.js new file mode 100644 index 000000000000..585e3b4c9e99 --- /dev/null +++ b/test/runtime/samples/component-slot-fallback-2/_config.js @@ -0,0 +1,39 @@ +export default { + html: ` `, + ssrHtml: ` `, + + async test({ assert, target, component, window }) { + const [input1, input2, inputFallback] = target.querySelectorAll("input"); + + assert.equal(component.getSubscriberCount(), 3); + + input1.value = "a"; + await input1.dispatchEvent(new window.Event("input")); + input1.value = "ab"; + await input1.dispatchEvent(new window.Event("input")); + assert.equal(input1.value, "ab"); + assert.equal(input2.value, "ab"); + assert.equal(inputFallback.value, "ab"); + + component.props = "hello"; + + assert.htmlEqual( + target.innerHTML, + ` + hello + hello + + ` + ); + + component.fallback = "world"; + assert.htmlEqual( + target.innerHTML, + ` + hello + hello + world + ` + ); + } +}; diff --git a/test/runtime/samples/component-slot-fallback-2/main.svelte b/test/runtime/samples/component-slot-fallback-2/main.svelte new file mode 100644 index 000000000000..458366701534 --- /dev/null +++ b/test/runtime/samples/component-slot-fallback-2/main.svelte @@ -0,0 +1,23 @@ + + + + + + + + + + + + diff --git a/test/runtime/samples/component-slot-fallback-2/store.svelte b/test/runtime/samples/component-slot-fallback-2/store.svelte new file mode 100644 index 000000000000..e377aaf3149c --- /dev/null +++ b/test/runtime/samples/component-slot-fallback-2/store.svelte @@ -0,0 +1,23 @@ + \ No newline at end of file From 5bb5ba4c7620865c2b137e3bb95b532383670ea7 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Sun, 15 Mar 2020 17:54:06 +0800 Subject: [PATCH 048/158] complain if named slots other than direct descendant of component (#4509) --- CHANGELOG.md | 1 + src/compiler/compile/nodes/Element.ts | 31 +++++++------------ .../Nested.svelte | 1 + .../component-slot-nested-error-2/_config.js | 3 ++ .../component-slot-nested-error-2/main.svelte | 11 +++++++ .../Nested.svelte | 1 + .../component-slot-nested-error-3/_config.js | 3 ++ .../component-slot-nested-error-3/main.svelte | 11 +++++++ .../component-slot-nested-error/Nested.svelte | 1 + .../component-slot-nested-error/_config.js | 3 ++ .../component-slot-nested-error/main.svelte | 9 ++++++ .../errors.json | 9 ++++++ .../input.svelte | 14 +++++++++ .../errors.json | 1 + .../input.svelte | 15 +++++++++ .../component-slotted-each-block/errors.json | 2 +- .../component-slotted-if-block/errors.json | 2 +- .../slot-attribute-invalid/errors.json | 2 +- 18 files changed, 98 insertions(+), 22 deletions(-) create mode 100644 test/runtime/samples/component-slot-nested-error-2/Nested.svelte create mode 100644 test/runtime/samples/component-slot-nested-error-2/_config.js create mode 100644 test/runtime/samples/component-slot-nested-error-2/main.svelte create mode 100644 test/runtime/samples/component-slot-nested-error-3/Nested.svelte create mode 100644 test/runtime/samples/component-slot-nested-error-3/_config.js create mode 100644 test/runtime/samples/component-slot-nested-error-3/main.svelte create mode 100644 test/runtime/samples/component-slot-nested-error/Nested.svelte create mode 100644 test/runtime/samples/component-slot-nested-error/_config.js create mode 100644 test/runtime/samples/component-slot-nested-error/main.svelte create mode 100644 test/validator/samples/component-slotted-custom-element-2/errors.json create mode 100644 test/validator/samples/component-slotted-custom-element-2/input.svelte create mode 100644 test/validator/samples/component-slotted-custom-element/errors.json create mode 100644 test/validator/samples/component-slotted-custom-element/input.svelte diff --git a/CHANGELOG.md b/CHANGELOG.md index 11648dbcd801..b85ec4ba16de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Allow `` to be used in a slot ([#2798](https://github.com/sveltejs/svelte/issues/2798)) * Expose object of unknown props in `$$restProps` ([#2930](https://github.com/sveltejs/svelte/issues/2930)) +* Prevent passing named slots other than from the top level within a component ([#3385](https://github.com/sveltejs/svelte/issues/3385)) * Allow transitions and animations to work within iframes ([#3624](https://github.com/sveltejs/svelte/issues/3624)) * Fix initialising slot fallbacks when unnecessary ([#3763](https://github.com/sveltejs/svelte/issues/3763)) * Disallow binding directly to `const` variables ([#4479](https://github.com/sveltejs/svelte/issues/4479)) diff --git a/src/compiler/compile/nodes/Element.ts b/src/compiler/compile/nodes/Element.ts index e8108858c53b..8c9c0bfe1841 100644 --- a/src/compiler/compile/nodes/Element.ts +++ b/src/compiler/compile/nodes/Element.ts @@ -278,7 +278,7 @@ export default class Element extends Node { } validate_attributes() { - const { component } = this; + const { component, parent } = this; const attribute_map = new Map(); @@ -395,26 +395,10 @@ export default class Element extends Node { component.slot_outlets.add(name); } - let ancestor = this.parent; - do { - if (ancestor.type === 'InlineComponent') break; - if (ancestor.type === 'Element' && /-/.test(ancestor.name)) break; - - if (ancestor.type === 'IfBlock' || ancestor.type === 'EachBlock') { - const type = ancestor.type === 'IfBlock' ? 'if' : 'each'; - const message = `Cannot place slotted elements inside an ${type}-block`; - - component.error(attribute, { - code: `invalid-slotted-content`, - message - }); - } - } while (ancestor = ancestor.parent); - - if (!ancestor) { + if (!(parent.type === 'InlineComponent' || within_custom_element(parent))) { component.error(attribute, { code: `invalid-slotted-content`, - message: `Element with a slot='...' attribute must be a descendant of a component or custom element` + message: `Element with a slot='...' attribute must be a child of a component or a descendant of a custom element`, }); } } @@ -776,3 +760,12 @@ function should_have_attribute( message: `A11y: <${name}> element should have ${article} ${sequence} attribute` }); } + +function within_custom_element(parent: INode) { + while (parent) { + if (parent.type === 'InlineComponent') return false; + if (parent.type === 'Element' && /-/.test(parent.name)) return true; + parent = parent.parent; + } + return false; +} \ No newline at end of file diff --git a/test/runtime/samples/component-slot-nested-error-2/Nested.svelte b/test/runtime/samples/component-slot-nested-error-2/Nested.svelte new file mode 100644 index 000000000000..c6f086d96c19 --- /dev/null +++ b/test/runtime/samples/component-slot-nested-error-2/Nested.svelte @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/runtime/samples/component-slot-nested-error-2/_config.js b/test/runtime/samples/component-slot-nested-error-2/_config.js new file mode 100644 index 000000000000..98a9f1cab00d --- /dev/null +++ b/test/runtime/samples/component-slot-nested-error-2/_config.js @@ -0,0 +1,3 @@ +export default { + error: [`Element with a slot='...' attribute must be a child of a component or a descendant of a custom element`] +}; diff --git a/test/runtime/samples/component-slot-nested-error-2/main.svelte b/test/runtime/samples/component-slot-nested-error-2/main.svelte new file mode 100644 index 000000000000..a7142d6dc13b --- /dev/null +++ b/test/runtime/samples/component-slot-nested-error-2/main.svelte @@ -0,0 +1,11 @@ + + + +