@angular/core 21.0.0-next.9 → 21.0.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/fesm2022/_attribute-chunk.mjs +2 -14
  2. package/fesm2022/_attribute-chunk.mjs.map +1 -1
  3. package/fesm2022/_debug_node-chunk.mjs +15164 -28368
  4. package/fesm2022/_debug_node-chunk.mjs.map +1 -1
  5. package/fesm2022/_effect-chunk.mjs +322 -504
  6. package/fesm2022/_effect-chunk.mjs.map +1 -1
  7. package/fesm2022/_effect-chunk2.mjs +2204 -4061
  8. package/fesm2022/_effect-chunk2.mjs.map +1 -1
  9. package/fesm2022/_not_found-chunk.mjs +18 -35
  10. package/fesm2022/_not_found-chunk.mjs.map +1 -1
  11. package/fesm2022/_resource-chunk.mjs +312 -391
  12. package/fesm2022/_resource-chunk.mjs.map +1 -1
  13. package/fesm2022/_untracked-chunk.mjs +75 -96
  14. package/fesm2022/_untracked-chunk.mjs.map +1 -1
  15. package/fesm2022/_weak_ref-chunk.mjs +2 -4
  16. package/fesm2022/_weak_ref-chunk.mjs.map +1 -1
  17. package/fesm2022/core.mjs +2461 -4305
  18. package/fesm2022/core.mjs.map +1 -1
  19. package/fesm2022/primitives-di.mjs +9 -9
  20. package/fesm2022/primitives-di.mjs.map +1 -1
  21. package/fesm2022/primitives-event-dispatch.mjs +626 -1460
  22. package/fesm2022/primitives-event-dispatch.mjs.map +1 -1
  23. package/fesm2022/primitives-signals.mjs +154 -188
  24. package/fesm2022/primitives-signals.mjs.map +1 -1
  25. package/fesm2022/rxjs-interop.mjs +204 -304
  26. package/fesm2022/rxjs-interop.mjs.map +1 -1
  27. package/fesm2022/testing.mjs +2303 -3162
  28. package/fesm2022/testing.mjs.map +1 -1
  29. package/package.json +8 -2
  30. package/resources/best-practices.md +56 -0
  31. package/schematics/bundles/add-bootstrap-context-to-server-main.cjs +7 -25
  32. package/schematics/bundles/application-config-core.cjs +8 -19
  33. package/schematics/bundles/{apply_import_manager-CoeTX_Ob.cjs → apply_import_manager-1Zs_gpB6.cjs} +4 -5
  34. package/schematics/bundles/bootstrap-options-migration.cjs +93 -132
  35. package/schematics/bundles/cleanup-unused-imports.cjs +9 -13
  36. package/schematics/bundles/common-to-standalone-migration.cjs +12 -16
  37. package/schematics/bundles/{compiler_host-emLDwK2U.cjs → compiler_host-DBwYMlTo.cjs} +10 -11
  38. package/schematics/bundles/control-flow-migration.cjs +29 -31
  39. package/schematics/bundles/{imports-DwPXlGFl.cjs → imports-DP72APSx.cjs} +1 -23
  40. package/schematics/bundles/{index-CLxYZ09c.cjs → index-B7I9sIUx.cjs} +36 -37
  41. package/schematics/bundles/inject-migration.cjs +9 -26
  42. package/schematics/bundles/leading_space-D9nQ8UQC.cjs +1 -1
  43. package/schematics/bundles/{migrate_ts_type_references-CpM5FPGa.cjs → migrate_ts_type_references-UGIUl7En.cjs} +458 -24
  44. package/schematics/bundles/{ng_component_template-BRbBIAUX.cjs → ng_component_template-Dsuq1Lw7.cjs} +4 -5
  45. package/schematics/bundles/{ng_decorators-BI0uV7KI.cjs → ng_decorators-DSFlWYQY.cjs} +2 -2
  46. package/schematics/bundles/ngclass-to-class-migration.cjs +16 -19
  47. package/schematics/bundles/ngstyle-to-style-migration.cjs +15 -18
  48. package/schematics/bundles/nodes-B16H9JUd.cjs +1 -1
  49. package/schematics/bundles/output-migration.cjs +16 -19
  50. package/schematics/bundles/{parse_html-CPWfkfhR.cjs → parse_html-8VLCL37B.cjs} +5 -5
  51. package/schematics/bundles/{project_paths-C8H7KDJ3.cjs → project_paths-DvD50ouC.cjs} +14 -247
  52. package/schematics/bundles/project_tsconfig_paths-CDVxT6Ov.cjs +90 -0
  53. package/schematics/bundles/property_name-BBwFuqMe.cjs +1 -1
  54. package/schematics/bundles/route-lazy-loading.cjs +9 -25
  55. package/schematics/bundles/router-current-navigation.cjs +6 -17
  56. package/schematics/bundles/router-last-successful-navigation.cjs +6 -17
  57. package/schematics/bundles/router-testing-module-migration.cjs +7 -18
  58. package/schematics/bundles/self-closing-tags-migration.cjs +14 -17
  59. package/schematics/bundles/signal-input-migration.cjs +23 -26
  60. package/schematics/bundles/signal-queries-migration.cjs +22 -25
  61. package/schematics/bundles/signals.cjs +10 -13
  62. package/schematics/bundles/standalone-migration.cjs +22 -56
  63. package/schematics/bundles/symbol-BObKoqes.cjs +1 -1
  64. package/types/_api-chunk.d.ts +1 -1
  65. package/types/_chrome_dev_tools_performance-chunk.d.ts +1 -1
  66. package/types/_discovery-chunk.d.ts +7 -9
  67. package/types/_effect-chunk.d.ts +1 -1
  68. package/types/_event_dispatcher-chunk.d.ts +1 -1
  69. package/types/_formatter-chunk.d.ts +1 -1
  70. package/types/_weak_ref-chunk.d.ts +1 -1
  71. package/types/core.d.ts +1 -81
  72. package/types/primitives-di.d.ts +1 -1
  73. package/types/primitives-event-dispatch.d.ts +1 -1
  74. package/types/primitives-signals.d.ts +1 -1
  75. package/types/rxjs-interop.d.ts +1 -1
  76. package/types/testing.d.ts +1 -1
  77. package/schematics/bundles/index-Dvqnp6JS.cjs +0 -22419
  78. package/schematics/bundles/project_tsconfig_paths-CiBzGSIa.cjs +0 -51591
