diff --git a/src/compiler/compile/compiler_warnings.ts b/src/compiler/compile/compiler_warnings.ts index 86ec98cb8b..c065c39c49 100644 --- a/src/compiler/compile/compiler_warnings.ts +++ b/src/compiler/compile/compiler_warnings.ts @@ -6,7 +6,7 @@ export default { custom_element_no_tag: { code: 'custom-element-no-tag', - message: 'No custom element \'tag\' option was specified. To automatically register a custom element, specify a name with a hyphen in it, e.g. . To hide this warning, use ' + message: 'No custom element \'tag\' option was specified. To automatically register a custom element, specify a name with a hyphen in it, e.g. . To hide this warning, use ' }, unused_export_let: (component: string, property: string) => ({ code: 'unused-export-let', @@ -143,5 +143,9 @@ export default { redundant_event_modifier_passive: { code: 'redundant-event-modifier', message: 'The passive modifier only works with wheel and touch events' - } + }, + invalid_rest_eachblock_binding: (rest_element_name: string) => ({ + code: 'invalid-rest-eachblock-binding', + message: `...${rest_element_name} operator will create a new object and binding propogation with original object will not work` + }) }; diff --git a/src/compiler/compile/nodes/EachBlock.ts b/src/compiler/compile/nodes/EachBlock.ts index bea6fb7910..627e40fb3e 100644 --- a/src/compiler/compile/nodes/EachBlock.ts +++ b/src/compiler/compile/nodes/EachBlock.ts @@ -5,7 +5,7 @@ import AbstractBlock from './shared/AbstractBlock'; import Element from './Element'; import ConstTag from './ConstTag'; import { Context, unpack_destructuring } from './shared/Context'; -import { Node } from 'estree'; +import { Node, Identifier } from 'estree'; import Component from '../Component'; import { TemplateNode } from '../../interfaces'; import compiler_errors from '../compiler_errors'; @@ -28,7 +28,7 @@ export default class EachBlock extends AbstractBlock { has_animation: boolean; has_binding = false; has_index_binding = false; - + context_rest_properties: Map; else?: ElseBlock; constructor(component: Component, parent: Node, scope: TemplateScope, info: TemplateNode) { @@ -40,10 +40,17 @@ export default class EachBlock extends AbstractBlock { this.index = info.index; this.scope = scope.child(); - + this.context_rest_properties = new Map(); this.contexts = []; unpack_destructuring({ contexts: this.contexts, node: info.context, scope, component }); + if (this.context_node.type === 'ObjectPattern') { + this.context_node.properties.forEach(i => { + if (i.type === 'RestElement') { + this.context_rest_properties.set((i.argument as Identifier).name, i); + } + }); + } this.contexts.forEach(context => { this.scope.add(context.key.name, this.expression.dependencies, this); }); diff --git a/src/compiler/compile/render_dom/wrappers/shared/mark_each_block_bindings.ts b/src/compiler/compile/render_dom/wrappers/shared/mark_each_block_bindings.ts index df7185bb69..76b3ee5c49 100644 --- a/src/compiler/compile/render_dom/wrappers/shared/mark_each_block_bindings.ts +++ b/src/compiler/compile/render_dom/wrappers/shared/mark_each_block_bindings.ts @@ -2,6 +2,7 @@ import EachBlock from '../../../nodes/EachBlock'; import InlineComponentWrapper from '../InlineComponent'; import ElementWrapper from '../Element'; import Binding from '../../../nodes/Binding'; +import compiler_warnings from '../../../compiler_warnings'; export default function mark_each_block_bindings( parent: ElementWrapper | InlineComponentWrapper, @@ -11,6 +12,12 @@ export default function mark_each_block_bindings( // the list and the index, if they're not otherwise referenced binding.expression.references.forEach(name => { const each_block = parent.node.scope.get_owner(name); + if (each_block && each_block.type === 'EachBlock') { + const rest_node = each_block.context_rest_properties.get(name); + if (rest_node) { + parent.renderer.component.warn(rest_node as any, compiler_warnings.invalid_rest_eachblock_binding(name)); + } + } if (each_block) { (each_block as EachBlock).has_binding = true; } diff --git a/test/validator/samples/rest-eachblock-binding/input.svelte b/test/validator/samples/rest-eachblock-binding/input.svelte new file mode 100644 index 0000000000..7b96705448 --- /dev/null +++ b/test/validator/samples/rest-eachblock-binding/input.svelte @@ -0,0 +1,8 @@ + + +{#each objArray as { id, ...rest } (id)} + +
+{/each} diff --git a/test/validator/samples/rest-eachblock-binding/warnings.json b/test/validator/samples/rest-eachblock-binding/warnings.json new file mode 100644 index 0000000000..a1111fefd2 --- /dev/null +++ b/test/validator/samples/rest-eachblock-binding/warnings.json @@ -0,0 +1,6 @@ +[ + { + "code": "invalid-rest-eachblock-binding", + "message": "...rest operator will create a new object and binding propogation with original object will not work" + } +]