Skip to content

Commit

Permalink
[fix] propagate bindings correctly
Browse files Browse the repository at this point in the history
Fixes sveltejs#8103 introduced through sveltejs#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.
  • Loading branch information
dummdidumm committed Dec 15, 2022
1 parent 3ba0e30 commit 87d4912
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 15 deletions.
19 changes: 8 additions & 11 deletions src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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}) {
Expand All @@ -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 => {
Expand Down
6 changes: 2 additions & 4 deletions src/runtime/internal/Component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
}
}

Expand Down
6 changes: 6 additions & 0 deletions test/runtime/samples/binding-indirect-value/Component.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<script>
export let value;
value = "bar";
</script>

Child component "{value}"<br />
8 changes: 8 additions & 0 deletions test/runtime/samples/binding-indirect-value/_config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default {
async test({ assert, target }) {
assert.htmlEqual(target.innerHTML, `
Parent component "bar"<br />
Child component "bar"<br />
`);
}
};
8 changes: 8 additions & 0 deletions test/runtime/samples/binding-indirect-value/main.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<script>
import Component from "./Component.svelte";
let value = "foo";
</script>

Parent component "{value}"<br />
<Component bind:value />

0 comments on commit 87d4912

Please sign in to comment.