@@ -1,604 +1,422 @@
1
1
  /**
2
- * @license Angular v21.0.0-next.9
2
+ * @license Angular v21.0.0-rc.0
3
3
  * (c) 2010-2025 Google LLC. https://angular.dev/
4
4
  * License: MIT
5
5
  */
6
6
 
7
- /**
8
- * The currently active consumer `ReactiveNode`, if running code in a reactive context.
9
- *
10
- * Change this via `setActiveConsumer`.
11
- */
12
7
  let activeConsumer = null;
13
8
  let inNotificationPhase = false;
14
- /**
15
- * Global epoch counter. Incremented whenever a source signal is set.
16
- */
17
9
  let epoch = 1;
18
- /**
19
- * If set, called after a producer `ReactiveNode` is created.
20
- */
21
10
  let postProducerCreatedFn = null;
22
- /**
23
- * Symbol used to tell `Signal`s apart from other functions.
24
- *
25
- * This can be used to auto-unwrap signals in various cases, or to auto-wrap non-signal values.
26
- */
27
- const SIGNAL = /* @__PURE__ */ Symbol('SIGNAL');
11
+ const SIGNAL = /* @__PURE__ */Symbol('SIGNAL');
28
12
  function setActiveConsumer(consumer) {
29
- const prev = activeConsumer;
30
- activeConsumer = consumer;
31
- return prev;
13
+ const prev = activeConsumer;
14
+ activeConsumer = consumer;
15
+ return prev;
32
16
  }
33
17
  function getActiveConsumer() {
34
- return activeConsumer;
18
+ return activeConsumer;
35
19
  }
36
20
  function isInNotificationPhase() {
37
- return inNotificationPhase;
21
+ return inNotificationPhase;
38
22
  }
39
23
  function isReactive(value) {
40
- return value[SIGNAL] !== undefined;
24
+ return value[SIGNAL] !== undefined;
41
25
  }
42
26
  const REACTIVE_NODE = {
43
- version: 0,
44
- lastCleanEpoch: 0,
45
- dirty: false,
46
- producers: undefined,
47
- producersTail: undefined,
48
- consumers: undefined,
49
- consumersTail: undefined,
50
- recomputing: false,
51
- consumerAllowSignalWrites: false,
52
- consumerIsAlwaysLive: false,
53
- kind: 'unknown',
54
- producerMustRecompute: () => false,
55
- producerRecomputeValue: () => { },
56
- consumerMarkedDirty: () => { },
57
- consumerOnSignalRead: () => { },
27
+ version: 0,
28
+ lastCleanEpoch: 0,
29
+ dirty: false,
30
+ producers: undefined,
31
+ producersTail: undefined,
32
+ consumers: undefined,
33
+ consumersTail: undefined,
34
+ recomputing: false,
35
+ consumerAllowSignalWrites: false,
36
+ consumerIsAlwaysLive: false,
37
+ kind: 'unknown',
38
+ producerMustRecompute: () => false,
39
+ producerRecomputeValue: () => {},
40
+ consumerMarkedDirty: () => {},
41
+ consumerOnSignalRead: () => {}
58
42
  };
