wait until flush complete before unlocking bindings - fixes #2356

pull/2415/head
Richard Harris 6 years ago
parent b03cfcf09d
commit 5535110066

@ -112,7 +112,6 @@ export default class InlineComponentWrapper extends Wrapper {
const statements: string[] = []; const statements: string[] = [];
const updates: string[] = []; const updates: string[] = [];
const postupdates: string[] = [];
let props; let props;
const name_changes = block.get_unique_name(`${name}_changes`); const name_changes = block.get_unique_name(`${name}_changes`);
@ -311,8 +310,6 @@ export default class InlineComponentWrapper extends Wrapper {
} }
`); `);
postupdates.push(updating);
const contextual_dependencies = Array.from(binding.expression.contextual_dependencies); const contextual_dependencies = Array.from(binding.expression.contextual_dependencies);
const dependencies = Array.from(binding.expression.dependencies); const dependencies = Array.from(binding.expression.dependencies);
@ -333,9 +330,9 @@ export default class InlineComponentWrapper extends Wrapper {
block.builders.init.add_block(deindent` block.builders.init.add_block(deindent`
function ${name}(value) { function ${name}(value) {
if (ctx.${name}.call(null, value, ctx)) { ctx.${name}.call(null, value, ctx);
${updating} = true; ${updating} = true;
} @add_flush_callback(() => ${updating} = false);
} }
`); `);
@ -343,9 +340,9 @@ export default class InlineComponentWrapper extends Wrapper {
} else { } else {
block.builders.init.add_block(deindent` block.builders.init.add_block(deindent`
function ${name}(value) { function ${name}(value) {
if (ctx.${name}.call(null, value)) { ctx.${name}.call(null, value);
${updating} = true; ${updating} = true;
} @add_flush_callback(() => ${updating} = false);
} }
`); `);
} }
@ -353,7 +350,7 @@ export default class InlineComponentWrapper extends Wrapper {
const body = deindent` const body = deindent`
function ${name}(${args.join(', ')}) { function ${name}(${args.join(', ')}) {
${lhs} = value; ${lhs} = value;
return ${component.invalidate(dependencies[0])} ${component.invalidate(dependencies[0])};
} }
`; `;
@ -452,8 +449,6 @@ export default class InlineComponentWrapper extends Wrapper {
else if (${switch_value}) { else if (${switch_value}) {
${name}.$set(${name_changes}); ${name}.$set(${name_changes});
} }
${postupdates.length > 0 && `${postupdates.join(' = ')} = false;`}
`); `);
} }
@ -497,7 +492,6 @@ export default class InlineComponentWrapper extends Wrapper {
block.builders.update.add_block(deindent` block.builders.update.add_block(deindent`
${updates} ${updates}
${name}.$set(${name_changes}); ${name}.$set(${name_changes});
${postupdates.length > 0 && `${postupdates.join(' = ')} = false;`}
`); `);
} }

@ -85,15 +85,9 @@ export function init(component, options, instance, create_fragment, not_equal, p
$$.ctx = instance $$.ctx = instance
? instance(component, props, (key, value) => { ? instance(component, props, (key, value) => {
if ($$.ctx) { if ($$.ctx && not_equal($$.ctx[key], $$.ctx[key] = value)) {
const changed = not_equal(value, $$.ctx[key]); if ($$.bound[key]) $$.bound[key](value);
if (ready && changed) { if (ready) make_dirty(component, key);
if ($$.bound[key]) $$.bound[key](value);
make_dirty(component, key);
}
$$.ctx[key] = value;
return changed;
} }
}) })
: props; : props;

@ -7,6 +7,7 @@ export const intros = { enabled: false };
let update_promise; let update_promise;
const binding_callbacks = []; const binding_callbacks = [];
const render_callbacks = []; const render_callbacks = [];
const flush_callbacks = [];
export function schedule_update() { export function schedule_update() {
if (!update_promise) { if (!update_promise) {
@ -15,10 +16,6 @@ export function schedule_update() {
} }
} }
export function add_render_callback(fn) {
render_callbacks.push(fn);
}
export function tick() { export function tick() {
schedule_update(); schedule_update();
return update_promise; return update_promise;
@ -28,6 +25,14 @@ export function add_binding_callback(fn) {
binding_callbacks.push(fn); binding_callbacks.push(fn);
} }
export function add_render_callback(fn) {
render_callbacks.push(fn);
}
export function add_flush_callback(fn) {
flush_callbacks.push(fn);
}
export function flush() { export function flush() {
const seen_callbacks = new Set(); const seen_callbacks = new Set();
@ -56,6 +61,10 @@ export function flush() {
} }
} while (dirty_components.length); } while (dirty_components.length);
while (flush_callbacks.length) {
flush_callbacks.pop()();
}
update_promise = null; update_promise = null;
} }

