@angular/core 16.2.4 → 16.2.6

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.
package/fesm2022/core.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v16.2.4
2
+ * @license Angular v16.2.6
3
3
  * (c) 2010-2022 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -2294,7 +2294,7 @@ function getFactoryDef(type, throwNotFound) {
2294
2294
  *
2295
2295
  * This can be used to auto-unwrap signals in various cases, or to auto-wrap non-signal values.
2296
2296
  */
2297
- const SIGNAL = Symbol('SIGNAL');
2297
+ const SIGNAL = /* @__PURE__ */ Symbol('SIGNAL');
2298
2298
  /**
2299
2299
  * Checks if the given `value` is a reactive `Signal`.
2300
2300
  *
@@ -2472,7 +2472,9 @@ function consumerAfterComputation(node, prevConsumer) {
2472
2472
  }
2473
2473
  }
2474
2474
  // Truncate the producer tracking arrays.
2475
- for (let i = node.nextProducerIndex; i < node.producerNode.length; i++) {
2475
+ // Perf note: this is essentially truncating the length to `node.nextProducerIndex`, but
2476
+ // benchmarking has shown that individual pop operations are faster.
2477
+ while (node.producerNode.length > node.nextProducerIndex) {
2476
2478
  node.producerNode.pop();
2477
2479
  node.producerLastReadVersion.pop();
2478
2480
  node.producerIndexOfThis.pop();
@@ -2546,6 +2548,9 @@ function producerAddLiveConsumer(node, consumer, indexOfThis) {
2546
2548
  function producerRemoveLiveConsumerAtIndex(node, idx) {
2547
2549
  assertProducerNode(node);
2548
2550
  assertConsumerNode(node);
2551
+ if (typeof ngDevMode !== 'undefined' && ngDevMode && idx >= node.liveConsumerNode.length) {
2552
+ throw new Error(`Assertion error: active consumer index ${idx} is out of bounds of ${node.liveConsumerNode.length} consumers)`);
2553
+ }
2549
2554
  if (node.liveConsumerNode.length === 1) {
2550
2555
  // When removing the last live consumer, we will no longer be live. We need to remove
2551
2556
  // ourselves from our producers' tracking (which may cause consumer-producers to lose
@@ -2610,60 +2615,65 @@ function computed(computation, options) {
2610
2615
  * A dedicated symbol used before a computed value has been calculated for the first time.
2611
2616
  * Explicitly typed as `any` so we can use it as signal's value.
2612
2617
  */
2613
- const UNSET = Symbol('UNSET');
2618
+ const UNSET = /* @__PURE__ */ Symbol('UNSET');
2614
2619
  /**
2615
2620
  * A dedicated symbol used in place of a computed signal value to indicate that a given computation
2616
2621
  * is in progress. Used to detect cycles in computation chains.
2617
2622
  * Explicitly typed as `any` so we can use it as signal's value.
2618
2623
  */
2619
- const COMPUTING = Symbol('COMPUTING');
2624
+ const COMPUTING = /* @__PURE__ */ Symbol('COMPUTING');
2620
2625
  /**
2621
2626
  * A dedicated symbol used in place of a computed signal value to indicate that a given computation
2622
2627
  * failed. The thrown error is cached until the computation gets dirty again.
2623
2628
  * Explicitly typed as `any` so we can use it as signal's value.
2624
2629
  */
2625
- const ERRORED = Symbol('ERRORED');
2626
- const COMPUTED_NODE = {
2627
- ...REACTIVE_NODE,
2628
- value: UNSET,
2629
- dirty: true,
2630
- error: null,
2631
- equal: defaultEquals,
2632
- producerMustRecompute(node) {
2633
- // Force a recomputation if there's no current value, or if the current value is in the process
2634
- // of being calculated (which should throw an error).
2635
- return node.value === UNSET || node.value === COMPUTING;
2636
- },
2637
- producerRecomputeValue(node) {
2638
- if (node.value === COMPUTING) {
2639
- // Our computation somehow led to a cyclic read of itself.
2640
- throw new Error('Detected cycle in computations.');
2641
- }
2642
- const oldValue = node.value;
2643
- node.value = COMPUTING;
2644
- const prevConsumer = consumerBeforeComputation(node);
2645
- let newValue;
2646
- try {
2647
- newValue = node.computation();
2648
- }
2649
- catch (err) {
2650
- newValue = ERRORED;
2651
- node.error = err;
2652
- }
2653
- finally {
2654
- consumerAfterComputation(node, prevConsumer);
2655
- }
2656
- if (oldValue !== UNSET && oldValue !== ERRORED && newValue !== ERRORED &&
2657
- node.equal(oldValue, newValue)) {
2658
- // No change to `valueVersion` - old and new values are
2659
- // semantically equivalent.
2660
- node.value = oldValue;
2661
- return;
2662
- }
2663
- node.value = newValue;
2664
- node.version++;
2665
- },
2666
- };
2630
+ const ERRORED = /* @__PURE__ */ Symbol('ERRORED');
2631
+ // Note: Using an IIFE here to ensure that the spread assignment is not considered
2632
+ // a side-effect, ending up preserving `COMPUTED_NODE` and `REACTIVE_NODE`.
2633
+ // TODO: remove when https://github.com/evanw/esbuild/issues/3392 is resolved.
2634
+ const COMPUTED_NODE = /* @__PURE__ */ (() => {
2635
+ return {
2636
+ ...REACTIVE_NODE,
2637
+ value: UNSET,
2638
+ dirty: true,
2639
+ error: null,
2640
+ equal: defaultEquals,
2641
+ producerMustRecompute(node) {
2642
+ // Force a recomputation if there's no current value, or if the current value is in the
2643
+ // process of being calculated (which should throw an error).
2644
+ return node.value === UNSET || node.value === COMPUTING;
2645
+ },
2646
+ producerRecomputeValue(node) {
2647
+ if (node.value === COMPUTING) {
2648
+ // Our computation somehow led to a cyclic read of itself.
2649
+ throw new Error('Detected cycle in computations.');
2650
+ }
2651
+ const oldValue = node.value;
2652
+ node.value = COMPUTING;
2653
+ const prevConsumer = consumerBeforeComputation(node);
2654
+ let newValue;
2655
+ try {
2656
+ newValue = node.computation();
2657
+ }
2658
+ catch (err) {
2659
+ newValue = ERRORED;
2660
+ node.error = err;
2661
+ }
2662
+ finally {
2663
+ consumerAfterComputation(node, prevConsumer);
2664
+ }
2665
+ if (oldValue !== UNSET && oldValue !== ERRORED && newValue !== ERRORED &&
2666
+ node.equal(oldValue, newValue)) {
2667
+ // No change to `valueVersion` - old and new values are
2668
+ // semantically equivalent.
2669
+ node.value = oldValue;
2670
+ return;
2671
+ }
2672
+ node.value = newValue;
2673
+ node.version++;
2674
+ },
2675
+ };
2676
+ })();
2667
2677
 
2668
2678
  function defaultThrowError() {
2669
2679
  throw new Error();
@@ -2708,11 +2718,16 @@ function setPostSignalSetFn(fn) {
2708
2718
  postSignalSetFn = fn;
2709
2719
  return prev;
2710
2720
  }
2711
- const SIGNAL_NODE = {
2712
- ...REACTIVE_NODE,
2713
- equal: defaultEquals,
2714
- readonlyFn: undefined,
2715
- };
2721
+ // Note: Using an IIFE here to ensure that the spread assignment is not considered
2722
+ // a side-effect, ending up preserving `COMPUTED_NODE` and `REACTIVE_NODE`.
2723
+ // TODO: remove when https://github.com/evanw/esbuild/issues/3392 is resolved.
2724
+ const SIGNAL_NODE = /* @__PURE__ */ (() => {
2725
+ return {
2726
+ ...REACTIVE_NODE,
2727
+ equal: defaultEquals,
2728
+ readonlyFn: undefined,
2729
+ };
2730
+ })();
2716
2731
  function signalValueChanged(node) {
2717
2732
  node.version++;
2718
2733
  producerNotifyConsumers(node);
@@ -2805,16 +2820,21 @@ function watch(fn, schedule, allowSignalWrites) {
2805
2820
  return node.ref;
2806
2821
  }
2807
2822
  const NOOP_CLEANUP_FN = () => { };
2808
- const WATCH_NODE = {
2809
- ...REACTIVE_NODE,
2810
- consumerIsAlwaysLive: true,
2811
- consumerAllowSignalWrites: false,
2812
- consumerMarkedDirty: (node) => {
2813
- node.schedule(node.ref);
2814
- },
2815
- hasRun: false,
2816
- cleanupFn: NOOP_CLEANUP_FN,
2817
- };
2823
+ // Note: Using an IIFE here to ensure that the spread assignment is not considered
2824
+ // a side-effect, ending up preserving `COMPUTED_NODE` and `REACTIVE_NODE`.
2825
+ // TODO: remove when https://github.com/evanw/esbuild/issues/3392 is resolved.
2826
+ const WATCH_NODE = /* @__PURE__ */ (() => {
2827
+ return {
2828
+ ...REACTIVE_NODE,
2829
+ consumerIsAlwaysLive: true,
2830
+ consumerAllowSignalWrites: false,
2831
+ consumerMarkedDirty: (node) => {
2832
+ node.schedule(node.ref);
2833
+ },
2834
+ hasRun: false,
2835
+ cleanupFn: NOOP_CLEANUP_FN,
2836
+ };
2837
+ })();
2818
2838
 
2819
2839
  function setAlternateWeakRefImpl(impl) {
2820
2840
  // TODO: remove this function
@@ -10256,7 +10276,7 @@ class Version {
10256
10276
  /**
10257
10277
  * @publicApi
10258
10278
  */
10259
- const VERSION = new Version('16.2.4');
10279
+ const VERSION = new Version('16.2.6');
10260
10280
 
10261
10281
  // This default value is when checking the hierarchy for a token.
10262
10282
  //
@@ -10524,6 +10544,66 @@ class Injector {
10524
10544
  * safe to delete this file.
10525
10545
  */
10526
10546
 
10547
+ const ERROR_ORIGINAL_ERROR = 'ngOriginalError';
10548
+ function wrappedError(message, originalError) {
10549
+ const msg = `${message} caused by: ${originalError instanceof Error ? originalError.message : originalError}`;
10550
+ const error = Error(msg);
10551
+ error[ERROR_ORIGINAL_ERROR] = originalError;
10552
+ return error;
10553
+ }
10554
+ function getOriginalError(error) {
10555
+ return error[ERROR_ORIGINAL_ERROR];
10556
+ }
10557
+
10558
+ /**
10559
+ * Provides a hook for centralized exception handling.
10560
+ *
10561
+ * The default implementation of `ErrorHandler` prints error messages to the `console`. To
10562
+ * intercept error handling, write a custom exception handler that replaces this default as
10563
+ * appropriate for your app.
10564
+ *
10565
+ * @usageNotes
10566
+ * ### Example
10567
+ *
10568
+ * ```
10569
+ * class MyErrorHandler implements ErrorHandler {
10570
+ * handleError(error) {
10571
+ * // do something with the exception
10572
+ * }
10573
+ * }
10574
+ *
10575
+ * @NgModule({
10576
+ * providers: [{provide: ErrorHandler, useClass: MyErrorHandler}]
10577
+ * })
10578
+ * class MyModule {}
10579
+ * ```
10580
+ *
10581
+ * @publicApi
10582
+ */
10583
+ class ErrorHandler {
10584
+ constructor() {
10585
+ /**
10586
+ * @internal
10587
+ */
10588
+ this._console = console;
10589
+ }
10590
+ handleError(error) {
10591
+ const originalError = this._findOriginalError(error);
10592
+ this._console.error('ERROR', error);
10593
+ if (originalError) {
10594
+ this._console.error('ORIGINAL ERROR', originalError);
10595
+ }
10596
+ }
10597
+ /** @internal */
10598
+ _findOriginalError(error) {
10599
+ let e = error && getOriginalError(error);
10600
+ while (e && getOriginalError(e)) {
10601
+ e = getOriginalError(e);
10602
+ }
10603
+ return e || null;
10604
+ }
10605
+ }
10606
+
10527
10607
  /**
10528
10608
  * `DestroyRef` lets you set callbacks to run for any cleanup or destruction behavior.
10529
10609
  * The scope of this destruction depends on where `DestroyRef` is injected. If `DestroyRef`
@@ -11234,14 +11314,18 @@ function afterRender(callback, options) {
11234
11314
  }
11235
11315
  let destroy;
11236
11316
  const unregisterFn = injector.get(DestroyRef).onDestroy(() => destroy?.());
11237
- const manager = injector.get(AfterRenderEventManager);
11317
+ const afterRenderEventManager = injector.get(AfterRenderEventManager);
11318
+ // Lazily initialize the handler implementation, if necessary. This is so that it can be
11319
+ // tree-shaken if `afterRender` and `afterNextRender` aren't used.
11320
+ const callbackHandler = afterRenderEventManager.handler ??= new AfterRenderCallbackHandlerImpl();
11238
11321
  const ngZone = injector.get(NgZone);
11239
- const instance = new AfterRenderCallback(() => ngZone.runOutsideAngular(callback));
11322
+ const errorHandler = injector.get(ErrorHandler, null, { optional: true });
11323
+ const instance = new AfterRenderCallback(ngZone, errorHandler, callback);
11240
11324
  destroy = () => {
11241
- manager.unregister(instance);
11325
+ callbackHandler.unregister(instance);
11242
11326
  unregisterFn();
11243
11327
  };
11244
- manager.register(instance);
11328
+ callbackHandler.register(instance);
11245
11329
  return { destroy };
11246
11330
  }
11247
11331
  /**
@@ -11294,89 +11378,117 @@ function afterNextRender(callback, options) {
11294
11378
  }
11295
11379
  let destroy;
11296
11380
  const unregisterFn = injector.get(DestroyRef).onDestroy(() => destroy?.());
11297
- const manager = injector.get(AfterRenderEventManager);
11381
+ const afterRenderEventManager = injector.get(AfterRenderEventManager);
11382
+ // Lazily initialize the handler implementation, if necessary. This is so that it can be
11383
+ // tree-shaken if `afterRender` and `afterNextRender` aren't used.
11384
+ const callbackHandler = afterRenderEventManager.handler ??= new AfterRenderCallbackHandlerImpl();
11298
11385
  const ngZone = injector.get(NgZone);
11299
- const instance = new AfterRenderCallback(() => {
11386
+ const errorHandler = injector.get(ErrorHandler, null, { optional: true });
11387
+ const instance = new AfterRenderCallback(ngZone, errorHandler, () => {
11300
11388
  destroy?.();
11301
- ngZone.runOutsideAngular(callback);
11389
+ callback();
11302
11390
  });
11303
11391
  destroy = () => {
11304
- manager.unregister(instance);
11392
+ callbackHandler.unregister(instance);
11305
11393
  unregisterFn();
11306
11394
  };
11307
- manager.register(instance);
11395
+ callbackHandler.register(instance);
11308
11396
  return { destroy };
11309
11397
  }
11310
11398
  /**
11311
11399
  * A wrapper around a function to be used as an after render callback.
11312
- * @private
11313
11400
  */
11314
11401
  class AfterRenderCallback {
11315
- constructor(callback) {
11316
- this.callback = callback;
11402
+ constructor(zone, errorHandler, callbackFn) {
11403
+ this.zone = zone;
11404
+ this.errorHandler = errorHandler;
11405
+ this.callbackFn = callbackFn;
11317
11406
  }
11318
11407
  invoke() {
11319
- this.callback();
11408
+ try {
11409
+ this.zone.runOutsideAngular(this.callbackFn);
11410
+ }
11411
+ catch (err) {
11412
+ this.errorHandler?.handleError(err);
11413
+ }
11320
11414
  }
11321
11415
  }
11322
11416
  /**
11323
- * Implements `afterRender` and `afterNextRender` callback manager logic.
11417
+ * Core functionality for `afterRender` and `afterNextRender`. Kept separate from
11418
+ * `AfterRenderEventManager` for tree-shaking.
11324
11419
  */
11325
- class AfterRenderEventManager {
11420
+ class AfterRenderCallbackHandlerImpl {
11326
11421
  constructor() {
11422
+ this.executingCallbacks = false;
11327
11423
  this.callbacks = new Set();
11328
11424
  this.deferredCallbacks = new Set();
11329
- this.renderDepth = 0;
11330
- this.runningCallbacks = false;
11331
11425
  }
11332
- /**
11333
- * Mark the beginning of a render operation (i.e. CD cycle).
11334
- * Throws if called from an `afterRender` callback.
11335
- */
11336
- begin() {
11337
- if (this.runningCallbacks) {
11426
+ validateBegin() {
11427
+ if (this.executingCallbacks) {
11338
11428
  throw new RuntimeError(102 /* RuntimeErrorCode.RECURSIVE_APPLICATION_RENDER */, ngDevMode &&
11339
11429
  'A new render operation began before the previous operation ended. ' +
11340
11430
  'Did you trigger change detection from afterRender or afterNextRender?');
11341
11431
  }
11342
- this.renderDepth++;
11343
- }
11344
- /**
11345
- * Mark the end of a render operation. Registered callbacks
11346
- * are invoked if there are no more pending operations.
11347
- */
11348
- end() {
11349
- this.renderDepth--;
11350
- if (this.renderDepth === 0) {
11351
- try {
11352
- this.runningCallbacks = true;
11353
- for (const callback of this.callbacks) {
11354
- callback.invoke();
11355
- }
11356
- }
11357
- finally {
11358
- this.runningCallbacks = false;
11359
- for (const callback of this.deferredCallbacks) {
11360
- this.callbacks.add(callback);
11361
- }
11362
- this.deferredCallbacks.clear();
11363
- }
11364
- }
11365
11432
  }
11366
11433
  register(callback) {
11367
11434
  // If we're currently running callbacks, new callbacks should be deferred
11368
11435
  // until the next render operation.
11369
- const target = this.runningCallbacks ? this.deferredCallbacks : this.callbacks;
11436
+ const target = this.executingCallbacks ? this.deferredCallbacks : this.callbacks;
11370
11437
  target.add(callback);
11371
11438
  }
11372
11439
  unregister(callback) {
11373
11440
  this.callbacks.delete(callback);
11374
11441
  this.deferredCallbacks.delete(callback);
11375
11442
  }
11376
- ngOnDestroy() {
11443
+ execute() {
11444
+ this.executingCallbacks = true;
11445
+ for (const callback of this.callbacks) {
11446
+ callback.invoke();
11447
+ }
11448
+ this.executingCallbacks = false;
11449
+ for (const callback of this.deferredCallbacks) {
11450
+ this.callbacks.add(callback);
11451
+ }
11452
+ this.deferredCallbacks.clear();
11453
+ }
11454
+ destroy() {
11377
11455
  this.callbacks.clear();
11378
11456
  this.deferredCallbacks.clear();
11379
11457
  }
11458
+ }
11459
+ /**
11460
+ * Implements core timing for `afterRender` and `afterNextRender` events.
11461
+ * Delegates to an optional `AfterRenderCallbackHandler` for implementation.
11462
+ */
11463
+ class AfterRenderEventManager {
11464
+ constructor() {
11465
+ this.renderDepth = 0;
11466
+ /* @internal */
11467
+ this.handler = null;
11468
+ }
11469
+ /**
11470
+ * Mark the beginning of a render operation (i.e. CD cycle).
11471
+ * Throws if called while executing callbacks.
11472
+ */
11473
+ begin() {
11474
+ this.handler?.validateBegin();
11475
+ this.renderDepth++;
11476
+ }
11477
+ /**
11478
+ * Mark the end of a render operation. Callbacks will be
11479
+ * executed if there are no more pending operations.
11480
+ */
11481
+ end() {
11482
+ ngDevMode && assertGreaterThan(this.renderDepth, 0, 'renderDepth must be greater than 0');
11483
+ this.renderDepth--;
11484
+ if (this.renderDepth === 0) {
11485
+ this.handler?.execute();
11486
+ }
11487
+ }
11488
+ ngOnDestroy() {
11489
+ this.handler?.destroy();
11490
+ this.handler = null;
11491
+ }
11380
11492
  /** @nocollapse */
11381
11493
  static { this.ɵprov = ɵɵdefineInjectable({
11382
11494
  token: AfterRenderEventManager,
@@ -11410,66 +11522,6 @@ function markViewDirty(lView) {
11410
11522
  return null;
11411
11523
  }
11412
11524
 
11413
- const ERROR_ORIGINAL_ERROR = 'ngOriginalError';
11414
- function wrappedError(message, originalError) {
11415
- const msg = `${message} caused by: ${originalError instanceof Error ? originalError.message : originalError}`;
11416
- const error = Error(msg);
11417
- error[ERROR_ORIGINAL_ERROR] = originalError;
11418
- return error;
11419
- }
11420
- function getOriginalError(error) {
11421
- return error[ERROR_ORIGINAL_ERROR];
11422
- }
11423
-
11424
- /**
11425
- * Provides a hook for centralized exception handling.
11426
- *
11427
- * The default implementation of `ErrorHandler` prints error messages to the `console`. To
11428
- * intercept error handling, write a custom exception handler that replaces this default as
11429
- * appropriate for your app.
11430
- *
11431
- * @usageNotes
11432
- * ### Example
11433
- *
11434
- * ```
11435
- * class MyErrorHandler implements ErrorHandler {
11436
- * handleError(error) {
11437
- * // do something with the exception
11438
- * }
11439
- * }
11440
- *
11441
- * @NgModule({
11442
- * providers: [{provide: ErrorHandler, useClass: MyErrorHandler}]
11443
- * })
11444
- * class MyModule {}
11445
- * ```
11446
- *
11447
- * @publicApi
11448
- */
11449
- class ErrorHandler {
11450
- constructor() {
11451
- /**
11452
- * @internal
11453
- */
11454
- this._console = console;
11455
- }
11456
- handleError(error) {
11457
- const originalError = this._findOriginalError(error);
11458
- this._console.error('ERROR', error);
11459
- if (originalError) {
11460
- this._console.error('ORIGINAL ERROR', originalError);
11461
- }
11462
- }
11463
- /** @internal */
11464
- _findOriginalError(error) {
11465
- let e = error && getOriginalError(error);
11466
- while (e && getOriginalError(e)) {
11467
- e = getOriginalError(e);
11468
- }
11469
- return e || null;
11470
- }
11471
- }
11472
-
11473
11525
  /**
11474
11526
  * Internal token that specifies whether DOM reuse logic
11475
11527
  * during hydration is enabled.