Skip to content

Commit

Permalink
[fix] propagate bindings correctly (#8114)
Browse files Browse the repository at this point in the history
Fixes #8103 introduced through #7981
Keeps the infinite loop from happening but reopens #6298 and #5689
  • Loading branch information
dummdidumm authored Jan 2, 2023
1 parent 1d658e7 commit 762d042
Show file tree
Hide file tree
Showing 9 changed files with 49 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,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
25 changes: 20 additions & 5 deletions src/runtime/internal/scheduler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,32 @@ export function add_flush_callback(fn) {
const seen_callbacks = new Set();
let flushidx = 0; // Do *not* move this inside the flush() function
export function flush() {
// Do not reenter flush while dirty components are updated, as this can
// result in an infinite loop. Instead, let the inner flush handle it.
// Reentrancy is ok afterwards for bindings etc.
if (flushidx !== 0) {
return;
}

const saved_component = current_component;

do {
// first, call beforeUpdate functions
// and update components
while (flushidx < dirty_components.length) {
const component = dirty_components[flushidx];
flushidx++;
set_current_component(component);
update(component.$$);
try {
while (flushidx < dirty_components.length) {
const component = dirty_components[flushidx];
flushidx++;
set_current_component(component);
update(component.$$);
}
} catch (e) {
// reset dirty state to not end up in a deadlocked state and then rethrow
dirty_components.length = 0;
flushidx = 0;
throw e;
}

set_current_component(null);

dirty_components.length = 0;
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 />
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
export default {
async test({ assert, target }) {
assert.htmlEqual(target.innerHTML, `
<p>0</p>
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 />
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// this test currently fails because the fix that made it pass broke other tests,
// see https://github.com/sveltejs/svelte/pull/8114 for more context.
export default {
skip: true,
async test({ assert, target }) {
assert.htmlEqual(target.innerHTML, `
<p>0</p>
`);
}
};

0 comments on commit 762d042

Please sign in to comment.