@maverick-js/signals
Advanced tools
| // src/symbols.ts | ||
| var SCOPE = Symbol("SCOPE" ); | ||
| // src/core.ts | ||
| var scheduledEffects = false; | ||
| var runningEffects = false; | ||
| var currentScope = null; | ||
| var currentObserver = null; | ||
| var currentObservers = null; | ||
| var currentObserversIndex = 0; | ||
| var effects = []; | ||
| var NOOP = () => { | ||
| }; | ||
| var HANDLERS = Symbol("ERROR_HANDLERS" ); | ||
| var STATE_CLEAN = 0; | ||
| var STATE_CHECK = 1; | ||
| var STATE_DIRTY = 2; | ||
| var STATE_DISPOSED = 3; | ||
| function flushEffects() { | ||
| scheduledEffects = true; | ||
| queueMicrotask(runEffects); | ||
| } | ||
| function runEffects() { | ||
| if (!effects.length) { | ||
| scheduledEffects = false; | ||
| return; | ||
| } | ||
| runningEffects = true; | ||
| for (let i = 0; i < effects.length; i++) { | ||
| if (!isZombie(effects[i])) | ||
| read.call(effects[i]); | ||
| } | ||
| effects = []; | ||
| scheduledEffects = false; | ||
| runningEffects = false; | ||
| } | ||
| function root(init) { | ||
| const scope = createScope(); | ||
| return compute(scope, !init.length ? init : init.bind(null, dispose.bind(scope)), null); | ||
| } | ||
| function peek(compute2) { | ||
| const prev = currentObserver; | ||
| currentObserver = null; | ||
| const result = compute2(); | ||
| currentObserver = prev; | ||
| return result; | ||
| } | ||
| function untrack(compute2) { | ||
| const prev = currentScope; | ||
| currentScope = null; | ||
| const result = peek(compute2); | ||
| currentScope = prev; | ||
| return result; | ||
| } | ||
| function tick() { | ||
| if (!runningEffects) | ||
| runEffects(); | ||
| } | ||
| function getScope() { | ||
| return currentScope; | ||
| } | ||
| function scoped(run, scope) { | ||
| try { | ||
| compute(scope, run, null); | ||
| } catch (error) { | ||
| handleError(scope, error); | ||
| } | ||
| } | ||
| function getContext(key) { | ||
| return lookup(currentScope, key); | ||
| } | ||
| function setContext(key, value) { | ||
| if (currentScope) | ||
| (currentScope._context ??= {})[key] = value; | ||
| } | ||
| function onError(handler) { | ||
| if (!currentScope) | ||
| return; | ||
| const context = currentScope._context ??= {}; | ||
| if (!context[HANDLERS]) | ||
| context[HANDLERS] = [handler]; | ||
| else | ||
| context[HANDLERS].push(handler); | ||
| } | ||
| function onDispose(disposable) { | ||
| if (!disposable || !currentScope) | ||
| return disposable || NOOP; | ||
| const node = currentScope; | ||
| if (!node._disposal) { | ||
| node._disposal = disposable; | ||
| } else if (Array.isArray(node._disposal)) { | ||
| node._disposal.push(disposable); | ||
| } else { | ||
| node._disposal = [node._disposal, disposable]; | ||
| } | ||
| return function removeDispose() { | ||
| if (node._state === STATE_DISPOSED) | ||
| return; | ||
| disposable.call(null); | ||
| if (isFunction(node._disposal)) { | ||
| node._disposal = null; | ||
| } else if (Array.isArray(node._disposal)) { | ||
| node._disposal.splice(node._disposal.indexOf(disposable), 1); | ||
| } | ||
| }; | ||
| } | ||
| var scopes = []; | ||
| function dispose(self = true) { | ||
| if (this._state === STATE_DISPOSED) | ||
| return; | ||
| let current = self ? this : this._nextSibling, head = self ? this._prevSibling : this; | ||
| if (current) { | ||
| scopes.push(this); | ||
| do { | ||
| if (current._disposal) | ||
| emptyDisposal(current); | ||
| if (current._sources) | ||
| removeSourceObservers(current, 0); | ||
| current[SCOPE] = null; | ||
| current._sources = null; | ||
| current._observers = null; | ||
| current._prevSibling = null; | ||
| current._context = null; | ||
| current._state = STATE_DISPOSED; | ||
| scopes.push(current); | ||
| current = current._nextSibling; | ||
| if (current) | ||
| current._prevSibling._nextSibling = null; | ||
| } while (current && scopes.includes(current[SCOPE])); | ||
| } | ||
| if (head) | ||
| head._nextSibling = current; | ||
| if (current) | ||
| current._prevSibling = head; | ||
| scopes = []; | ||
| } | ||
| function emptyDisposal(scope) { | ||
| try { | ||
| if (Array.isArray(scope._disposal)) { | ||
| for (let i = 0; i < scope._disposal.length; i++) { | ||
| const callable = scope._disposal[i]; | ||
| callable.call(callable); | ||
| } | ||
| } else { | ||
| scope._disposal.call(scope._disposal); | ||
| } | ||
| scope._disposal = null; | ||
| } catch (error) { | ||
| handleError(scope, error); | ||
| } | ||
| } | ||
| function compute(scope, compute2, observer) { | ||
| const prevScope = currentScope, prevObserver = currentObserver; | ||
| currentScope = scope; | ||
| currentObserver = observer; | ||
| try { | ||
| return compute2.call(scope); | ||
| } finally { | ||
| currentScope = prevScope; | ||
| currentObserver = prevObserver; | ||
| } | ||
| } | ||
| function lookup(scope, key) { | ||
| if (!scope) | ||
| return; | ||
| let current = scope, value; | ||
| while (current) { | ||
| value = current._context?.[key]; | ||
| if (value !== void 0) | ||
| return value; | ||
| current = current[SCOPE]; | ||
| } | ||
| } | ||
| function handleError(scope, error, depth) { | ||
| const handlers = lookup(scope, HANDLERS); | ||
| if (!handlers) | ||
| throw error; | ||
| try { | ||
| const coercedError = error instanceof Error ? error : Error(JSON.stringify(error)); | ||
| for (const handler of handlers) | ||
| handler(coercedError); | ||
| } catch (error2) { | ||
| handleError(scope[SCOPE], error2); | ||
| } | ||
| } | ||
| function read() { | ||
| if (this._state === STATE_DISPOSED) | ||
| return this._value; | ||
| if (currentObserver) { | ||
| if (!currentObservers && currentObserver._sources && currentObserver._sources[currentObserversIndex] == this) { | ||
| currentObserversIndex++; | ||
| } else if (!currentObservers) | ||
| currentObservers = [this]; | ||
| else | ||
| currentObservers.push(this); | ||
| } | ||
| if (this._compute) | ||
| shouldUpdate(this); | ||
| return this._value; | ||
| } | ||
| function write(newValue) { | ||
| const value = isFunction(newValue) ? newValue(this._value) : newValue; | ||
| if (this._changed(this._value, value)) { | ||
| this._value = value; | ||
| if (this._observers) { | ||
| for (let i = 0; i < this._observers.length; i++) { | ||
| notify(this._observers[i], STATE_DIRTY); | ||
| } | ||
| } | ||
| } | ||
| return this._value; | ||
| } | ||
| var ScopeNode = function Scope() { | ||
| this[SCOPE] = currentScope; | ||
| this._state = STATE_CLEAN; | ||
| this._nextSibling = null; | ||
| this._prevSibling = currentScope; | ||
| if (currentScope) | ||
| currentScope.append(this); | ||
| }; | ||
| var ScopeProto = ScopeNode.prototype; | ||
| ScopeProto._context = null; | ||
| ScopeProto._compute = null; | ||
| ScopeProto._disposal = null; | ||
| ScopeProto.append = function appendScope(scope) { | ||
| if (this._nextSibling) | ||
| this._nextSibling._prevSibling = scope; | ||
| scope._nextSibling = this._nextSibling; | ||
| this._nextSibling = scope; | ||
| }; | ||
| function createScope() { | ||
| return new ScopeNode(); | ||
| } | ||
| var ComputeNode = function Computation(initialValue, compute2, options) { | ||
| ScopeNode.call(this); | ||
| this._state = compute2 ? STATE_DIRTY : STATE_CLEAN; | ||
| this._scoped = false; | ||
| this._init = false; | ||
| this._sources = null; | ||
| this._observers = null; | ||
| this._value = initialValue; | ||
| this.id = options?.id ?? (this._compute ? "computed" : "signal"); | ||
| if (compute2) | ||
| this._compute = compute2; | ||
| if (options) { | ||
| if (options.scoped) | ||
| this._scoped = true; | ||
| if (options.dirty) | ||
| this._changed = options.dirty; | ||
| } | ||
| }; | ||
| var ComputeProto = ComputeNode.prototype; | ||
| Object.setPrototypeOf(ComputeProto, ScopeProto); | ||
| ComputeProto._changed = isNotEqual; | ||
| ComputeProto.call = read; | ||
| function createComputation(initialValue, compute2, options) { | ||
| return new ComputeNode(initialValue, compute2, options); | ||
| } | ||
| function isNotEqual(a, b) { | ||
| return a !== b; | ||
| } | ||
| function isFunction(value) { | ||
| return typeof value === "function"; | ||
| } | ||
| function isZombie(node) { | ||
| let scope = node[SCOPE]; | ||
| while (scope) { | ||
| if (scope._compute && scope._state === STATE_DIRTY) | ||
| return true; | ||
| scope = scope[SCOPE]; | ||
| } | ||
| return false; | ||
| } | ||
| function shouldUpdate(node) { | ||
| if (node._state === STATE_CHECK) { | ||
| for (let i = 0; i < node._sources.length; i++) { | ||
| shouldUpdate(node._sources[i]); | ||
| if (node._state === STATE_DIRTY) { | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| if (node._state === STATE_DIRTY) | ||
| update(node); | ||
| else | ||
| node._state = STATE_CLEAN; | ||
| } | ||
| function update(node) { | ||
| let prevObservers = currentObservers, prevObserversIndex = currentObserversIndex; | ||
| currentObservers = null; | ||
| currentObserversIndex = 0; | ||
| try { | ||
| if (node._scoped) { | ||
| if (node._nextSibling && node._nextSibling[SCOPE] === node) | ||
| dispose.call(node, false); | ||
| if (node._disposal) | ||
| emptyDisposal(node); | ||
| if (node._context && node._context[HANDLERS]) | ||
| node._context[HANDLERS] = []; | ||
| } | ||
| const result = compute(node._scoped ? node : currentScope, node._compute, node); | ||
| if (currentObservers) { | ||
| if (node._sources) | ||
| removeSourceObservers(node, currentObserversIndex); | ||
| if (node._sources && currentObserversIndex > 0) { | ||
| node._sources.length = currentObserversIndex + currentObservers.length; | ||
| for (let i = 0; i < currentObservers.length; i++) { | ||
| node._sources[currentObserversIndex + i] = currentObservers[i]; | ||
| } | ||
| } else { | ||
| node._sources = currentObservers; | ||
| } | ||
| let source; | ||
| for (let i = currentObserversIndex; i < node._sources.length; i++) { | ||
| source = node._sources[i]; | ||
| if (!source._observers) | ||
| source._observers = [node]; | ||
| else | ||
| source._observers.push(node); | ||
| } | ||
| } else if (node._sources && currentObserversIndex < node._sources.length) { | ||
| removeSourceObservers(node, currentObserversIndex); | ||
| node._sources.length = currentObserversIndex; | ||
| } | ||
| if (!node._scoped && node._init) { | ||
| write.call(node, result); | ||
| } else { | ||
| node._value = result; | ||
| node._init = true; | ||
| } | ||
| } catch (error) { | ||
| if (!node._init && typeof node._value === "undefined") { | ||
| console.error( | ||
| `computed \`${node.id}\` threw error during first run, this can be fatal. | ||
| Solutions: | ||
| 1. Set the \`initial\` option to silence this error`, | ||
| "\n2. Or, use an `effect` if the return value is not being used", | ||
| "\n\n", | ||
| error | ||
| ); | ||
| } | ||
| handleError(node, error); | ||
| return; | ||
| } | ||
| currentObservers = prevObservers; | ||
| currentObserversIndex = prevObserversIndex; | ||
| node._state = STATE_CLEAN; | ||
| } | ||
| function notify(node, state) { | ||
| if (node._state >= state) | ||
| return; | ||
| if (node._scoped && node._state === STATE_CLEAN) { | ||
| effects.push(node); | ||
| if (!scheduledEffects) | ||
| flushEffects(); | ||
| } | ||
| node._state = state; | ||
| if (node._observers) { | ||
| for (let i = 0; i < node._observers.length; i++) { | ||
| notify(node._observers[i], STATE_CHECK); | ||
| } | ||
| } | ||
| } | ||
| function removeSourceObservers(node, index) { | ||
| let source, swap; | ||
| for (let i = index; i < node._sources.length; i++) { | ||
| source = node._sources[i]; | ||
| if (source._observers) { | ||
| swap = source._observers.indexOf(node); | ||
| source._observers[swap] = source._observers[source._observers.length - 1]; | ||
| source._observers.pop(); | ||
| } | ||
| } | ||
| } | ||
| // src/signals.ts | ||
| function signal(initialValue, options) { | ||
| const node = createComputation(initialValue, null, options), signal2 = read.bind(node); | ||
| signal2.node = node; | ||
| signal2.set = write.bind(node); | ||
| return signal2; | ||
| } | ||
| function isReadSignal(fn) { | ||
| return isFunction(fn); | ||
| } | ||
| function computed(compute2, options) { | ||
| { | ||
| const node = createComputation( | ||
| options?.initial, | ||
| compute2, | ||
| options | ||
| ); | ||
| const signal2 = read.bind(node); | ||
| signal2.node = node; | ||
| return signal2; | ||
| } | ||
| } | ||
| function effect(effect2, options) { | ||
| const signal2 = createComputation( | ||
| null, | ||
| function runEffect() { | ||
| let effectResult = effect2(); | ||
| isFunction(effectResult) && onDispose(effectResult); | ||
| return null; | ||
| }, | ||
| { id: options?.id ?? "effect" } | ||
| ); | ||
| signal2._scoped = true; | ||
| read.call(signal2); | ||
| { | ||
| return function stopEffect() { | ||
| dispose.call(signal2, true); | ||
| }; | ||
| } | ||
| } | ||
| function readonly(signal2) { | ||
| { | ||
| const readonly2 = () => signal2(); | ||
| readonly2.node = signal2.node; | ||
| return readonly2; | ||
| } | ||
| } | ||
| function isWriteSignal(fn) { | ||
| return isReadSignal(fn) && "set" in fn; | ||
| } | ||
| export { SCOPE, compute, computed, createComputation, createScope, dispose, effect, getContext, getScope, isFunction, isNotEqual, isReadSignal, isWriteSignal, onDispose, onError, peek, read, readonly, root, scoped, setContext, signal, tick, untrack, write }; |
| // src/symbols.ts | ||
| var SCOPE = Symbol(0); | ||
| // src/core.ts | ||
| var scheduledEffects = false; | ||
| var runningEffects = false; | ||
| var currentScope = null; | ||
| var currentObserver = null; | ||
| var currentObservers = null; | ||
| var currentObserversIndex = 0; | ||
| var effects = []; | ||
| var NOOP = () => { | ||
| }; | ||
| var HANDLERS = Symbol(0); | ||
| var STATE_CLEAN = 0; | ||
| var STATE_CHECK = 1; | ||
| var STATE_DIRTY = 2; | ||
| var STATE_DISPOSED = 3; | ||
| function flushEffects() { | ||
| scheduledEffects = true; | ||
| queueMicrotask(runEffects); | ||
| } | ||
| function runEffects() { | ||
| if (!effects.length) { | ||
| scheduledEffects = false; | ||
| return; | ||
| } | ||
| runningEffects = true; | ||
| for (let i = 0; i < effects.length; i++) { | ||
| if (!isZombie(effects[i])) | ||
| read.call(effects[i]); | ||
| } | ||
| effects = []; | ||
| scheduledEffects = false; | ||
| runningEffects = false; | ||
| } | ||
| function root(init) { | ||
| const scope = createScope(); | ||
| return compute(scope, !init.length ? init : init.bind(null, dispose.bind(scope)), null); | ||
| } | ||
| function peek(compute2) { | ||
| const prev = currentObserver; | ||
| currentObserver = null; | ||
| const result = compute2(); | ||
| currentObserver = prev; | ||
| return result; | ||
| } | ||
| function untrack(compute2) { | ||
| const prev = currentScope; | ||
| currentScope = null; | ||
| const result = peek(compute2); | ||
| currentScope = prev; | ||
| return result; | ||
| } | ||
| function tick() { | ||
| if (!runningEffects) | ||
| runEffects(); | ||
| } | ||
| function getScope() { | ||
| return currentScope; | ||
| } | ||
| function scoped(run, scope) { | ||
| try { | ||
| compute(scope, run, null); | ||
| } catch (error) { | ||
| handleError(scope, error); | ||
| } | ||
| } | ||
| function getContext(key) { | ||
| return lookup(currentScope, key); | ||
| } | ||
| function setContext(key, value) { | ||
| if (currentScope) | ||
| (currentScope.k ??= {})[key] = value; | ||
| } | ||
| function onError(handler) { | ||
| if (!currentScope) | ||
| return; | ||
| const context = currentScope.k ??= {}; | ||
| if (!context[HANDLERS]) | ||
| context[HANDLERS] = [handler]; | ||
| else | ||
| context[HANDLERS].push(handler); | ||
| } | ||
| function onDispose(disposable) { | ||
| if (!disposable || !currentScope) | ||
| return disposable || NOOP; | ||
| const node = currentScope; | ||
| if (!node.a) { | ||
| node.a = disposable; | ||
| } else if (Array.isArray(node.a)) { | ||
| node.a.push(disposable); | ||
| } else { | ||
| node.a = [node.a, disposable]; | ||
| } | ||
| return function removeDispose() { | ||
| if (node.f === STATE_DISPOSED) | ||
| return; | ||
| disposable.call(null); | ||
| if (isFunction(node.a)) { | ||
| node.a = null; | ||
| } else if (Array.isArray(node.a)) { | ||
| node.a.splice(node.a.indexOf(disposable), 1); | ||
| } | ||
| }; | ||
| } | ||
| var scopes = []; | ||
| function dispose(self = true) { | ||
| if (this.f === STATE_DISPOSED) | ||
| return; | ||
| let current = self ? this : this.i, head = self ? this.m : this; | ||
| if (current) { | ||
| scopes.push(this); | ||
| do { | ||
| if (current.a) | ||
| emptyDisposal(current); | ||
| if (current.c) | ||
| removeSourceObservers(current, 0); | ||
| current[SCOPE] = null; | ||
| current.c = null; | ||
| current.d = null; | ||
| current.m = null; | ||
| current.k = null; | ||
| current.f = STATE_DISPOSED; | ||
| scopes.push(current); | ||
| current = current.i; | ||
| if (current) | ||
| current.m.i = null; | ||
| } while (current && scopes.includes(current[SCOPE])); | ||
| } | ||
| if (head) | ||
| head.i = current; | ||
| if (current) | ||
| current.m = head; | ||
| scopes = []; | ||
| } | ||
| function emptyDisposal(scope) { | ||
| try { | ||
| if (Array.isArray(scope.a)) { | ||
| for (let i = 0; i < scope.a.length; i++) { | ||
| const callable = scope.a[i]; | ||
| callable.call(callable); | ||
| } | ||
| } else { | ||
| scope.a.call(scope.a); | ||
| } | ||
| scope.a = null; | ||
| } catch (error) { | ||
| handleError(scope, error); | ||
| } | ||
| } | ||
| function compute(scope, compute2, observer) { | ||
| const prevScope = currentScope, prevObserver = currentObserver; | ||
| currentScope = scope; | ||
| currentObserver = observer; | ||
| try { | ||
| return compute2.call(scope); | ||
| } finally { | ||
| currentScope = prevScope; | ||
| currentObserver = prevObserver; | ||
| } | ||
| } | ||
| function lookup(scope, key) { | ||
| if (!scope) | ||
| return; | ||
| let current = scope, value; | ||
| while (current) { | ||
| value = current.k?.[key]; | ||
| if (value !== void 0) | ||
| return value; | ||
| current = current[SCOPE]; | ||
| } | ||
| } | ||
| function handleError(scope, error, depth) { | ||
| const handlers = lookup(scope, HANDLERS); | ||
| if (!handlers) | ||
| throw error; | ||
| try { | ||
| const coercedError = error instanceof Error ? error : Error(JSON.stringify(error)); | ||
| for (const handler of handlers) | ||
| handler(coercedError); | ||
| } catch (error2) { | ||
| handleError(scope[SCOPE], error2); | ||
| } | ||
| } | ||
| function read() { | ||
| if (this.f === STATE_DISPOSED) | ||
| return this.j; | ||
| if (currentObserver) { | ||
| if (!currentObservers && currentObserver.c && currentObserver.c[currentObserversIndex] == this) { | ||
| currentObserversIndex++; | ||
| } else if (!currentObservers) | ||
| currentObservers = [this]; | ||
| else | ||
| currentObservers.push(this); | ||
| } | ||
| if (this.p) | ||
| shouldUpdate(this); | ||
| return this.j; | ||
| } | ||
| function write(newValue) { | ||
| const value = isFunction(newValue) ? newValue(this.j) : newValue; | ||
| if (this.q(this.j, value)) { | ||
| this.j = value; | ||
| if (this.d) { | ||
| for (let i = 0; i < this.d.length; i++) { | ||
| notify(this.d[i], STATE_DIRTY); | ||
| } | ||
| } | ||
| } | ||
| return this.j; | ||
| } | ||
| var ScopeNode = function Scope() { | ||
| this[SCOPE] = currentScope; | ||
| this.f = STATE_CLEAN; | ||
| this.i = null; | ||
| this.m = currentScope; | ||
| if (currentScope) | ||
| currentScope.append(this); | ||
| }; | ||
| var ScopeProto = ScopeNode.prototype; | ||
| ScopeProto.k = null; | ||
| ScopeProto.p = null; | ||
| ScopeProto.a = null; | ||
| ScopeProto.append = function appendScope(scope) { | ||
| if (this.i) | ||
| this.i.m = scope; | ||
| scope.i = this.i; | ||
| this.i = scope; | ||
| }; | ||
| function createScope() { | ||
| return new ScopeNode(); | ||
| } | ||
| var ComputeNode = function Computation(initialValue, compute2, options) { | ||
| ScopeNode.call(this); | ||
| this.f = compute2 ? STATE_DIRTY : STATE_CLEAN; | ||
| this.l = false; | ||
| this.t = false; | ||
| this.c = null; | ||
| this.d = null; | ||
| this.j = initialValue; | ||
| if (compute2) | ||
| this.p = compute2; | ||
| if (options) { | ||
| if (options.scoped) | ||
| this.l = true; | ||
| if (options.dirty) | ||
| this.q = options.dirty; | ||
| } | ||
| }; | ||
| var ComputeProto = ComputeNode.prototype; | ||
| Object.setPrototypeOf(ComputeProto, ScopeProto); | ||
| ComputeProto.q = isNotEqual; | ||
| ComputeProto.call = read; | ||
| function createComputation(initialValue, compute2, options) { | ||
| return new ComputeNode(initialValue, compute2, options); | ||
| } | ||
| function isNotEqual(a, b) { | ||
| return a !== b; | ||
| } | ||
| function isFunction(value) { | ||
| return typeof value === "function"; | ||
| } | ||
| function isZombie(node) { | ||
| let scope = node[SCOPE]; | ||
| while (scope) { | ||
| if (scope.p && scope.f === STATE_DIRTY) | ||
| return true; | ||
| scope = scope[SCOPE]; | ||
| } | ||
| return false; | ||
| } | ||
| function shouldUpdate(node) { | ||
| if (node.f === STATE_CHECK) { | ||
| for (let i = 0; i < node.c.length; i++) { | ||
| shouldUpdate(node.c[i]); | ||
| if (node.f === STATE_DIRTY) { | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| if (node.f === STATE_DIRTY) | ||
| update(node); | ||
| else | ||
| node.f = STATE_CLEAN; | ||
| } | ||
| function update(node) { | ||
| let prevObservers = currentObservers, prevObserversIndex = currentObserversIndex; | ||
| currentObservers = null; | ||
| currentObserversIndex = 0; | ||
| try { | ||
| if (node.l) { | ||
| if (node.i && node.i[SCOPE] === node) | ||
| dispose.call(node, false); | ||
| if (node.a) | ||
| emptyDisposal(node); | ||
| if (node.k && node.k[HANDLERS]) | ||
| node.k[HANDLERS] = []; | ||
| } | ||
| const result = compute(node.l ? node : currentScope, node.p, node); | ||
| if (currentObservers) { | ||
| if (node.c) | ||
| removeSourceObservers(node, currentObserversIndex); | ||
| if (node.c && currentObserversIndex > 0) { | ||
| node.c.length = currentObserversIndex + currentObservers.length; | ||
| for (let i = 0; i < currentObservers.length; i++) { | ||
| node.c[currentObserversIndex + i] = currentObservers[i]; | ||
| } | ||
| } else { | ||
| node.c = currentObservers; | ||
| } | ||
| let source; | ||
| for (let i = currentObserversIndex; i < node.c.length; i++) { | ||
| source = node.c[i]; | ||
| if (!source.d) | ||
| source.d = [node]; | ||
| else | ||
| source.d.push(node); | ||
| } | ||
| } else if (node.c && currentObserversIndex < node.c.length) { | ||
| removeSourceObservers(node, currentObserversIndex); | ||
| node.c.length = currentObserversIndex; | ||
| } | ||
| if (!node.l && node.t) { | ||
| write.call(node, result); | ||
| } else { | ||
| node.j = result; | ||
| node.t = true; | ||
| } | ||
| } catch (error) { | ||
| handleError(node, error); | ||
| return; | ||
| } | ||
| currentObservers = prevObservers; | ||
| currentObserversIndex = prevObserversIndex; | ||
| node.f = STATE_CLEAN; | ||
| } | ||
| function notify(node, state) { | ||
| if (node.f >= state) | ||
| return; | ||
| if (node.l && node.f === STATE_CLEAN) { | ||
| effects.push(node); | ||
| if (!scheduledEffects) | ||
| flushEffects(); | ||
| } | ||
| node.f = state; | ||
| if (node.d) { | ||
| for (let i = 0; i < node.d.length; i++) { | ||
| notify(node.d[i], STATE_CHECK); | ||
| } | ||
| } | ||
| } | ||
| function removeSourceObservers(node, index) { | ||
| let source, swap; | ||
| for (let i = index; i < node.c.length; i++) { | ||
| source = node.c[i]; | ||
| if (source.d) { | ||
| swap = source.d.indexOf(node); | ||
| source.d[swap] = source.d[source.d.length - 1]; | ||
| source.d.pop(); | ||
| } | ||
| } | ||
| } | ||
| // src/signals.ts | ||
| function signal(initialValue, options) { | ||
| const node = createComputation(initialValue, null, options), signal2 = read.bind(node); | ||
| signal2.set = write.bind(node); | ||
| return signal2; | ||
| } | ||
| function isReadSignal(fn) { | ||
| return isFunction(fn); | ||
| } | ||
| function computed(compute2, options) { | ||
| return read.bind( | ||
| createComputation( | ||
| options?.initial, | ||
| compute2, | ||
| options | ||
| ) | ||
| ); | ||
| } | ||
| function effect(effect2, options) { | ||
| const signal2 = createComputation( | ||
| null, | ||
| function runEffect() { | ||
| let effectResult = effect2(); | ||
| isFunction(effectResult) && onDispose(effectResult); | ||
| return null; | ||
| }, | ||
| void 0 | ||
| ); | ||
| signal2.l = true; | ||
| read.call(signal2); | ||
| return dispose.bind(signal2, true); | ||
| } | ||
| function readonly(signal2) { | ||
| return () => signal2(); | ||
| } | ||
| function isWriteSignal(fn) { | ||
| return isReadSignal(fn) && "set" in fn; | ||
| } | ||
| export { SCOPE, compute, computed, createComputation, createScope, dispose, effect, getContext, getScope, isFunction, isNotEqual, isReadSignal, isWriteSignal, onDispose, onError, peek, read, readonly, root, scoped, setContext, signal, tick, untrack, write }; |
| 'use strict'; | ||
| // src/symbols.ts | ||
| var SCOPE = Symbol(0); | ||
| // src/core.ts | ||
| var scheduledEffects = false; | ||
| var runningEffects = false; | ||
| var currentScope = null; | ||
| var currentObserver = null; | ||
| var currentObservers = null; | ||
| var currentObserversIndex = 0; | ||
| var effects = []; | ||
| var NOOP = () => { | ||
| }; | ||
| var HANDLERS = Symbol(0); | ||
| var STATE_CLEAN = 0; | ||
| var STATE_CHECK = 1; | ||
| var STATE_DIRTY = 2; | ||
| var STATE_DISPOSED = 3; | ||
| function flushEffects() { | ||
| scheduledEffects = true; | ||
| queueMicrotask(runEffects); | ||
| } | ||
| function runEffects() { | ||
| if (!effects.length) { | ||
| scheduledEffects = false; | ||
| return; | ||
| } | ||
| runningEffects = true; | ||
| for (let i = 0; i < effects.length; i++) { | ||
| if (!isZombie(effects[i])) | ||
| read.call(effects[i]); | ||
| } | ||
| effects = []; | ||
| scheduledEffects = false; | ||
| runningEffects = false; | ||
| } | ||
| function root(init) { | ||
| const scope = createScope(); | ||
| return compute(scope, !init.length ? init : init.bind(null, dispose.bind(scope)), null); | ||
| } | ||
| function peek(compute2) { | ||
| const prev = currentObserver; | ||
| currentObserver = null; | ||
| const result = compute2(); | ||
| currentObserver = prev; | ||
| return result; | ||
| } | ||
| function untrack(compute2) { | ||
| const prev = currentScope; | ||
| currentScope = null; | ||
| const result = peek(compute2); | ||
| currentScope = prev; | ||
| return result; | ||
| } | ||
| function tick() { | ||
| if (!runningEffects) | ||
| runEffects(); | ||
| } | ||
| function getScope() { | ||
| return currentScope; | ||
| } | ||
| function scoped(run, scope) { | ||
| try { | ||
| compute(scope, run, null); | ||
| } catch (error) { | ||
| handleError(scope, error); | ||
| } | ||
| } | ||
| function getContext(key) { | ||
| return lookup(currentScope, key); | ||
| } | ||
| function setContext(key, value) { | ||
| if (currentScope) | ||
| (currentScope.k ??= {})[key] = value; | ||
| } | ||
| function onError(handler) { | ||
| if (!currentScope) | ||
| return; | ||
| const context = currentScope.k ??= {}; | ||
| if (!context[HANDLERS]) | ||
| context[HANDLERS] = [handler]; | ||
| else | ||
| context[HANDLERS].push(handler); | ||
| } | ||
| function onDispose(disposable) { | ||
| if (!disposable || !currentScope) | ||
| return disposable || NOOP; | ||
| const node = currentScope; | ||
| if (!node.a) { | ||
| node.a = disposable; | ||
| } else if (Array.isArray(node.a)) { | ||
| node.a.push(disposable); | ||
| } else { | ||
| node.a = [node.a, disposable]; | ||
| } | ||
| return function removeDispose() { | ||
| if (node.f === STATE_DISPOSED) | ||
| return; | ||
| disposable.call(null); | ||
| if (isFunction(node.a)) { | ||
| node.a = null; | ||
| } else if (Array.isArray(node.a)) { | ||
| node.a.splice(node.a.indexOf(disposable), 1); | ||
| } | ||
| }; | ||
| } | ||
| var scopes = []; | ||
| function dispose(self = true) { | ||
| if (this.f === STATE_DISPOSED) | ||
| return; | ||
| let current = self ? this : this.i, head = self ? this.m : this; | ||
| if (current) { | ||
| scopes.push(this); | ||
| do { | ||
| if (current.a) | ||
| emptyDisposal(current); | ||
| if (current.c) | ||
| removeSourceObservers(current, 0); | ||
| current[SCOPE] = null; | ||
| current.c = null; | ||
| current.d = null; | ||
| current.m = null; | ||
| current.k = null; | ||
| current.f = STATE_DISPOSED; | ||
| scopes.push(current); | ||
| current = current.i; | ||
| if (current) | ||
| current.m.i = null; | ||
| } while (current && scopes.includes(current[SCOPE])); | ||
| } | ||
| if (head) | ||
| head.i = current; | ||
| if (current) | ||
| current.m = head; | ||
| scopes = []; | ||
| } | ||
| function emptyDisposal(scope) { | ||
| try { | ||
| if (Array.isArray(scope.a)) { | ||
| for (let i = 0; i < scope.a.length; i++) { | ||
| const callable = scope.a[i]; | ||
| callable.call(callable); | ||
| } | ||
| } else { | ||
| scope.a.call(scope.a); | ||
| } | ||
| scope.a = null; | ||
| } catch (error) { | ||
| handleError(scope, error); | ||
| } | ||
| } | ||
| function compute(scope, compute2, observer) { | ||
| const prevScope = currentScope, prevObserver = currentObserver; | ||
| currentScope = scope; | ||
| currentObserver = observer; | ||
| try { | ||
| return compute2.call(scope); | ||
| } finally { | ||
| currentScope = prevScope; | ||
| currentObserver = prevObserver; | ||
| } | ||
| } | ||
| function lookup(scope, key) { | ||
| var _a; | ||
| if (!scope) | ||
| return; | ||
| let current = scope, value; | ||
| while (current) { | ||
| value = (_a = current.k) == null ? void 0 : _a[key]; | ||
| if (value !== void 0) | ||
| return value; | ||
| current = current[SCOPE]; | ||
| } | ||
| } | ||
| function handleError(scope, error, depth) { | ||
| const handlers = lookup(scope, HANDLERS); | ||
| if (!handlers) | ||
| throw error; | ||
| try { | ||
| const coercedError = error instanceof Error ? error : Error(JSON.stringify(error)); | ||
| for (const handler of handlers) | ||
| handler(coercedError); | ||
| } catch (error2) { | ||
| handleError(scope[SCOPE], error2); | ||
| } | ||
| } | ||
| function read() { | ||
| if (this.f === STATE_DISPOSED) | ||
| return this.j; | ||
| if (currentObserver) { | ||
| if (!currentObservers && currentObserver.c && currentObserver.c[currentObserversIndex] == this) { | ||
| currentObserversIndex++; | ||
| } else if (!currentObservers) | ||
| currentObservers = [this]; | ||
| else | ||
| currentObservers.push(this); | ||
| } | ||
| if (this.p) | ||
| shouldUpdate(this); | ||
| return this.j; | ||
| } | ||
| function write(newValue) { | ||
| const value = isFunction(newValue) ? newValue(this.j) : newValue; | ||
| if (this.q(this.j, value)) { | ||
| this.j = value; | ||
| if (this.d) { | ||
| for (let i = 0; i < this.d.length; i++) { | ||
| notify(this.d[i], STATE_DIRTY); | ||
| } | ||
| } | ||
| } | ||
| return this.j; | ||
| } | ||
| var ScopeNode = function Scope() { | ||
| this[SCOPE] = currentScope; | ||
| this.f = STATE_CLEAN; | ||
| this.i = null; | ||
| this.m = currentScope; | ||
| if (currentScope) | ||
| currentScope.append(this); | ||
| }; | ||
| var ScopeProto = ScopeNode.prototype; | ||
| ScopeProto.k = null; | ||
| ScopeProto.p = null; | ||
| ScopeProto.a = null; | ||
| ScopeProto.append = function appendScope(scope) { | ||
| if (this.i) | ||
| this.i.m = scope; | ||
| scope.i = this.i; | ||
| this.i = scope; | ||
| }; | ||
| function createScope() { | ||
| return new ScopeNode(); | ||
| } | ||
| var ComputeNode = function Computation(initialValue, compute2, options) { | ||
| ScopeNode.call(this); | ||
| this.f = compute2 ? STATE_DIRTY : STATE_CLEAN; | ||
| this.l = false; | ||
| this.t = false; | ||
| this.c = null; | ||
| this.d = null; | ||
| this.j = initialValue; | ||
| if (compute2) | ||
| this.p = compute2; | ||
| if (options) { | ||
| if (options.scoped) | ||
| this.l = true; | ||
| if (options.dirty) | ||
| this.q = options.dirty; | ||
| } | ||
| }; | ||
| var ComputeProto = ComputeNode.prototype; | ||
| Object.setPrototypeOf(ComputeProto, ScopeProto); | ||
| ComputeProto.q = isNotEqual; | ||
| ComputeProto.call = read; | ||
| function createComputation(initialValue, compute2, options) { | ||
| return new ComputeNode(initialValue, compute2, options); | ||
| } | ||
| function isNotEqual(a, b) { | ||
| return a !== b; | ||
| } | ||
| function isFunction(value) { | ||
| return typeof value === "function"; | ||
| } | ||
| function isZombie(node) { | ||
| let scope = node[SCOPE]; | ||
| while (scope) { | ||
| if (scope.p && scope.f === STATE_DIRTY) | ||
| return true; | ||
| scope = scope[SCOPE]; | ||
| } | ||
| return false; | ||
| } | ||
| function shouldUpdate(node) { | ||
| if (node.f === STATE_CHECK) { | ||
| for (let i = 0; i < node.c.length; i++) { | ||
| shouldUpdate(node.c[i]); | ||
| if (node.f === STATE_DIRTY) { | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| if (node.f === STATE_DIRTY) | ||
| update(node); | ||
| else | ||
| node.f = STATE_CLEAN; | ||
| } | ||
| function update(node) { | ||
| let prevObservers = currentObservers, prevObserversIndex = currentObserversIndex; | ||
| currentObservers = null; | ||
| currentObserversIndex = 0; | ||
| try { | ||
| if (node.l) { | ||
| if (node.i && node.i[SCOPE] === node) | ||
| dispose.call(node, false); | ||
| if (node.a) | ||
| emptyDisposal(node); | ||
| if (node.k && node.k[HANDLERS]) | ||
| node.k[HANDLERS] = []; | ||
| } | ||
| const result = compute(node.l ? node : currentScope, node.p, node); | ||
| if (currentObservers) { | ||
| if (node.c) | ||
| removeSourceObservers(node, currentObserversIndex); | ||
| if (node.c && currentObserversIndex > 0) { | ||
| node.c.length = currentObserversIndex + currentObservers.length; | ||
| for (let i = 0; i < currentObservers.length; i++) { | ||
| node.c[currentObserversIndex + i] = currentObservers[i]; | ||
| } | ||
| } else { | ||
| node.c = currentObservers; | ||
| } | ||
| let source; | ||
| for (let i = currentObserversIndex; i < node.c.length; i++) { | ||
| source = node.c[i]; | ||
| if (!source.d) | ||
| source.d = [node]; | ||
| else | ||
| source.d.push(node); | ||
| } | ||
| } else if (node.c && currentObserversIndex < node.c.length) { | ||
| removeSourceObservers(node, currentObserversIndex); | ||
| node.c.length = currentObserversIndex; | ||
| } | ||
| if (!node.l && node.t) { | ||
| write.call(node, result); | ||
| } else { | ||
| node.j = result; | ||
| node.t = true; | ||
| } | ||
| } catch (error) { | ||
| handleError(node, error); | ||
| return; | ||
| } | ||
| currentObservers = prevObservers; | ||
| currentObserversIndex = prevObserversIndex; | ||
| node.f = STATE_CLEAN; | ||
| } | ||
| function notify(node, state) { | ||
| if (node.f >= state) | ||
| return; | ||
| if (node.l && node.f === STATE_CLEAN) { | ||
| effects.push(node); | ||
| if (!scheduledEffects) | ||
| flushEffects(); | ||
| } | ||
| node.f = state; | ||
| if (node.d) { | ||
| for (let i = 0; i < node.d.length; i++) { | ||
| notify(node.d[i], STATE_CHECK); | ||
| } | ||
| } | ||
| } | ||
| function removeSourceObservers(node, index) { | ||
| let source, swap; | ||
| for (let i = index; i < node.c.length; i++) { | ||
| source = node.c[i]; | ||
| if (source.d) { | ||
| swap = source.d.indexOf(node); | ||
| source.d[swap] = source.d[source.d.length - 1]; | ||
| source.d.pop(); | ||
| } | ||
| } | ||
| } | ||
| // src/signals.ts | ||
| function signal(initialValue, options) { | ||
| const node = createComputation(initialValue, null, options), signal2 = read.bind(node); | ||
| signal2.set = write.bind(node); | ||
| return signal2; | ||
| } | ||
| function isReadSignal(fn) { | ||
| return isFunction(fn); | ||
| } | ||
| function computed(compute2, options) { | ||
| return read.bind( | ||
| createComputation( | ||
| options == null ? void 0 : options.initial, | ||
| compute2, | ||
| options | ||
| ) | ||
| ); | ||
| } | ||
| function effect(effect2, options) { | ||
| return () => { | ||
| }; | ||
| } | ||
| function readonly(signal2) { | ||
| return () => signal2(); | ||
| } | ||
| function isWriteSignal(fn) { | ||
| return isReadSignal(fn) && "set" in fn; | ||
| } | ||
| exports.SCOPE = SCOPE; | ||
| exports.compute = compute; | ||
| exports.computed = computed; | ||
| exports.createComputation = createComputation; | ||
| exports.createScope = createScope; | ||
| exports.dispose = dispose; | ||
| exports.effect = effect; | ||
| exports.getContext = getContext; | ||
| exports.getScope = getScope; | ||
| exports.isFunction = isFunction; | ||
| exports.isNotEqual = isNotEqual; | ||
| exports.isReadSignal = isReadSignal; | ||
| exports.isWriteSignal = isWriteSignal; | ||
| exports.onDispose = onDispose; | ||
| exports.onError = onError; | ||
| exports.peek = peek; | ||
| exports.read = read; | ||
| exports.readonly = readonly; | ||
| exports.root = root; | ||
| exports.scoped = scoped; | ||
| exports.setContext = setContext; | ||
| exports.signal = signal; | ||
| exports.tick = tick; | ||
| exports.untrack = untrack; | ||
| exports.write = write; |
| // src/symbols.ts | ||
| var SCOPE = Symbol(0); | ||
| // src/core.ts | ||
| var scheduledEffects = false; | ||
| var runningEffects = false; | ||
| var currentScope = null; | ||
| var currentObserver = null; | ||
| var currentObservers = null; | ||
| var currentObserversIndex = 0; | ||
| var effects = []; | ||
| var NOOP = () => { | ||
| }; | ||
| var HANDLERS = Symbol(0); | ||
| var STATE_CLEAN = 0; | ||
| var STATE_CHECK = 1; | ||
| var STATE_DIRTY = 2; | ||
| var STATE_DISPOSED = 3; | ||
| function flushEffects() { | ||
| scheduledEffects = true; | ||
| queueMicrotask(runEffects); | ||
| } | ||
| function runEffects() { | ||
| if (!effects.length) { | ||
| scheduledEffects = false; | ||
| return; | ||
| } | ||
| runningEffects = true; | ||
| for (let i = 0; i < effects.length; i++) { | ||
| if (!isZombie(effects[i])) | ||
| read.call(effects[i]); | ||
| } | ||
| effects = []; | ||
| scheduledEffects = false; | ||
| runningEffects = false; | ||
| } | ||
| function root(init) { | ||
| const scope = createScope(); | ||
| return compute(scope, !init.length ? init : init.bind(null, dispose.bind(scope)), null); | ||
| } | ||
| function peek(compute2) { | ||
| const prev = currentObserver; | ||
| currentObserver = null; | ||
| const result = compute2(); | ||
| currentObserver = prev; | ||
| return result; | ||
| } | ||
| function untrack(compute2) { | ||
| const prev = currentScope; | ||
| currentScope = null; | ||
| const result = peek(compute2); | ||
| currentScope = prev; | ||
| return result; | ||
| } | ||
| function tick() { | ||
| if (!runningEffects) | ||
| runEffects(); | ||
| } | ||
| function getScope() { | ||
| return currentScope; | ||
| } | ||
| function scoped(run, scope) { | ||
| try { | ||
| compute(scope, run, null); | ||
| } catch (error) { | ||
| handleError(scope, error); | ||
| } | ||
| } | ||
| function getContext(key) { | ||
| return lookup(currentScope, key); | ||
| } | ||
| function setContext(key, value) { | ||
| if (currentScope) | ||
| (currentScope.k ??= {})[key] = value; | ||
| } | ||
| function onError(handler) { | ||
| if (!currentScope) | ||
| return; | ||
| const context = currentScope.k ??= {}; | ||
| if (!context[HANDLERS]) | ||
| context[HANDLERS] = [handler]; | ||
| else | ||
| context[HANDLERS].push(handler); | ||
| } | ||
| function onDispose(disposable) { | ||
| if (!disposable || !currentScope) | ||
| return disposable || NOOP; | ||
| const node = currentScope; | ||
| if (!node.a) { | ||
| node.a = disposable; | ||
| } else if (Array.isArray(node.a)) { | ||
| node.a.push(disposable); | ||
| } else { | ||
| node.a = [node.a, disposable]; | ||
| } | ||
| return function removeDispose() { | ||
| if (node.f === STATE_DISPOSED) | ||
| return; | ||
| disposable.call(null); | ||
| if (isFunction(node.a)) { | ||
| node.a = null; | ||
| } else if (Array.isArray(node.a)) { | ||
| node.a.splice(node.a.indexOf(disposable), 1); | ||
| } | ||
| }; | ||
| } | ||
| var scopes = []; | ||
| function dispose(self = true) { | ||
| if (this.f === STATE_DISPOSED) | ||
| return; | ||
| let current = self ? this : this.i, head = self ? this.m : this; | ||
| if (current) { | ||
| scopes.push(this); | ||
| do { | ||
| if (current.a) | ||
| emptyDisposal(current); | ||
| if (current.c) | ||
| removeSourceObservers(current, 0); | ||
| current[SCOPE] = null; | ||
| current.c = null; | ||
| current.d = null; | ||
| current.m = null; | ||
| current.k = null; | ||
| current.f = STATE_DISPOSED; | ||
| scopes.push(current); | ||
| current = current.i; | ||
| if (current) | ||
| current.m.i = null; | ||
| } while (current && scopes.includes(current[SCOPE])); | ||
| } | ||
| if (head) | ||
| head.i = current; | ||
| if (current) | ||
| current.m = head; | ||
| scopes = []; | ||
| } | ||
| function emptyDisposal(scope) { | ||
| try { | ||
| if (Array.isArray(scope.a)) { | ||
| for (let i = 0; i < scope.a.length; i++) { | ||
| const callable = scope.a[i]; | ||
| callable.call(callable); | ||
| } | ||
| } else { | ||
| scope.a.call(scope.a); | ||
| } | ||
| scope.a = null; | ||
| } catch (error) { | ||
| handleError(scope, error); | ||
| } | ||
| } | ||
| function compute(scope, compute2, observer) { | ||
| const prevScope = currentScope, prevObserver = currentObserver; | ||
| currentScope = scope; | ||
| currentObserver = observer; | ||
| try { | ||
| return compute2.call(scope); | ||
| } finally { | ||
| currentScope = prevScope; | ||
| currentObserver = prevObserver; | ||
| } | ||
| } | ||
| function lookup(scope, key) { | ||
| var _a; | ||
| if (!scope) | ||
| return; | ||
| let current = scope, value; | ||
| while (current) { | ||
| value = (_a = current.k) == null ? void 0 : _a[key]; | ||
| if (value !== void 0) | ||
| return value; | ||
| current = current[SCOPE]; | ||
| } | ||
| } | ||
| function handleError(scope, error, depth) { | ||
| const handlers = lookup(scope, HANDLERS); | ||
| if (!handlers) | ||
| throw error; | ||
| try { | ||
| const coercedError = error instanceof Error ? error : Error(JSON.stringify(error)); | ||
| for (const handler of handlers) | ||
| handler(coercedError); | ||
| } catch (error2) { | ||
| handleError(scope[SCOPE], error2); | ||
| } | ||
| } | ||
| function read() { | ||
| if (this.f === STATE_DISPOSED) | ||
| return this.j; | ||
| if (currentObserver) { | ||
| if (!currentObservers && currentObserver.c && currentObserver.c[currentObserversIndex] == this) { | ||
| currentObserversIndex++; | ||
| } else if (!currentObservers) | ||
| currentObservers = [this]; | ||
| else | ||
| currentObservers.push(this); | ||
| } | ||
| if (this.p) | ||
| shouldUpdate(this); | ||
| return this.j; | ||
| } | ||
| function write(newValue) { | ||
| const value = isFunction(newValue) ? newValue(this.j) : newValue; | ||
| if (this.q(this.j, value)) { | ||
| this.j = value; | ||
| if (this.d) { | ||
| for (let i = 0; i < this.d.length; i++) { | ||
| notify(this.d[i], STATE_DIRTY); | ||
| } | ||
| } | ||
| } | ||
| return this.j; | ||
| } | ||
| var ScopeNode = function Scope() { | ||
| this[SCOPE] = currentScope; | ||
| this.f = STATE_CLEAN; | ||
| this.i = null; | ||
| this.m = currentScope; | ||
| if (currentScope) | ||
| currentScope.append(this); | ||
| }; | ||
| var ScopeProto = ScopeNode.prototype; | ||
| ScopeProto.k = null; | ||
| ScopeProto.p = null; | ||
| ScopeProto.a = null; | ||
| ScopeProto.append = function appendScope(scope) { | ||
| if (this.i) | ||
| this.i.m = scope; | ||
| scope.i = this.i; | ||
| this.i = scope; | ||
| }; | ||
| function createScope() { | ||
| return new ScopeNode(); | ||
| } | ||
| var ComputeNode = function Computation(initialValue, compute2, options) { | ||
| ScopeNode.call(this); | ||
| this.f = compute2 ? STATE_DIRTY : STATE_CLEAN; | ||
| this.l = false; | ||
| this.t = false; | ||
| this.c = null; | ||
| this.d = null; | ||
| this.j = initialValue; | ||
| if (compute2) | ||
| this.p = compute2; | ||
| if (options) { | ||
| if (options.scoped) | ||
| this.l = true; | ||
| if (options.dirty) | ||
| this.q = options.dirty; | ||
| } | ||
| }; | ||
| var ComputeProto = ComputeNode.prototype; | ||
| Object.setPrototypeOf(ComputeProto, ScopeProto); | ||
| ComputeProto.q = isNotEqual; | ||
| ComputeProto.call = read; | ||
| function createComputation(initialValue, compute2, options) { | ||
| return new ComputeNode(initialValue, compute2, options); | ||
| } | ||
| function isNotEqual(a, b) { | ||
| return a !== b; | ||
| } | ||
| function isFunction(value) { | ||
| return typeof value === "function"; | ||
| } | ||
| function isZombie(node) { | ||
| let scope = node[SCOPE]; | ||
| while (scope) { | ||
| if (scope.p && scope.f === STATE_DIRTY) | ||
| return true; | ||
| scope = scope[SCOPE]; | ||
| } | ||
| return false; | ||
| } | ||
| function shouldUpdate(node) { | ||
| if (node.f === STATE_CHECK) { | ||
| for (let i = 0; i < node.c.length; i++) { | ||
| shouldUpdate(node.c[i]); | ||
| if (node.f === STATE_DIRTY) { | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| if (node.f === STATE_DIRTY) | ||
| update(node); | ||
| else | ||
| node.f = STATE_CLEAN; | ||
| } | ||
| function update(node) { | ||
| let prevObservers = currentObservers, prevObserversIndex = currentObserversIndex; | ||
| currentObservers = null; | ||
| currentObserversIndex = 0; | ||
| try { | ||
| if (node.l) { | ||
| if (node.i && node.i[SCOPE] === node) | ||
| dispose.call(node, false); | ||
| if (node.a) | ||
| emptyDisposal(node); | ||
| if (node.k && node.k[HANDLERS]) | ||
| node.k[HANDLERS] = []; | ||
| } | ||
| const result = compute(node.l ? node : currentScope, node.p, node); | ||
| if (currentObservers) { | ||
| if (node.c) | ||
| removeSourceObservers(node, currentObserversIndex); | ||
| if (node.c && currentObserversIndex > 0) { | ||
| node.c.length = currentObserversIndex + currentObservers.length; | ||
| for (let i = 0; i < currentObservers.length; i++) { | ||
| node.c[currentObserversIndex + i] = currentObservers[i]; | ||
| } | ||
| } else { | ||
| node.c = currentObservers; | ||
| } | ||
| let source; | ||
| for (let i = currentObserversIndex; i < node.c.length; i++) { | ||
| source = node.c[i]; | ||
| if (!source.d) | ||
| source.d = [node]; | ||
| else | ||
| source.d.push(node); | ||
| } | ||
| } else if (node.c && currentObserversIndex < node.c.length) { | ||
| removeSourceObservers(node, currentObserversIndex); | ||
| node.c.length = currentObserversIndex; | ||
| } | ||
| if (!node.l && node.t) { | ||
| write.call(node, result); | ||
| } else { | ||
| node.j = result; | ||
| node.t = true; | ||
| } | ||
| } catch (error) { | ||
| handleError(node, error); | ||
| return; | ||
| } | ||
| currentObservers = prevObservers; | ||
| currentObserversIndex = prevObserversIndex; | ||
| node.f = STATE_CLEAN; | ||
| } | ||
| function notify(node, state) { | ||
| if (node.f >= state) | ||
| return; | ||
| if (node.l && node.f === STATE_CLEAN) { | ||
| effects.push(node); | ||
| if (!scheduledEffects) | ||
| flushEffects(); | ||
| } | ||
| node.f = state; | ||
| if (node.d) { | ||
| for (let i = 0; i < node.d.length; i++) { | ||
| notify(node.d[i], STATE_CHECK); | ||
| } | ||
| } | ||
| } | ||
| function removeSourceObservers(node, index) { | ||
| let source, swap; | ||
| for (let i = index; i < node.c.length; i++) { | ||
| source = node.c[i]; | ||
| if (source.d) { | ||
| swap = source.d.indexOf(node); | ||
| source.d[swap] = source.d[source.d.length - 1]; | ||
| source.d.pop(); | ||
| } | ||
| } | ||
| } | ||
| // src/signals.ts | ||
| function signal(initialValue, options) { | ||
| const node = createComputation(initialValue, null, options), signal2 = read.bind(node); | ||
| signal2.set = write.bind(node); | ||
| return signal2; | ||
| } | ||
| function isReadSignal(fn) { | ||
| return isFunction(fn); | ||
| } | ||
| function computed(compute2, options) { | ||
| return read.bind( | ||
| createComputation( | ||
| options == null ? void 0 : options.initial, | ||
| compute2, | ||
| options | ||
| ) | ||
| ); | ||
| } | ||
| function effect(effect2, options) { | ||
| return () => { | ||
| }; | ||
| } | ||
| function readonly(signal2) { | ||
| return () => signal2(); | ||
| } | ||
| function isWriteSignal(fn) { | ||
| return isReadSignal(fn) && "set" in fn; | ||
| } | ||
| export { SCOPE, compute, computed, createComputation, createScope, dispose, effect, getContext, getScope, isFunction, isNotEqual, isReadSignal, isWriteSignal, onDispose, onError, peek, read, readonly, root, scoped, setContext, signal, tick, untrack, write }; |
@@ -1,1 +0,1 @@ | ||
| export { SCOPE, computed, effect, getContext, getScope, isFunction, isNotEqual, isReadSignal, isWriteSignal, onDispose, onError, peek, readonly, root, scoped, setContext, signal, tick, untrack } from './chunks/chunk-LCACZ65R.js'; | ||
| export { SCOPE, computed, effect, getContext, getScope, isFunction, isNotEqual, isReadSignal, isWriteSignal, onDispose, onError, peek, readonly, root, scoped, setContext, signal, tick, untrack } from './chunks/chunk-ABCDPNOY.js'; |
+1
-1
@@ -1,2 +0,2 @@ | ||
| import { effect, write, onDispose, read, isNotEqual, createComputation, createScope, scoped, dispose, compute } from './chunks/chunk-LCACZ65R.js'; | ||
| import { effect, write, onDispose, read, isNotEqual, createComputation, createScope, scoped, dispose, compute } from './chunks/chunk-ABCDPNOY.js'; | ||
@@ -3,0 +3,0 @@ // src/selector.ts |
@@ -1,1 +0,1 @@ | ||
| export { SCOPE, computed, effect, getContext, getScope, isFunction, isNotEqual, isReadSignal, isWriteSignal, onDispose, onError, peek, readonly, root, scoped, setContext, signal, tick, untrack } from './chunks/chunk-IWWNKX5N.js'; | ||
| export { SCOPE, computed, effect, getContext, getScope, isFunction, isNotEqual, isReadSignal, isWriteSignal, onDispose, onError, peek, readonly, root, scoped, setContext, signal, tick, untrack } from './chunks/chunk-DQUSPEAV.js'; |
+1
-1
@@ -1,2 +0,2 @@ | ||
| import { effect, write, onDispose, read, isNotEqual, createComputation, createScope, scoped, dispose, compute } from './chunks/chunk-IWWNKX5N.js'; | ||
| import { effect, write, onDispose, read, isNotEqual, createComputation, createScope, scoped, dispose, compute } from './chunks/chunk-DQUSPEAV.js'; | ||
@@ -3,0 +3,0 @@ // src/selector.ts |
+20
-20
| 'use strict'; | ||
| var chunkGE3RIFAZ_cjs = require('./chunks/chunk-GE3RIFAZ.cjs'); | ||
| var chunk6H4AAM6D_cjs = require('./chunks/chunk-6H4AAM6D.cjs'); | ||
@@ -9,75 +9,75 @@ | ||
| enumerable: true, | ||
| get: function () { return chunkGE3RIFAZ_cjs.SCOPE; } | ||
| get: function () { return chunk6H4AAM6D_cjs.SCOPE; } | ||
| }); | ||
| Object.defineProperty(exports, 'computed', { | ||
| enumerable: true, | ||
| get: function () { return chunkGE3RIFAZ_cjs.computed; } | ||
| get: function () { return chunk6H4AAM6D_cjs.computed; } | ||
| }); | ||
| Object.defineProperty(exports, 'effect', { | ||
| enumerable: true, | ||
| get: function () { return chunkGE3RIFAZ_cjs.effect; } | ||
| get: function () { return chunk6H4AAM6D_cjs.effect; } | ||
| }); | ||
| Object.defineProperty(exports, 'getContext', { | ||
| enumerable: true, | ||
| get: function () { return chunkGE3RIFAZ_cjs.getContext; } | ||
| get: function () { return chunk6H4AAM6D_cjs.getContext; } | ||
| }); | ||
| Object.defineProperty(exports, 'getScope', { | ||
| enumerable: true, | ||
| get: function () { return chunkGE3RIFAZ_cjs.getScope; } | ||
| get: function () { return chunk6H4AAM6D_cjs.getScope; } | ||
| }); | ||
| Object.defineProperty(exports, 'isFunction', { | ||
| enumerable: true, | ||
| get: function () { return chunkGE3RIFAZ_cjs.isFunction; } | ||
| get: function () { return chunk6H4AAM6D_cjs.isFunction; } | ||
| }); | ||
| Object.defineProperty(exports, 'isNotEqual', { | ||
| enumerable: true, | ||
| get: function () { return chunkGE3RIFAZ_cjs.isNotEqual; } | ||
| get: function () { return chunk6H4AAM6D_cjs.isNotEqual; } | ||
| }); | ||
| Object.defineProperty(exports, 'isReadSignal', { | ||
| enumerable: true, | ||
| get: function () { return chunkGE3RIFAZ_cjs.isReadSignal; } | ||
| get: function () { return chunk6H4AAM6D_cjs.isReadSignal; } | ||
| }); | ||
| Object.defineProperty(exports, 'isWriteSignal', { | ||
| enumerable: true, | ||
| get: function () { return chunkGE3RIFAZ_cjs.isWriteSignal; } | ||
| get: function () { return chunk6H4AAM6D_cjs.isWriteSignal; } | ||
| }); | ||
| Object.defineProperty(exports, 'onDispose', { | ||
| enumerable: true, | ||
| get: function () { return chunkGE3RIFAZ_cjs.onDispose; } | ||
| get: function () { return chunk6H4AAM6D_cjs.onDispose; } | ||
| }); | ||
| Object.defineProperty(exports, 'onError', { | ||
| enumerable: true, | ||
| get: function () { return chunkGE3RIFAZ_cjs.onError; } | ||
| get: function () { return chunk6H4AAM6D_cjs.onError; } | ||
| }); | ||
| Object.defineProperty(exports, 'peek', { | ||
| enumerable: true, | ||
| get: function () { return chunkGE3RIFAZ_cjs.peek; } | ||
| get: function () { return chunk6H4AAM6D_cjs.peek; } | ||
| }); | ||
| Object.defineProperty(exports, 'readonly', { | ||
| enumerable: true, | ||
| get: function () { return chunkGE3RIFAZ_cjs.readonly; } | ||
| get: function () { return chunk6H4AAM6D_cjs.readonly; } | ||
| }); | ||
| Object.defineProperty(exports, 'root', { | ||
| enumerable: true, | ||
| get: function () { return chunkGE3RIFAZ_cjs.root; } | ||
| get: function () { return chunk6H4AAM6D_cjs.root; } | ||
| }); | ||
| Object.defineProperty(exports, 'scoped', { | ||
| enumerable: true, | ||
| get: function () { return chunkGE3RIFAZ_cjs.scoped; } | ||
| get: function () { return chunk6H4AAM6D_cjs.scoped; } | ||
| }); | ||
| Object.defineProperty(exports, 'setContext', { | ||
| enumerable: true, | ||
| get: function () { return chunkGE3RIFAZ_cjs.setContext; } | ||
| get: function () { return chunk6H4AAM6D_cjs.setContext; } | ||
| }); | ||
| Object.defineProperty(exports, 'signal', { | ||
| enumerable: true, | ||
| get: function () { return chunkGE3RIFAZ_cjs.signal; } | ||
| get: function () { return chunk6H4AAM6D_cjs.signal; } | ||
| }); | ||
| Object.defineProperty(exports, 'tick', { | ||
| enumerable: true, | ||
| get: function () { return chunkGE3RIFAZ_cjs.tick; } | ||
| get: function () { return chunk6H4AAM6D_cjs.tick; } | ||
| }); | ||
| Object.defineProperty(exports, 'untrack', { | ||
| enumerable: true, | ||
| get: function () { return chunkGE3RIFAZ_cjs.untrack; } | ||
| get: function () { return chunk6H4AAM6D_cjs.untrack; } | ||
| }); |
@@ -1,1 +0,1 @@ | ||
| export { SCOPE, computed, effect, getContext, getScope, isFunction, isNotEqual, isReadSignal, isWriteSignal, onDispose, onError, peek, readonly, root, scoped, setContext, signal, tick, untrack } from './chunks/chunk-O32V2YYU.js'; | ||
| export { SCOPE, computed, effect, getContext, getScope, isFunction, isNotEqual, isReadSignal, isWriteSignal, onDispose, onError, peek, readonly, root, scoped, setContext, signal, tick, untrack } from './chunks/chunk-LCJZBPJV.js'; |
+29
-29
| 'use strict'; | ||
| var chunkGE3RIFAZ_cjs = require('./chunks/chunk-GE3RIFAZ.cjs'); | ||
| var chunk6H4AAM6D_cjs = require('./chunks/chunk-6H4AAM6D.cjs'); | ||
@@ -8,6 +8,6 @@ // src/selector.ts | ||
| let currentKey, nodes = /* @__PURE__ */ new Map(); | ||
| chunkGE3RIFAZ_cjs.effect(() => { | ||
| chunk6H4AAM6D_cjs.effect(() => { | ||
| const newKey = source(), prev = nodes.get(currentKey), next = nodes.get(newKey); | ||
| prev && chunkGE3RIFAZ_cjs.write.call(prev, false); | ||
| next && chunkGE3RIFAZ_cjs.write.call(next, true); | ||
| prev && chunk6H4AAM6D_cjs.write.call(prev, false); | ||
| next && chunk6H4AAM6D_cjs.write.call(next, true); | ||
| currentKey = newKey; | ||
@@ -20,4 +20,4 @@ }); | ||
| node.r += 1; | ||
| chunkGE3RIFAZ_cjs.onDispose(node); | ||
| return chunkGE3RIFAZ_cjs.read.bind(node); | ||
| chunk6H4AAM6D_cjs.onDispose(node); | ||
| return chunk6H4AAM6D_cjs.read.bind(node); | ||
| }; | ||
@@ -34,3 +34,3 @@ } | ||
| var SelectorProto = Selector.prototype; | ||
| SelectorProto.q = chunkGE3RIFAZ_cjs.isNotEqual; | ||
| SelectorProto.q = chunk6H4AAM6D_cjs.isNotEqual; | ||
| SelectorProto.call = function() { | ||
@@ -46,7 +46,7 @@ this.r -= 1; | ||
| function computedMap(list, map, options) { | ||
| return chunkGE3RIFAZ_cjs.read.bind( | ||
| chunkGE3RIFAZ_cjs.createComputation( | ||
| return chunk6H4AAM6D_cjs.read.bind( | ||
| chunk6H4AAM6D_cjs.createComputation( | ||
| [], | ||
| updateMap.bind({ | ||
| n: chunkGE3RIFAZ_cjs.createScope(), | ||
| n: chunk6H4AAM6D_cjs.createScope(), | ||
| h: 0, | ||
@@ -64,7 +64,7 @@ s: list, | ||
| function updateMap() { | ||
| let i = 0, newItems = this.s() || [], mapper = () => this.o(chunkGE3RIFAZ_cjs.read.bind(this.b[i]), i); | ||
| chunkGE3RIFAZ_cjs.scoped(() => { | ||
| let i = 0, newItems = this.s() || [], mapper = () => this.o(chunk6H4AAM6D_cjs.read.bind(this.b[i]), i); | ||
| chunk6H4AAM6D_cjs.scoped(() => { | ||
| if (newItems.length === 0) { | ||
| if (this.h !== 0) { | ||
| chunkGE3RIFAZ_cjs.dispose.call(this.n, false); | ||
| chunk6H4AAM6D_cjs.dispose.call(this.n, false); | ||
| this.g = []; | ||
@@ -79,6 +79,6 @@ this.e = []; | ||
| if (i < this.g.length && this.g[i] !== newItems[i]) { | ||
| chunkGE3RIFAZ_cjs.write.call(this.b[i], newItems[i]); | ||
| chunk6H4AAM6D_cjs.write.call(this.b[i], newItems[i]); | ||
| } else if (i >= this.g.length) { | ||
| this.e[i] = chunkGE3RIFAZ_cjs.compute( | ||
| this.b[i] = chunkGE3RIFAZ_cjs.createComputation(newItems[i], null), | ||
| this.e[i] = chunk6H4AAM6D_cjs.compute( | ||
| this.b[i] = chunk6H4AAM6D_cjs.createComputation(newItems[i], null), | ||
| mapper, | ||
@@ -90,3 +90,3 @@ null | ||
| for (; i < this.g.length; i++) | ||
| chunkGE3RIFAZ_cjs.dispose.call(this.b[i]); | ||
| chunk6H4AAM6D_cjs.dispose.call(this.b[i]); | ||
| this.h = this.b.length = newItems.length; | ||
@@ -99,7 +99,7 @@ this.g = newItems.slice(0); | ||
| function computedKeyedMap(list, map, options) { | ||
| return chunkGE3RIFAZ_cjs.read.bind( | ||
| chunkGE3RIFAZ_cjs.createComputation( | ||
| return chunk6H4AAM6D_cjs.read.bind( | ||
| chunk6H4AAM6D_cjs.createComputation( | ||
| [], | ||
| updateKeyedMap.bind({ | ||
| n: chunkGE3RIFAZ_cjs.createScope(), | ||
| n: chunk6H4AAM6D_cjs.createScope(), | ||
| h: 0, | ||
@@ -118,7 +118,7 @@ s: list, | ||
| const newItems = this.s() || [], indexed = this.o.length > 1; | ||
| chunkGE3RIFAZ_cjs.scoped(() => { | ||
| let newLen = newItems.length, i, j, mapper = indexed ? () => this.o(newItems[j], chunkGE3RIFAZ_cjs.read.bind(this.b[j])) : () => this.o(newItems[j]); | ||
| chunk6H4AAM6D_cjs.scoped(() => { | ||
| let newLen = newItems.length, i, j, mapper = indexed ? () => this.o(newItems[j], chunk6H4AAM6D_cjs.read.bind(this.b[j])) : () => this.o(newItems[j]); | ||
| if (newLen === 0) { | ||
| if (this.h !== 0) { | ||
| chunkGE3RIFAZ_cjs.dispose.call(this.n, false); | ||
| chunk6H4AAM6D_cjs.dispose.call(this.n, false); | ||
| this.b = []; | ||
@@ -133,4 +133,4 @@ this.g = []; | ||
| this.g[j] = newItems[j]; | ||
| this.e[j] = chunkGE3RIFAZ_cjs.compute( | ||
| this.b[j] = chunkGE3RIFAZ_cjs.createComputation(j, null), | ||
| this.e[j] = chunk6H4AAM6D_cjs.compute( | ||
| this.b[j] = chunk6H4AAM6D_cjs.createComputation(j, null), | ||
| mapper, | ||
@@ -166,3 +166,3 @@ null | ||
| } else | ||
| chunkGE3RIFAZ_cjs.dispose.call(this.b[i]); | ||
| chunk6H4AAM6D_cjs.dispose.call(this.b[i]); | ||
| } | ||
@@ -173,6 +173,6 @@ for (j = start; j < newLen; j++) { | ||
| this.b[j] = tempNodes[j]; | ||
| chunkGE3RIFAZ_cjs.write.call(this.b[j], j); | ||
| chunk6H4AAM6D_cjs.write.call(this.b[j], j); | ||
| } else { | ||
| this.e[j] = chunkGE3RIFAZ_cjs.compute( | ||
| this.b[j] = chunkGE3RIFAZ_cjs.createComputation(j, null), | ||
| this.e[j] = chunk6H4AAM6D_cjs.compute( | ||
| this.b[j] = chunk6H4AAM6D_cjs.createComputation(j, null), | ||
| mapper, | ||
@@ -179,0 +179,0 @@ null |
@@ -1,2 +0,2 @@ | ||
| import { effect, write, onDispose, read, isNotEqual, createComputation, createScope, scoped, dispose, compute } from './chunks/chunk-O32V2YYU.js'; | ||
| import { effect, write, onDispose, read, isNotEqual, createComputation, createScope, scoped, dispose, compute } from './chunks/chunk-LCJZBPJV.js'; | ||
@@ -3,0 +3,0 @@ // src/selector.ts |
| import type { SCOPE } from './symbols'; | ||
| export interface Computation<T = any> extends Scope { | ||
| id?: string | undefined; | ||
| /** @internal */ | ||
| _scoped: boolean; | ||
| /** @internal */ | ||
| _init: boolean; | ||
| /** @internal */ | ||
| _value: T; | ||
| /** @internal */ | ||
| _sources: Computation[] | null; | ||
| /** @internal */ | ||
| _observers: Computation[] | null; | ||
| /** @internal */ | ||
| _compute: (() => T) | null; | ||
| /** @internal */ | ||
| _changed: (prev: T, next: T) => boolean; | ||
@@ -38,8 +45,15 @@ /** read */ | ||
| [SCOPE]: Scope | null; | ||
| /** @internal */ | ||
| _state: number; | ||
| /** @internal */ | ||
| _compute: unknown; | ||
| /** @internal */ | ||
| _prevSibling: Scope | null; | ||
| /** @internal */ | ||
| _nextSibling: Scope | null; | ||
| /** @internal */ | ||
| _context: ContextRecord | null; | ||
| /** @internal */ | ||
| _disposal: Disposable | Disposable[] | null; | ||
| append(scope: Scope): void; | ||
| } | ||
@@ -46,0 +60,0 @@ export interface Dispose { |
+1
-1
@@ -5,3 +5,3 @@ { | ||
| "license": "MIT", | ||
| "version": "5.6.5", | ||
| "version": "5.7.0", | ||
| "type": "module", | ||
@@ -8,0 +8,0 @@ "types": "dist/types/index.d.ts", |
+3
-2
@@ -254,4 +254,4 @@ # Signals | ||
| Returns the current value stored inside the given compute function without triggering any | ||
| dependencies. Use [`untrack`](#untrack) if you want to also disable scope tracking. | ||
| Returns the current value stored inside the given compute function whilst disabling observer tracking, i.e. | ||
| without triggering any dependencies. Use [`untrack`](#untrack) if you want to also disable scope tracking. | ||
@@ -471,2 +471,3 @@ ```js | ||
| isReadSignal(() => {}); | ||
| isReadSignal(signal(10)); | ||
| isReadSignal(computed(() => 10)); | ||
@@ -473,0 +474,0 @@ isReadSignal(readonly(signal(10))); |
| // src/symbols.ts | ||
| var SCOPE = Symbol("SCOPE" ); | ||
| // src/core.ts | ||
| var scheduledEffects = false; | ||
| var runningEffects = false; | ||
| var currentScope = null; | ||
| var currentObserver = null; | ||
| var currentObservers = null; | ||
| var currentObserversIndex = 0; | ||
| var effects = []; | ||
| var NOOP = () => { | ||
| }; | ||
| var HANDLERS = Symbol("ERROR_HANDLERS" ); | ||
| var STATE_CLEAN = 0; | ||
| var STATE_CHECK = 1; | ||
| var STATE_DIRTY = 2; | ||
| var STATE_DISPOSED = 3; | ||
| function flushEffects() { | ||
| scheduledEffects = true; | ||
| queueMicrotask(runEffects); | ||
| } | ||
| function runEffects() { | ||
| if (!effects.length) { | ||
| scheduledEffects = false; | ||
| return; | ||
| } | ||
| runningEffects = true; | ||
| for (let i = 0; i < effects.length; i++) { | ||
| if (!isZombie(effects[i])) | ||
| read.call(effects[i]); | ||
| } | ||
| effects = []; | ||
| scheduledEffects = false; | ||
| runningEffects = false; | ||
| } | ||
| function root(init) { | ||
| const scope = createScope(); | ||
| return compute(scope, !init.length ? init : init.bind(null, dispose.bind(scope)), null); | ||
| } | ||
| function peek(compute2) { | ||
| const prev = currentObserver; | ||
| currentObserver = null; | ||
| const result = compute2(); | ||
| currentObserver = prev; | ||
| return result; | ||
| } | ||
| function untrack(compute2) { | ||
| const prev = currentScope; | ||
| currentScope = null; | ||
| const result = peek(compute2); | ||
| currentScope = prev; | ||
| return result; | ||
| } | ||
| function tick() { | ||
| if (!runningEffects) | ||
| runEffects(); | ||
| } | ||
| function getScope() { | ||
| return currentScope; | ||
| } | ||
| function scoped(run, scope) { | ||
| try { | ||
| compute(scope, run, null); | ||
| } catch (error) { | ||
| handleError(scope, error); | ||
| } | ||
| } | ||
| function getContext(key) { | ||
| return lookup(currentScope, key); | ||
| } | ||
| function setContext(key, value) { | ||
| if (currentScope) | ||
| (currentScope._context ??= {})[key] = value; | ||
| } | ||
| function onError(handler) { | ||
| if (!currentScope) | ||
| return; | ||
| const context = currentScope._context ??= {}; | ||
| if (!context[HANDLERS]) | ||
| context[HANDLERS] = [handler]; | ||
| else | ||
| context[HANDLERS].push(handler); | ||
| } | ||
| function onDispose(disposable) { | ||
| if (!disposable || !currentScope) | ||
| return disposable || NOOP; | ||
| const node = currentScope; | ||
| if (!node._disposal) { | ||
| node._disposal = disposable; | ||
| } else if (Array.isArray(node._disposal)) { | ||
| node._disposal.push(disposable); | ||
| } else { | ||
| node._disposal = [node._disposal, disposable]; | ||
| } | ||
| return function removeDispose() { | ||
| if (node._state === STATE_DISPOSED) | ||
| return; | ||
| disposable.call(null); | ||
| if (isFunction(node._disposal)) { | ||
| node._disposal = null; | ||
| } else if (Array.isArray(node._disposal)) { | ||
| node._disposal.splice(node._disposal.indexOf(disposable), 1); | ||
| } | ||
| }; | ||
| } | ||
| var scopes = []; | ||
| function dispose(self = true) { | ||
| if (this._state === STATE_DISPOSED) | ||
| return; | ||
| let current = self ? this : this._nextSibling, head = self ? this._prevSibling : this; | ||
| if (current) { | ||
| scopes.push(this); | ||
| do { | ||
| if (current._disposal) | ||
| emptyDisposal(current); | ||
| if (current._sources) | ||
| removeSourceObservers(current, 0); | ||
| current[SCOPE] = null; | ||
| current._sources = null; | ||
| current._observers = null; | ||
| current._prevSibling = null; | ||
| current._context = null; | ||
| current._state = STATE_DISPOSED; | ||
| scopes.push(current); | ||
| current = current._nextSibling; | ||
| if (current) | ||
| current._prevSibling._nextSibling = null; | ||
| } while (current && scopes.includes(current[SCOPE])); | ||
| } | ||
| if (head) | ||
| head._nextSibling = current; | ||
| if (current) | ||
| current._prevSibling = head; | ||
| scopes = []; | ||
| } | ||
| function emptyDisposal(scope) { | ||
| try { | ||
| if (Array.isArray(scope._disposal)) { | ||
| for (let i = 0; i < scope._disposal.length; i++) { | ||
| const callable = scope._disposal[i]; | ||
| callable.call(callable); | ||
| } | ||
| } else { | ||
| scope._disposal.call(scope._disposal); | ||
| } | ||
| scope._disposal = null; | ||
| } catch (error) { | ||
| handleError(scope, error); | ||
| } | ||
| } | ||
| function compute(scope, compute2, observer) { | ||
| const prevScope = currentScope, prevObserver = currentObserver; | ||
| currentScope = scope; | ||
| currentObserver = observer; | ||
| try { | ||
| return compute2.call(scope); | ||
| } finally { | ||
| currentScope = prevScope; | ||
| currentObserver = prevObserver; | ||
| } | ||
| } | ||
| function lookup(scope, key) { | ||
| if (!scope) | ||
| return; | ||
| let current = scope, value; | ||
| while (current) { | ||
| value = current._context?.[key]; | ||
| if (value !== void 0) | ||
| return value; | ||
| current = current[SCOPE]; | ||
| } | ||
| } | ||
| function handleError(scope, error, depth) { | ||
| const handlers = lookup(scope, HANDLERS); | ||
| if (!handlers) | ||
| throw error; | ||
| try { | ||
| const coercedError = error instanceof Error ? error : Error(JSON.stringify(error)); | ||
| for (const handler of handlers) | ||
| handler(coercedError); | ||
| } catch (error2) { | ||
| handleError(scope[SCOPE], error2); | ||
| } | ||
| } | ||
| function read() { | ||
| if (this._state === STATE_DISPOSED) | ||
| return this._value; | ||
| if (currentObserver) { | ||
| if (!currentObservers && currentObserver._sources && currentObserver._sources[currentObserversIndex] == this) { | ||
| currentObserversIndex++; | ||
| } else if (!currentObservers) | ||
| currentObservers = [this]; | ||
| else | ||
| currentObservers.push(this); | ||
| } | ||
| if (this._compute) | ||
| shouldUpdate(this); | ||
| return this._value; | ||
| } | ||
| function write(newValue) { | ||
| const value = isFunction(newValue) ? newValue(this._value) : newValue; | ||
| if (this._changed(this._value, value)) { | ||
| this._value = value; | ||
| if (this._observers) { | ||
| for (let i = 0; i < this._observers.length; i++) { | ||
| notify(this._observers[i], STATE_DIRTY); | ||
| } | ||
| } | ||
| } | ||
| return this._value; | ||
| } | ||
| var ScopeNode = function Scope() { | ||
| this[SCOPE] = currentScope; | ||
| this._state = STATE_CLEAN; | ||
| this._nextSibling = null; | ||
| this._prevSibling = currentScope; | ||
| if (currentScope) { | ||
| const next = currentScope._nextSibling; | ||
| if (next) | ||
| next._prevSibling = this; | ||
| this._nextSibling = next; | ||
| currentScope._nextSibling = this; | ||
| } | ||
| }; | ||
| var ScopeProto = ScopeNode.prototype; | ||
| ScopeProto._context = null; | ||
| ScopeProto._compute = null; | ||
| ScopeProto._disposal = null; | ||
| function createScope() { | ||
| return new ScopeNode(); | ||
| } | ||
| var ComputeNode = function Computation(initialValue, compute2, options) { | ||
| ScopeNode.call(this); | ||
| this._state = compute2 ? STATE_DIRTY : STATE_CLEAN; | ||
| this._scoped = false; | ||
| this._init = false; | ||
| this._sources = null; | ||
| this._observers = null; | ||
| this._value = initialValue; | ||
| this.id = options?.id ?? (this._compute ? "computed" : "signal"); | ||
| if (compute2) | ||
| this._compute = compute2; | ||
| if (options) { | ||
| if (options.scoped) | ||
| this._scoped = true; | ||
| if (options.dirty) | ||
| this._changed = options.dirty; | ||
| } | ||
| }; | ||
| var ComputeProto = ComputeNode.prototype; | ||
| Object.setPrototypeOf(ComputeProto, ScopeProto); | ||
| ComputeProto._changed = isNotEqual; | ||
| ComputeProto.call = read; | ||
| function createComputation(initialValue, compute2, options) { | ||
| return new ComputeNode(initialValue, compute2, options); | ||
| } | ||
| function isNotEqual(a, b) { | ||
| return a !== b; | ||
| } | ||
| function isFunction(value) { | ||
| return typeof value === "function"; | ||
| } | ||
| function isZombie(node) { | ||
| let scope = node[SCOPE]; | ||
| while (scope) { | ||
| if (scope._compute && scope._state === STATE_DIRTY) | ||
| return true; | ||
| scope = scope[SCOPE]; | ||
| } | ||
| return false; | ||
| } | ||
| function shouldUpdate(node) { | ||
| if (node._state === STATE_CHECK) { | ||
| for (let i = 0; i < node._sources.length; i++) { | ||
| shouldUpdate(node._sources[i]); | ||
| if (node._state === STATE_DIRTY) { | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| if (node._state === STATE_DIRTY) | ||
| update(node); | ||
| else | ||
| node._state = STATE_CLEAN; | ||
| } | ||
| function update(node) { | ||
| let prevObservers = currentObservers, prevObserversIndex = currentObserversIndex; | ||
| currentObservers = null; | ||
| currentObserversIndex = 0; | ||
| try { | ||
| if (node._scoped) { | ||
| if (node._nextSibling && node._nextSibling[SCOPE] === node) | ||
| dispose.call(node, false); | ||
| if (node._disposal) | ||
| emptyDisposal(node); | ||
| if (node._context && node._context[HANDLERS]) | ||
| node._context[HANDLERS] = []; | ||
| } | ||
| const result = compute(node._scoped ? node : currentScope, node._compute, node); | ||
| if (currentObservers) { | ||
| if (node._sources) | ||
| removeSourceObservers(node, currentObserversIndex); | ||
| if (node._sources && currentObserversIndex > 0) { | ||
| node._sources.length = currentObserversIndex + currentObservers.length; | ||
| for (let i = 0; i < currentObservers.length; i++) { | ||
| node._sources[currentObserversIndex + i] = currentObservers[i]; | ||
| } | ||
| } else { | ||
| node._sources = currentObservers; | ||
| } | ||
| let source; | ||
| for (let i = currentObserversIndex; i < node._sources.length; i++) { | ||
| source = node._sources[i]; | ||
| if (!source._observers) | ||
| source._observers = [node]; | ||
| else | ||
| source._observers.push(node); | ||
| } | ||
| } else if (node._sources && currentObserversIndex < node._sources.length) { | ||
| removeSourceObservers(node, currentObserversIndex); | ||
| node._sources.length = currentObserversIndex; | ||
| } | ||
| if (!node._scoped && node._init) { | ||
| write.call(node, result); | ||
| } else { | ||
| node._value = result; | ||
| node._init = true; | ||
| } | ||
| } catch (error) { | ||
| if (!node._init && typeof node._value === "undefined") { | ||
| console.error( | ||
| `computed \`${node.id}\` threw error during first run, this can be fatal. | ||
| Solutions: | ||
| 1. Set the \`initial\` option to silence this error`, | ||
| "\n2. Or, use an `effect` if the return value is not being used", | ||
| "\n\n", | ||
| error | ||
| ); | ||
| } | ||
| handleError(node, error); | ||
| return; | ||
| } | ||
| currentObservers = prevObservers; | ||
| currentObserversIndex = prevObserversIndex; | ||
| node._state = STATE_CLEAN; | ||
| } | ||
| function notify(node, state) { | ||
| if (node._state >= state) | ||
| return; | ||
| if (node._scoped && node._state === STATE_CLEAN) { | ||
| effects.push(node); | ||
| if (!scheduledEffects) | ||
| flushEffects(); | ||
| } | ||
| node._state = state; | ||
| if (node._observers) { | ||
| for (let i = 0; i < node._observers.length; i++) { | ||
| notify(node._observers[i], STATE_CHECK); | ||
| } | ||
| } | ||
| } | ||
| function removeSourceObservers(node, index) { | ||
| let source, swap; | ||
| for (let i = index; i < node._sources.length; i++) { | ||
| source = node._sources[i]; | ||
| if (source._observers) { | ||
| swap = source._observers.indexOf(node); | ||
| source._observers[swap] = source._observers[source._observers.length - 1]; | ||
| source._observers.pop(); | ||
| } | ||
| } | ||
| } | ||
| // src/signals.ts | ||
| function signal(initialValue, options) { | ||
| const node = createComputation(initialValue, null, options), signal2 = read.bind(node); | ||
| signal2.node = node; | ||
| signal2.set = write.bind(node); | ||
| return signal2; | ||
| } | ||
| function isReadSignal(fn) { | ||
| return isFunction(fn); | ||
| } | ||
| function computed(compute2, options) { | ||
| { | ||
| const node = createComputation( | ||
| options?.initial, | ||
| compute2, | ||
| options | ||
| ); | ||
| const signal2 = read.bind(node); | ||
| signal2.node = node; | ||
| return signal2; | ||
| } | ||
| } | ||
| function effect(effect2, options) { | ||
| const signal2 = createComputation( | ||
| null, | ||
| function runEffect() { | ||
| let effectResult = effect2(); | ||
| isFunction(effectResult) && onDispose(effectResult); | ||
| return null; | ||
| }, | ||
| { id: options?.id ?? "effect" } | ||
| ); | ||
| signal2._scoped = true; | ||
| read.call(signal2); | ||
| { | ||
| return function stopEffect() { | ||
| dispose.call(signal2, true); | ||
| }; | ||
| } | ||
| } | ||
| function readonly(signal2) { | ||
| { | ||
| const readonly2 = () => signal2(); | ||
| readonly2.node = signal2.node; | ||
| return readonly2; | ||
| } | ||
| } | ||
| function isWriteSignal(fn) { | ||
| return isReadSignal(fn) && "set" in fn; | ||
| } | ||
| export { SCOPE, compute, computed, createComputation, createScope, dispose, effect, getContext, getScope, isFunction, isNotEqual, isReadSignal, isWriteSignal, onDispose, onError, peek, read, readonly, root, scoped, setContext, signal, tick, untrack, write }; |
| // src/symbols.ts | ||
| var SCOPE = Symbol(0); | ||
| // src/core.ts | ||
| var scheduledEffects = false; | ||
| var runningEffects = false; | ||
| var currentScope = null; | ||
| var currentObserver = null; | ||
| var currentObservers = null; | ||
| var currentObserversIndex = 0; | ||
| var effects = []; | ||
| var NOOP = () => { | ||
| }; | ||
| var HANDLERS = Symbol(0); | ||
| var STATE_CLEAN = 0; | ||
| var STATE_CHECK = 1; | ||
| var STATE_DIRTY = 2; | ||
| var STATE_DISPOSED = 3; | ||
| function flushEffects() { | ||
| scheduledEffects = true; | ||
| queueMicrotask(runEffects); | ||
| } | ||
| function runEffects() { | ||
| if (!effects.length) { | ||
| scheduledEffects = false; | ||
| return; | ||
| } | ||
| runningEffects = true; | ||
| for (let i = 0; i < effects.length; i++) { | ||
| if (!isZombie(effects[i])) | ||
| read.call(effects[i]); | ||
| } | ||
| effects = []; | ||
| scheduledEffects = false; | ||
| runningEffects = false; | ||
| } | ||
| function root(init) { | ||
| const scope = createScope(); | ||
| return compute(scope, !init.length ? init : init.bind(null, dispose.bind(scope)), null); | ||
| } | ||
| function peek(compute2) { | ||
| const prev = currentObserver; | ||
| currentObserver = null; | ||
| const result = compute2(); | ||
| currentObserver = prev; | ||
| return result; | ||
| } | ||
| function untrack(compute2) { | ||
| const prev = currentScope; | ||
| currentScope = null; | ||
| const result = peek(compute2); | ||
| currentScope = prev; | ||
| return result; | ||
| } | ||
| function tick() { | ||
| if (!runningEffects) | ||
| runEffects(); | ||
| } | ||
| function getScope() { | ||
| return currentScope; | ||
| } | ||
| function scoped(run, scope) { | ||
| try { | ||
| compute(scope, run, null); | ||
| } catch (error) { | ||
| handleError(scope, error); | ||
| } | ||
| } | ||
| function getContext(key) { | ||
| return lookup(currentScope, key); | ||
| } | ||
| function setContext(key, value) { | ||
| if (currentScope) | ||
| (currentScope.k ??= {})[key] = value; | ||
| } | ||
| function onError(handler) { | ||
| if (!currentScope) | ||
| return; | ||
| const context = currentScope.k ??= {}; | ||
| if (!context[HANDLERS]) | ||
| context[HANDLERS] = [handler]; | ||
| else | ||
| context[HANDLERS].push(handler); | ||
| } | ||
| function onDispose(disposable) { | ||
| if (!disposable || !currentScope) | ||
| return disposable || NOOP; | ||
| const node = currentScope; | ||
| if (!node.a) { | ||
| node.a = disposable; | ||
| } else if (Array.isArray(node.a)) { | ||
| node.a.push(disposable); | ||
| } else { | ||
| node.a = [node.a, disposable]; | ||
| } | ||
| return function removeDispose() { | ||
| if (node.f === STATE_DISPOSED) | ||
| return; | ||
| disposable.call(null); | ||
| if (isFunction(node.a)) { | ||
| node.a = null; | ||
| } else if (Array.isArray(node.a)) { | ||
| node.a.splice(node.a.indexOf(disposable), 1); | ||
| } | ||
| }; | ||
| } | ||
| var scopes = []; | ||
| function dispose(self = true) { | ||
| if (this.f === STATE_DISPOSED) | ||
| return; | ||
| let current = self ? this : this.i, head = self ? this.m : this; | ||
| if (current) { | ||
| scopes.push(this); | ||
| do { | ||
| if (current.a) | ||
| emptyDisposal(current); | ||
| if (current.c) | ||
| removeSourceObservers(current, 0); | ||
| current[SCOPE] = null; | ||
| current.c = null; | ||
| current.d = null; | ||
| current.m = null; | ||
| current.k = null; | ||
| current.f = STATE_DISPOSED; | ||
| scopes.push(current); | ||
| current = current.i; | ||
| if (current) | ||
| current.m.i = null; | ||
| } while (current && scopes.includes(current[SCOPE])); | ||
| } | ||
| if (head) | ||
| head.i = current; | ||
| if (current) | ||
| current.m = head; | ||
| scopes = []; | ||
| } | ||
| function emptyDisposal(scope) { | ||
| try { | ||
| if (Array.isArray(scope.a)) { | ||
| for (let i = 0; i < scope.a.length; i++) { | ||
| const callable = scope.a[i]; | ||
| callable.call(callable); | ||
| } | ||
| } else { | ||
| scope.a.call(scope.a); | ||
| } | ||
| scope.a = null; | ||
| } catch (error) { | ||
| handleError(scope, error); | ||
| } | ||
| } | ||
| function compute(scope, compute2, observer) { | ||
| const prevScope = currentScope, prevObserver = currentObserver; | ||
| currentScope = scope; | ||
| currentObserver = observer; | ||
| try { | ||
| return compute2.call(scope); | ||
| } finally { | ||
| currentScope = prevScope; | ||
| currentObserver = prevObserver; | ||
| } | ||
| } | ||
| function lookup(scope, key) { | ||
| if (!scope) | ||
| return; | ||
| let current = scope, value; | ||
| while (current) { | ||
| value = current.k?.[key]; | ||
| if (value !== void 0) | ||
| return value; | ||
| current = current[SCOPE]; | ||
| } | ||
| } | ||
| function handleError(scope, error, depth) { | ||
| const handlers = lookup(scope, HANDLERS); | ||
| if (!handlers) | ||
| throw error; | ||
| try { | ||
| const coercedError = error instanceof Error ? error : Error(JSON.stringify(error)); | ||
| for (const handler of handlers) | ||
| handler(coercedError); | ||
| } catch (error2) { | ||
| handleError(scope[SCOPE], error2); | ||
| } | ||
| } | ||
| function read() { | ||
| if (this.f === STATE_DISPOSED) | ||
| return this.j; | ||
| if (currentObserver) { | ||
| if (!currentObservers && currentObserver.c && currentObserver.c[currentObserversIndex] == this) { | ||
| currentObserversIndex++; | ||
| } else if (!currentObservers) | ||
| currentObservers = [this]; | ||
| else | ||
| currentObservers.push(this); | ||
| } | ||
| if (this.p) | ||
| shouldUpdate(this); | ||
| return this.j; | ||
| } | ||
| function write(newValue) { | ||
| const value = isFunction(newValue) ? newValue(this.j) : newValue; | ||
| if (this.q(this.j, value)) { | ||
| this.j = value; | ||
| if (this.d) { | ||
| for (let i = 0; i < this.d.length; i++) { | ||
| notify(this.d[i], STATE_DIRTY); | ||
| } | ||
| } | ||
| } | ||
| return this.j; | ||
| } | ||
| var ScopeNode = function Scope() { | ||
| this[SCOPE] = currentScope; | ||
| this.f = STATE_CLEAN; | ||
| this.i = null; | ||
| this.m = currentScope; | ||
| if (currentScope) { | ||
| const next = currentScope.i; | ||
| if (next) | ||
| next.m = this; | ||
| this.i = next; | ||
| currentScope.i = this; | ||
| } | ||
| }; | ||
| var ScopeProto = ScopeNode.prototype; | ||
| ScopeProto.k = null; | ||
| ScopeProto.p = null; | ||
| ScopeProto.a = null; | ||
| function createScope() { | ||
| return new ScopeNode(); | ||
| } | ||
| var ComputeNode = function Computation(initialValue, compute2, options) { | ||
| ScopeNode.call(this); | ||
| this.f = compute2 ? STATE_DIRTY : STATE_CLEAN; | ||
| this.l = false; | ||
| this.t = false; | ||
| this.c = null; | ||
| this.d = null; | ||
| this.j = initialValue; | ||
| if (compute2) | ||
| this.p = compute2; | ||
| if (options) { | ||
| if (options.scoped) | ||
| this.l = true; | ||
| if (options.dirty) | ||
| this.q = options.dirty; | ||
| } | ||
| }; | ||
| var ComputeProto = ComputeNode.prototype; | ||
| Object.setPrototypeOf(ComputeProto, ScopeProto); | ||
| ComputeProto.q = isNotEqual; | ||
| ComputeProto.call = read; | ||
| function createComputation(initialValue, compute2, options) { | ||
| return new ComputeNode(initialValue, compute2, options); | ||
| } | ||
| function isNotEqual(a, b) { | ||
| return a !== b; | ||
| } | ||
| function isFunction(value) { | ||
| return typeof value === "function"; | ||
| } | ||
| function isZombie(node) { | ||
| let scope = node[SCOPE]; | ||
| while (scope) { | ||
| if (scope.p && scope.f === STATE_DIRTY) | ||
| return true; | ||
| scope = scope[SCOPE]; | ||
| } | ||
| return false; | ||
| } | ||
| function shouldUpdate(node) { | ||
| if (node.f === STATE_CHECK) { | ||
| for (let i = 0; i < node.c.length; i++) { | ||
| shouldUpdate(node.c[i]); | ||
| if (node.f === STATE_DIRTY) { | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| if (node.f === STATE_DIRTY) | ||
| update(node); | ||
| else | ||
| node.f = STATE_CLEAN; | ||
| } | ||
| function update(node) { | ||
| let prevObservers = currentObservers, prevObserversIndex = currentObserversIndex; | ||
| currentObservers = null; | ||
| currentObserversIndex = 0; | ||
| try { | ||
| if (node.l) { | ||
| if (node.i && node.i[SCOPE] === node) | ||
| dispose.call(node, false); | ||
| if (node.a) | ||
| emptyDisposal(node); | ||
| if (node.k && node.k[HANDLERS]) | ||
| node.k[HANDLERS] = []; | ||
| } | ||
| const result = compute(node.l ? node : currentScope, node.p, node); | ||
| if (currentObservers) { | ||
| if (node.c) | ||
| removeSourceObservers(node, currentObserversIndex); | ||
| if (node.c && currentObserversIndex > 0) { | ||
| node.c.length = currentObserversIndex + currentObservers.length; | ||
| for (let i = 0; i < currentObservers.length; i++) { | ||
| node.c[currentObserversIndex + i] = currentObservers[i]; | ||
| } | ||
| } else { | ||
| node.c = currentObservers; | ||
| } | ||
| let source; | ||
| for (let i = currentObserversIndex; i < node.c.length; i++) { | ||
| source = node.c[i]; | ||
| if (!source.d) | ||
| source.d = [node]; | ||
| else | ||
| source.d.push(node); | ||
| } | ||
| } else if (node.c && currentObserversIndex < node.c.length) { | ||
| removeSourceObservers(node, currentObserversIndex); | ||
| node.c.length = currentObserversIndex; | ||
| } | ||
| if (!node.l && node.t) { | ||
| write.call(node, result); | ||
| } else { | ||
| node.j = result; | ||
| node.t = true; | ||
| } | ||
| } catch (error) { | ||
| handleError(node, error); | ||
| return; | ||
| } | ||
| currentObservers = prevObservers; | ||
| currentObserversIndex = prevObserversIndex; | ||
| node.f = STATE_CLEAN; | ||
| } | ||
| function notify(node, state) { | ||
| if (node.f >= state) | ||
| return; | ||
| if (node.l && node.f === STATE_CLEAN) { | ||
| effects.push(node); | ||
| if (!scheduledEffects) | ||
| flushEffects(); | ||
| } | ||
| node.f = state; | ||
| if (node.d) { | ||
| for (let i = 0; i < node.d.length; i++) { | ||
| notify(node.d[i], STATE_CHECK); | ||
| } | ||
| } | ||
| } | ||
| function removeSourceObservers(node, index) { | ||
| let source, swap; | ||
| for (let i = index; i < node.c.length; i++) { | ||
| source = node.c[i]; | ||
| if (source.d) { | ||
| swap = source.d.indexOf(node); | ||
| source.d[swap] = source.d[source.d.length - 1]; | ||
| source.d.pop(); | ||
| } | ||
| } | ||
| } | ||
| // src/signals.ts | ||
| function signal(initialValue, options) { | ||
| const node = createComputation(initialValue, null, options), signal2 = read.bind(node); | ||
| signal2.set = write.bind(node); | ||
| return signal2; | ||
| } | ||
| function isReadSignal(fn) { | ||
| return isFunction(fn); | ||
| } | ||
| function computed(compute2, options) { | ||
| return read.bind( | ||
| createComputation( | ||
| options?.initial, | ||
| compute2, | ||
| options | ||
| ) | ||
| ); | ||
| } | ||
| function effect(effect2, options) { | ||
| const signal2 = createComputation( | ||
| null, | ||
| function runEffect() { | ||
| let effectResult = effect2(); | ||
| isFunction(effectResult) && onDispose(effectResult); | ||
| return null; | ||
| }, | ||
| void 0 | ||
| ); | ||
| signal2.l = true; | ||
| read.call(signal2); | ||
| return dispose.bind(signal2, true); | ||
| } | ||
| function readonly(signal2) { | ||
| return () => signal2(); | ||
| } | ||
| function isWriteSignal(fn) { | ||
| return isReadSignal(fn) && "set" in fn; | ||
| } | ||
| export { SCOPE, compute, computed, createComputation, createScope, dispose, effect, getContext, getScope, isFunction, isNotEqual, isReadSignal, isWriteSignal, onDispose, onError, peek, read, readonly, root, scoped, setContext, signal, tick, untrack, write }; |
| 'use strict'; | ||
| // src/symbols.ts | ||
| var SCOPE = Symbol(0); | ||
| // src/core.ts | ||
| var scheduledEffects = false; | ||
| var runningEffects = false; | ||
| var currentScope = null; | ||
| var currentObserver = null; | ||
| var currentObservers = null; | ||
| var currentObserversIndex = 0; | ||
| var effects = []; | ||
| var NOOP = () => { | ||
| }; | ||
| var HANDLERS = Symbol(0); | ||
| var STATE_CLEAN = 0; | ||
| var STATE_CHECK = 1; | ||
| var STATE_DIRTY = 2; | ||
| var STATE_DISPOSED = 3; | ||
| function flushEffects() { | ||
| scheduledEffects = true; | ||
| queueMicrotask(runEffects); | ||
| } | ||
| function runEffects() { | ||
| if (!effects.length) { | ||
| scheduledEffects = false; | ||
| return; | ||
| } | ||
| runningEffects = true; | ||
| for (let i = 0; i < effects.length; i++) { | ||
| if (!isZombie(effects[i])) | ||
| read.call(effects[i]); | ||
| } | ||
| effects = []; | ||
| scheduledEffects = false; | ||
| runningEffects = false; | ||
| } | ||
| function root(init) { | ||
| const scope = createScope(); | ||
| return compute(scope, !init.length ? init : init.bind(null, dispose.bind(scope)), null); | ||
| } | ||
| function peek(compute2) { | ||
| const prev = currentObserver; | ||
| currentObserver = null; | ||
| const result = compute2(); | ||
| currentObserver = prev; | ||
| return result; | ||
| } | ||
| function untrack(compute2) { | ||
| const prev = currentScope; | ||
| currentScope = null; | ||
| const result = peek(compute2); | ||
| currentScope = prev; | ||
| return result; | ||
| } | ||
| function tick() { | ||
| if (!runningEffects) | ||
| runEffects(); | ||
| } | ||
| function getScope() { | ||
| return currentScope; | ||
| } | ||
| function scoped(run, scope) { | ||
| try { | ||
| compute(scope, run, null); | ||
| } catch (error) { | ||
| handleError(scope, error); | ||
| } | ||
| } | ||
| function getContext(key) { | ||
| return lookup(currentScope, key); | ||
| } | ||
| function setContext(key, value) { | ||
| if (currentScope) | ||
| (currentScope.k ??= {})[key] = value; | ||
| } | ||
| function onError(handler) { | ||
| if (!currentScope) | ||
| return; | ||
| const context = currentScope.k ??= {}; | ||
| if (!context[HANDLERS]) | ||
| context[HANDLERS] = [handler]; | ||
| else | ||
| context[HANDLERS].push(handler); | ||
| } | ||
| function onDispose(disposable) { | ||
| if (!disposable || !currentScope) | ||
| return disposable || NOOP; | ||
| const node = currentScope; | ||
| if (!node.a) { | ||
| node.a = disposable; | ||
| } else if (Array.isArray(node.a)) { | ||
| node.a.push(disposable); | ||
| } else { | ||
| node.a = [node.a, disposable]; | ||
| } | ||
| return function removeDispose() { | ||
| if (node.f === STATE_DISPOSED) | ||
| return; | ||
| disposable.call(null); | ||
| if (isFunction(node.a)) { | ||
| node.a = null; | ||
| } else if (Array.isArray(node.a)) { | ||
| node.a.splice(node.a.indexOf(disposable), 1); | ||
| } | ||
| }; | ||
| } | ||
| var scopes = []; | ||
| function dispose(self = true) { | ||
| if (this.f === STATE_DISPOSED) | ||
| return; | ||
| let current = self ? this : this.i, head = self ? this.m : this; | ||
| if (current) { | ||
| scopes.push(this); | ||
| do { | ||
| if (current.a) | ||
| emptyDisposal(current); | ||
| if (current.c) | ||
| removeSourceObservers(current, 0); | ||
| current[SCOPE] = null; | ||
| current.c = null; | ||
| current.d = null; | ||
| current.m = null; | ||
| current.k = null; | ||
| current.f = STATE_DISPOSED; | ||
| scopes.push(current); | ||
| current = current.i; | ||
| if (current) | ||
| current.m.i = null; | ||
| } while (current && scopes.includes(current[SCOPE])); | ||
| } | ||
| if (head) | ||
| head.i = current; | ||
| if (current) | ||
| current.m = head; | ||
| scopes = []; | ||
| } | ||
| function emptyDisposal(scope) { | ||
| try { | ||
| if (Array.isArray(scope.a)) { | ||
| for (let i = 0; i < scope.a.length; i++) { | ||
| const callable = scope.a[i]; | ||
| callable.call(callable); | ||
| } | ||
| } else { | ||
| scope.a.call(scope.a); | ||
| } | ||
| scope.a = null; | ||
| } catch (error) { | ||
| handleError(scope, error); | ||
| } | ||
| } | ||
| function compute(scope, compute2, observer) { | ||
| const prevScope = currentScope, prevObserver = currentObserver; | ||
| currentScope = scope; | ||
| currentObserver = observer; | ||
| try { | ||
| return compute2.call(scope); | ||
| } finally { | ||
| currentScope = prevScope; | ||
| currentObserver = prevObserver; | ||
| } | ||
| } | ||
| function lookup(scope, key) { | ||
| var _a; | ||
| if (!scope) | ||
| return; | ||
| let current = scope, value; | ||
| while (current) { | ||
| value = (_a = current.k) == null ? void 0 : _a[key]; | ||
| if (value !== void 0) | ||
| return value; | ||
| current = current[SCOPE]; | ||
| } | ||
| } | ||
| function handleError(scope, error, depth) { | ||
| const handlers = lookup(scope, HANDLERS); | ||
| if (!handlers) | ||
| throw error; | ||
| try { | ||
| const coercedError = error instanceof Error ? error : Error(JSON.stringify(error)); | ||
| for (const handler of handlers) | ||
| handler(coercedError); | ||
| } catch (error2) { | ||
| handleError(scope[SCOPE], error2); | ||
| } | ||
| } | ||
| function read() { | ||
| if (this.f === STATE_DISPOSED) | ||
| return this.j; | ||
| if (currentObserver) { | ||
| if (!currentObservers && currentObserver.c && currentObserver.c[currentObserversIndex] == this) { | ||
| currentObserversIndex++; | ||
| } else if (!currentObservers) | ||
| currentObservers = [this]; | ||
| else | ||
| currentObservers.push(this); | ||
| } | ||
| if (this.p) | ||
| shouldUpdate(this); | ||
| return this.j; | ||
| } | ||
| function write(newValue) { | ||
| const value = isFunction(newValue) ? newValue(this.j) : newValue; | ||
| if (this.q(this.j, value)) { | ||
| this.j = value; | ||
| if (this.d) { | ||
| for (let i = 0; i < this.d.length; i++) { | ||
| notify(this.d[i], STATE_DIRTY); | ||
| } | ||
| } | ||
| } | ||
| return this.j; | ||
| } | ||
| var ScopeNode = function Scope() { | ||
| this[SCOPE] = currentScope; | ||
| this.f = STATE_CLEAN; | ||
| this.i = null; | ||
| this.m = currentScope; | ||
| if (currentScope) { | ||
| const next = currentScope.i; | ||
| if (next) | ||
| next.m = this; | ||
| this.i = next; | ||
| currentScope.i = this; | ||
| } | ||
| }; | ||
| var ScopeProto = ScopeNode.prototype; | ||
| ScopeProto.k = null; | ||
| ScopeProto.p = null; | ||
| ScopeProto.a = null; | ||
| function createScope() { | ||
| return new ScopeNode(); | ||
| } | ||
| var ComputeNode = function Computation(initialValue, compute2, options) { | ||
| ScopeNode.call(this); | ||
| this.f = compute2 ? STATE_DIRTY : STATE_CLEAN; | ||
| this.l = false; | ||
| this.t = false; | ||
| this.c = null; | ||
| this.d = null; | ||
| this.j = initialValue; | ||
| if (compute2) | ||
| this.p = compute2; | ||
| if (options) { | ||
| if (options.scoped) | ||
| this.l = true; | ||
| if (options.dirty) | ||
| this.q = options.dirty; | ||
| } | ||
| }; | ||
| var ComputeProto = ComputeNode.prototype; | ||
| Object.setPrototypeOf(ComputeProto, ScopeProto); | ||
| ComputeProto.q = isNotEqual; | ||
| ComputeProto.call = read; | ||
| function createComputation(initialValue, compute2, options) { | ||
| return new ComputeNode(initialValue, compute2, options); | ||
| } | ||
| function isNotEqual(a, b) { | ||
| return a !== b; | ||
| } | ||
| function isFunction(value) { | ||
| return typeof value === "function"; | ||
| } | ||
| function isZombie(node) { | ||
| let scope = node[SCOPE]; | ||
| while (scope) { | ||
| if (scope.p && scope.f === STATE_DIRTY) | ||
| return true; | ||
| scope = scope[SCOPE]; | ||
| } | ||
| return false; | ||
| } | ||
| function shouldUpdate(node) { | ||
| if (node.f === STATE_CHECK) { | ||
| for (let i = 0; i < node.c.length; i++) { | ||
| shouldUpdate(node.c[i]); | ||
| if (node.f === STATE_DIRTY) { | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| if (node.f === STATE_DIRTY) | ||
| update(node); | ||
| else | ||
| node.f = STATE_CLEAN; | ||
| } | ||
| function update(node) { | ||
| let prevObservers = currentObservers, prevObserversIndex = currentObserversIndex; | ||
| currentObservers = null; | ||
| currentObserversIndex = 0; | ||
| try { | ||
| if (node.l) { | ||
| if (node.i && node.i[SCOPE] === node) | ||
| dispose.call(node, false); | ||
| if (node.a) | ||
| emptyDisposal(node); | ||
| if (node.k && node.k[HANDLERS]) | ||
| node.k[HANDLERS] = []; | ||
| } | ||
| const result = compute(node.l ? node : currentScope, node.p, node); | ||
| if (currentObservers) { | ||
| if (node.c) | ||
| removeSourceObservers(node, currentObserversIndex); | ||
| if (node.c && currentObserversIndex > 0) { | ||
| node.c.length = currentObserversIndex + currentObservers.length; | ||
| for (let i = 0; i < currentObservers.length; i++) { | ||
| node.c[currentObserversIndex + i] = currentObservers[i]; | ||
| } | ||
| } else { | ||
| node.c = currentObservers; | ||
| } | ||
| let source; | ||
| for (let i = currentObserversIndex; i < node.c.length; i++) { | ||
| source = node.c[i]; | ||
| if (!source.d) | ||
| source.d = [node]; | ||
| else | ||
| source.d.push(node); | ||
| } | ||
| } else if (node.c && currentObserversIndex < node.c.length) { | ||
| removeSourceObservers(node, currentObserversIndex); | ||
| node.c.length = currentObserversIndex; | ||
| } | ||
| if (!node.l && node.t) { | ||
| write.call(node, result); | ||
| } else { | ||
| node.j = result; | ||
| node.t = true; | ||
| } | ||
| } catch (error) { | ||
| handleError(node, error); | ||
| return; | ||
| } | ||
| currentObservers = prevObservers; | ||
| currentObserversIndex = prevObserversIndex; | ||
| node.f = STATE_CLEAN; | ||
| } | ||
| function notify(node, state) { | ||
| if (node.f >= state) | ||
| return; | ||
| if (node.l && node.f === STATE_CLEAN) { | ||
| effects.push(node); | ||
| if (!scheduledEffects) | ||
| flushEffects(); | ||
| } | ||
| node.f = state; | ||
| if (node.d) { | ||
| for (let i = 0; i < node.d.length; i++) { | ||
| notify(node.d[i], STATE_CHECK); | ||
| } | ||
| } | ||
| } | ||
| function removeSourceObservers(node, index) { | ||
| let source, swap; | ||
| for (let i = index; i < node.c.length; i++) { | ||
| source = node.c[i]; | ||
| if (source.d) { | ||
| swap = source.d.indexOf(node); | ||
| source.d[swap] = source.d[source.d.length - 1]; | ||
| source.d.pop(); | ||
| } | ||
| } | ||
| } | ||
| // src/signals.ts | ||
| function signal(initialValue, options) { | ||
| const node = createComputation(initialValue, null, options), signal2 = read.bind(node); | ||
| signal2.set = write.bind(node); | ||
| return signal2; | ||
| } | ||
| function isReadSignal(fn) { | ||
| return isFunction(fn); | ||
| } | ||
| function computed(compute2, options) { | ||
| return read.bind( | ||
| createComputation( | ||
| options == null ? void 0 : options.initial, | ||
| compute2, | ||
| options | ||
| ) | ||
| ); | ||
| } | ||
| function effect(effect2, options) { | ||
| return () => { | ||
| }; | ||
| } | ||
| function readonly(signal2) { | ||
| return () => signal2(); | ||
| } | ||
| function isWriteSignal(fn) { | ||
| return isReadSignal(fn) && "set" in fn; | ||
| } | ||
| exports.SCOPE = SCOPE; | ||
| exports.compute = compute; | ||
| exports.computed = computed; | ||
| exports.createComputation = createComputation; | ||
| exports.createScope = createScope; | ||
| exports.dispose = dispose; | ||
| exports.effect = effect; | ||
| exports.getContext = getContext; | ||
| exports.getScope = getScope; | ||
| exports.isFunction = isFunction; | ||
| exports.isNotEqual = isNotEqual; | ||
| exports.isReadSignal = isReadSignal; | ||
| exports.isWriteSignal = isWriteSignal; | ||
| exports.onDispose = onDispose; | ||
| exports.onError = onError; | ||
| exports.peek = peek; | ||
| exports.read = read; | ||
| exports.readonly = readonly; | ||
| exports.root = root; | ||
| exports.scoped = scoped; | ||
| exports.setContext = setContext; | ||
| exports.signal = signal; | ||
| exports.tick = tick; | ||
| exports.untrack = untrack; | ||
| exports.write = write; |
| // src/symbols.ts | ||
| var SCOPE = Symbol(0); | ||
| // src/core.ts | ||
| var scheduledEffects = false; | ||
| var runningEffects = false; | ||
| var currentScope = null; | ||
| var currentObserver = null; | ||
| var currentObservers = null; | ||
| var currentObserversIndex = 0; | ||
| var effects = []; | ||
| var NOOP = () => { | ||
| }; | ||
| var HANDLERS = Symbol(0); | ||
| var STATE_CLEAN = 0; | ||
| var STATE_CHECK = 1; | ||
| var STATE_DIRTY = 2; | ||
| var STATE_DISPOSED = 3; | ||
| function flushEffects() { | ||
| scheduledEffects = true; | ||
| queueMicrotask(runEffects); | ||
| } | ||
| function runEffects() { | ||
| if (!effects.length) { | ||
| scheduledEffects = false; | ||
| return; | ||
| } | ||
| runningEffects = true; | ||
| for (let i = 0; i < effects.length; i++) { | ||
| if (!isZombie(effects[i])) | ||
| read.call(effects[i]); | ||
| } | ||
| effects = []; | ||
| scheduledEffects = false; | ||
| runningEffects = false; | ||
| } | ||
| function root(init) { | ||
| const scope = createScope(); | ||
| return compute(scope, !init.length ? init : init.bind(null, dispose.bind(scope)), null); | ||
| } | ||
| function peek(compute2) { | ||
| const prev = currentObserver; | ||
| currentObserver = null; | ||
| const result = compute2(); | ||
| currentObserver = prev; | ||
| return result; | ||
| } | ||
| function untrack(compute2) { | ||
| const prev = currentScope; | ||
| currentScope = null; | ||
| const result = peek(compute2); | ||
| currentScope = prev; | ||
| return result; | ||
| } | ||
| function tick() { | ||
| if (!runningEffects) | ||
| runEffects(); | ||
| } | ||
| function getScope() { | ||
| return currentScope; | ||
| } | ||
| function scoped(run, scope) { | ||
| try { | ||
| compute(scope, run, null); | ||
| } catch (error) { | ||
| handleError(scope, error); | ||
| } | ||
| } | ||
| function getContext(key) { | ||
| return lookup(currentScope, key); | ||
| } | ||
| function setContext(key, value) { | ||
| if (currentScope) | ||
| (currentScope.k ??= {})[key] = value; | ||
| } | ||
| function onError(handler) { | ||
| if (!currentScope) | ||
| return; | ||
| const context = currentScope.k ??= {}; | ||
| if (!context[HANDLERS]) | ||
| context[HANDLERS] = [handler]; | ||
| else | ||
| context[HANDLERS].push(handler); | ||
| } | ||
| function onDispose(disposable) { | ||
| if (!disposable || !currentScope) | ||
| return disposable || NOOP; | ||
| const node = currentScope; | ||
| if (!node.a) { | ||
| node.a = disposable; | ||
| } else if (Array.isArray(node.a)) { | ||
| node.a.push(disposable); | ||
| } else { | ||
| node.a = [node.a, disposable]; | ||
| } | ||
| return function removeDispose() { | ||
| if (node.f === STATE_DISPOSED) | ||
| return; | ||
| disposable.call(null); | ||
| if (isFunction(node.a)) { | ||
| node.a = null; | ||
| } else if (Array.isArray(node.a)) { | ||
| node.a.splice(node.a.indexOf(disposable), 1); | ||
| } | ||
| }; | ||
| } | ||
| var scopes = []; | ||
| function dispose(self = true) { | ||
| if (this.f === STATE_DISPOSED) | ||
| return; | ||
| let current = self ? this : this.i, head = self ? this.m : this; | ||
| if (current) { | ||
| scopes.push(this); | ||
| do { | ||
| if (current.a) | ||
| emptyDisposal(current); | ||
| if (current.c) | ||
| removeSourceObservers(current, 0); | ||
| current[SCOPE] = null; | ||
| current.c = null; | ||
| current.d = null; | ||
| current.m = null; | ||
| current.k = null; | ||
| current.f = STATE_DISPOSED; | ||
| scopes.push(current); | ||
| current = current.i; | ||
| if (current) | ||
| current.m.i = null; | ||
| } while (current && scopes.includes(current[SCOPE])); | ||
| } | ||
| if (head) | ||
| head.i = current; | ||
| if (current) | ||
| current.m = head; | ||
| scopes = []; | ||
| } | ||
| function emptyDisposal(scope) { | ||
| try { | ||
| if (Array.isArray(scope.a)) { | ||
| for (let i = 0; i < scope.a.length; i++) { | ||
| const callable = scope.a[i]; | ||
| callable.call(callable); | ||
| } | ||
| } else { | ||
| scope.a.call(scope.a); | ||
| } | ||
| scope.a = null; | ||
| } catch (error) { | ||
| handleError(scope, error); | ||
| } | ||
| } | ||
| function compute(scope, compute2, observer) { | ||
| const prevScope = currentScope, prevObserver = currentObserver; | ||
| currentScope = scope; | ||
| currentObserver = observer; | ||
| try { | ||
| return compute2.call(scope); | ||
| } finally { | ||
| currentScope = prevScope; | ||
| currentObserver = prevObserver; | ||
| } | ||
| } | ||
| function lookup(scope, key) { | ||
| var _a; | ||
| if (!scope) | ||
| return; | ||
| let current = scope, value; | ||
| while (current) { | ||
| value = (_a = current.k) == null ? void 0 : _a[key]; | ||
| if (value !== void 0) | ||
| return value; | ||
| current = current[SCOPE]; | ||
| } | ||
| } | ||
| function handleError(scope, error, depth) { | ||
| const handlers = lookup(scope, HANDLERS); | ||
| if (!handlers) | ||
| throw error; | ||
| try { | ||
| const coercedError = error instanceof Error ? error : Error(JSON.stringify(error)); | ||
| for (const handler of handlers) | ||
| handler(coercedError); | ||
| } catch (error2) { | ||
| handleError(scope[SCOPE], error2); | ||
| } | ||
| } | ||
| function read() { | ||
| if (this.f === STATE_DISPOSED) | ||
| return this.j; | ||
| if (currentObserver) { | ||
| if (!currentObservers && currentObserver.c && currentObserver.c[currentObserversIndex] == this) { | ||
| currentObserversIndex++; | ||
| } else if (!currentObservers) | ||
| currentObservers = [this]; | ||
| else | ||
| currentObservers.push(this); | ||
| } | ||
| if (this.p) | ||
| shouldUpdate(this); | ||
| return this.j; | ||
| } | ||
| function write(newValue) { | ||
| const value = isFunction(newValue) ? newValue(this.j) : newValue; | ||
| if (this.q(this.j, value)) { | ||
| this.j = value; | ||
| if (this.d) { | ||
| for (let i = 0; i < this.d.length; i++) { | ||
| notify(this.d[i], STATE_DIRTY); | ||
| } | ||
| } | ||
| } | ||
| return this.j; | ||
| } | ||
| var ScopeNode = function Scope() { | ||
| this[SCOPE] = currentScope; | ||
| this.f = STATE_CLEAN; | ||
| this.i = null; | ||
| this.m = currentScope; | ||
| if (currentScope) { | ||
| const next = currentScope.i; | ||
| if (next) | ||
| next.m = this; | ||
| this.i = next; | ||
| currentScope.i = this; | ||
| } | ||
| }; | ||
| var ScopeProto = ScopeNode.prototype; | ||
| ScopeProto.k = null; | ||
| ScopeProto.p = null; | ||
| ScopeProto.a = null; | ||
| function createScope() { | ||
| return new ScopeNode(); | ||
| } | ||
| var ComputeNode = function Computation(initialValue, compute2, options) { | ||
| ScopeNode.call(this); | ||
| this.f = compute2 ? STATE_DIRTY : STATE_CLEAN; | ||
| this.l = false; | ||
| this.t = false; | ||
| this.c = null; | ||
| this.d = null; | ||
| this.j = initialValue; | ||
| if (compute2) | ||
| this.p = compute2; | ||
| if (options) { | ||
| if (options.scoped) | ||
| this.l = true; | ||
| if (options.dirty) | ||
| this.q = options.dirty; | ||
| } | ||
| }; | ||
| var ComputeProto = ComputeNode.prototype; | ||
| Object.setPrototypeOf(ComputeProto, ScopeProto); | ||
| ComputeProto.q = isNotEqual; | ||
| ComputeProto.call = read; | ||
| function createComputation(initialValue, compute2, options) { | ||
| return new ComputeNode(initialValue, compute2, options); | ||
| } | ||
| function isNotEqual(a, b) { | ||
| return a !== b; | ||
| } | ||
| function isFunction(value) { | ||
| return typeof value === "function"; | ||
| } | ||
| function isZombie(node) { | ||
| let scope = node[SCOPE]; | ||
| while (scope) { | ||
| if (scope.p && scope.f === STATE_DIRTY) | ||
| return true; | ||
| scope = scope[SCOPE]; | ||
| } | ||
| return false; | ||
| } | ||
| function shouldUpdate(node) { | ||
| if (node.f === STATE_CHECK) { | ||
| for (let i = 0; i < node.c.length; i++) { | ||
| shouldUpdate(node.c[i]); | ||
| if (node.f === STATE_DIRTY) { | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| if (node.f === STATE_DIRTY) | ||
| update(node); | ||
| else | ||
| node.f = STATE_CLEAN; | ||
| } | ||
| function update(node) { | ||
| let prevObservers = currentObservers, prevObserversIndex = currentObserversIndex; | ||
| currentObservers = null; | ||
| currentObserversIndex = 0; | ||
| try { | ||
| if (node.l) { | ||
| if (node.i && node.i[SCOPE] === node) | ||
| dispose.call(node, false); | ||
| if (node.a) | ||
| emptyDisposal(node); | ||
| if (node.k && node.k[HANDLERS]) | ||
| node.k[HANDLERS] = []; | ||
| } | ||
| const result = compute(node.l ? node : currentScope, node.p, node); | ||
| if (currentObservers) { | ||
| if (node.c) | ||
| removeSourceObservers(node, currentObserversIndex); | ||
| if (node.c && currentObserversIndex > 0) { | ||
| node.c.length = currentObserversIndex + currentObservers.length; | ||
| for (let i = 0; i < currentObservers.length; i++) { | ||
| node.c[currentObserversIndex + i] = currentObservers[i]; | ||
| } | ||
| } else { | ||
| node.c = currentObservers; | ||
| } | ||
| let source; | ||
| for (let i = currentObserversIndex; i < node.c.length; i++) { | ||
| source = node.c[i]; | ||
| if (!source.d) | ||
| source.d = [node]; | ||
| else | ||
| source.d.push(node); | ||
| } | ||
| } else if (node.c && currentObserversIndex < node.c.length) { | ||
| removeSourceObservers(node, currentObserversIndex); | ||
| node.c.length = currentObserversIndex; | ||
| } | ||
| if (!node.l && node.t) { | ||
| write.call(node, result); | ||
| } else { | ||
| node.j = result; | ||
| node.t = true; | ||
| } | ||
| } catch (error) { | ||
| handleError(node, error); | ||
| return; | ||
| } | ||
| currentObservers = prevObservers; | ||
| currentObserversIndex = prevObserversIndex; | ||
| node.f = STATE_CLEAN; | ||
| } | ||
| function notify(node, state) { | ||
| if (node.f >= state) | ||
| return; | ||
| if (node.l && node.f === STATE_CLEAN) { | ||
| effects.push(node); | ||
| if (!scheduledEffects) | ||
| flushEffects(); | ||
| } | ||
| node.f = state; | ||
| if (node.d) { | ||
| for (let i = 0; i < node.d.length; i++) { | ||
| notify(node.d[i], STATE_CHECK); | ||
| } | ||
| } | ||
| } | ||
| function removeSourceObservers(node, index) { | ||
| let source, swap; | ||
| for (let i = index; i < node.c.length; i++) { | ||
| source = node.c[i]; | ||
| if (source.d) { | ||
| swap = source.d.indexOf(node); | ||
| source.d[swap] = source.d[source.d.length - 1]; | ||
| source.d.pop(); | ||
| } | ||
| } | ||
| } | ||
| // src/signals.ts | ||
| function signal(initialValue, options) { | ||
| const node = createComputation(initialValue, null, options), signal2 = read.bind(node); | ||
| signal2.set = write.bind(node); | ||
| return signal2; | ||
| } | ||
| function isReadSignal(fn) { | ||
| return isFunction(fn); | ||
| } | ||
| function computed(compute2, options) { | ||
| return read.bind( | ||
| createComputation( | ||
| options == null ? void 0 : options.initial, | ||
| compute2, | ||
| options | ||
| ) | ||
| ); | ||
| } | ||
| function effect(effect2, options) { | ||
| return () => { | ||
| }; | ||
| } | ||
| function readonly(signal2) { | ||
| return () => signal2(); | ||
| } | ||
| function isWriteSignal(fn) { | ||
| return isReadSignal(fn) && "set" in fn; | ||
| } | ||
| export { SCOPE, compute, computed, createComputation, createScope, dispose, effect, getContext, getScope, isFunction, isNotEqual, isReadSignal, isWriteSignal, onDispose, onError, peek, read, readonly, root, scoped, setContext, signal, tick, untrack, write }; |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
96477
0.57%2652
0.68%675
0.15%1
Infinity%