@angular/core
Version:
Angular - the core framework
433 lines (424 loc) • 12.8 kB
JavaScript
/**
* @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