"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getActiveSub = getActiveSub; exports.setActiveSub = setActiveSub; exports.getBatchDepth = getBatchDepth; exports.startBatch = startBatch; exports.endBatch = endBatch; exports.isSignal = isSignal; exports.isComputed = isComputed; exports.isEffect = isEffect; exports.isEffectScope = isEffectScope; exports.signal = signal; exports.computed = computed; exports.effect = effect; exports.effectScope = effectScope; const system_js_1 = require("./system.cjs"); let cycle = 0; const queuedEffects = []; const { link, unlink, propagate, checkDirty, shallowPropagate, } = (0, system_js_1.createReactiveSystem)({ update(signal) { if ('getter' in signal) { return updateComputed(signal); } else { return updateSignal(signal, signal.value); } }, notify, unwatched(node) { if ('getter' in node) { let toRemove = node.deps; if (toRemove !== undefined) { node.flags = 17; do { toRemove = unlink(toRemove, node); } while (toRemove !== undefined); } } else if ('fn' in node) { effectOper.call(node); } else if (!('previousValue' in node)) { effectScopeOper.call(node); } }, }); let batchDepth = 0; let notifyIndex = 0; let queuedEffectsLength = 0; let activeSub; function getActiveSub() { return activeSub; } function setActiveSub(sub) { const prevSub = activeSub; activeSub = sub; return prevSub; } function getBatchDepth() { return batchDepth; } function startBatch() { ++batchDepth; } function endBatch() { if (!--batchDepth) { flush(); } } function isSignal(fn) { return fn.name === 'bound signalOper'; } function isComputed(fn) { return fn.name === 'bound computedOper'; } function isEffect(fn) { return fn.name === 'bound effectOper'; } function isEffectScope(fn) { return fn.name === 'bound effectScopeOper'; } function signal(initialValue) { return signalOper.bind({ previousValue: initialValue, value: initialValue, subs: undefined, subsTail: undefined, flags: 1, }); } function computed(getter) { return computedOper.bind({ value: undefined, subs: undefined, subsTail: undefined, deps: undefined, depsTail: undefined, flags: 0, getter: getter, }); } function effect(fn) { const e = { fn, subs: undefined, subsTail: undefined, deps: undefined, depsTail: undefined, flags: 2, }; const prevSub = setActiveSub(e); if (prevSub !== undefined) { link(e, prevSub, 0); } try { e.fn(); } finally { activeSub = prevSub; } return effectOper.bind(e); } function effectScope(fn) { const e = { deps: undefined, depsTail: undefined, subs: undefined, subsTail: undefined, flags: 0, }; const prevSub = setActiveSub(e); if (prevSub !== undefined) { link(e, prevSub, 0); } try { fn(); } finally { activeSub = prevSub; } return effectScopeOper.bind(e); } function updateComputed(c) { ++cycle; c.depsTail = undefined; c.flags = 5; const prevSub = setActiveSub(c); try { const oldValue = c.value; return oldValue !== (c.value = c.getter(oldValue)); } finally { activeSub = prevSub; c.flags &= ~4; purgeDeps(c); } } function updateSignal(s, value) { s.flags = 1; return s.previousValue !== (s.previousValue = value); } function notify(e) { const flags = e.flags; if (!(flags & 64)) { e.flags = flags | 64; const subs = e.subs; if (subs !== undefined) { notify(subs.sub); } else { queuedEffects[queuedEffectsLength++] = e; } } } function run(e, flags) { if (flags & 16 || (flags & 32 && (checkDirty(e.deps, e) || (e.flags = flags & ~32, false)))) { ++cycle; e.depsTail = undefined; e.flags = 6; const prevSub = setActiveSub(e); try { e.fn(); } finally { activeSub = prevSub; e.flags &= ~4; purgeDeps(e); } } else { let link = e.deps; while (link !== undefined) { const dep = link.dep; const depFlags = dep.flags; if (depFlags & 64) { run(dep, dep.flags = depFlags & ~(64)); } link = link.nextDep; } } } function flush() { while (notifyIndex < queuedEffectsLength) { const effect = queuedEffects[notifyIndex]; queuedEffects[notifyIndex++] = undefined; run(effect, effect.flags &= ~(64)); } notifyIndex = 0; queuedEffectsLength = 0; } function computedOper() { const flags = this.flags; if (flags & 16 || (flags & 32 && (checkDirty(this.deps, this) || (this.flags = flags & ~32, false)))) { if (updateComputed(this)) { const subs = this.subs; if (subs !== undefined) { shallowPropagate(subs); } } } else if (!flags) { this.flags = 1; const prevSub = setActiveSub(this); try { this.value = this.getter(); } finally { activeSub = prevSub; } } const sub = activeSub; if (sub !== undefined) { link(this, sub, cycle); } return this.value; } function signalOper(...value) { if (value.length) { if (this.value !== (this.value = value[0])) { this.flags = 17; const subs = this.subs; if (subs !== undefined) { propagate(subs); if (!batchDepth) { flush(); } } } } else { const value = this.value; if (this.flags & 16) { if (updateSignal(this, value)) { const subs = this.subs; if (subs !== undefined) { shallowPropagate(subs); } } } let sub = activeSub; while (sub !== undefined) { if (sub.flags & 3) { link(this, sub, cycle); break; } sub = sub.subs?.sub; } return value; } } function effectOper() { effectScopeOper.call(this); this.flags = 0; } function effectScopeOper() { let dep = this.deps; while (dep !== undefined) { dep = unlink(dep, this); } const sub = this.subs; if (sub !== undefined) { unlink(sub); } } function purgeDeps(sub) { const depsTail = sub.depsTail; let toRemove = depsTail !== undefined ? depsTail.nextDep : sub.deps; while (toRemove !== undefined) { toRemove = unlink(toRemove, sub); } }