summaryrefslogtreecommitdiff
path: root/node_modules/svelte/src/runtime/internal/scheduler.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/svelte/src/runtime/internal/scheduler.js')
-rw-r--r--node_modules/svelte/src/runtime/internal/scheduler.js135
1 files changed, 135 insertions, 0 deletions
diff --git a/node_modules/svelte/src/runtime/internal/scheduler.js b/node_modules/svelte/src/runtime/internal/scheduler.js
new file mode 100644
index 0000000..e62f536
--- /dev/null
+++ b/node_modules/svelte/src/runtime/internal/scheduler.js
@@ -0,0 +1,135 @@
+import { run_all } from './utils.js';
+import { current_component, set_current_component } from './lifecycle.js';
+
+export const dirty_components = [];
+export const intros = { enabled: false };
+export const binding_callbacks = [];
+
+let render_callbacks = [];
+
+const flush_callbacks = [];
+
+const resolved_promise = /* @__PURE__ */ Promise.resolve();
+
+let update_scheduled = false;
+
+/** @returns {void} */
+export function schedule_update() {
+ if (!update_scheduled) {
+ update_scheduled = true;
+ resolved_promise.then(flush);
+ }
+}
+
+/** @returns {Promise<void>} */
+export function tick() {
+ schedule_update();
+ return resolved_promise;
+}
+
+/** @returns {void} */
+export function add_render_callback(fn) {
+ render_callbacks.push(fn);
+}
+
+/** @returns {void} */
+export function add_flush_callback(fn) {
+ flush_callbacks.push(fn);
+}
+
+// flush() calls callbacks in this order:
+// 1. All beforeUpdate callbacks, in order: parents before children
+// 2. All bind:this callbacks, in reverse order: children before parents.
+// 3. All afterUpdate callbacks, in order: parents before children. EXCEPT
+// for afterUpdates called during the initial onMount, which are called in
+// reverse order: children before parents.
+// Since callbacks might update component values, which could trigger another
+// call to flush(), the following steps guard against this:
+// 1. During beforeUpdate, any updated components will be added to the
+// dirty_components array and will cause a reentrant call to flush(). Because
+// the flush index is kept outside the function, the reentrant call will pick
+// up where the earlier call left off and go through all dirty components. The
+// current_component value is saved and restored so that the reentrant call will
+// not interfere with the "parent" flush() call.
+// 2. bind:this callbacks cannot trigger new flush() calls.
+// 3. During afterUpdate, any updated components will NOT have their afterUpdate
+// callback called a second time; the seen_callbacks set, outside the flush()
+// function, guarantees this behavior.
+const seen_callbacks = new Set();
+
+let flushidx = 0; // Do *not* move this inside the flush() function
+
+/** @returns {void} */
+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;
+ do {
+ // first, call beforeUpdate functions
+ // and update components
+ try {
+ while (flushidx < dirty_components.length) {
+ const component = dirty_components[flushidx];
+ flushidx++;
+ 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);
+ dirty_components.length = 0;
+ flushidx = 0;
+ while (binding_callbacks.length) binding_callbacks.pop()();
+ // then, once components are updated, call
+ // afterUpdate functions. This may cause
+ // subsequent updates...
+ for (let i = 0; i < render_callbacks.length; i += 1) {
+ const callback = render_callbacks[i];
+ if (!seen_callbacks.has(callback)) {
+ // ...so guard against infinite loops
+ seen_callbacks.add(callback);
+ callback();
+ }
+ }
+ render_callbacks.length = 0;
+ } while (dirty_components.length);
+ while (flush_callbacks.length) {
+ flush_callbacks.pop()();
+ }
+ update_scheduled = false;
+ seen_callbacks.clear();
+ set_current_component(saved_component);
+}
+
+/** @returns {void} */
+function update($$) {
+ if ($$.fragment !== null) {
+ $$.update();
+ run_all($$.before_update);
+ const dirty = $$.dirty;
+ $$.dirty = [-1];
+ $$.fragment && $$.fragment.p($$.ctx, dirty);
+ $$.after_update.forEach(add_render_callback);
+ }
+}
+
+/**
+ * Useful for example to execute remaining `afterUpdate` callbacks before executing `destroy`.
+ * @param {Function[]} fns
+ * @returns {void}
+ */
+export function flush_render_callbacks(fns) {
+ const filtered = [];
+ const targets = [];
+ render_callbacks.forEach((c) => (fns.indexOf(c) === -1 ? filtered.push(c) : targets.push(c)));
+ targets.forEach((c) => c());
+ render_callbacks = filtered;
+}