From 75b8d3fb21f91b61e5937e8eb46a13b70cc945cc Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Tue, 24 Dec 2019 00:15:23 +0800 Subject: [PATCH] fix destructuring in slot let binding --- .../wrappers/shared/get_slot_definition.ts | 44 ++++++++++-- .../Nested.svelte | 5 ++ .../_config.js | 68 +++++++++++++++++++ .../main.svelte | 28 ++++++++ 4 files changed, 140 insertions(+), 5 deletions(-) create mode 100644 test/runtime/samples/component-slot-let-destructured-2/Nested.svelte create mode 100644 test/runtime/samples/component-slot-let-destructured-2/_config.js create mode 100644 test/runtime/samples/component-slot-let-destructured-2/main.svelte 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 2adbd3b1d0..9ab48dd035 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 @@ -7,7 +7,7 @@ import { BinaryExpression } from 'estree'; export function get_slot_definition(block: Block, scope: TemplateScope, lets: Let[]) { if (lets.length === 0) return { block, scope }; - const input = { + const context_input = { type: 'ObjectPattern', properties: lets.map(l => ({ type: 'Property', @@ -17,10 +17,41 @@ export function get_slot_definition(block: Block, scope: TemplateScope, lets: Le })) }; + const properties = []; + const value_map = new Map(); + + lets.forEach(l => { + let value; + if (l.names.length > 1) { + // more than one, probably destructuring + const unique_name = block.get_unique_name(l.names.join('_')).name; + value_map.set(l.value, unique_name); + value = { type: 'Identifier', name: unique_name }; + } else { + value = l.value || l.name; + } + properties.push({ + type: 'Property', + kind: 'init', + key: l.name, + value, + }); + }); + + const changes_input = { + type: 'ObjectPattern', + properties, + }; + const names: Set = new Set(); + const names_lookup: Map = new Map(); + lets.forEach(l => { l.names.forEach(name => { names.add(name); + if (value_map.has(l.value)) { + names_lookup.set(name, value_map.get(l.value)); + } }); }); @@ -43,8 +74,10 @@ export function get_slot_definition(block: Block, scope: TemplateScope, lets: Le const i = context_lookup.get(name).index.value as number; const g = Math.floor(i / 31); + const lookup_name = names_lookup.has(name) ? names_lookup.get(name) : name; + if (!grouped[g]) grouped[g] = []; - grouped[g].push({ name, n: i % 31 }); + grouped[g].push({ name: lookup_name, n: i % 31 }); }); const elements = []; @@ -65,8 +98,9 @@ export function get_slot_definition(block: Block, scope: TemplateScope, lets: Le return Array.from(names) .map(name => { + const lookup_name = names_lookup.has(name) ? names_lookup.get(name) : name; const i = context_lookup.get(name).index.value as number; - return x`${name} ? ${1 << i} : 0`; + return x`${lookup_name} ? ${1 << i} : 0`; }) .reduce((lhs, rhs) => x`${lhs} | ${rhs}`) as BinaryExpression; } @@ -75,7 +109,7 @@ export function get_slot_definition(block: Block, scope: TemplateScope, lets: Le return { block, scope, - get_context: x`${input} => ${context}`, - get_changes: x`${input} => ${changes}` + get_context: x`${context_input} => ${context}`, + get_changes: x`${changes_input} => ${changes}` }; } \ No newline at end of file diff --git a/test/runtime/samples/component-slot-let-destructured-2/Nested.svelte b/test/runtime/samples/component-slot-let-destructured-2/Nested.svelte new file mode 100644 index 0000000000..5dfe32bc7f --- /dev/null +++ b/test/runtime/samples/component-slot-let-destructured-2/Nested.svelte @@ -0,0 +1,5 @@ + + + diff --git a/test/runtime/samples/component-slot-let-destructured-2/_config.js b/test/runtime/samples/component-slot-let-destructured-2/_config.js new file mode 100644 index 0000000000..38b04b7b5e --- /dev/null +++ b/test/runtime/samples/component-slot-let-destructured-2/_config.js @@ -0,0 +1,68 @@ +export default { + html: ` +
+ hello world 0 hello + +
+
+ hello world 0 hello + +
+
+ hello world 0 hello + +
+ `, + async test({ assert, component, target, window }) { + const [button1, button2, button3] = target.querySelectorAll('button'); + const event = new window.MouseEvent('click'); + + await button1.dispatchEvent(event); + assert.htmlEqual(target.innerHTML, ` +
+ hello world 1 hello + +
+
+ hello world 0 hello + +
+
+ hello world 0 hello + +
+ `); + + await button2.dispatchEvent(event); + assert.htmlEqual(target.innerHTML, ` +
+ hello world 1 hello + +
+
+ hello world 1 hello + +
+
+ hello world 0 hello + +
+ `); + + await button3.dispatchEvent(event); + assert.htmlEqual(target.innerHTML, ` +
+ hello world 1 hello + +
+
+ hello world 1 hello + +
+
+ hello world 1 hello + +
+ `); + } +}; diff --git a/test/runtime/samples/component-slot-let-destructured-2/main.svelte b/test/runtime/samples/component-slot-let-destructured-2/main.svelte new file mode 100644 index 0000000000..215a1390d9 --- /dev/null +++ b/test/runtime/samples/component-slot-let-destructured-2/main.svelte @@ -0,0 +1,28 @@ + + +
+ + {pair[0]} {pair[1]} {c} {foo} + + + +
+ +
+ + {a} {b} {d} {foo} + + + +
+ +
+ + {a} {b} {e} {foo} + + + +
\ No newline at end of file