[fix] propagate bindings correctly (#8114)

Fixes #8103 introduced through #7981
Keeps the infinite loop from happening but reopens #6298 and #5689
pull/8160/head
Simon H 2 years ago committed by GitHub
parent 1d658e7501
commit 762d0429b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -393,7 +393,7 @@ export default class InlineComponentWrapper extends Wrapper {
component.partly_hoisted.push(body); 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 => { const munged_handlers = this.node.handlers.map(handler => {

@ -5,13 +5,11 @@ import { children, detach, start_hydrating, end_hydrating } from './dom';
import { transition_in } from './transitions'; import { transition_in } from './transitions';
import { T$$ } from './types'; import { T$$ } from './types';
export function bind(component, name, callback, value) { export function bind(component, name, callback) {
const index = component.$$.props[name]; const index = component.$$.props[name];
if (index !== undefined) { if (index !== undefined) {
component.$$.bound[index] = callback; component.$$.bound[index] = callback;
if (value === undefined) { callback(component.$$.ctx[index]);
callback(component.$$.ctx[index]);
}
} }
} }

@ -52,17 +52,32 @@ export function add_flush_callback(fn) {
const seen_callbacks = new Set(); const seen_callbacks = new Set();
let flushidx = 0; // Do *not* move this inside the flush() function let flushidx = 0; // Do *not* move this inside the flush() function
export function flush() { 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; const saved_component = current_component;
do { do {
// first, call beforeUpdate functions // first, call beforeUpdate functions
// and update components // and update components
while (flushidx < dirty_components.length) { try {
const component = dirty_components[flushidx]; while (flushidx < dirty_components.length) {
flushidx++; const component = dirty_components[flushidx];
set_current_component(component); flushidx++;
update(component.$$); 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); set_current_component(null);
dirty_components.length = 0; dirty_components.length = 0;

@ -0,0 +1,6 @@
<script>
export let value;
value = "bar";
</script>
Child component "{value}"<br />

@ -1,7 +1,8 @@
export default { export default {
async test({ assert, target }) { async test({ assert, target }) {
assert.htmlEqual(target.innerHTML, ` assert.htmlEqual(target.innerHTML, `
<p>0</p> Parent component "bar"<br />
Child component "bar"<br />
`); `);
} }
}; };

@ -0,0 +1,8 @@
<script>
import Component from "./Component.svelte";
let value = "foo";
</script>
Parent component "{value}"<br />
<Component bind:value />

@ -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>
`);
}
};
Loading…
Cancel
Save