UNPKG

@angular/core

Version:

Angular - the core framework

433 lines (424 loc) 12.8 kB
/** * @license Angular v21.0.6 * (c) 2010-2025 Google LLC. https://angular.dev/ * License: MIT */ let activeConsumer = null; let inNotificationPhase = false; let epoch = 1; let postProducerCreatedFn = null; const SIGNAL = /* @__PURE__ */Symbol('SIGNAL'); function setActiveConsumer(consumer) { const prev = activeConsumer; activeConsumer = consumer; return prev; } function getActiveConsumer() { return activeConsumer; } function isInNotificationPhase() { return inNotificationPhase; } function isReactive(value) { return value[SIGNAL] !== undefined; } const REACTIVE_NODE = { version: 0, lastCleanEpoch: 0, dirty: false, producers: undefined, producersTail: undefined, consumers: undefined, consumersTail: undefined, recomputing: false, consumerAllowSignalWrites: false, consumerIsAlwaysLive: false, kind: 'unknown', producerMustRecompute: () => false, producerRecomputeValue: () => {}, consumerMarkedDirty: () => {}, consumerOnSignalRead: () => {} }; function producerAccessed(node) { if (inNotificationPhase) { throw new Error(typeof ngDevMode !== 'undefined' && ngDevMode ? `Assertion error: signal read during notification phase` : ''); } if (activeConsumer === null) { return; } activeConsumer.consumerOnSignalRead(node); const prevProducerLink = activeConsumer.producersTail; if (prevProducerLink !== undefined && prevProducerLink.producer === node) { return; } let nextProducerLink = undefined; const isRecomputing = activeConsumer.recomputing; if (isRecomputing) { nextProducerLink = prevProducerLink !== undefined ? prevProducerLink.nextProducer : activeConsumer.producers; if (nextProducerLink !== undefined && nextProducerLink.producer === node) { activeConsumer.producersTail = nextProducerLink; nextProducerLink.lastReadVersion = node.version; return; } } const prevConsumerLink = node.consumersTail; if (prevConsumerLink !== undefined && prevConsumerLink.consumer === activeConsumer && (!isRecomputing || isValidLink(prevConsumerLink, activeConsumer))) { return; } const isLive = consumerIsLive(activeConsumer); const newLink = { producer: node, consumer: activeConsumer, nextProducer: nextProducerLink, prevConsumer: prevConsumerLink, lastReadVersion: node.version, nextConsumer: undefined }; activeConsumer.producersTail = newLink; if (prevProducerLink !== undefined) { prevProducerLink.nextProducer = newLink; } else { activeConsumer.producers = newLink; } if (isLive) { producerAddLiveConsumer(node, newLink); } } function producerIncrementEpoch() { epoch++; } function producerUpdateValueVersion(node) { if (consumerIsLive(node) && !node.dirty) { return; } if (!node.dirty && node.lastCleanEpoch === epoch) { return; } if (!node.producerMustRecompute(node) && !consumerPollProducersForChange(node)) { producerMarkClean(node); return; } node.producerRecomputeValue(node); producerMarkClean(node); } function producerNotifyConsumers(node) { if (node.consumers === undefined) { return; } const prev = inNotificationPhase; inNotificationPhase = true; try { for (let link = node.consumers; link !== undefined; link = link.nextConsumer) { const consumer = link.consumer; if (!consumer.dirty) { consumerMarkDirty(consumer); } } } finally { inNotificationPhase = prev; } } function producerUpdatesAllowed() { return activeConsumer?.consumerAllowSignalWrites !== false; } function consumerMarkDirty(node) { node.dirty = true; producerNotifyConsumers(node); node.consumerMarkedDirty?.(node); } function producerMarkClean(node) { node.dirty = false; node.lastCleanEpoch = epoch; } function consumerBeforeComputation(node) { if (node) resetConsumerBeforeComputation(node); return setActiveConsumer(node); } function resetConsumerBeforeComputation(node) { node.producersTail = undefined; node.recomputing = true; } function consumerAfterComputation(node, prevConsumer) { setActiveConsumer(prevConsumer); if (node) finalizeConsumerAfterComputation(node); } function finalizeConsumerAfterComputation(node) { node.recomputing = false; const producersTail = node.producersTail; let toRemove = producersTail !== undefined ? producersTail.nextProducer : node.producers; if (toRemove !== undefined) { if (consumerIsLive(node)) { do { toRemove = producerRemoveLiveConsumerLink(toRemove); } while (toRemove !== undefined); } if (producersTail !== undefined) { producersTail.nextProducer = undefined; } else { node.producers = undefined; } } } function consumerPollProducersForChange(node) { for (let link = node.producers; link !== undefined; link = link.nextProducer) { const producer = link.producer; const seenVersion = link.lastReadVersion; if (seenVersion !== producer.version) { return true; } producerUpdateValueVersion(producer); if (seenVersion !== producer.version) { return true; } } return false; } function consumerDestroy(node) { if (consumerIsLive(node)) { let link = node.producers; while (link !== undefined) { link = producerRemoveLiveConsumerLink(link); } } node.producers = undefined; node.producersTail = undefined; node.consumers = undefined; node.consumersTail = undefined; } function producerAddLiveConsumer(node, link) { const consumersTail = node.consumersTail; const wasLive = consumerIsLive(node); if (consumersTail !== undefined) { link.nextConsumer = consumersTail.nextConsumer; consumersTail.nextConsumer = link; } else { link.nextConsumer = undefined; node.consumers = link; } link.prevConsumer = consumersTail; node.consumersTail = link; if (!wasLive) { for (let link = node.producers; link !== undefined; link = link.nextProducer) { producerAddLiveConsumer(link.producer, link); } } } function producerRemoveLiveConsumerLink(link) { const producer = link.producer; const nextProducer = link.nextProducer; const nextConsumer = link.nextConsumer; const prevConsumer = link.prevConsumer; link.nextConsumer = undefined; link.prevConsumer = undefined; if (nextConsumer !== undefined) { nextConsumer.prevConsumer = prevConsumer; } else { producer.consumersTail = prevConsumer; } if (prevConsumer !== undefined) { prevConsumer.nextConsumer = nextConsumer; } else { producer.consumers = nextConsumer; if (!consumerIsLive(producer)) { let producerLink = producer.producers; while (producerLink !== undefined) { producerLink = producerRemoveLiveConsumerLink(producerLink); } } } return nextProducer; } function consumerIsLive(node) { return node.consumerIsAlwaysLive || node.consumers !== undefined; } function runPostProducerCreatedFn(node) { postProducerCreatedFn?.(node); } function setPostProducerCreatedFn(fn) { const prev = postProducerCreatedFn; postProducerCreatedFn = fn; return prev; } function isValidLink(checkLink, consumer) { const producersTail = consumer.producersTail; if (producersTail !== undefined) { let link = consumer.producers; do { if (link === checkLink) { return true; } if (link === producersTail) { break; } link = link.nextProducer; } while (link !== undefined); } return false; } function defaultEquals(a, b) { return Object.is(a, b); } function createComputed(computation, equal) { const node = Object.create(COMPUTED_NODE); node.computation = computation; if (equal !== undefined) { node.equal = equal; } const computed = () => { producerUpdateValueVersion(node); producerAccessed(node); if (node.value === ERRORED) { throw node.error; } return node.value; }; computed[SIGNAL] = node; if (typeof ngDevMode !== 'undefined' && ngDevMode) { const debugName = node.debugName ? ' (' + node.debugName + ')' : ''; computed.toString = () => `[Computed${debugName}: ${node.value}]`; } runPostProducerCreatedFn(node); return computed; } const UNSET = /* @__PURE__ */Symbol('UNSET'); const COMPUTING = /* @__PURE__ */Symbol('COMPUTING'); const ERRORED = /* @__PURE__ */Symbol('ERRORED'); const COMPUTED_NODE = /* @__PURE__ */(() => { return { ...REACTIVE_NODE, value: UNSET, dirty: true, error: null, equal: defaultEquals, kind: 'computed', producerMustRecompute(node) { return node.value === UNSET || node.value === COMPUTING; }, producerRecomputeValue(node) { if (node.value === COMPUTING) { throw new Error(typeof ngDevMode !== 'undefined' && ngDevMode ? 'Detected cycle in computations.' : ''); } const oldValue = node.value; node.value = COMPUTING; const prevConsumer = consumerBeforeComputation(node); let newValue; let wasEqual = false; try { newValue = node.computation(); setActiveConsumer(null); wasEqual = oldValue !== UNSET && oldValue !== ERRORED && newValue !== ERRORED && node.equal(oldValue, newValue); } catch (err) { newValue = ERRORED; node.error = err; } finally { consumerAfterComputation(node, prevConsumer); } if (wasEqual) { node.value = oldValue; return; } node.value = newValue; node.version++; } }; })(); function defaultThrowError() { throw new Error(); } let throwInvalidWriteToSignalErrorFn = defaultThrowError; function throwInvalidWriteToSignalError(node) { throwInvalidWriteToSignalErrorFn(node); } function setThrowInvalidWriteToSignalError(fn) { throwInvalidWriteToSignalErrorFn = fn; } let postSignalSetFn = null; function createSignal(initialValue, equal) { const node = Object.create(SIGNAL_NODE); node.value = initialValue; if (equal !== undefined) { node.equal = equal; } const getter = () => signalGetFn(node); getter[SIGNAL] = node; if (typeof ngDevMode !== 'undefined' && ngDevMode) { const debugName = node.debugName ? ' (' + node.debugName + ')' : ''; getter.toString = () => `[Signal${debugName}: ${node.value}]`; } runPostProducerCreatedFn(node); const set = newValue => signalSetFn(node, newValue); const update = updateFn => signalUpdateFn(node, updateFn); return [getter, set, update]; } function setPostSignalSetFn(fn) { const prev = postSignalSetFn; postSignalSetFn = fn; return prev; } function signalGetFn(node) { producerAccessed(node); return node.value; } function signalSetFn(node, newValue) { if (!producerUpdatesAllowed()) { throwInvalidWriteToSignalError(node); } if (!node.equal(node.value, newValue)) { node.value = newValue; signalValueChanged(node); } } function signalUpdateFn(node, updater) { if (!producerUpdatesAllowed()) { throwInvalidWriteToSignalError(node); } signalSetFn(node, updater(node.value)); } function runPostSignalSetFn(node) { postSignalSetFn?.(node); } const SIGNAL_NODE = /* @__PURE__ */(() => { return { ...REACTIVE_NODE, equal: defaultEquals, value: undefined, kind: 'signal' }; })(); function signalValueChanged(node) { node.version++; producerIncrementEpoch(); producerNotifyConsumers(node); postSignalSetFn?.(node); } function untracked(nonReactiveReadsFn) { const prevConsumer = setActiveConsumer(null); try { return nonReactiveReadsFn(); } finally { setActiveConsumer(prevConsumer); } } const BASE_EFFECT_NODE = /* @__PURE__ */(() => ({ ...REACTIVE_NODE, consumerIsAlwaysLive: true, consumerAllowSignalWrites: true, dirty: true, kind: 'effect' }))(); function runEffect(node) { node.dirty = false; if (node.version > 0 && !consumerPollProducersForChange(node)) { return; } node.version++; const prevNode = consumerBeforeComputation(node); try { node.cleanup(); node.fn(); } finally { consumerAfterComputation(node, prevNode); } } export { BASE_EFFECT_NODE, COMPUTING, ERRORED, REACTIVE_NODE, SIGNAL, SIGNAL_NODE, UNSET, consumerAfterComputation, consumerBeforeComputation, consumerDestroy, consumerMarkDirty, consumerPollProducersForChange, createComputed, createSignal, defaultEquals, finalizeConsumerAfterComputation, getActiveConsumer, isInNotificationPhase, isReactive, producerAccessed, producerIncrementEpoch, producerMarkClean, producerNotifyConsumers, producerUpdateValueVersion, producerUpdatesAllowed, resetConsumerBeforeComputation, runEffect, runPostProducerCreatedFn, runPostSignalSetFn, setActiveConsumer, setPostProducerCreatedFn, setPostSignalSetFn, setThrowInvalidWriteToSignalError, signalGetFn, signalSetFn, signalUpdateFn, untracked }; //# sourceMappingURL=_effect-chunk.mjs.map