59
- /**
60
- * Called by implementations when a producer's signal is read.
61
- */
62
43
  function producerAccessed(node) {
63
- if (inNotificationPhase) {
64
- throw new Error(typeof ngDevMode !== 'undefined' && ngDevMode
65
- ? `Assertion error: signal read during notification phase`
66
- : '');
67
- }
68
- if (activeConsumer === null) {
69
- // Accessed outside of a reactive context, so nothing to record.
70
- return;
71
- }
72
- activeConsumer.consumerOnSignalRead(node);
73
- const prevProducerLink = activeConsumer.producersTail;
74
- // If the last producer we accessed is the same as the current one, we can skip adding a new
75
- // link
76
- if (prevProducerLink !== undefined && prevProducerLink.producer === node) {
77
- return;
78
- }
79
- let nextProducerLink = undefined;
80
- const isRecomputing = activeConsumer.recomputing;
81
- if (isRecomputing) {
82
- // If we're incrementally rebuilding the producers list, we want to check if the next producer
83
- // in the list is the same as the one we're trying to add.
84
- // If the previous producer is defined, then the next producer is just the one that follows it.
85
- // Otherwise, we should check the head of the producers list (the first node that we accessed the last time this consumer was run).
86
- nextProducerLink =
87
- prevProducerLink !== undefined ? prevProducerLink.nextProducer : activeConsumer.producers;
88
- if (nextProducerLink !== undefined && nextProducerLink.producer === node) {
89
- // If the next producer is the same as the one we're trying to add, we can just update the
90
- // last read version, update the tail of the producers list of this rerun, and return.
91
- activeConsumer.producersTail = nextProducerLink;
92
- nextProducerLink.lastReadVersion = node.version;
93
- return;
94
- }
95
- }
96
- const prevConsumerLink = node.consumersTail;
97
- // If the producer we're accessing already has a link to this consumer, we can skip adding a new
98
- // link. This can short circuit the creation of a new link in the case where the consumer reads alternating ReeactiveNodes
99
- if (prevConsumerLink !== undefined &&
100
- prevConsumerLink.consumer === activeConsumer &&
101
- // However, we have to make sure that the link we've discovered isn't from a node that is incrementally rebuilding its producer list
102
- (!isRecomputing || isValidLink(prevConsumerLink, activeConsumer))) {
103
- // If we found an existing link to the consumer we can just return.
104
- return;
105
- }
106
- // If we got here, it means that we need to create a new link between the producer and the consumer.
107
- const isLive = consumerIsLive(activeConsumer);
108
- const newLink = {
109
- producer: node,
110
- consumer: activeConsumer,
111
- // instead of eagerly destroying the previous link, we delay until we've finished recomputing
112
- // the producers list, so that we can destroy all of the old links at once.
113
- nextProducer: nextProducerLink,
114
- prevConsumer: prevConsumerLink,
115
- lastReadVersion: node.version,
116
- nextConsumer: undefined,
117
- };
118
- activeConsumer.producersTail = newLink;
119
- if (prevProducerLink !== undefined) {
120
- prevProducerLink.nextProducer = newLink;
121
- }
122
- else {
123
- activeConsumer.producers = newLink;
124
- }
125
- if (isLive) {
126
- producerAddLiveConsumer(node, newLink);
127
- }
44
+ if (inNotificationPhase) {
45
+ throw new Error(typeof ngDevMode !== 'undefined' && ngDevMode ? `Assertion error: signal read during notification phase` : '');
46
+ }
47
+ if (activeConsumer === null) {
48
+ return;
49
+ }
50
+ activeConsumer.consumerOnSignalRead(node);
51
+ const prevProducerLink = activeConsumer.producersTail;
52
+ if (prevProducerLink !== undefined && prevProducerLink.producer === node) {
53
+ return;
54
+ }
55
+ let nextProducerLink = undefined;
56
+ const isRecomputing = activeConsumer.recomputing;
57
+ if (isRecomputing) {
58
+ nextProducerLink = prevProducerLink !== undefined ? prevProducerLink.nextProducer : activeConsumer.producers;
59
+ if (nextProducerLink !== undefined && nextProducerLink.producer === node) {
60
+ activeConsumer.producersTail = nextProducerLink;
61
+ nextProducerLink.lastReadVersion = node.version;
62
+ return;
63
+ }
64
+ }
65
+ const prevConsumerLink = node.consumersTail;
66
+ if (prevConsumerLink !== undefined && prevConsumerLink.consumer === activeConsumer && (!isRecomputing || isValidLink(prevConsumerLink, activeConsumer))) {
67
+ return;
68
+ }
69
+ const isLive = consumerIsLive(activeConsumer);
70
+ const newLink = {
71
+ producer: node,
72
+ consumer: activeConsumer,
73
+ nextProducer: nextProducerLink,
74
+ prevConsumer: prevConsumerLink,
75
+ lastReadVersion: node.version,
76
+ nextConsumer: undefined
77
+ };
78
+ activeConsumer.producersTail = newLink;
79
+ if (prevProducerLink !== undefined) {
80
+ prevProducerLink.nextProducer = newLink;
81
+ } else {
82
+ activeConsumer.producers = newLink;
83
+ }
84
+ if (isLive) {
85
+ producerAddLiveConsumer(node, newLink);
86
+ }
128
87
  }
129
- /**
130
- * Increment the global epoch counter.
131
- *
132
- * Called by source producers (that is, not computeds) whenever their values change.
133
- */
134
88
  function producerIncrementEpoch() {
135
- epoch++;
89
+ epoch++;
136
90
  }
137
- /**
138
- * Ensure this producer's `version` is up-to-date.
139
- */
140
91
  function producerUpdateValueVersion(node) {
141
- if (consumerIsLive(node) && !node.dirty) {
142
- // A live consumer will be marked dirty by producers, so a clean state means that its version
143
- // is guaranteed to be up-to-date.
144
- return;
145
- }
146
- if (!node.dirty && node.lastCleanEpoch === epoch) {
147
- // Even non-live consumers can skip polling if they previously found themselves to be clean at
148
- // the current epoch, since their dependencies could not possibly have changed (such a change
149
- // would've increased the epoch).
150
- return;
151
- }
152
- if (!node.producerMustRecompute(node) && !consumerPollProducersForChange(node)) {
153
- // None of our producers report a change since the last time they were read, so no
154
- // recomputation of our value is necessary, and we can consider ourselves clean.
155
- producerMarkClean(node);
156
- return;
157
- }
158
- node.producerRecomputeValue(node);
159
- // After recomputing the value, we're no longer dirty.
92
+ if (consumerIsLive(node) && !node.dirty) {
93
+ return;
94
+ }
95
+ if (!node.dirty && node.lastCleanEpoch === epoch) {
96
+ return;
97
+ }
98
+ if (!node.producerMustRecompute(node) && !consumerPollProducersForChange(node)) {
160
99
  producerMarkClean(node);
100
+ return;
101
+ }
102
+ node.producerRecomputeValue(node);
103
+ producerMarkClean(node);
161
104
  }
