From f09c47a5184b590ccc0dc195648b017e59d1d3d1 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Thu, 24 Sep 2020 18:25:50 +0800 Subject: [PATCH 1/5] handle destructure to a store value --- src/compiler/compile/render_dom/invalidate.ts | 3 +- .../_config.js | 9 ++++++ .../main.svelte | 29 +++++++++++++++++++ .../_config.js | 8 ++++- .../main.svelte | 15 +++++++++- 5 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 test/runtime/samples/reactive-assignment-in-complex-declaration-with-store-2/_config.js create mode 100644 test/runtime/samples/reactive-assignment-in-complex-declaration-with-store-2/main.svelte diff --git a/src/compiler/compile/render_dom/invalidate.ts b/src/compiler/compile/render_dom/invalidate.ts index b045db079f3..96dfb808bfd 100644 --- a/src/compiler/compile/render_dom/invalidate.ts +++ b/src/compiler/compile/render_dom/invalidate.ts @@ -46,6 +46,7 @@ export function invalidate(renderer: Renderer, scope: Scope, node: Node, names: const extra_args = tail.map(variable => get_invalidated(variable)).filter(Boolean); const pass_value = ( + !is_store_value && !main_execution_context && ( extra_args.length > 0 || @@ -62,7 +63,7 @@ export function invalidate(renderer: Renderer, scope: Scope, node: Node, names: } let invalidate = is_store_value - ? x`@set_store_value(${head.name.slice(1)}, ${node}, ${head.name})` + ? x`@set_store_value(${head.name.slice(1)}, ${node}, ${head.name}, ${extra_args})` : !main_execution_context ? x`$$invalidate(${renderer.context_lookup.get(head.name).index}, ${node}, ${extra_args})` : extra_args.length diff --git a/test/runtime/samples/reactive-assignment-in-complex-declaration-with-store-2/_config.js b/test/runtime/samples/reactive-assignment-in-complex-declaration-with-store-2/_config.js new file mode 100644 index 00000000000..3d86cef8a8d --- /dev/null +++ b/test/runtime/samples/reactive-assignment-in-complex-declaration-with-store-2/_config.js @@ -0,0 +1,9 @@ +// destructure to store value +export default { + skip_if_ssr: true, + html: `

2 2 xxx 5 6 9 10 2

`, + async test({ assert, target, component }) { + await component.update(); + assert.htmlEqual(target.innerHTML, `

11 11 yyy 12 13 14 15 11

`); + } +}; \ No newline at end of file diff --git a/test/runtime/samples/reactive-assignment-in-complex-declaration-with-store-2/main.svelte b/test/runtime/samples/reactive-assignment-in-complex-declaration-with-store-2/main.svelte new file mode 100644 index 00000000000..367c008e8ed --- /dev/null +++ b/test/runtime/samples/reactive-assignment-in-complex-declaration-with-store-2/main.svelte @@ -0,0 +1,29 @@ + + +

{foo} {$eid} {$u.name} {$v} {$w} {$x} {$y} {$z}

diff --git a/test/runtime/samples/reactive-assignment-in-complex-declaration-with-store/_config.js b/test/runtime/samples/reactive-assignment-in-complex-declaration-with-store/_config.js index e74cea70fe3..0318e63b0a1 100644 --- a/test/runtime/samples/reactive-assignment-in-complex-declaration-with-store/_config.js +++ b/test/runtime/samples/reactive-assignment-in-complex-declaration-with-store/_config.js @@ -1,3 +1,9 @@ +// destructure to store export default { - html: `

2 2 xxx 5 6

` + html: `

2 2 xxx 5 6 9 10 2

`, + skip_if_ssr: true, + async test({ assert, target, component }) { + await component.update(); + assert.htmlEqual(target.innerHTML, `

11 11 yyy 12 13 14 15 11

`); + } }; \ No newline at end of file diff --git a/test/runtime/samples/reactive-assignment-in-complex-declaration-with-store/main.svelte b/test/runtime/samples/reactive-assignment-in-complex-declaration-with-store/main.svelte index 5ad442e1dad..cd492235352 100644 --- a/test/runtime/samples/reactive-assignment-in-complex-declaration-with-store/main.svelte +++ b/test/runtime/samples/reactive-assignment-in-complex-declaration-with-store/main.svelte @@ -6,11 +6,24 @@ let u; let v; let w; + let x; + let y; [u, v, w] = [ {id: eid = writable(foo = 2), name: 'xxx'}, 5, writable(6) ]; + ({ a: x, b: y } = { a: writable(9), b: writable(10) }); + $: z = u.id; + + export function update() { + [u, v, w] = [ + {id: eid = writable(foo = 11), name: 'yyy'}, + 12, + writable(13) + ]; + ({ a: x, b: y } = { a: writable(14), b: writable(15) }); + } -

{foo} {$eid} {u.name} {v} {$w}

+

{foo} {$eid} {u.name} {v} {$w} {$x} {$y} {$z}

From b098c6f7f0f5d869aa2e48d6cb2ef7d6a25fefa9 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Thu, 24 Sep 2020 19:01:26 +0800 Subject: [PATCH 2/5] refactor --- src/compiler/compile/render_dom/invalidate.ts | 72 +++++++++---------- 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/src/compiler/compile/render_dom/invalidate.ts b/src/compiler/compile/render_dom/invalidate.ts index 96dfb808bfd..b891b48cb50 100644 --- a/src/compiler/compile/render_dom/invalidate.ts +++ b/src/compiler/compile/render_dom/invalidate.ts @@ -36,48 +36,46 @@ export function invalidate(renderer: Renderer, scope: Scope, node: Node, names: return renderer.invalidate(variable.name, undefined, main_execution_context); } - if (head) { - component.has_reactive_assignments = true; - - if (node.type === 'AssignmentExpression' && node.operator === '=' && nodes_match(node.left, node.right) && tail.length === 0) { - return get_invalidated(head, node); - } else { - const is_store_value = head.name[0] === '$' && head.name[1] !== '$'; - const extra_args = tail.map(variable => get_invalidated(variable)).filter(Boolean); - - const pass_value = ( - !is_store_value && - !main_execution_context && - ( - extra_args.length > 0 || - (node.type === 'AssignmentExpression' && node.left.type !== 'Identifier') || - (node.type === 'UpdateExpression' && (!node.prefix || node.argument.type !== 'Identifier')) - ) - ); + if (!head) { + return node; + } - if (pass_value) { - extra_args.unshift({ - type: 'Identifier', - name: head.name - }); - } + component.has_reactive_assignments = true; - let invalidate = is_store_value - ? x`@set_store_value(${head.name.slice(1)}, ${node}, ${head.name}, ${extra_args})` - : !main_execution_context - ? x`$$invalidate(${renderer.context_lookup.get(head.name).index}, ${node}, ${extra_args})` - : extra_args.length - ? [node, ...extra_args] - : node; + if (node.type === 'AssignmentExpression' && node.operator === '=' && nodes_match(node.left, node.right) && tail.length === 0) { + return get_invalidated(head, node); + } - if (head.subscribable && head.reassigned) { - const subscribe = `$$subscribe_${head.name}`; - invalidate = x`${subscribe}(${invalidate})`; - } + const is_store_value = head.name[0] === '$' && head.name[1] !== '$'; + const extra_args = tail.map(variable => get_invalidated(variable)).filter(Boolean); - return invalidate; + if (is_store_value) { + return x`@set_store_value(${head.name.slice(1)}, ${node}, ${head.name}, ${extra_args})`; + } + + let invalidate; + if (!main_execution_context) { + const pass_value = ( + extra_args.length > 0 || + (node.type === 'AssignmentExpression' && node.left.type !== 'Identifier') || + (node.type === 'UpdateExpression' && (!node.prefix || node.argument.type !== 'Identifier')) + ); + if (pass_value) { + extra_args.unshift({ + type: 'Identifier', + name: head.name + }); } + invalidate = x`$$invalidate(${renderer.context_lookup.get(head.name).index}, ${node}, ${extra_args})`; + } else { + // skip `$$invalidate` if it is in the main execution context + invalidate = extra_args.length ? [node, ...extra_args] : node; + } + + if (head.subscribable && head.reassigned) { + const subscribe = `$$subscribe_${head.name}`; + invalidate = x`${subscribe}(${invalidate})`; } - return node; + return invalidate; } \ No newline at end of file From 7238aed8e9b1afc6da513e7439e6d7b2c7ca40ca Mon Sep 17 00:00:00 2001 From: Conduitry Date: Thu, 24 Sep 2020 14:48:10 -0400 Subject: [PATCH 3/5] add note on which issue SSR is skipped for --- .../_config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/runtime/samples/reactive-assignment-in-complex-declaration-with-store-2/_config.js b/test/runtime/samples/reactive-assignment-in-complex-declaration-with-store-2/_config.js index 3d86cef8a8d..f737cad2aa1 100644 --- a/test/runtime/samples/reactive-assignment-in-complex-declaration-with-store-2/_config.js +++ b/test/runtime/samples/reactive-assignment-in-complex-declaration-with-store-2/_config.js @@ -1,6 +1,6 @@ // destructure to store value export default { - skip_if_ssr: true, + skip_if_ssr: true, // pending https://github.com/sveltejs/svelte/issues/3582 html: `

2 2 xxx 5 6 9 10 2

`, async test({ assert, target, component }) { await component.update(); From b5dee7fff0dd62b877b4be316e3e28817eb85bbf Mon Sep 17 00:00:00 2001 From: Conduitry Date: Thu, 24 Sep 2020 14:48:16 -0400 Subject: [PATCH 4/5] lint --- .../main.svelte | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/runtime/samples/reactive-assignment-in-complex-declaration-with-store-2/main.svelte b/test/runtime/samples/reactive-assignment-in-complex-declaration-with-store-2/main.svelte index 367c008e8ed..c1bf63d9cd7 100644 --- a/test/runtime/samples/reactive-assignment-in-complex-declaration-with-store-2/main.svelte +++ b/test/runtime/samples/reactive-assignment-in-complex-declaration-with-store-2/main.svelte @@ -3,11 +3,11 @@ let eid = writable(1); let foo; - let u = writable(2); - let v = writable(3); - let w = writable(4); - let x = writable(5); - let y = writable(6); + const u = writable(2); + const v = writable(3); + const w = writable(4); + const x = writable(5); + const y = writable(6); [$u, $v, $w] = [ {id: eid = writable(foo = 2), name: 'xxx'}, 5, From f358230f656d4f93bc1e1da69c2cf037f2f4758c Mon Sep 17 00:00:00 2001 From: Conduitry Date: Thu, 24 Sep 2020 14:49:13 -0400 Subject: [PATCH 5/5] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 69edc48b0e3..f280dc32a3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased +* Fix destructuring into store values ([#5449](https://github.com/sveltejs/svelte/issues/5449)) * Fix erroneous `missing-declaration` warning with `use:obj.method` ([#5451](https://github.com/sveltejs/svelte/issues/5451)) ## 3.26.0