diff --git a/CHANGELOG.md b/CHANGELOG.md index b4ffb19d3c32..2c9922a0866a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Fix specificity of certain styles involving a child selector ([#4795](https://github.com/sveltejs/svelte/issues/4795)) * Fix transitions that are parameterised with stores ([#5244](https://github.com/sveltejs/svelte/issues/5244)) * Fix scoping of styles involving child selector and `*` ([#5370](https://github.com/sveltejs/svelte/issues/5370)) +* Fix destructuring which reassigns stores ([#5388](https://github.com/sveltejs/svelte/issues/5388)) ## 3.25.0 diff --git a/src/compiler/compile/Component.ts b/src/compiler/compile/Component.ts index ed2b10e40432..078ecb8869b2 100644 --- a/src/compiler/compile/Component.ts +++ b/src/compiler/compile/Component.ts @@ -947,12 +947,6 @@ export default class Component { const variable = component.var_lookup.get(name); if (variable.export_name && variable.writable) { - const insert = variable.subscribable - ? get_insert(variable) - : null; - - parent[key].splice(index + 1, 0, insert); - declarator.id = { type: 'ObjectPattern', properties: [{ @@ -973,7 +967,9 @@ export default class Component { }; declarator.init = x`$$props`; - } else if (variable.subscribable) { + } + + if (variable.subscribable && declarator.init) { const insert = get_insert(variable); parent[key].splice(index + 1, 0, ...insert); } diff --git a/src/compiler/compile/render_dom/Renderer.ts b/src/compiler/compile/render_dom/Renderer.ts index 6fc026de230e..0990281d912a 100644 --- a/src/compiler/compile/render_dom/Renderer.ts +++ b/src/compiler/compile/render_dom/Renderer.ts @@ -166,12 +166,14 @@ export default class Renderer { return member; } - invalidate(name: string, value?) { + invalidate(name: string, value?, main_execution_context: boolean = false) { const variable = this.component.var_lookup.get(name); const member = this.context_lookup.get(name); if (variable && (variable.subscribable && (variable.reassigned || variable.export_name))) { - return x`${`$$subscribe_${name}`}($$invalidate(${member.index}, ${value || name}))`; + return main_execution_context + ? x`${`$$subscribe_${name}`}(${value || name})` + : x`${`$$subscribe_${name}`}($$invalidate(${member.index}, ${value || name}))`; } if (name[0] === '$' && name[1] !== '$') { diff --git a/src/compiler/compile/render_dom/invalidate.ts b/src/compiler/compile/render_dom/invalidate.ts index 28e4f37e3fd1..c7d9759ccd0a 100644 --- a/src/compiler/compile/render_dom/invalidate.ts +++ b/src/compiler/compile/render_dom/invalidate.ts @@ -31,10 +31,9 @@ export function invalidate(renderer: Renderer, scope: Scope, node: Node, names: function get_invalidated(variable: Var, node?: Expression) { if (main_execution_context && !variable.subscribable && variable.name[0] !== '$') { - return node || x`${variable.name}`; + return node; } - - return renderer.invalidate(variable.name); + return renderer.invalidate(variable.name, undefined, main_execution_context); } if (head) { @@ -44,12 +43,15 @@ export function invalidate(renderer: Renderer, scope: Scope, node: Node, names: 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)); + const extra_args = tail.map(variable => get_invalidated(variable)).filter(Boolean); const pass_value = ( - extra_args.length > 0 || - (node.type === 'AssignmentExpression' && node.left.type !== 'Identifier') || - (node.type === 'UpdateExpression' && (!node.prefix || node.argument.type !== 'Identifier')) + !main_execution_context && + ( + extra_args.length > 0 || + (node.type === 'AssignmentExpression' && node.left.type !== 'Identifier') || + (node.type === 'UpdateExpression' && (!node.prefix || node.argument.type !== 'Identifier')) + ) ); if (pass_value) { @@ -63,7 +65,9 @@ export function invalidate(renderer: Renderer, scope: Scope, node: Node, names: ? x`@set_store_value(${head.name.slice(1)}, ${node}, ${extra_args})` : !main_execution_context ? x`$$invalidate(${renderer.context_lookup.get(head.name).index}, ${node}, ${extra_args})` - : node; + : extra_args.length + ? [node, ...extra_args] + : node; if (head.subscribable && head.reassigned) { const subscribe = `$$subscribe_${head.name}`; 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 new file mode 100644 index 000000000000..e74cea70fe3c --- /dev/null +++ b/test/runtime/samples/reactive-assignment-in-complex-declaration-with-store/_config.js @@ -0,0 +1,3 @@ +export default { + html: `