diff --git a/src/runtime/internal/scheduler.ts b/src/runtime/internal/scheduler.ts index c910ba10394b..986d69b87f8d 100644 --- a/src/runtime/internal/scheduler.ts +++ b/src/runtime/internal/scheduler.ts @@ -50,6 +50,7 @@ export function add_flush_callback(fn) { // callback called a second time; the seen_callbacks set, outside the flush() // function, guarantees this behavior. const seen_callbacks = new Set(); +let previous_dirty_components = 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 @@ -69,10 +70,12 @@ export function flush() { const component = dirty_components[flushidx]; flushidx++; set_current_component(component); - update(component.$$); + const is_previous_dirty = previous_dirty_components.has(component); + update(component.$$, is_previous_dirty); } } catch (e) { // reset dirty state to not end up in a deadlocked state and then rethrow + previous_dirty_components.clear(); dirty_components.length = 0; flushidx = 0; throw e; @@ -83,8 +86,10 @@ export function flush() { dirty_components.length = 0; flushidx = 0; - while (binding_callbacks.length) binding_callbacks.pop()(); - + while (binding_callbacks.length) { + binding_callbacks.pop()(); + } + previous_dirty_components = new Set(dirty_components); // then, once components are updated, call // afterUpdate functions. This may cause // subsequent updates... @@ -108,17 +113,18 @@ export function flush() { update_scheduled = false; seen_callbacks.clear(); + previous_dirty_components.clear(); set_current_component(saved_component); } -function update($$) { +function update($$, is_previous_dirty) { if ($$.fragment !== null) { $$.update(); - run_all($$.before_update); + if (!is_previous_dirty) run_all($$.before_update); const dirty = $$.dirty; $$.dirty = [-1]; $$.fragment && $$.fragment.p($$.ctx, dirty); - + // if (!is_previous_dirty) run_all($$.after_update); $$.after_update.forEach(add_render_callback); } } diff --git a/test/runtime/samples/lifecycle-render-order-for-children-with-binding/Item.svelte b/test/runtime/samples/lifecycle-render-order-for-children-with-binding/Item.svelte new file mode 100755 index 000000000000..85d47d524520 --- /dev/null +++ b/test/runtime/samples/lifecycle-render-order-for-children-with-binding/Item.svelte @@ -0,0 +1,30 @@ + + +
  • + {logRender()} +
  • diff --git a/test/runtime/samples/lifecycle-render-order-for-children-with-binding/_config.js b/test/runtime/samples/lifecycle-render-order-for-children-with-binding/_config.js new file mode 100644 index 000000000000..32bc35d49caa --- /dev/null +++ b/test/runtime/samples/lifecycle-render-order-for-children-with-binding/_config.js @@ -0,0 +1,49 @@ +import order from './order.js'; + +export default { + skip_if_ssr: true, + before_test() { + order.length = 0; + }, + test({ assert, compileOptions }) { + if (compileOptions.hydratable) { + assert.deepEqual(order, [ + '0: beforeUpdate', + '0: render', + '1: beforeUpdate', + '1: render', + '2: beforeUpdate', + '2: render', + '3: beforeUpdate', + '3: render', + '1: onMount', + '1: afterUpdate', + '2: onMount', + '2: afterUpdate', + '3: onMount', + '3: afterUpdate', + '0: onMount', + '0: afterUpdate' + ]); + } else { + assert.deepEqual(order, [ + '0: beforeUpdate', + '0: render', + '1: beforeUpdate', + '2: beforeUpdate', + '3: beforeUpdate', + '1: render', + '2: render', + '3: render', + '1: onMount', + '1: afterUpdate', + '2: onMount', + '2: afterUpdate', + '3: onMount', + '3: afterUpdate', + '0: onMount', + '0: afterUpdate' + ]); + } + } +}; diff --git a/test/runtime/samples/lifecycle-render-order-for-children-with-binding/main.svelte b/test/runtime/samples/lifecycle-render-order-for-children-with-binding/main.svelte new file mode 100644 index 000000000000..c5061d32187d --- /dev/null +++ b/test/runtime/samples/lifecycle-render-order-for-children-with-binding/main.svelte @@ -0,0 +1,34 @@ + + +{logRender()} + + + diff --git a/test/runtime/samples/lifecycle-render-order-for-children-with-binding/order.js b/test/runtime/samples/lifecycle-render-order-for-children-with-binding/order.js new file mode 100644 index 000000000000..d6d1738de67e --- /dev/null +++ b/test/runtime/samples/lifecycle-render-order-for-children-with-binding/order.js @@ -0,0 +1 @@ +export default [];