@ -2,14 +2,15 @@
import Two from './Two.svelte'; import Two from './Two.svelte';
export let list; export let list;
export let i;
function handle_click() { function handle_click() {
list = [...list, {}]; list = [...list, {}];
} }
</script> </script>
{#each list as item} {#each list as item, j}
<Two bind:value={item.value}/> <Two bind:value={item.value} {i} {j}/>
{/each} {/each}
<button on:click={handle_click}> <button on:click={handle_click}>

@ -1,3 +1,4 @@
<script> <script>
export let value = 'x'; export let i, j;
export let value = `${i}:${j}`;
</script> </script>

@ -3,7 +3,7 @@ export default {
<button>click me</button> <button>click me</button>
<button>click me</button> <button>click me</button>
<p>{"value":"x"}</p> <p>{"value":"0:0"}</p>
<p></p> <p></p>
`, `,
@ -16,8 +16,8 @@ export default {
<button>click me</button> <button>click me</button>
<button>click me</button> <button>click me</button>
<p>{"value":"x"}</p> <p>{"value":"0:0"}</p>
<p>{"value":"x"}</p> <p>{"value":"1:0"}</p>
`); `);
} }
}; };

@ -7,8 +7,8 @@
}; };
</script> </script>
<One bind:list={obj.a}/> <One bind:list={obj.a} i={0}/>
<One bind:list={obj.b}/> <One bind:list={obj.b} i={1}/>
<p>{obj.a.map(JSON.stringify)}</p> <p>{obj.a.map(JSON.stringify)}</p>
<p>{obj.b.map(JSON.stringify)}</p> <p>{obj.b.map(JSON.stringify)}</p>

@ -2,14 +2,15 @@
import Two from './Two.svelte'; import Two from './Two.svelte';
export let list; export let list;
export let i;
function handle_click() { function handle_click() {
list = [...list, {}]; list = [...list, {}];
} }
</script> </script>
{#each list as item} {#each list as item, j}
<Two bind:value={item.value}/> <Two bind:value={item.value} {i} {j}/>
{/each} {/each}
<button on:click={handle_click}> <button on:click={handle_click}>

@ -1,3 +1,4 @@
<script> <script>
export let value = { x: true }; export let i, j;
export let value = { i, j };
</script> </script>

@ -3,7 +3,7 @@ export default {
<button>click me</button> <button>click me</button>
<button>click me</button> <button>click me</button>
<p>{"value":{"x":true}}</p> <p>{"value":{"i":0,"j":0}}</p>
<p></p> <p></p>
`, `,
@ -16,8 +16,8 @@ export default {
<button>click me</button> <button>click me</button>
<button>click me</button> <button>click me</button>
<p>{"value":{"x":true}}</p> <p>{"value":{"i":0,"j":0}}</p>
<p>{"value":{"x":true}}</p> <p>{"value":{"i":1,"j":0}}</p>
`); `);
} }
}; };

@ -7,8 +7,8 @@
}; };
</script> </script>
<One bind:list={obj.a}/> <One bind:list={obj.a} i={0}/>
<One bind:list={obj.b}/> <One bind:list={obj.b} i={1}/>
<p>{obj.a.map(JSON.stringify)}</p> <p>{obj.a.map(JSON.stringify)}</p>
<p>{obj.b.map(JSON.stringify)}</p> <p>{obj.b.map(JSON.stringify)}</p>

@ -2,14 +2,15 @@
import Two from './Two.svelte'; import Two from './Two.svelte';
export let list; export let list;
export let i;
function handle_click() { function handle_click() {
list = [...list, {}]; list = [...list, {}];
} }
</script> </script>
{#each list as item} {#each list as item, j}
<Two bind:value={item.value}/> <Two bind:value={item.value} {i} {j}/>
{/each} {/each}
<button on:click={handle_click}> <button on:click={handle_click}>

@ -1,9 +1,10 @@
<script> <script>
import { onMount } from 'svelte'; import { onMount } from 'svelte';
export let i, j;
export let value; export let value;
onMount(() => { onMount(() => {
value = { x: true }; value = { i, j };
}); });
</script> </script>

@ -1,11 +1,17 @@
export default { export default {
skip: 1,
html: ` html: `
<button>click me</button> <button>click me</button>
<button>click me</button> <button>click me</button>
<p>{"value":{"x":true}}</p> <p>{"value":{"i":0,"j":0}}</p>
<p></p>
`,
ssrHtml: `
<button>click me</button>
<button>click me</button>
<p>{}</p>
<p></p> <p></p>
`, `,
@ -18,8 +24,8 @@ export default {
<button>click me</button> <button>click me</button>
<button>click me</button> <button>click me</button>
<p>{"value":{"x":true}}</p> <p>{"value":{"i":0,"j":0}}</p>
<p>{"value":{"x":true}}</p> <p>{"value":{"i":1,"j":0}}</p>
`); `);
} }
}; };

@ -7,8 +7,8 @@
}; };
</script> </script>
<One bind:list={obj.a}/> <One bind:list={obj.a} i={0}/>
<One bind:list={obj.b}/> <One bind:list={obj.b} i={1}/>
<p>{obj.a.map(JSON.stringify)}</p> <p>{obj.a.map(JSON.stringify)}</p>
<p>{obj.b.map(JSON.stringify)}</p> <p>{obj.b.map(JSON.stringify)}</p>
Loading…
Cancel
Save