Convert src/runtime/internal/scheduler.ts to JavaScript

pull/8569/head
S. Elliott Johnson 3 years ago
parent f04902918b
commit fb6a83acf9

@ -1,36 +1,32 @@
import { run_all } from './utils'; import { run_all } from './utils';
import { current_component, set_current_component } from './lifecycle'; import { current_component, set_current_component } from './lifecycle';
export const dirty_components = []; export const dirty_components = [];
export const intros = { enabled: false }; export const intros = { enabled: false };
export const binding_callbacks = []; export const binding_callbacks = [];
let render_callbacks = []; let render_callbacks = [];
const flush_callbacks = []; const flush_callbacks = [];
const resolved_promise = /* @__PURE__ */ Promise.resolve(); const resolved_promise = /* @__PURE__ */ Promise.resolve();
let update_scheduled = false; let update_scheduled = false;
/** @returns {void} */
export function schedule_update() { export function schedule_update() {
if (!update_scheduled) { if (!update_scheduled) {
update_scheduled = true; update_scheduled = true;
resolved_promise.then(flush); resolved_promise.then(flush);
} }
} }
/** @returns {Promise<void>} */
export function tick() { export function tick() {
schedule_update(); schedule_update();
return resolved_promise; return resolved_promise;
} }
/** @returns {void} */
export function add_render_callback(fn) { export function add_render_callback(fn) {
render_callbacks.push(fn); render_callbacks.push(fn);
} }
/** @returns {void} */
export function add_flush_callback(fn) { export function add_flush_callback(fn) {
flush_callbacks.push(fn); flush_callbacks.push(fn);
} }
// flush() calls callbacks in this order: // flush() calls callbacks in this order:
// 1. All beforeUpdate callbacks, in order: parents before children // 1. All beforeUpdate callbacks, in order: parents before children
// 2. All bind:this callbacks, in reverse order: children before parents. // 2. All bind:this callbacks, in reverse order: children before parents.
@ -51,85 +47,81 @@ export function add_flush_callback(fn) {
// function, guarantees this behavior. // function, guarantees this behavior.
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
/** @returns {void} */
export function flush() { export function flush() {
// Do not reenter flush while dirty components are updated, as this can // Do not reenter flush while dirty components are updated, as this can
// result in an infinite loop. Instead, let the inner flush handle it. // result in an infinite loop. Instead, let the inner flush handle it.
// Reentrancy is ok afterwards for bindings etc. // Reentrancy is ok afterwards for bindings etc.
if (flushidx !== 0) { if (flushidx !== 0) {
return; return;
} }
const saved_component = current_component;
const saved_component = current_component; do {
// first, call beforeUpdate functions
do { // and update components
// first, call beforeUpdate functions try {
// 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) {
} catch (e) { // reset dirty state to not end up in a deadlocked state and then rethrow
// reset dirty state to not end up in a deadlocked state and then rethrow dirty_components.length = 0;
dirty_components.length = 0; flushidx = 0;
flushidx = 0; throw e;
throw e; }
} set_current_component(null);
dirty_components.length = 0;
set_current_component(null); flushidx = 0;
while (binding_callbacks.length)
dirty_components.length = 0; binding_callbacks.pop()();
flushidx = 0; // then, once components are updated, call
// afterUpdate functions. This may cause
while (binding_callbacks.length) binding_callbacks.pop()(); // subsequent updates...
for (let i = 0; i < render_callbacks.length; i += 1) {
// then, once components are updated, call const callback = render_callbacks[i];
// afterUpdate functions. This may cause if (!seen_callbacks.has(callback)) {
// subsequent updates... // ...so guard against infinite loops
for (let i = 0; i < render_callbacks.length; i += 1) { seen_callbacks.add(callback);
const callback = render_callbacks[i]; callback();
}
if (!seen_callbacks.has(callback)) { }
// ...so guard against infinite loops render_callbacks.length = 0;
seen_callbacks.add(callback); } while (dirty_components.length);
while (flush_callbacks.length) {
callback(); flush_callbacks.pop()();
} }
} update_scheduled = false;
seen_callbacks.clear();
render_callbacks.length = 0; set_current_component(saved_component);
} 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($$) { function update($$) {
if ($$.fragment !== null) { if ($$.fragment !== null) {
$$.update(); $$.update();
run_all($$.before_update); run_all($$.before_update);
const dirty = $$.dirty; const dirty = $$.dirty;
$$.dirty = [-1]; $$.dirty = [-1];
$$.fragment && $$.fragment.p($$.ctx, dirty); $$.fragment && $$.fragment.p($$.ctx, dirty);
$$.after_update.forEach(add_render_callback);
$$.after_update.forEach(add_render_callback); }
}
} }
/** /**
* Useful for example to execute remaining `afterUpdate` callbacks before executing `destroy`. * Useful for example to execute remaining `afterUpdate` callbacks before executing `destroy`.
* @param {Function[]} fns
* @returns {void}
*/ */
export function flush_render_callbacks(fns: Function[]): void { export function flush_render_callbacks(fns) {
const filtered = []; const filtered = [];
const targets = []; const targets = [];
render_callbacks.forEach((c) => (fns.indexOf(c) === -1 ? filtered.push(c) : targets.push(c))); render_callbacks.forEach((c) => (fns.indexOf(c) === -1 ? filtered.push(c) : targets.push(c)));
targets.forEach((c) => c()); targets.forEach((c) => c());
render_callbacks = filtered; render_callbacks = filtered;
} }

Loading…
Cancel
Save