Skip to content

Commit 762d042

Browse files
authored
[fix] propagate bindings correctly (#8114)
Fixes #8103 introduced through #7981 Keeps the infinite loop from happening but reopens #6298 and #5689
1 parent 1d658e7 commit 762d042

File tree

9 files changed

+49
-11
lines changed

9 files changed

+49
-11
lines changed

src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ export default class InlineComponentWrapper extends Wrapper {
393393

394394
component.partly_hoisted.push(body);
395395

396-
return b`@binding_callbacks.push(() => @bind(${this.var}, '${binding.name}', ${id}, ${snippet}));`;
396+
return b`@binding_callbacks.push(() => @bind(${this.var}, '${binding.name}', ${id}));`;
397397
});
398398

399399
const munged_handlers = this.node.handlers.map(handler => {

src/runtime/internal/Component.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,11 @@ import { children, detach, start_hydrating, end_hydrating } from './dom';
55
import { transition_in } from './transitions';
66
import { T$$ } from './types';
77

8-
export function bind(component, name, callback, value) {
8+
export function bind(component, name, callback) {
99
const index = component.$$.props[name];
1010
if (index !== undefined) {
1111
component.$$.bound[index] = callback;
12-
if (value === undefined) {
13-
callback(component.$$.ctx[index]);
14-
}
12+
callback(component.$$.ctx[index]);
1513
}
1614
}
1715

src/runtime/internal/scheduler.ts

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,17 +52,32 @@ export function add_flush_callback(fn) {
5252
const seen_callbacks = new Set();
5353
let flushidx = 0; // Do *not* move this inside the flush() function
5454
export function flush() {
55+
// Do not reenter flush while dirty components are updated, as this can
56+
// result in an infinite loop. Instead, let the inner flush handle it.
57+
// Reentrancy is ok afterwards for bindings etc.
58+
if (flushidx !== 0) {
59+
return;
60+
}
61+
5562
const saved_component = current_component;
5663

5764
do {
5865
// first, call beforeUpdate functions
5966
// and update components
60-
while (flushidx < dirty_components.length) {
61-
const component = dirty_components[flushidx];
62-
flushidx++;
63-
set_current_component(component);
64-
update(component.$$);
67+
try {
68+
while (flushidx < dirty_components.length) {
69+
const component = dirty_components[flushidx];
70+
flushidx++;
71+
set_current_component(component);
72+
update(component.$$);
73+
}
74+
} catch (e) {
75+
// reset dirty state to not end up in a deadlocked state and then rethrow
76+
dirty_components.length = 0;
77+
flushidx = 0;
78+
throw e;
6579
}
80+
6681
set_current_component(null);
6782

6883
dirty_components.length = 0;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<script>
2+
export let value;
3+
value = "bar";
4+
</script>
5+
6+
Child component "{value}"<br />
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
export default {
22
async test({ assert, target }) {
33
assert.htmlEqual(target.innerHTML, `
4-
<p>0</p>
4+
Parent component "bar"<br />
5+
Child component "bar"<br />
56
`);
67
}
78
};
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<script>
2+
import Component from "./Component.svelte";
3+
4+
let value = "foo";
5+
</script>
6+
7+
Parent component "{value}"<br />
8+
<Component bind:value />
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// this test currently fails because the fix that made it pass broke other tests,
2+
// see https://github.com/sveltejs/svelte/pull/8114 for more context.
3+
export default {
4+
skip: true,
5+
async test({ assert, target }) {
6+
assert.htmlEqual(target.innerHTML, `
7+
<p>0</p>
8+
`);
9+
}
10+
};

0 commit comments

Comments
 (0)