From 976213d4a11a63fdf5d34daa0cffe41bd8b9106a Mon Sep 17 00:00:00 2001 From: tanhauhau Date: Mon, 4 Jul 2022 10:44:03 +0800 Subject: [PATCH] add more test case, supporting deep destructuring and array destructuring --- src/compiler/compile/nodes/AwaitBlock.ts | 6 +++-- src/compiler/compile/nodes/ConstTag.ts | 5 +++- src/compiler/compile/nodes/EachBlock.ts | 13 +++------- src/compiler/compile/nodes/shared/Context.ts | 25 +++++++++++++------ .../rest-eachblock-binding-2/input.svelte | 11 ++++++++ .../rest-eachblock-binding-2/warnings.json | 9 +++++++ .../rest-eachblock-binding-3/input.svelte | 8 ++++++ .../rest-eachblock-binding-3/warnings.json | 9 +++++++ 8 files changed, 66 insertions(+), 20 deletions(-) create mode 100644 test/validator/samples/rest-eachblock-binding-2/input.svelte create mode 100644 test/validator/samples/rest-eachblock-binding-2/warnings.json create mode 100644 test/validator/samples/rest-eachblock-binding-3/input.svelte create mode 100644 test/validator/samples/rest-eachblock-binding-3/warnings.json diff --git a/src/compiler/compile/nodes/AwaitBlock.ts b/src/compiler/compile/nodes/AwaitBlock.ts index 735fdbfff3..4a669b6365 100644 --- a/src/compiler/compile/nodes/AwaitBlock.ts +++ b/src/compiler/compile/nodes/AwaitBlock.ts @@ -23,6 +23,8 @@ export default class AwaitBlock extends Node { then: ThenBlock; catch: CatchBlock; + context_rest_properties: Map = new Map(); + constructor(component: Component, parent: Node, scope: TemplateScope, info: TemplateNode) { super(component, parent, scope, info); @@ -33,12 +35,12 @@ export default class AwaitBlock extends Node { if (this.then_node) { this.then_contexts = []; - unpack_destructuring({ contexts: this.then_contexts, node: info.value, scope, component }); + unpack_destructuring({ contexts: this.then_contexts, node: info.value, scope, component, context_rest_properties: this.context_rest_properties }); } if (this.catch_node) { this.catch_contexts = []; - unpack_destructuring({ contexts: this.catch_contexts, node: info.error, scope, component }); + unpack_destructuring({ contexts: this.catch_contexts, node: info.error, scope, component, context_rest_properties: this.context_rest_properties }); } this.pending = new PendingBlock(component, this, scope, info.pending); diff --git a/src/compiler/compile/nodes/ConstTag.ts b/src/compiler/compile/nodes/ConstTag.ts index 87a9039008..44a50aa005 100644 --- a/src/compiler/compile/nodes/ConstTag.ts +++ b/src/compiler/compile/nodes/ConstTag.ts @@ -10,6 +10,7 @@ import { extract_identifiers } from 'periscopic'; import is_reference, { NodeWithPropertyDefinition } from 'is-reference'; import get_object from '../utils/get_object'; import compiler_errors from '../compiler_errors'; +import { Node as ESTreeNode } from 'estree'; const allowed_parents = new Set(['EachBlock', 'CatchBlock', 'ThenBlock', 'InlineComponent', 'SlotTemplate', 'IfBlock', 'ElseBlock']); @@ -19,6 +20,7 @@ export default class ConstTag extends Node { contexts: Context[] = []; node: ConstTagType; scope: TemplateScope; + context_rest_properties: Map = new Map(); assignees: Set = new Set(); dependencies: Set = new Set(); @@ -58,7 +60,8 @@ export default class ConstTag extends Node { contexts: this.contexts, node: this.node.expression.left, scope: this.scope, - component: this.component + component: this.component, + context_rest_properties: this.context_rest_properties }); this.expression = new Expression(this.component, this, this.scope, this.node.expression.right); this.contexts.forEach(context => { diff --git a/src/compiler/compile/nodes/EachBlock.ts b/src/compiler/compile/nodes/EachBlock.ts index 627e40fb3e..4a5ea19e37 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, Identifier } from 'estree'; +import { Node } from 'estree'; import Component from '../Component'; import { TemplateNode } from '../../interfaces'; import compiler_errors from '../compiler_errors'; @@ -42,15 +42,8 @@ export default class EachBlock extends AbstractBlock { 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); - } - }); - } + unpack_destructuring({ contexts: this.contexts, node: info.context, scope, component, context_rest_properties: this.context_rest_properties }); + this.contexts.forEach(context => { this.scope.add(context.key.name, this.expression.dependencies, this); }); diff --git a/src/compiler/compile/nodes/shared/Context.ts b/src/compiler/compile/nodes/shared/Context.ts index 670f0531e6..47180d24cd 100644 --- a/src/compiler/compile/nodes/shared/Context.ts +++ b/src/compiler/compile/nodes/shared/Context.ts @@ -20,7 +20,8 @@ export function unpack_destructuring({ modifier = (node) => node, default_modifier = (node) => node, scope, - component + component, + context_rest_properties }: { contexts: Context[]; node: Node; @@ -28,6 +29,7 @@ export function unpack_destructuring({ default_modifier?: Context['default_modifier']; scope: TemplateScope; component: Component; + context_rest_properties: Map; }) { if (!node) return; @@ -43,6 +45,7 @@ export function unpack_destructuring({ modifier, default_modifier }); + context_rest_properties.set((node.argument as Identifier).name, node); } else if (node.type === 'ArrayPattern') { node.elements.forEach((element, i) => { if (element && element.type === 'RestElement') { @@ -52,8 +55,10 @@ export function unpack_destructuring({ modifier: (node) => x`${modifier(node)}.slice(${i})` as Node, default_modifier, scope, - component + component, + context_rest_properties }); + context_rest_properties.set((element.argument as Identifier).name, element); } else if (element && element.type === 'AssignmentPattern') { const n = contexts.length; mark_referenced(element.right, scope, component); @@ -70,7 +75,8 @@ export function unpack_destructuring({ to_ctx )}` as Node, scope, - component + component, + context_rest_properties }); } else { unpack_destructuring({ @@ -79,7 +85,8 @@ export function unpack_destructuring({ modifier: (node) => x`${modifier(node)}[${i}]` as Node, default_modifier, scope, - component + component, + context_rest_properties }); } }); @@ -97,8 +104,10 @@ export function unpack_destructuring({ )}, [${used_properties}])` as Node, default_modifier, scope, - component + component, + context_rest_properties }); + context_rest_properties.set((property.argument as Identifier).name, property); } else { const key = property.key as Identifier; const value = property.value; @@ -121,7 +130,8 @@ export function unpack_destructuring({ to_ctx )}` as Node, scope, - component + component, + context_rest_properties }); } else { unpack_destructuring({ @@ -130,7 +140,8 @@ export function unpack_destructuring({ modifier: (node) => x`${modifier(node)}.${key.name}` as Node, default_modifier, scope, - component + component, + context_rest_properties }); } } diff --git a/test/validator/samples/rest-eachblock-binding-2/input.svelte b/test/validator/samples/rest-eachblock-binding-2/input.svelte new file mode 100644 index 0000000000..d92557673b --- /dev/null +++ b/test/validator/samples/rest-eachblock-binding-2/input.svelte @@ -0,0 +1,11 @@ + + +{#each objArray as [id, ...rest] (id)} + +
+{/each} diff --git a/test/validator/samples/rest-eachblock-binding-2/warnings.json b/test/validator/samples/rest-eachblock-binding-2/warnings.json new file mode 100644 index 0000000000..a55e08ac05 --- /dev/null +++ b/test/validator/samples/rest-eachblock-binding-2/warnings.json @@ -0,0 +1,9 @@ +[ + { + "code": "invalid-rest-eachblock-binding", + "message": "...rest operator will create a new object and binding propogation with original object will not work", + "pos": 102, + "start": { "line": 8, "column": 24, "character": 102 }, + "end": { "line": 8, "column": 31, "character": 109 } + } +] diff --git a/test/validator/samples/rest-eachblock-binding-3/input.svelte b/test/validator/samples/rest-eachblock-binding-3/input.svelte new file mode 100644 index 0000000000..b8bae0cd7f --- /dev/null +++ b/test/validator/samples/rest-eachblock-binding-3/input.svelte @@ -0,0 +1,8 @@ + + +{#each objArray as { bar: { id, ...rest } } (id)} + +
+{/each} diff --git a/test/validator/samples/rest-eachblock-binding-3/warnings.json b/test/validator/samples/rest-eachblock-binding-3/warnings.json new file mode 100644 index 0000000000..c3410b3888 --- /dev/null +++ b/test/validator/samples/rest-eachblock-binding-3/warnings.json @@ -0,0 +1,9 @@ +[ + { + "code": "invalid-rest-eachblock-binding", + "message": "...rest operator will create a new object and binding propogation with original object will not work", + "pos": 168, + "start": { "line": 5, "column": 32, "character": 168 }, + "end": { "line": 5, "column": 39, "character": 175 } + } +]