162
- /**
163
- * Propagate a dirty notification to live consumers of this producer.
164
- */
165
105
  function producerNotifyConsumers(node) {
166
- if (node.consumers === undefined) {
167
- return;
168
- }
169
- // Prevent signal reads when we're updating the graph
170
- const prev = inNotificationPhase;
171
- inNotificationPhase = true;
172
- try {
173
- for (let link = node.consumers; link !== undefined; link = link.nextConsumer) {
174
- const consumer = link.consumer;
175
- if (!consumer.dirty) {
176
- consumerMarkDirty(consumer);
177
- }
178
- }
179
- }
180
- finally {
181
- inNotificationPhase = prev;
182
- }
106
+ if (node.consumers === undefined) {
107
+ return;
108
+ }
109
+ const prev = inNotificationPhase;
110
+ inNotificationPhase = true;
111
+ try {
112
+ for (let link = node.consumers; link !== undefined; link = link.nextConsumer) {
113
+ const consumer = link.consumer;
114
+ if (!consumer.dirty) {
115
+ consumerMarkDirty(consumer);
116
+ }
117
+ }
118
+ } finally {
119
+ inNotificationPhase = prev;
120
+ }
183
121
  }
184
- /**
185
- * Whether this `ReactiveNode` in its producer capacity is currently allowed to initiate updates,
186
- * based on the current consumer context.
187
- */
188
122
  function producerUpdatesAllowed() {
189
- return activeConsumer?.consumerAllowSignalWrites !== false;
123
+ return activeConsumer?.consumerAllowSignalWrites !== false;
190
124
  }
191
125
  function consumerMarkDirty(node) {
192
- node.dirty = true;
193
- producerNotifyConsumers(node);
194
- node.consumerMarkedDirty?.(node);
126
+ node.dirty = true;
127
+ producerNotifyConsumers(node);
128
+ node.consumerMarkedDirty?.(node);
195
129
  }
196
130
  function producerMarkClean(node) {
197
- node.dirty = false;
198
- node.lastCleanEpoch = epoch;
131
+ node.dirty = false;
132
+ node.lastCleanEpoch = epoch;
199
133
  }
200
- /**
201
- * Prepare this consumer to run a computation in its reactive context and set
202
- * it as the active consumer.
203
- *
204
- * Must be called by subclasses which represent reactive computations, before those computations
205
- * begin.
206
- */
207
134
  function consumerBeforeComputation(node) {
208
- if (node)
209
- resetConsumerBeforeComputation(node);
210
- return setActiveConsumer(node);
135
+ if (node) resetConsumerBeforeComputation(node);
136
+ return setActiveConsumer(node);
211
137
  }
212
- /**
213
- * Prepare this consumer to run a computation in its reactive context.
214
- *
215
- * We expose this mainly for code where we manually batch effects into a single
216
- * consumer. In those cases we may wish to "reopen" a consumer multiple times
217
- * in initial render before finalizing it. Most code should just call
218
- * `consumerBeforeComputation` instead of calling this directly.
219
- */
220
138
  function resetConsumerBeforeComputation(node) {
221
- node.producersTail = undefined;
222
- node.recomputing = true;
139
+ node.producersTail = undefined;
140
+ node.recomputing = true;
223
141
  }
224
- /**
225
- * Finalize this consumer's state and set previous consumer as the active consumer after a
226
- * reactive computation has run.
227
- *
228
- * Must be called by subclasses which represent reactive computations, after those computations
229
- * have finished.
230
- */
231
142
  function consumerAfterComputation(node, prevConsumer) {
232
- setActiveConsumer(prevConsumer);
233
- if (node)
234
- finalizeConsumerAfterComputation(node);
143
+ setActiveConsumer(prevConsumer);
144
+ if (node) finalizeConsumerAfterComputation(node);
235
145
  }
