From 16f502a9d5d4751b876a62b3bb5b5683a21dc9be Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Wed, 15 Jan 2025 22:59:47 +0000 Subject: [PATCH] more fixes --- .../src/internal/client/dom/blocks/await.js | 4 +- .../internal/client/dom/blocks/boundary.js | 8 +-- .../src/internal/client/dom/blocks/each.js | 4 +- .../svelte/src/internal/client/dom/css.js | 6 +-- .../client/dom/elements/bindings/input.js | 6 +-- .../client/dom/elements/bindings/this.js | 4 +- .../internal/client/dom/elements/events.js | 4 +- .../src/internal/client/dom/elements/misc.js | 4 +- .../client/dom/elements/transitions.js | 4 +- .../svelte/src/internal/client/dom/task.js | 50 ++++++++++++++----- .../svelte/src/internal/client/runtime.js | 12 +++-- packages/svelte/tests/animation-helpers.js | 4 +- 12 files changed, 69 insertions(+), 41 deletions(-) diff --git a/packages/svelte/src/internal/client/dom/blocks/await.js b/packages/svelte/src/internal/client/dom/blocks/await.js index 62b2e4dd0c..546abd95dd 100644 --- a/packages/svelte/src/internal/client/dom/blocks/await.js +++ b/packages/svelte/src/internal/client/dom/blocks/await.js @@ -13,7 +13,7 @@ import { set_dev_current_component_function } from '../../runtime.js'; import { hydrate_next, hydrate_node, hydrating } from '../hydration.js'; -import { queue_micro_task } from '../task.js'; +import { queue_after_micro_task } from '../task.js'; import { UNINITIALIZED } from '../../../../constants.js'; const PENDING = 0; @@ -148,7 +148,7 @@ export function await_block(node, get_input, pending_fn, then_fn, catch_fn) { } else { // Wait a microtask before checking if we should show the pending state as // the promise might have resolved by the next microtask. - queue_micro_task(() => { + queue_after_micro_task(() => { if (!resolved) update(PENDING, true); }); } diff --git a/packages/svelte/src/internal/client/dom/blocks/boundary.js b/packages/svelte/src/internal/client/dom/blocks/boundary.js index c9e2f3d405..e2c84e5a40 100644 --- a/packages/svelte/src/internal/client/dom/blocks/boundary.js +++ b/packages/svelte/src/internal/client/dom/blocks/boundary.js @@ -27,7 +27,7 @@ import { set_hydrate_node } from '../hydration.js'; import { get_next_sibling } from '../operations.js'; -import { queue_micro_task } from '../task.js'; +import { queue_before_micro_task } from '../task.js'; const SUSPEND_INCREMENT = Symbol(); const SUSPEND_DECREMENT = Symbol(); @@ -107,7 +107,7 @@ export function boundary(node, props, boundary_fn) { } if (suspend_count++ === 0) { - queue_micro_task(() => { + queue_before_micro_task(() => { if (suspended_effect) { return; } @@ -151,7 +151,7 @@ export function boundary(node, props, boundary_fn) { } if (--suspend_count === 0) { - queue_micro_task(() => { + queue_before_micro_task(() => { if (!suspended_effect) { return; } @@ -199,7 +199,7 @@ export function boundary(node, props, boundary_fn) { } if (failed) { - queue_micro_task(() => { + queue_before_micro_task(() => { render_snippet(() => { failed( anchor, diff --git a/packages/svelte/src/internal/client/dom/blocks/each.js b/packages/svelte/src/internal/client/dom/blocks/each.js index b17090948a..970d3e37e5 100644 --- a/packages/svelte/src/internal/client/dom/blocks/each.js +++ b/packages/svelte/src/internal/client/dom/blocks/each.js @@ -34,7 +34,7 @@ import { import { source, mutable_source, internal_set } from '../../reactivity/sources.js'; import { array_from, is_array } from '../../../shared/utils.js'; import { INERT } from '../../constants.js'; -import { queue_micro_task } from '../task.js'; +import { queue_after_micro_task } from '../task.js'; import { active_effect, active_reaction, get } from '../../runtime.js'; import { DEV } from 'esm-env'; import { derived_safe_equal } from '../../reactivity/deriveds.js'; @@ -470,7 +470,7 @@ function reconcile(array, state, anchor, render_fn, flags, is_inert, get_key, ge } if (is_animated) { - queue_micro_task(() => { + queue_after_micro_task(() => { if (to_animate === undefined) return; for (item of to_animate) { item.a?.apply(); diff --git a/packages/svelte/src/internal/client/dom/css.js b/packages/svelte/src/internal/client/dom/css.js index 52be36aa1f..3934940204 100644 --- a/packages/svelte/src/internal/client/dom/css.js +++ b/packages/svelte/src/internal/client/dom/css.js @@ -1,5 +1,5 @@ import { DEV } from 'esm-env'; -import { queue_micro_task } from './task.js'; +import { queue_after_micro_task } from './task.js'; import { register_style } from '../dev/css.js'; /** @@ -7,8 +7,8 @@ import { register_style } from '../dev/css.js'; * @param {{ hash: string, code: string }} css */ export function append_styles(anchor, css) { - // Use `queue_micro_task` to ensure `anchor` is in the DOM, otherwise getRootNode() will yield wrong results - queue_micro_task(() => { + // Use `queue_after_micro_task` to ensure `anchor` is in the DOM, otherwise getRootNode() will yield wrong results + queue_after_micro_task(() => { var root = anchor.getRootNode(); var target = /** @type {ShadowRoot} */ (root).host diff --git a/packages/svelte/src/internal/client/dom/elements/bindings/input.js b/packages/svelte/src/internal/client/dom/elements/bindings/input.js index ec123d3968..188b91fa0b 100644 --- a/packages/svelte/src/internal/client/dom/elements/bindings/input.js +++ b/packages/svelte/src/internal/client/dom/elements/bindings/input.js @@ -3,7 +3,7 @@ import { render_effect, teardown } from '../../../reactivity/effects.js'; import { listen_to_event_and_reset_event } from './shared.js'; import * as e from '../../../errors.js'; import { is } from '../../../proxy.js'; -import { queue_micro_task } from '../../task.js'; +import { queue_after_micro_task } from '../../task.js'; import { hydrating } from '../../hydration.js'; import { is_runes, untrack } from '../../../runtime.js'; @@ -158,14 +158,14 @@ export function bind_group(inputs, group_index, input, get, set = get) { if (!pending.has(binding_group)) { pending.add(binding_group); - queue_micro_task(() => { + queue_after_micro_task(() => { // necessary to maintain binding group order in all insertion scenarios binding_group.sort((a, b) => (a.compareDocumentPosition(b) === 4 ? -1 : 1)); pending.delete(binding_group); }); } - queue_micro_task(() => { + queue_after_micro_task(() => { if (hydration_mismatch) { var value; diff --git a/packages/svelte/src/internal/client/dom/elements/bindings/this.js b/packages/svelte/src/internal/client/dom/elements/bindings/this.js index 56b0a56e71..d3e2349d42 100644 --- a/packages/svelte/src/internal/client/dom/elements/bindings/this.js +++ b/packages/svelte/src/internal/client/dom/elements/bindings/this.js @@ -1,7 +1,7 @@ import { STATE_SYMBOL } from '../../../constants.js'; import { effect, render_effect } from '../../../reactivity/effects.js'; import { untrack } from '../../../runtime.js'; -import { queue_micro_task } from '../../task.js'; +import { queue_after_micro_task } from '../../task.js'; /** * @param {any} bound_value @@ -49,7 +49,7 @@ export function bind_this(element_or_component = {}, update, get_value, get_part return () => { // We cannot use effects in the teardown phase, we we use a microtask instead. - queue_micro_task(() => { + queue_after_micro_task(() => { if (parts && is_bound_this(get_value(...parts), element_or_component)) { update(null, ...parts); } diff --git a/packages/svelte/src/internal/client/dom/elements/events.js b/packages/svelte/src/internal/client/dom/elements/events.js index f2038f96ad..591faaec9c 100644 --- a/packages/svelte/src/internal/client/dom/elements/events.js +++ b/packages/svelte/src/internal/client/dom/elements/events.js @@ -2,7 +2,7 @@ import { teardown } from '../../reactivity/effects.js'; import { define_property, is_array } from '../../../shared/utils.js'; import { hydrating } from '../hydration.js'; -import { queue_micro_task } from '../task.js'; +import { queue_after_micro_task } from '../task.js'; import { FILENAME } from '../../../../constants.js'; import * as w from '../../warnings.js'; import { @@ -77,7 +77,7 @@ export function create_event(event_name, dom, handler, options) { event_name.startsWith('touch') || event_name === 'wheel' ) { - queue_micro_task(() => { + queue_after_micro_task(() => { dom.addEventListener(event_name, target_handler, options); }); } else { diff --git a/packages/svelte/src/internal/client/dom/elements/misc.js b/packages/svelte/src/internal/client/dom/elements/misc.js index 61e513903f..0eefaf104c 100644 --- a/packages/svelte/src/internal/client/dom/elements/misc.js +++ b/packages/svelte/src/internal/client/dom/elements/misc.js @@ -1,6 +1,6 @@ import { hydrating } from '../hydration.js'; import { clear_text_content, get_first_child } from '../operations.js'; -import { queue_micro_task } from '../task.js'; +import { queue_after_micro_task } from '../task.js'; /** * @param {HTMLElement} dom @@ -12,7 +12,7 @@ export function autofocus(dom, value) { const body = document.body; dom.autofocus = true; - queue_micro_task(() => { + queue_after_micro_task(() => { if (document.activeElement === body) { dom.focus(); } diff --git a/packages/svelte/src/internal/client/dom/elements/transitions.js b/packages/svelte/src/internal/client/dom/elements/transitions.js index b3c16cdd08..9834cd05e6 100644 --- a/packages/svelte/src/internal/client/dom/elements/transitions.js +++ b/packages/svelte/src/internal/client/dom/elements/transitions.js @@ -13,7 +13,7 @@ import { should_intro } from '../../render.js'; import { current_each_item } from '../blocks/each.js'; import { TRANSITION_GLOBAL, TRANSITION_IN, TRANSITION_OUT } from '../../../../constants.js'; import { BLOCK_EFFECT, EFFECT_RAN, EFFECT_TRANSPARENT } from '../../constants.js'; -import { queue_micro_task } from '../task.js'; +import { queue_after_micro_task } from '../task.js'; /** * @param {Element} element @@ -326,7 +326,7 @@ function animate(element, options, counterpart, t2, on_finish) { var a; var aborted = false; - queue_micro_task(() => { + queue_after_micro_task(() => { if (aborted) return; var o = options({ direction: is_intro ? 'in' : 'out' }); a = animate(element, o, counterpart, t2, on_finish); diff --git a/packages/svelte/src/internal/client/dom/task.js b/packages/svelte/src/internal/client/dom/task.js index acb5a5b117..9f88086276 100644 --- a/packages/svelte/src/internal/client/dom/task.js +++ b/packages/svelte/src/internal/client/dom/task.js @@ -10,33 +10,59 @@ let is_micro_task_queued = false; let is_idle_task_queued = false; /** @type {Array<() => void>} */ -let current_queued_micro_tasks = []; +let queued_before_microtasks = []; /** @type {Array<() => void>} */ -let current_queued_idle_tasks = []; +let queued_after_microtasks = []; +/** @type {Array<() => void>} */ +let queued_idle_tasks = []; -function process_micro_tasks() { - is_micro_task_queued = false; - const tasks = current_queued_micro_tasks.slice(); - current_queued_micro_tasks = []; +export function flush_before_micro_tasks() { + const tasks = queued_before_microtasks.slice(); + queued_before_microtasks = []; + run_all(tasks); +} + +function flush_after_micro_tasks() { + const tasks = queued_after_microtasks.slice(); + queued_after_microtasks = []; run_all(tasks); } +function process_micro_tasks() { + if (is_micro_task_queued) { + is_micro_task_queued = false; + flush_before_micro_tasks(); + flush_after_micro_tasks(); + } +} + function process_idle_tasks() { is_idle_task_queued = false; - const tasks = current_queued_idle_tasks.slice(); - current_queued_idle_tasks = []; + const tasks = queued_idle_tasks.slice(); + queued_idle_tasks = []; run_all(tasks); } /** * @param {() => void} fn */ -export function queue_micro_task(fn) { +export function queue_before_micro_task(fn) { + if (!is_micro_task_queued) { + is_micro_task_queued = true; + queueMicrotask(process_micro_tasks); + } + queued_before_microtasks.push(fn); +} + +/** + * @param {() => void} fn + */ +export function queue_after_micro_task(fn) { if (!is_micro_task_queued) { is_micro_task_queued = true; queueMicrotask(process_micro_tasks); } - current_queued_micro_tasks.push(fn); + queued_after_microtasks.push(fn); } /** @@ -47,13 +73,13 @@ export function queue_idle_task(fn) { is_idle_task_queued = true; request_idle_callback(process_idle_tasks); } - current_queued_idle_tasks.push(fn); + queued_idle_tasks.push(fn); } /** * Synchronously run any queued tasks. */ -export function flush_tasks() { +export function flush_after_tasks() { if (is_micro_task_queued) { process_micro_tasks(); } diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index 55a8ccf32d..3f6a2e18e9 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -27,7 +27,7 @@ import { DISCONNECTED, BOUNDARY_EFFECT } from './constants.js'; -import { flush_tasks } from './dom/task.js'; +import { flush_after_tasks, flush_before_micro_tasks } from './dom/task.js'; import { add_owner } from './dev/ownership.js'; import { internal_set, set, source } from './reactivity/sources.js'; import { destroy_derived, execute_derived, update_derived } from './reactivity/deriveds.js'; @@ -737,11 +737,12 @@ function flush_queued_effects(effects) { } } -function process_deferred() { +function flushed_deferred() { is_micro_task_queued = false; if (flush_count > 1001) { return; } + // flush_before_process_microtasks(); const previous_queued_root_effects = queued_root_effects; queued_root_effects = []; flush_queued_root_effects(previous_queued_root_effects); @@ -763,7 +764,7 @@ export function schedule_effect(signal) { if (scheduler_mode === FLUSH_MICROTASK) { if (!is_micro_task_queued) { is_micro_task_queued = true; - queueMicrotask(process_deferred); + queueMicrotask(flushed_deferred); } } @@ -776,7 +777,7 @@ export function schedule_effect(signal) { var flags = effect.f; if ((flags & (ROOT_EFFECT | BRANCH_EFFECT)) !== 0) { - if ((flags & CLEAN) === 0) return + if ((flags & CLEAN) === 0) return; effect.f ^= CLEAN; } } @@ -878,11 +879,12 @@ export function flush_sync(fn) { queued_root_effects = root_effects; is_micro_task_queued = false; + flush_before_micro_tasks(); flush_queued_root_effects(previous_queued_root_effects); var result = fn?.(); - flush_tasks(); + flush_after_tasks(); if (queued_root_effects.length > 0 || root_effects.length > 0) { flush_sync(); } diff --git a/packages/svelte/tests/animation-helpers.js b/packages/svelte/tests/animation-helpers.js index dcbb062923..27fb04b46f 100644 --- a/packages/svelte/tests/animation-helpers.js +++ b/packages/svelte/tests/animation-helpers.js @@ -1,6 +1,6 @@ import { flushSync } from 'svelte'; import { raf as svelte_raf } from 'svelte/internal/client'; -import { queue_micro_task } from '../src/internal/client/dom/task.js'; +import { queue_after_micro_task } from '../src/internal/client/dom/task.js'; export const raf = { animations: new Set(), @@ -132,7 +132,7 @@ class Animation { /** @param {() => {}} fn */ set onfinish(fn) { if (this.#duration === 0) { - queue_micro_task(fn); + queue_after_micro_task(fn); } else { this.#onfinish = () => { fn();