Fix 6860: Warn user when binding rest operator

pull/7526/head
vaibhav rai 4 years ago committed by tanhauhau
parent 34eb6efedc
commit 4af59e463f

@ -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`
})
};

@ -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<string, Node>;
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);
});

@ -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;
}

@ -0,0 +1,8 @@
<script>
let objArray = [{foo: '1', id: 0, innerValue: "test"}, {foo: '2', id:1, innerValue: "Somethin"}]
</script>
{#each objArray as { id, ...rest } (id)}
<input bind:value={rest.innerValue} type="text" placeholder={rest.foo}/>
<br/>
{/each}

@ -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"
}
]
Loading…
Cancel
Save