From a93242a85ea245b02dc87317c55e206f51c08911 Mon Sep 17 00:00:00 2001 From: swyx Date: Sat, 15 Feb 2020 14:15:55 -0500 Subject: [PATCH] tests pass --- src/compiler/compile/render_dom/wrappers/EachBlock.ts | 10 ++++++++-- src/runtime/internal/dev.ts | 11 +++++++++++ .../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 | 7 +++++++ 6 files changed, 45 insertions(+), 2 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 8f8fe29564..05a6b88bf9 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` @@ -374,9 +377,12 @@ export default class EachBlockWrapper extends Wrapper { block.chunks.init.push(b` const ${get_key} = #ctx => ${this.node.key.manipulate(block)}; - ${this.renderer.options.dev && b`@validate_each_keys(#ctx, ${this.vars.each_block_value}, ${this.vars.get_each_context}, ${get_key});`} + ${this.renderer.options.dev && + b`@validate_each_keys(#ctx, ${this.vars.each_block_value}, ${this.vars.get_each_context}, ${get_key});`} for (let #i = 0; #i < ${data_length}; #i += 1) { - let child_ctx = ${this.vars.get_each_context}(#ctx, ${this.vars.each_block_value}, #i); + let child_ctx = ${this.vars.get_each_context}(#ctx, ${ + this.vars.each_block_value + }, #i); let key = ${get_key}(child_ctx); ${lookup}.set(key, ${iterations}[#i] = ${create_each_block}(key, child_ctx)); } diff --git a/src/runtime/internal/dev.ts b/src/runtime/internal/dev.ts index 1829225ad9..551da1f1f3 100644 --- a/src/runtime/internal/dev.ts +++ b/src/runtime/internal/dev.ts @@ -79,6 +79,17 @@ export function set_data_dev(text, data) { text.data = data; } +export function validate_each_argument(arg) { + if (arg instanceof Set || arg instanceof Map) { + throw new Error(`Svelte does not allow Sets or Maps in an {#each} block. Use [...arg.values()] instead.`); + } + if (arg.length === undefined) { + throw new Error( + `Svelte needs an array-like value for the {#each} block. You can spread your iterable into an array instead, e.g. [...iterable]` + ); + } +} + type Props = Record; export interface SvelteComponentDev { 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 0000000000..a38f96d8d6 --- /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: `Svelte does not allow Sets or Maps in an {#each} block. Use [...arg.values()] instead.` +}; 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 0000000000..9c6ec835f9 --- /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 0000000000..e0f48fb582 --- /dev/null +++ b/test/runtime/samples/dev-warning-each-block-require-arraylike/_config.js @@ -0,0 +1,6 @@ +export default { + compileOptions: { + dev: true + }, + error: `Svelte needs an array-like value for the {#each} block. You can spread your iterable into an array instead, e.g. [...iterable]` +}; 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 0000000000..8b5057dfe4 --- /dev/null +++ b/test/runtime/samples/dev-warning-each-block-require-arraylike/main.svelte @@ -0,0 +1,7 @@ + + +{#each foo.values() as item} +
{item}
+{/each} \ No newline at end of file