From 87d4912adbdb70673cefb9d9a294c88e1f15e8a1 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Thu, 15 Dec 2022 13:32:45 +0100 Subject: [PATCH] [fix] propagate bindings correctly Fixes #8103 introduced through #7981 while keeping the referenced bug in that PR fixed. This expands the "are the values equal"-check from just member expressions (bind:foo={member.expression}) to all occasions, because in loop scenarios the ctx object is temporarily lagging behind when doing the $$invalidate call. --- .../wrappers/InlineComponent/index.ts | 19 ++++++++----------- src/runtime/internal/Component.ts | 6 ++---- .../binding-indirect-value/Component.svelte | 6 ++++++ .../samples/binding-indirect-value/_config.js | 8 ++++++++ .../binding-indirect-value/main.svelte | 8 ++++++++ 5 files changed, 32 insertions(+), 15 deletions(-) create mode 100644 test/runtime/samples/binding-indirect-value/Component.svelte create mode 100644 test/runtime/samples/binding-indirect-value/_config.js create mode 100644 test/runtime/samples/binding-indirect-value/main.svelte diff --git a/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts b/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts index f7875dc1b07d..43eceb3f67bb 100644 --- a/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts +++ b/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts @@ -373,17 +373,14 @@ export default class InlineComponentWrapper extends Wrapper { } `); - let invalidate_binding = b` - ${lhs} = #value; - ${renderer.invalidate(dependencies[0])}; + // Always check for equality, don't wait for the dirty check in invalidate later + // as it may not be updated correctly yet in loop conditions. + const invalidate_binding = b` + if ($$self.$$.not_equal(${lhs}, #value)) { + ${lhs} = #value; + ${renderer.invalidate(dependencies[0])}; + } `; - if (binding.expression.node.type === 'MemberExpression') { - invalidate_binding = b` - if ($$self.$$.not_equal(${lhs}, #value)) { - ${invalidate_binding} - } - `; - } const body = b` function ${id}(${params}) { @@ -393,7 +390,7 @@ export default class InlineComponentWrapper extends Wrapper { component.partly_hoisted.push(body); - return b`@binding_callbacks.push(() => @bind(${this.var}, '${binding.name}', ${id}, ${snippet}));`; + return b`@binding_callbacks.push(() => @bind(${this.var}, '${binding.name}', ${id}));`; }); const munged_handlers = this.node.handlers.map(handler => { diff --git a/src/runtime/internal/Component.ts b/src/runtime/internal/Component.ts index eedf8dd1ada4..5aec24c651f7 100644 --- a/src/runtime/internal/Component.ts +++ b/src/runtime/internal/Component.ts @@ -5,13 +5,11 @@ import { children, detach, start_hydrating, end_hydrating } from './dom'; import { transition_in } from './transitions'; import { T$$ } from './types'; -export function bind(component, name, callback, value) { +export function bind(component, name, callback) { const index = component.$$.props[name]; if (index !== undefined) { component.$$.bound[index] = callback; - if (value === undefined) { - callback(component.$$.ctx[index]); - } + callback(component.$$.ctx[index]); } } diff --git a/test/runtime/samples/binding-indirect-value/Component.svelte b/test/runtime/samples/binding-indirect-value/Component.svelte new file mode 100644 index 000000000000..25bf0d6758c6 --- /dev/null +++ b/test/runtime/samples/binding-indirect-value/Component.svelte @@ -0,0 +1,6 @@ + + +Child component "{value}"
diff --git a/test/runtime/samples/binding-indirect-value/_config.js b/test/runtime/samples/binding-indirect-value/_config.js new file mode 100644 index 000000000000..4eaf6839aa1e --- /dev/null +++ b/test/runtime/samples/binding-indirect-value/_config.js @@ -0,0 +1,8 @@ +export default { + async test({ assert, target }) { + assert.htmlEqual(target.innerHTML, ` + Parent component "bar"
+ Child component "bar"
+ `); + } +}; diff --git a/test/runtime/samples/binding-indirect-value/main.svelte b/test/runtime/samples/binding-indirect-value/main.svelte new file mode 100644 index 000000000000..db2734c89091 --- /dev/null +++ b/test/runtime/samples/binding-indirect-value/main.svelte @@ -0,0 +1,8 @@ + + +Parent component "{value}"
+