UNPKG

agera

Version:

A small push-pull based signal library based on alien-signals algorithm.

547 lines (494 loc) 12.8 kB
function maybeDestroyEffect(dep) { if ("g" in dep && dep.g !== void 0) { dep.g(); dep.g = void 0; } } function clearTracking(link) { do { const dep = link.k; const nextDep = link.o; const nextSub = link.n; const prevSub = link.m; if (nextSub !== void 0) nextSub.m = prevSub; else dep.b = prevSub; if (prevSub !== void 0) prevSub.n = nextSub; else { dep.a = nextSub; if (nextSub === void 0) if ("j" in dep) dep.j(false); else maybeDestroyEffect(dep); } if (dep.a === void 0 && "d" in dep) { const depFlags = dep.c; if (!(depFlags & 128)) dep.c = depFlags | 128; const depDeps = dep.d; if (depDeps !== void 0) { link = depDeps; dep.e.o = nextDep; dep.d = void 0; dep.e = void 0; continue; } } link = nextDep; } while (link !== void 0); } function startTracking(sub) { sub.e = void 0; sub.c = sub.c & -993 | 16; } function endTracking(sub) { const depsTail = sub.e; if (depsTail !== void 0) { const nextDep = depsTail.o; if (nextDep !== void 0) { clearTracking(nextDep); depsTail.o = void 0; } } else if (sub.d !== void 0) { clearTracking(sub.d); sub.d = void 0; } sub.c &= -17; notifyActivateListeners(); } function runLazyEffects(link) { do { const dep = link.k; const nextDep = link.o; if (dep.c & 8) { dep.c &= -9; if (dep.c & 4) { if (dep.d !== void 0) runLazyEffects(dep.d); } else runEffect(dep, true); } link = nextDep; } while (link !== void 0); } const pauseStack = []; let activeSub; let queuedEffects; let queuedEffectsTail; function updateComputed(computed) { const prevSub = activeSub; activeSub = computed; startTracking(computed); try { const oldValue = computed.i; const newValue = computed.h(oldValue); if (oldValue !== newValue) { computed.i = newValue; return true; } return false; } finally { activeSub = prevSub; endTracking(computed); } } function shallowPropagate(link) { do { const sub = link.l; const subFlags = sub.c; if ((subFlags & 384) == 256) { sub.c = 160 | subFlags; if ((subFlags & 34) == 2) { if (queuedEffectsTail !== void 0) queuedEffectsTail.e.o = sub.d; else queuedEffects = sub; queuedEffectsTail = sub; } } link = link.n; } while (link !== void 0); } function propagate(link) { let targetFlag = 128; let subs = link; let stack = 0; top: do { const sub = link.l; const subFlags = sub.c; if (!(subFlags & 976) && (sub.c = subFlags | targetFlag | 32, true) || subFlags & 64 && !(subFlags & 16) && (sub.c = subFlags & -65 | targetFlag | 32, true) || !(subFlags & 896) && isValidLink(link, sub) && (sub.c = subFlags | 64 | targetFlag | 32, sub.a !== void 0)) { const subSubs = sub.a; if (subSubs !== void 0) { if (subSubs.n !== void 0) { subSubs.m = subs; link = subs = subSubs; targetFlag = 256; ++stack; } else { link = subSubs; targetFlag = subFlags & 2 ? 512 : 256; } continue; } if (subFlags & 2) { if (queuedEffectsTail !== void 0) queuedEffectsTail.e.o = sub.d; else queuedEffects = sub; queuedEffectsTail = sub; } } else if (!(subFlags & (16 | targetFlag))) { sub.c = subFlags | targetFlag | 32; if ((subFlags & 34) == 2) { if (queuedEffectsTail !== void 0) queuedEffectsTail.e.o = sub.d; else queuedEffects = sub; queuedEffectsTail = sub; } } else if (!(subFlags & targetFlag) && subFlags & 896 && isValidLink(link, sub)) sub.c = subFlags | targetFlag; if ((link = subs.n) !== void 0) { subs = link; targetFlag = stack ? 256 : 128; continue; } while (stack) { --stack; const depSubs = subs.k.a; subs = depSubs.m; depSubs.m = void 0; if ((link = subs.n) !== void 0) { subs = link; targetFlag = stack ? 256 : 128; continue top; } } break; } while (true); } function checkDirty(link) { let stack = 0; let dirty; top: do { dirty = false; const dep = link.k; if ("c" in dep) { const depFlags = dep.c; if (!(129 & ~depFlags)) { if (updateComputed(dep)) { const subs = dep.a; if (subs.n !== void 0) shallowPropagate(subs); dirty = true; } } else if (!(257 & ~depFlags)) { const depSubs = dep.a; if (depSubs.n !== void 0) depSubs.m = link; link = dep.d; ++stack; continue; } } if (!dirty && link.o !== void 0) { link = link.o; continue; } if (stack) { let sub = link.l; do { --stack; const subSubs = sub.a; if (dirty) { if (updateComputed(sub)) { if ((link = subSubs.m) !== void 0) { subSubs.m = void 0; shallowPropagate(subSubs); sub = link.l; } else sub = subSubs.l; continue; } } else sub.c &= -257; if ((link = subSubs.m) !== void 0) { subSubs.m = void 0; if (link.o !== void 0) { link = link.o; continue top; } sub = link.l; } else { if ((link = subSubs.o) !== void 0) continue top; sub = subSubs.l; } dirty = false; } while (stack); } return dirty; } while (true); } function updateDirtyFlag(sub, flags) { if (checkDirty(sub.d)) { sub.c = flags | 128; return true; } sub.c = flags & -257; return false; } function processComputedUpdate(computed, flags) { if (flags & 128 || (checkDirty(computed.d) ? true : (computed.c = flags & -257, false))) if (updateComputed(computed)) { const subs = computed.a; if (subs !== void 0) shallowPropagate(subs); } } function processPendingInnerEffects(sub, flags) { if (flags & 512) { sub.c = flags & -513; let link = sub.d; do { const dep = link.k; if ("c" in dep && dep.c & 2 && dep.c & 896) notifyEffect(dep); link = link.o; } while (link !== void 0); } } function runEffect(e, warmup) { const prevSub = activeSub; activeSub = e; startTracking(e); try { if (e.g !== void 0) e.g(); e.g = e.f(warmup); } finally { activeSub = prevSub; endTracking(e); } } function runEffectScope(e, fn) { const prevSub = activeSub; activeSub = e; try { fn(); } finally { activeSub = prevSub; } } function notifyEffect(e) { if (e.c & 4) return notifyEffectScope(e); return notifyEffectSub(e); } function notifyEffectSub(e) { const flags = e.c; if (flags & 128 || flags & 256 && updateDirtyFlag(e, flags)) runEffect(e); else processPendingInnerEffects(e, e.c); return true; } function notifyEffectScope(e) { if (e.c & 512) { processPendingInnerEffects(e, e.c); return true; } return false; } function processEffectNotifications() { while (queuedEffects !== void 0) { const effect = queuedEffects; const depsTail = effect.e; const queuedNext = depsTail?.o; if (queuedNext !== void 0) { depsTail.o = void 0; queuedEffects = queuedNext.l; } else { queuedEffects = void 0; queuedEffectsTail = void 0; } if (!notifyEffect(effect)) effect.c &= -33; } } function pauseTracking() { pauseStack.push(activeSub); activeSub = void 0; } function resumeTracking() { activeSub = pauseStack.pop(); } let activateListeners; let activateListenersTail; function queueActivateListener(onActivate) { const listener = { j: onActivate, n: void 0 }; if (activateListenersTail === void 0) activateListeners = listener; else activateListenersTail.n = listener; activateListenersTail = listener; } function notifyActivateListeners() { if (activateListeners !== void 0 && (activeSub === void 0 || activeSub.c & 4 && !(activeSub.c & 8))) { let listener = activateListeners; activateListeners = void 0; activateListenersTail = void 0; do { listener.j(true); listener = listener.n; } while (listener !== void 0); } } function linkNewDep(dep, sub, nextDep, depsTail) { const newLink = { k: dep, l: sub, o: nextDep, m: void 0, n: void 0 }; if (depsTail === void 0) sub.d = newLink; else depsTail.o = newLink; if (dep.a === void 0) { dep.a = newLink; if ("j" in dep) queueActivateListener(dep.j); } else { const oldTail = dep.b; newLink.m = oldTail; oldTail.n = newLink; } sub.e = newLink; dep.b = newLink; return newLink; } function isValidLink(checkLink, sub) { const depsTail = sub.e; if (depsTail !== void 0) { let link2 = sub.d; do { if (link2 === checkLink) return true; if (link2 === depsTail) break; link2 = link2.o; } while (link2 !== void 0); } return false; } function link(dep, sub) { const currentDep = sub.e; if (currentDep !== void 0 && currentDep.k === dep) return; const nextDep = currentDep !== void 0 ? currentDep.o : sub.d; if (nextDep !== void 0 && nextDep.k === dep) { sub.e = nextDep; return; } const depLastSub = dep.b; if (depLastSub !== void 0 && depLastSub.l === sub && isValidLink(depLastSub, sub)) return; return linkNewDep(dep, sub, nextDep, currentDep); } function effectStop() { startTracking(this); maybeDestroyEffect(this); endTracking(this); } function lazyEffectsRun() { this.c &= -9; notifyActivateListeners(); if (this.d !== void 0) runLazyEffects(this.d); return effectStop.bind(this); } function effect(fn, ignoreLazy = false) { const e = { f: fn, a: void 0, b: void 0, d: void 0, e: void 0, c: 2, g: void 0 }; if (activeSub !== void 0) { link(e, activeSub); if (!ignoreLazy && activeSub.c & 8) { e.c |= 8; return effectStop.bind(e); } } runEffect(e, true); return effectStop.bind(e); } function createEffectScopeInstance() { return { a: void 0, b: void 0, d: void 0, e: void 0, c: 6 }; } function runEffectScopeInstance(e, fn, lazy = false) { if (!lazy && activeSub !== void 0) link(e, activeSub); if (lazy || activeSub !== void 0 && activeSub.c & 8) e.c |= 8; runEffectScope(e, fn); if (lazy) return lazyEffectsRun.bind(e); return effectStop.bind(e); } function effectScope(fn, lazy) { return runEffectScopeInstance(createEffectScopeInstance(), fn, lazy); } function createEffectScope() { return runEffectScopeInstance.bind(null, createEffectScopeInstance()); } function onActivate($signal, listener) { const $active = $signal.s.j ||= signal(false); return effect((warmup => { const active = $active(); if (!warmup) listener(active); }), true); } let batchDepth = 0; function startBatch() { ++batchDepth; } function endBatch() { if (! --batchDepth) processEffectNotifications(); } function createSignal(constructor, instance, ctx = instance) { const $signal = constructor.bind(ctx); $signal.s = instance; return $signal; } function signal(value) { return createSignal(signalGetterSetter, { i: value, a: void 0, b: void 0 }); } function signalGetterSetter(...value) { if (value.length) { if (this.i !== (this.i = value[0])) { const subs = this.a; if (subs !== void 0) { propagate(subs); if (!batchDepth) processEffectNotifications(); } } } else { if (activeSub !== void 0 && !(activeSub.c & 4)) link(this, activeSub); return this.i; } } function computed(compute) { return createSignal(computedGetter, { i: void 0, a: void 0, b: void 0, d: void 0, e: void 0, c: 129, h: compute }); } function computedGetter() { const flags = this.c; if (flags & 384) processComputedUpdate(this, flags); if (activeSub !== void 0 && !(activeSub.c & 4)) link(this, activeSub); return this.i; } function morph($signal, context) { return createSignal(morphGetterSetter, $signal.s, { r: $signal, q: $signal, p: $signal, ...context }); } function morphGetterSetter(...value) { if (value.length) this.q(value[0]); else return this.p(); } function update($signal, fn) { $signal(fn($signal.s.i)); return $signal; } function isSignal(value) { return typeof value == "function" && "s" in value; } function isFunctionNotSignal(value) { return typeof value == "function" && !("s" in value); } export { computed, createEffectScope, effect, effectScope, endBatch, isFunctionNotSignal, isSignal, morph, onActivate, pauseTracking, resumeTracking, signal, startBatch, update }; //# sourceMappingURL=index.js.map