236
- /**
237
- * Finalize this consumer's state after a reactive computation has run.
238
- *
239
- * We expose this mainly for code where we manually batch effects into a single
240
- * consumer. In those cases we may wish to "reopen" a consumer multiple times
241
- * in initial render before finalizing it. Most code should just call
242
- * `consumerAfterComputation` instead of calling this directly.
243
- */
244
146
  function finalizeConsumerAfterComputation(node) {
245
- node.recomputing = false;
246
- // We've finished incrementally rebuilding the producers list, now if there are any producers
247
- // that are after producersTail, they are stale and should be removed.
248
- const producersTail = node.producersTail;
249
- let toRemove = producersTail !== undefined ? producersTail.nextProducer : node.producers;
250
- if (toRemove !== undefined) {
251
- if (consumerIsLive(node)) {
252
- // For each stale link, we first unlink it from the producers list of consumers
253
- do {
254
- toRemove = producerRemoveLiveConsumerLink(toRemove);
255
- } while (toRemove !== undefined);
256
- }
257
- // Now, we can truncate the producers list to remove all stale links.
258
- if (producersTail !== undefined) {
259
- producersTail.nextProducer = undefined;
260
- }
261
- else {
262
- node.producers = undefined;
263
- }
147
+ node.recomputing = false;
148
+ const producersTail = node.producersTail;
149
+ let toRemove = producersTail !== undefined ? producersTail.nextProducer : node.producers;
150
+ if (toRemove !== undefined) {
151
+ if (consumerIsLive(node)) {
152
+ do {
153
+ toRemove = producerRemoveLiveConsumerLink(toRemove);
154
+ } while (toRemove !== undefined);
264
155
  }
156
+ if (producersTail !== undefined) {
157
+ producersTail.nextProducer = undefined;
158
+ } else {
159
+ node.producers = undefined;
160
+ }
161
+ }
265
162
  }
266
- /**
267
- * Determine whether this consumer has any dependencies which have changed since the last time
268
- * they were read.
269
- */
270
163
  function consumerPollProducersForChange(node) {
271
- // Poll producers for change.
272
- for (let link = node.producers; link !== undefined; link = link.nextProducer) {
273
- const producer = link.producer;
274
- const seenVersion = link.lastReadVersion;
275
- // First check the versions. A mismatch means that the producer's value is known to have
276
- // changed since the last time we read it.
277
- if (seenVersion !== producer.version) {
278
- return true;
279
- }
280
- // The producer's version is the same as the last time we read it, but it might itself be
281
- // stale. Force the producer to recompute its version (calculating a new value if necessary).
282
- producerUpdateValueVersion(producer);
283
- // Now when we do this check, `producer.version` is guaranteed to be up to date, so if the
284
- // versions still match then it has not changed since the last time we read it.
285
- if (seenVersion !== producer.version) {
286
- return true;
287
- }
164
+ for (let link = node.producers; link !== undefined; link = link.nextProducer) {
165
+ const producer = link.producer;
166
+ const seenVersion = link.lastReadVersion;
167
+ if (seenVersion !== producer.version) {
168
+ return true;
288
169
  }
289
- return false;
170
+ producerUpdateValueVersion(producer);
171
+ if (seenVersion !== producer.version) {
172
+ return true;
173
+ }
174
+ }
175
+ return false;
290
176
  }
291
- /**
292
- * Disconnect this consumer from the graph.
293
- */
294
177
  function consumerDestroy(node) {
295
- if (consumerIsLive(node)) {
296
- // Drop all connections from the graph to this node.
297
- let link = node.producers;
298
- while (link !== undefined) {
299
- link = producerRemoveLiveConsumerLink(link);
300
- }
178
+ if (consumerIsLive(node)) {
179
+ let link = node.producers;
180
+ while (link !== undefined) {
181
+ link = producerRemoveLiveConsumerLink(link);
301
182
  }
302
- // Truncate all the linked lists to drop all connection from this node to the graph.
303
- node.producers = undefined;
304
- node.producersTail = undefined;
305
- node.consumers = undefined;
306
- node.consumersTail = undefined;
183
+ }
184
+ node.producers = undefined;
185
+ node.producersTail = undefined;
186
+ node.consumers = undefined;
187
+ node.consumersTail = undefined;
307
188
  }
308
- /**
309
- * Add `consumer` as a live consumer of this node.
310
- *
311
- * Note that this operation is potentially transitive. If this node becomes live, then it becomes
312
- * a live consumer of all of its current producers.
313
- */
314
189
  function producerAddLiveConsumer(node, link) {
315
- const consumersTail = node.consumersTail;
316
- const wasLive = consumerIsLive(node);
317
- if (consumersTail !== undefined) {
318
- link.nextConsumer = consumersTail.nextConsumer;
319
- consumersTail.nextConsumer = link;
320
- }
321
- else {
322
- link.nextConsumer = undefined;
323
- node.consumers = link;
324
- }
325
- link.prevConsumer = consumersTail;
326
- node.consumersTail = link;
327
- if (!wasLive) {
328
- for (let link = node.producers; link !== undefined; link = link.nextProducer) {
329
- producerAddLiveConsumer(link.producer, link);
330
- }
190
+ const consumersTail = node.consumersTail;
191
+ const wasLive = consumerIsLive(node);
192
+ if (consumersTail !== undefined) {
193
+ link.nextConsumer = consumersTail.nextConsumer;
194
+ consumersTail.nextConsumer = link;
195
+ } else {
196
+ link.nextConsumer = undefined;
197
+ node.consumers = link;
198
+ }
199
+ link.prevConsumer = consumersTail;
200
+ node.consumersTail = link;
201
+ if (!wasLive) {
202
+ for (let link = node.producers; link !== undefined; link = link.nextProducer) {
203
+ producerAddLiveConsumer(link.producer, link);
331
204
  }
205
+ }
332
206
  }
333
207
  function producerRemoveLiveConsumerLink(link) {
334
- const producer = link.producer;
335
- const nextProducer = link.nextProducer;
336
- const nextConsumer = link.nextConsumer;
337
- const prevConsumer = link.prevConsumer;
338
- link.nextConsumer = undefined;
339
- link.prevConsumer = undefined;
340
- if (nextConsumer !== undefined) {
341
- nextConsumer.prevConsumer = prevConsumer;
342
- }
343
- else {
344
- producer.consumersTail = prevConsumer;
345
- }
346
- if (prevConsumer !== undefined) {
347
- prevConsumer.nextConsumer = nextConsumer;
348
- }
349
- else {
350
- producer.consumers = nextConsumer;
351
- if (!consumerIsLive(producer)) {
352
- let producerLink = producer.producers;
353
- while (producerLink !== undefined) {
354
- producerLink = producerRemoveLiveConsumerLink(producerLink);
355
- }
356
- }
357
- }
358
- return nextProducer;
208
+ const producer = link.producer;
209
+ const nextProducer = link.nextProducer;
210
+ const nextConsumer = link.nextConsumer;
211
+ const prevConsumer = link.prevConsumer;
212
+ link.nextConsumer = undefined;
213
+ link.prevConsumer = undefined;
214
+ if (nextConsumer !== undefined) {
215
+ nextConsumer.prevConsumer = prevConsumer;
216
+ } else {
217
+ producer.consumersTail = prevConsumer;
218
+ }
219
+ if (prevConsumer !== undefined) {
220
+ prevConsumer.nextConsumer = nextConsumer;
221
+ } else {
222
+ producer.consumers = nextConsumer;
223
+ if (!consumerIsLive(producer)) {
224
+ let producerLink = producer.producers;
225
+ while (producerLink !== undefined) {
226
+ producerLink = producerRemoveLiveConsumerLink(producerLink);
227
+ }
228
+ }
229
+ }
230
+ return nextProducer;
359
231
  }
360
232
  function consumerIsLive(node) {
361
- return node.consumerIsAlwaysLive || node.consumers !== undefined;
233
+ return node.consumerIsAlwaysLive || node.consumers !== undefined;
362
234
  }
363
235
  function runPostProducerCreatedFn(node) {
364
- postProducerCreatedFn?.(node);
236
+ postProducerCreatedFn?.(node);
365
237
  }
366
238
  function setPostProducerCreatedFn(fn) {
367
- const prev = postProducerCreatedFn;
368
- postProducerCreatedFn = fn;
369
- return prev;
239
+ const prev = postProducerCreatedFn;
240
+ postProducerCreatedFn = fn;
241
+ return prev;
370
242
  }
371
- // While a ReactiveNode is recomputing, it may not have destroyed previous links
372
- // This allows us to check if a given link will be destroyed by a reactivenode if it were to finish running immediately without accesing any more producers
373
243
  function isValidLink(checkLink, consumer) {
374
- const producersTail = consumer.producersTail;
375
- if (producersTail !== undefined) {
376
- let link = consumer.producers;
377
- do {
378
- if (link === checkLink) {
379
- return true;
380
- }
381
- if (link === producersTail) {
382
- break;
383
- }
384
- link = link.nextProducer;
385
- } while (link !== undefined);
386
- }
387
- return false;
244
+ const producersTail = consumer.producersTail;
245
+ if (producersTail !== undefined) {
246
+ let link = consumer.producers;
247
+ do {
248
+ if (link === checkLink) {
249
+ return true;
250
+ }
251
+ if (link === producersTail) {
252
+ break;
253
+ }
254
+ link = link.nextProducer;
255
+ } while (link !== undefined);
256
+ }
257
+ return false;
388
258
  }
389
259
 
390
- /**
391
- * The default equality function used for `signal` and `computed`, which uses referential equality.
392
- */
393
260
  function defaultEquals(a, b) {
394
- return Object.is(a, b);
261
+ return Object.is(a, b);
395
262
  }
396
263
 
397
- /**
398
- * Create a computed signal which derives a reactive value from an expression.
399
- */
400
264
  function createComputed(computation, equal) {
401
- const node = Object.create(COMPUTED_NODE);
402
- node.computation = computation;
403
- if (equal !== undefined) {
404
- node.equal = equal;
265
+ const node = Object.create(COMPUTED_NODE);
266
+ node.computation = computation;
267
+ if (equal !== undefined) {
268
+ node.equal = equal;
269
+ }
270
+ const computed = () => {
271
+ producerUpdateValueVersion(node);
272
+ producerAccessed(node);
273
+ if (node.value === ERRORED) {
274
+ throw node.error;
405
275
  }
406
- const computed = () => {
407
- // Check if the value needs updating before returning it.
408
- producerUpdateValueVersion(node);
409
- // Record that someone looked at this signal.
410
- producerAccessed(node);
411
- if (node.value === ERRORED) {
412
- throw node.error;
413
- }
414
- return node.value;
415
- };
416
- computed[SIGNAL] = node;
417
- if (typeof ngDevMode !== 'undefined' && ngDevMode) {
418
- const debugName = node.debugName ? ' (' + node.debugName + ')' : '';
419
- computed.toString = () => `[Computed${debugName}: ${node.value}]`;
276
+ return node.value;
277
+ };
278
+ computed[SIGNAL] = node;
279
+ if (typeof ngDevMode !== 'undefined' && ngDevMode) {
280
+ const debugName = node.debugName ? ' (' + node.debugName + ')' : '';
281
+ computed.toString = () => `[Computed${debugName}: ${node.value}]`;
282
+ }
283
+ runPostProducerCreatedFn(node);
284
+ return computed;
285
+ }
286
+ const UNSET = /* @__PURE__ */Symbol('UNSET');
287
+ const COMPUTING = /* @__PURE__ */Symbol('COMPUTING');
288
+ const ERRORED = /* @__PURE__ */Symbol('ERRORED');
289
+ const COMPUTED_NODE = /* @__PURE__ */(() => {
290
+ return {
291
+ ...REACTIVE_NODE,
292
+ value: UNSET,
293
+ dirty: true,
294
+ error: null,
295
+ equal: defaultEquals,
296
+ kind: 'computed',
297
+ producerMustRecompute(node) {
298
+ return node.value === UNSET || node.value === COMPUTING;
299
+ },
300
+ producerRecomputeValue(node) {
301
+ if (node.value === COMPUTING) {
302
+ throw new Error(typeof ngDevMode !== 'undefined' && ngDevMode ? 'Detected cycle in computations.' : '');
303
+ }
304
+ const oldValue = node.value;
305
+ node.value = COMPUTING;
306
+ const prevConsumer = consumerBeforeComputation(node);
307
+ let newValue;
308
+ let wasEqual = false;
309
+ try {
310
+ newValue = node.computation();
311
+ setActiveConsumer(null);
312
+ wasEqual = oldValue !== UNSET && oldValue !== ERRORED && newValue !== ERRORED && node.equal(oldValue, newValue);
313
+ } catch (err) {
314
+ newValue = ERRORED;
315
+ node.error = err;
316
+ } finally {
317
+ consumerAfterComputation(node, prevConsumer);
318
+ }
319
+ if (wasEqual) {
320
+ node.value = oldValue;
321
+ return;
322
+ }
323
+ node.value = newValue;
324
+ node.version++;
420
325
  }
421
- runPostProducerCreatedFn(node);
422
- return computed;
423
- }
424
- /**
425
- * A dedicated symbol used before a computed value has been calculated for the first time.
426
- * Explicitly typed as `any` so we can use it as signal's value.
427
- */
428
- const UNSET = /* @__PURE__ */ Symbol('UNSET');
429
- /**
430
- * A dedicated symbol used in place of a computed signal value to indicate that a given computation
431
- * is in progress. Used to detect cycles in computation chains.
432
- * Explicitly typed as `any` so we can use it as signal's value.
433
- */
434
- const COMPUTING = /* @__PURE__ */ Symbol('COMPUTING');
435
- /**
436
- * A dedicated symbol used in place of a computed signal value to indicate that a given computation
437
- * failed. The thrown error is cached until the computation gets dirty again.
438
- * Explicitly typed as `any` so we can use it as signal's value.
439
- */
440
- const ERRORED = /* @__PURE__ */ Symbol('ERRORED');
441
- // Note: Using an IIFE here to ensure that the spread assignment is not considered
442
- // a side-effect, ending up preserving `COMPUTED_NODE` and `REACTIVE_NODE`.
443
- // TODO: remove when https://github.com/evanw/esbuild/issues/3392 is resolved.
444
- const COMPUTED_NODE = /* @__PURE__ */ (() => {
445
- return {
446
- ...REACTIVE_NODE,
447
- value: UNSET,
448
- dirty: true,
449
- error: null,
450
- equal: defaultEquals,
451
- kind: 'computed',
452
- producerMustRecompute(node) {
453
- // Force a recomputation if there's no current value, or if the current value is in the
454
- // process of being calculated (which should throw an error).
455
- return node.value === UNSET || node.value === COMPUTING;
456
- },
457
- producerRecomputeValue(node) {
458
- if (node.value === COMPUTING) {
459
- // Our computation somehow led to a cyclic read of itself.
460
- throw new Error(typeof ngDevMode !== 'undefined' && ngDevMode ? 'Detected cycle in computations.' : '');
461
- }
462
- const oldValue = node.value;
463
- node.value = COMPUTING;
464
- const prevConsumer = consumerBeforeComputation(node);
465
- let newValue;
466
- let wasEqual = false;
467
- try {
468
- newValue = node.computation();
469
- // We want to mark this node as errored if calling `equal` throws; however, we don't want
470
- // to track any reactive reads inside `equal`.
471
- setActiveConsumer(null);
472
- wasEqual =
473
- oldValue !== UNSET &&
474
- oldValue !== ERRORED &&
475
- newValue !== ERRORED &&
476
- node.equal(oldValue, newValue);
477
- }
478
- catch (err) {
479
- newValue = ERRORED;
480
- node.error = err;
481
- }
482
- finally {
483
- consumerAfterComputation(node, prevConsumer);
484
- }
485
- if (wasEqual) {
486
- // No change to `valueVersion` - old and new values are
487
- // semantically equivalent.
488
- node.value = oldValue;
489
- return;
490
- }
491
- node.value = newValue;
492
- node.version++;
493
- },
494
- };
326
+ };
495
327
  })();
496
328
 
497
329
  function defaultThrowError() {
498
- throw new Error();
330
+ throw new Error();
499
331
  }
500
332
  let throwInvalidWriteToSignalErrorFn = defaultThrowError;
501
333
  function throwInvalidWriteToSignalError(node) {
502
- throwInvalidWriteToSignalErrorFn(node);
334
+ throwInvalidWriteToSignalErrorFn(node);
503
335
  }
504
336
  function setThrowInvalidWriteToSignalError(fn) {
505
- throwInvalidWriteToSignalErrorFn = fn;
337
+ throwInvalidWriteToSignalErrorFn = fn;
506
338
  }
507
339
 
508
- /**
509
- * If set, called after `WritableSignal`s are updated.
510
- *
511
- * This hook can be used to achieve various effects, such as running effects synchronously as part
512
- * of setting a signal.
513
- */
514
340
  let postSignalSetFn = null;
515
- /**
516
- * Creates a `Signal` getter, setter, and updater function.
517
- */
518
341
  function createSignal(initialValue, equal) {
519
- const node = Object.create(SIGNAL_NODE);
520
- node.value = initialValue;
521
- if (equal !== undefined) {
522
- node.equal = equal;
523
- }
524
- const getter = (() => signalGetFn(node));
525
- getter[SIGNAL] = node;
526
- if (typeof ngDevMode !== 'undefined' && ngDevMode) {
527
- const debugName = node.debugName ? ' (' + node.debugName + ')' : '';
528
- getter.toString = () => `[Signal${debugName}: ${node.value}]`;
529
- }
530
- runPostProducerCreatedFn(node);
531
- const set = (newValue) => signalSetFn(node, newValue);
532
- const update = (updateFn) => signalUpdateFn(node, updateFn);
533
- return [getter, set, update];
342
+ const node = Object.create(SIGNAL_NODE);
343
+ node.value = initialValue;
344
+ if (equal !== undefined) {
345
+ node.equal = equal;
346
+ }
347
+ const getter = () => signalGetFn(node);
348
+ getter[SIGNAL] = node;
349
+ if (typeof ngDevMode !== 'undefined' && ngDevMode) {
350
+ const debugName = node.debugName ? ' (' + node.debugName + ')' : '';
351
+ getter.toString = () => `[Signal${debugName}: ${node.value}]`;
352
+ }
353
+ runPostProducerCreatedFn(node);
354
+ const set = newValue => signalSetFn(node, newValue);
355
+ const update = updateFn => signalUpdateFn(node, updateFn);
356
+ return [getter, set, update];
534
357
  }
535
358
  function setPostSignalSetFn(fn) {
536
- const prev = postSignalSetFn;
537
- postSignalSetFn = fn;
538
- return prev;
359
+ const prev = postSignalSetFn;
360
+ postSignalSetFn = fn;
361
+ return prev;
539
362
  }
540
363
  function signalGetFn(node) {
541
- producerAccessed(node);
542
- return node.value;
364
+ producerAccessed(node);
365
+ return node.value;
543
366
  }
544
367
  function signalSetFn(node, newValue) {
545
- if (!producerUpdatesAllowed()) {
546
- throwInvalidWriteToSignalError(node);
547
- }
548
- if (!node.equal(node.value, newValue)) {
549
- node.value = newValue;
550
- signalValueChanged(node);
551
- }
368
+ if (!producerUpdatesAllowed()) {
369
+ throwInvalidWriteToSignalError(node);
370
+ }
371
+ if (!node.equal(node.value, newValue)) {
372
+ node.value = newValue;
373
+ signalValueChanged(node);
374
+ }
552
375
  }
553
376
  function signalUpdateFn(node, updater) {
554
- if (!producerUpdatesAllowed()) {
555
- throwInvalidWriteToSignalError(node);
556
- }
557
- signalSetFn(node, updater(node.value));
377
+ if (!producerUpdatesAllowed()) {
378
+ throwInvalidWriteToSignalError(node);
379
+ }
380
+ signalSetFn(node, updater(node.value));
558
381
  }
559
382
  function runPostSignalSetFn(node) {
560
- postSignalSetFn?.(node);
561
- }
562
- // Note: Using an IIFE here to ensure that the spread assignment is not considered
563
- // a side-effect, ending up preserving `COMPUTED_NODE` and `REACTIVE_NODE`.
564
- // TODO: remove when https://github.com/evanw/esbuild/issues/3392 is resolved.
565
- const SIGNAL_NODE = /* @__PURE__ */ (() => {
566
- return {
567
- ...REACTIVE_NODE,
568
- equal: defaultEquals,
569
- value: undefined,
570
- kind: 'signal',
571
- };
383
+ postSignalSetFn?.(node);
384
+ }
385
+ const SIGNAL_NODE = /* @__PURE__ */(() => {
386
+ return {
387
+ ...REACTIVE_NODE,
388
+ equal: defaultEquals,
389
+ value: undefined,
390
+ kind: 'signal'
391
+ };
572
392
  })();
573
393
  function signalValueChanged(node) {
574
- node.version++;
575
- producerIncrementEpoch();
576
- producerNotifyConsumers(node);
577
- postSignalSetFn?.(node);
394
+ node.version++;
395
+ producerIncrementEpoch();
396
+ producerNotifyConsumers(node);
397
+ postSignalSetFn?.(node);
578
398
  }
579
399
 
580
- const BASE_EFFECT_NODE =
581
- /* @__PURE__ */ (() => ({
582
- ...REACTIVE_NODE,
583
- consumerIsAlwaysLive: true,
584
- consumerAllowSignalWrites: true,
585
- dirty: true,
586
- kind: 'effect',
400
+ const BASE_EFFECT_NODE = /* @__PURE__ */(() => ({
401
+ ...REACTIVE_NODE,
402
+ consumerIsAlwaysLive: true,
403
+ consumerAllowSignalWrites: true,
404
+ dirty: true,
405
+ kind: 'effect'
587
406
  }))();
588
407
  function runEffect(node) {
589
- node.dirty = false;
590
- if (node.version > 0 && !consumerPollProducersForChange(node)) {
591
- return;
592
- }
593
- node.version++;
594
- const prevNode = consumerBeforeComputation(node);
595
- try {
596
- node.cleanup();
597
- node.fn();
598
- }
599
- finally {
600
- consumerAfterComputation(node, prevNode);
601
- }
408
+ node.dirty = false;
409
+ if (node.version > 0 && !consumerPollProducersForChange(node)) {
410
+ return;
411
+ }
412
+ node.version++;
413
+ const prevNode = consumerBeforeComputation(node);
414
+ try {
415
+ node.cleanup();
416
+ node.fn();
417
+ } finally {
418
+ consumerAfterComputation(node, prevNode);
419
+ }
602
420
  }
603
421
 
604
422
  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 };