@angular/core 16.2.1 → 16.2.3

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.
@@ -1,12 +1,13 @@
1
1
  /**
2
- * @license Angular v16.2.1
2
+ * @license Angular v16.2.3
3
3
  * (c) 2010-2022 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
6
6
 
7
- import { getDebugNode, RendererFactory2 as RendererFactory2$1, InjectionToken as InjectionToken$1, ɵstringify, ɵReflectionCapabilities, Directive, Component, Pipe, NgModule, ɵgetInjectableDef, resolveForwardRef as resolveForwardRef$1, ɵNG_COMP_DEF, ɵRender3NgModuleRef, ApplicationInitStatus, LOCALE_ID as LOCALE_ID$1, ɵDEFAULT_LOCALE_ID, ɵsetLocaleId, ɵRender3ComponentFactory, ɵcompileComponent, ɵNG_DIR_DEF, ɵcompileDirective, ɵNG_PIPE_DEF, ɵcompilePipe, ɵNG_MOD_DEF, ɵtransitiveScopesFor, ɵpatchComponentDefWithScope, ɵNG_INJ_DEF, ɵcompileNgModuleDefs, provideZoneChangeDetection, Compiler, COMPILER_OPTIONS, Injector as Injector$1, ɵisEnvironmentProviders, ɵNgModuleFactory, ModuleWithComponentFactories, ɵconvertToBitFlags, InjectFlags as InjectFlags$1, ɵsetAllowDuplicateNgModuleIdsForTest, ɵresetCompiledComponents, ɵsetUnknownElementStrictMode as ɵsetUnknownElementStrictMode$1, ɵsetUnknownPropertyStrictMode as ɵsetUnknownPropertyStrictMode$1, ɵgetUnknownElementStrictMode as ɵgetUnknownElementStrictMode$1, ɵgetUnknownPropertyStrictMode as ɵgetUnknownPropertyStrictMode$1, EnvironmentInjector as EnvironmentInjector$1, NgZone, ɵflushModuleScopingQueueAsMuchAsPossible } from '@angular/core';
7
+ import { getDebugNode, RendererFactory2 as RendererFactory2$1, InjectionToken as InjectionToken$1, ɵstringify, ɵReflectionCapabilities, Directive, Component, Pipe, NgModule, ɵgetInjectableDef, resolveForwardRef as resolveForwardRef$1, ɵNG_COMP_DEF, ɵRender3NgModuleRef, ApplicationInitStatus, LOCALE_ID as LOCALE_ID$1, ɵDEFAULT_LOCALE_ID, ɵsetLocaleId, ɵRender3ComponentFactory, ɵcompileComponent, ɵNG_DIR_DEF, ɵcompileDirective, ɵNG_PIPE_DEF, ɵcompilePipe, ɵNG_MOD_DEF, ɵtransitiveScopesFor, ɵpatchComponentDefWithScope, ɵNG_INJ_DEF, ɵcompileNgModuleDefs, provideZoneChangeDetection, Compiler, COMPILER_OPTIONS, Injector as Injector$1, ɵisEnvironmentProviders, ɵNgModuleFactory, ModuleWithComponentFactories, ɵconvertToBitFlags, InjectFlags as InjectFlags$1, ɵsetAllowDuplicateNgModuleIdsForTest, ɵresetCompiledComponents, ɵsetUnknownElementStrictMode as ɵsetUnknownElementStrictMode$1, ɵsetUnknownPropertyStrictMode as ɵsetUnknownPropertyStrictMode$1, ɵgetUnknownElementStrictMode as ɵgetUnknownElementStrictMode$1, ɵgetUnknownPropertyStrictMode as ɵgetUnknownPropertyStrictMode$1, EnvironmentInjector as EnvironmentInjector$1, NgZone as NgZone$1, ɵflushModuleScopingQueueAsMuchAsPossible } from '@angular/core';
8
8
  import { ResourceLoader } from '@angular/compiler';
9
- import { Subject, Subscription } from 'rxjs';
9
+ import { Subject, Subscription, Observable, merge as merge$1 } from 'rxjs';
10
+ import { share } from 'rxjs/operators';
10
11
 
11
12
  /**
12
13
  * Wraps a test function in an asynchronous test zone. The test will automatically
@@ -6373,11 +6374,17 @@ function setAllowDuplicateNgModuleIdsForTest(allowDuplicates) {
6373
6374
  * `InjectionToken` is parameterized on `T` which is the type of object which will be returned by
6374
6375
  * the `Injector`. This provides an additional level of type safety.
6375
6376
  *
6376
- * ```
6377
- * interface MyInterface {...}
6378
- * const myInterface = injector.get(new InjectionToken<MyInterface>('SomeToken'));
6379
- * // myInterface is inferred to be MyInterface.
6380
- * ```
6377
+ * <div class="alert is-helpful">
6378
+ *
6379
+ * **Important Note**: Ensure that you use the same instance of the `InjectionToken` in both the
6380
+ * provider and the injection call. Creating a new instance of `InjectionToken` in different places,
6381
+ * even with the same description, will be treated as different tokens by Angular's DI system,
6382
+ * leading to a `NullInjectorError`.
6383
+ *
6384
+ * </div>
6385
+ *
6386
+ * <code-example format="typescript" language="typescript" path="injection-token/src/main.ts"
6387
+ * region="InjectionToken"></code-example>
6381
6388
  *
6382
6389
  * When creating an `InjectionToken`, you can optionally specify a factory function which returns
6383
6390
  * (possibly by creating) a default value of the parameterized type `T`. This sets up the
@@ -6404,7 +6411,6 @@ function setAllowDuplicateNgModuleIdsForTest(allowDuplicates) {
6404
6411
  *
6405
6412
  * {@example core/di/ts/injector_spec.ts region='ShakableInjectionToken'}
6406
6413
  *
6407
- *
6408
6414
  * @publicApi
6409
6415
  */
6410
6416
  class InjectionToken {
@@ -8009,7 +8015,7 @@ const COMMENT_DISALLOWED = /^>|^->|<!--|-->|--!>|<!-$/g;
8009
8015
  /**
8010
8016
  * Delimiter in the disallowed strings which needs to be wrapped with zero with character.
8011
8017
  */
8012
- const COMMENT_DELIMITER = /(<|>)/;
8018
+ const COMMENT_DELIMITER = /(<|>)/g;
8013
8019
  const COMMENT_DELIMITER_ESCAPED = '\u200B$1\u200B';
8014
8020
  /**
8015
8021
  * Escape the content of comment strings so that it can be safely inserted into a comment node.
@@ -10939,7 +10945,7 @@ class Version {
10939
10945
  /**
10940
10946
  * @publicApi
10941
10947
  */
10942
- const VERSION = new Version('16.2.1');
10948
+ const VERSION = new Version('16.2.3');
10943
10949
 
10944
10950
  // This default value is when checking the hierarchy for a token.
10945
10951
  //
@@ -10994,6 +11000,562 @@ function injectDestroyRef() {
10994
11000
  return new NodeInjectorDestroyRef(getLView());
10995
11001
  }
10996
11002
 
11003
+ /// <reference types="rxjs" />
11004
+ class EventEmitter_ extends Subject {
11005
+ constructor(isAsync = false) {
11006
+ super();
11007
+ this.__isAsync = isAsync;
11008
+ }
11009
+ emit(value) {
11010
+ super.next(value);
11011
+ }
11012
+ subscribe(observerOrNext, error, complete) {
11013
+ let nextFn = observerOrNext;
11014
+ let errorFn = error || (() => null);
11015
+ let completeFn = complete;
11016
+ if (observerOrNext && typeof observerOrNext === 'object') {
11017
+ const observer = observerOrNext;
11018
+ nextFn = observer.next?.bind(observer);
11019
+ errorFn = observer.error?.bind(observer);
11020
+ completeFn = observer.complete?.bind(observer);
11021
+ }
11022
+ if (this.__isAsync) {
11023
+ errorFn = _wrapInTimeout(errorFn);
11024
+ if (nextFn) {
11025
+ nextFn = _wrapInTimeout(nextFn);
11026
+ }
11027
+ if (completeFn) {
11028
+ completeFn = _wrapInTimeout(completeFn);
11029
+ }
11030
+ }
11031
+ const sink = super.subscribe({ next: nextFn, error: errorFn, complete: completeFn });
11032
+ if (observerOrNext instanceof Subscription) {
11033
+ observerOrNext.add(sink);
11034
+ }
11035
+ return sink;
11036
+ }
11037
+ }
11038
+ function _wrapInTimeout(fn) {
11039
+ return (value) => {
11040
+ setTimeout(fn, undefined, value);
11041
+ };
11042
+ }
11043
+ /**
11044
+ * @publicApi
11045
+ */
11046
+ const EventEmitter = EventEmitter_;
11047
+
11048
+ function noop(...args) {
11049
+ // Do nothing.
11050
+ }
11051
+
11052
+ function getNativeRequestAnimationFrame() {
11053
+ // Note: the `getNativeRequestAnimationFrame` is used in the `NgZone` class, but we cannot use the
11054
+ // `inject` function. The `NgZone` instance may be created manually, and thus the injection
11055
+ // context will be unavailable. This might be enough to check whether `requestAnimationFrame` is
11056
+ // available because otherwise, we'll fall back to `setTimeout`.
11057
+ const isBrowser = typeof _global['requestAnimationFrame'] === 'function';
11058
+ // Note: `requestAnimationFrame` is unavailable when the code runs in the Node.js environment. We
11059
+ // use `setTimeout` because no changes are required other than checking if the current platform is
11060
+ // the browser. `setTimeout` is a well-established API that is available in both environments.
11061
+ // `requestAnimationFrame` is used in the browser to coalesce event tasks since event tasks are
11062
+ // usually executed within the same rendering frame (but this is more implementation details of
11063
+ // browsers).
11064
+ let nativeRequestAnimationFrame = _global[isBrowser ? 'requestAnimationFrame' : 'setTimeout'];
11065
+ let nativeCancelAnimationFrame = _global[isBrowser ? 'cancelAnimationFrame' : 'clearTimeout'];
11066
+ if (typeof Zone !== 'undefined' && nativeRequestAnimationFrame && nativeCancelAnimationFrame) {
11067
+ // Note: zone.js sets original implementations on patched APIs behind the
11068
+ // `__zone_symbol__OriginalDelegate` key (see `attachOriginToPatched`). Given the following
11069
+ // example: `window.requestAnimationFrame.__zone_symbol__OriginalDelegate`; this would return an
11070
+ // unpatched implementation of the `requestAnimationFrame`, which isn't intercepted by the
11071
+ // Angular zone. We use the unpatched implementation to avoid another change detection when
11072
+ // coalescing tasks.
11073
+ const unpatchedRequestAnimationFrame = nativeRequestAnimationFrame[Zone.__symbol__('OriginalDelegate')];
11074
+ if (unpatchedRequestAnimationFrame) {
11075
+ nativeRequestAnimationFrame = unpatchedRequestAnimationFrame;
11076
+ }
11077
+ const unpatchedCancelAnimationFrame = nativeCancelAnimationFrame[Zone.__symbol__('OriginalDelegate')];
11078
+ if (unpatchedCancelAnimationFrame) {
11079
+ nativeCancelAnimationFrame = unpatchedCancelAnimationFrame;
11080
+ }
11081
+ }
11082
+ return { nativeRequestAnimationFrame, nativeCancelAnimationFrame };
11083
+ }
11084
+
11085
+ class AsyncStackTaggingZoneSpec {
11086
+ constructor(namePrefix, consoleAsyncStackTaggingImpl = console) {
11087
+ this.name = 'asyncStackTagging for ' + namePrefix;
11088
+ this.createTask = consoleAsyncStackTaggingImpl?.createTask ?? (() => null);
11089
+ }
11090
+ onScheduleTask(delegate, _current, target, task) {
11091
+ task.consoleTask = this.createTask(`Zone - ${task.source || task.type}`);
11092
+ return delegate.scheduleTask(target, task);
11093
+ }
11094
+ onInvokeTask(delegate, _currentZone, targetZone, task, applyThis, applyArgs) {
11095
+ let ret;
11096
+ if (task.consoleTask) {
11097
+ ret = task.consoleTask.run(() => delegate.invokeTask(targetZone, task, applyThis, applyArgs));
11098
+ }
11099
+ else {
11100
+ ret = delegate.invokeTask(targetZone, task, applyThis, applyArgs);
11101
+ }
11102
+ return ret;
11103
+ }
11104
+ }
11105
+
11106
+ /**
11107
+ * An injectable service for executing work inside or outside of the Angular zone.
11108
+ *
11109
+ * The most common use of this service is to optimize performance when starting a work consisting of
11110
+ * one or more asynchronous tasks that don't require UI updates or error handling to be handled by
11111
+ * Angular. Such tasks can be kicked off via {@link #runOutsideAngular} and if needed, these tasks
11112
+ * can reenter the Angular zone via {@link #run}.
11113
+ *
11114
+ * <!-- TODO: add/fix links to:
11115
+ * - docs explaining zones and the use of zones in Angular and change-detection
11116
+ * - link to runOutsideAngular/run (throughout this file!)
11117
+ * -->
11118
+ *
11119
+ * @usageNotes
11120
+ * ### Example
11121
+ *
11122
+ * ```
11123
+ * import {Component, NgZone} from '@angular/core';
11124
+ * import {NgIf} from '@angular/common';
11125
+ *
11126
+ * @Component({
11127
+ * selector: 'ng-zone-demo',
11128
+ * template: `
11129
+ * <h2>Demo: NgZone</h2>
11130
+ *
11131
+ * <p>Progress: {{progress}}%</p>
11132
+ * <p *ngIf="progress >= 100">Done processing {{label}} of Angular zone!</p>
11133
+ *
11134
+ * <button (click)="processWithinAngularZone()">Process within Angular zone</button>
11135
+ * <button (click)="processOutsideOfAngularZone()">Process outside of Angular zone</button>
11136
+ * `,
11137
+ * })
11138
+ * export class NgZoneDemo {
11139
+ * progress: number = 0;
11140
+ * label: string;
11141
+ *
11142
+ * constructor(private _ngZone: NgZone) {}
11143
+ *
11144
+ * // Loop inside the Angular zone
11145
+ * // so the UI DOES refresh after each setTimeout cycle
11146
+ * processWithinAngularZone() {
11147
+ * this.label = 'inside';
11148
+ * this.progress = 0;
11149
+ * this._increaseProgress(() => console.log('Inside Done!'));
11150
+ * }
11151
+ *
11152
+ * // Loop outside of the Angular zone
11153
+ * // so the UI DOES NOT refresh after each setTimeout cycle
11154
+ * processOutsideOfAngularZone() {
11155
+ * this.label = 'outside';
11156
+ * this.progress = 0;
11157
+ * this._ngZone.runOutsideAngular(() => {
11158
+ * this._increaseProgress(() => {
11159
+ * // reenter the Angular zone and display done
11160
+ * this._ngZone.run(() => { console.log('Outside Done!'); });
11161
+ * });
11162
+ * });
11163
+ * }
11164
+ *
11165
+ * _increaseProgress(doneCallback: () => void) {
11166
+ * this.progress += 1;
11167
+ * console.log(`Current progress: ${this.progress}%`);
11168
+ *
11169
+ * if (this.progress < 100) {
11170
+ * window.setTimeout(() => this._increaseProgress(doneCallback), 10);
11171
+ * } else {
11172
+ * doneCallback();
11173
+ * }
11174
+ * }
11175
+ * }
11176
+ * ```
11177
+ *
11178
+ * @publicApi
11179
+ */
11180
+ class NgZone {
11181
+ constructor({ enableLongStackTrace = false, shouldCoalesceEventChangeDetection = false, shouldCoalesceRunChangeDetection = false }) {
11182
+ this.hasPendingMacrotasks = false;
11183
+ this.hasPendingMicrotasks = false;
11184
+ /**
11185
+ * Whether there are no outstanding microtasks or macrotasks.
11186
+ */
11187
+ this.isStable = true;
11188
+ /**
11189
+ * Notifies when code enters Angular Zone. This gets fired first on VM Turn.
11190
+ */
11191
+ this.onUnstable = new EventEmitter(false);
11192
+ /**
11193
+ * Notifies when there is no more microtasks enqueued in the current VM Turn.
11194
+ * This is a hint for Angular to do change detection, which may enqueue more microtasks.
11195
+ * For this reason this event can fire multiple times per VM Turn.
11196
+ */
11197
+ this.onMicrotaskEmpty = new EventEmitter(false);
11198
+ /**
11199
+ * Notifies when the last `onMicrotaskEmpty` has run and there are no more microtasks, which
11200
+ * implies we are about to relinquish VM turn.
11201
+ * This event gets called just once.
11202
+ */
11203
+ this.onStable = new EventEmitter(false);
11204
+ /**
11205
+ * Notifies that an error has been delivered.
11206
+ */
11207
+ this.onError = new EventEmitter(false);
11208
+ if (typeof Zone == 'undefined') {
11209
+ throw new RuntimeError(908 /* RuntimeErrorCode.MISSING_ZONEJS */, ngDevMode && `In this configuration Angular requires Zone.js`);
11210
+ }
11211
+ Zone.assertZonePatched();
11212
+ const self = this;
11213
+ self._nesting = 0;
11214
+ self._outer = self._inner = Zone.current;
11215
+ // AsyncStackTaggingZoneSpec provides `linked stack traces` to show
11216
+ // where the async operation is scheduled. For more details, refer
11217
+ // to this article, https://developer.chrome.com/blog/devtools-better-angular-debugging/
11218
+ // And we only import this AsyncStackTaggingZoneSpec in development mode,
11219
+ // in the production mode, the AsyncStackTaggingZoneSpec will be tree shaken away.
11220
+ if (ngDevMode) {
11221
+ self._inner = self._inner.fork(new AsyncStackTaggingZoneSpec('Angular'));
11222
+ }
11223
+ if (Zone['TaskTrackingZoneSpec']) {
11224
+ self._inner = self._inner.fork(new Zone['TaskTrackingZoneSpec']);
11225
+ }
11226
+ if (enableLongStackTrace && Zone['longStackTraceZoneSpec']) {
11227
+ self._inner = self._inner.fork(Zone['longStackTraceZoneSpec']);
11228
+ }
11229
+ // if shouldCoalesceRunChangeDetection is true, all tasks including event tasks will be
11230
+ // coalesced, so shouldCoalesceEventChangeDetection option is not necessary and can be skipped.
11231
+ self.shouldCoalesceEventChangeDetection =
11232
+ !shouldCoalesceRunChangeDetection && shouldCoalesceEventChangeDetection;
11233
+ self.shouldCoalesceRunChangeDetection = shouldCoalesceRunChangeDetection;
11234
+ self.lastRequestAnimationFrameId = -1;
11235
+ self.nativeRequestAnimationFrame = getNativeRequestAnimationFrame().nativeRequestAnimationFrame;
11236
+ forkInnerZoneWithAngularBehavior(self);
11237
+ }
11238
+ /**
11239
+ This method checks whether the method call happens within an Angular Zone instance.
11240
+ */
11241
+ static isInAngularZone() {
11242
+ // Zone needs to be checked, because this method might be called even when NoopNgZone is used.
11243
+ return typeof Zone !== 'undefined' && Zone.current.get('isAngularZone') === true;
11244
+ }
11245
+ /**
11246
+ Assures that the method is called within the Angular Zone, otherwise throws an error.
11247
+ */
11248
+ static assertInAngularZone() {
11249
+ if (!NgZone.isInAngularZone()) {
11250
+ throw new RuntimeError(909 /* RuntimeErrorCode.UNEXPECTED_ZONE_STATE */, ngDevMode && 'Expected to be in Angular Zone, but it is not!');
11251
+ }
11252
+ }
11253
+ /**
11254
+ Assures that the method is called outside of the Angular Zone, otherwise throws an error.
11255
+ */
11256
+ static assertNotInAngularZone() {
11257
+ if (NgZone.isInAngularZone()) {
11258
+ throw new RuntimeError(909 /* RuntimeErrorCode.UNEXPECTED_ZONE_STATE */, ngDevMode && 'Expected to not be in Angular Zone, but it is!');
11259
+ }
11260
+ }
11261
+ /**
11262
+ * Executes the `fn` function synchronously within the Angular zone and returns value returned by
11263
+ * the function.
11264
+ *
11265
+ * Running functions via `run` allows you to reenter Angular zone from a task that was executed
11266
+ * outside of the Angular zone (typically started via {@link #runOutsideAngular}).
11267
+ *
11268
+ * Any future tasks or microtasks scheduled from within this function will continue executing from
11269
+ * within the Angular zone.
11270
+ *
11271
+ * If a synchronous error happens it will be rethrown and not reported via `onError`.
11272
+ */
11273
+ run(fn, applyThis, applyArgs) {
11274
+ return this._inner.run(fn, applyThis, applyArgs);
11275
+ }
11276
+ /**
11277
+ * Executes the `fn` function synchronously within the Angular zone as a task and returns value
11278
+ * returned by the function.
11279
+ *
11280
+ * Running functions via `run` allows you to reenter Angular zone from a task that was executed
11281
+ * outside of the Angular zone (typically started via {@link #runOutsideAngular}).
11282
+ *
11283
+ * Any future tasks or microtasks scheduled from within this function will continue executing from
11284
+ * within the Angular zone.
11285
+ *
11286
+ * If a synchronous error happens it will be rethrown and not reported via `onError`.
11287
+ */
11288
+ runTask(fn, applyThis, applyArgs, name) {
11289
+ const zone = this._inner;
11290
+ const task = zone.scheduleEventTask('NgZoneEvent: ' + name, fn, EMPTY_PAYLOAD, noop, noop);
11291
+ try {
11292
+ return zone.runTask(task, applyThis, applyArgs);
11293
+ }
11294
+ finally {
11295
+ zone.cancelTask(task);
11296
+ }
11297
+ }
11298
+ /**
11299
+ * Same as `run`, except that synchronous errors are caught and forwarded via `onError` and not
11300
+ * rethrown.
11301
+ */
11302
+ runGuarded(fn, applyThis, applyArgs) {
11303
+ return this._inner.runGuarded(fn, applyThis, applyArgs);
11304
+ }
11305
+ /**
11306
+ * Executes the `fn` function synchronously in Angular's parent zone and returns value returned by
11307
+ * the function.
11308
+ *
11309
+ * Running functions via {@link #runOutsideAngular} allows you to escape Angular's zone and do
11310
+ * work that
11311
+ * doesn't trigger Angular change-detection or is subject to Angular's error handling.
11312
+ *
11313
+ * Any future tasks or microtasks scheduled from within this function will continue executing from
11314
+ * outside of the Angular zone.
11315
+ *
11316
+ * Use {@link #run} to reenter the Angular zone and do work that updates the application model.
11317
+ */
11318
+ runOutsideAngular(fn) {
11319
+ return this._outer.run(fn);
11320
+ }
11321
+ }
11322
+ const EMPTY_PAYLOAD = {};
11323
+ function checkStable(zone) {
11324
+ // TODO: @JiaLiPassion, should check zone.isCheckStableRunning to prevent
11325
+ // re-entry. The case is:
11326
+ //
11327
+ // @Component({...})
11328
+ // export class AppComponent {
11329
+ // constructor(private ngZone: NgZone) {
11330
+ // this.ngZone.onStable.subscribe(() => {
11331
+ // this.ngZone.run(() => console.log('stable'););
11332
+ // });
11333
+ // }
11334
+ //
11335
+ // The onStable subscriber run another function inside ngZone
11336
+ // which causes `checkStable()` re-entry.
11337
+ // But this fix causes some issues in g3, so this fix will be
11338
+ // launched in another PR.
11339
+ if (zone._nesting == 0 && !zone.hasPendingMicrotasks && !zone.isStable) {
11340
+ try {
11341
+ zone._nesting++;
11342
+ zone.onMicrotaskEmpty.emit(null);
11343
+ }
11344
+ finally {
11345
+ zone._nesting--;
11346
+ if (!zone.hasPendingMicrotasks) {
11347
+ try {
11348
+ zone.runOutsideAngular(() => zone.onStable.emit(null));
11349
+ }
11350
+ finally {
11351
+ zone.isStable = true;
11352
+ }
11353
+ }
11354
+ }
11355
+ }
11356
+ }
11357
+ function delayChangeDetectionForEvents(zone) {
11358
+ /**
11359
+ * We also need to check _nesting here
11360
+ * Consider the following case with shouldCoalesceRunChangeDetection = true
11361
+ *
11362
+ * ngZone.run(() => {});
11363
+ * ngZone.run(() => {});
11364
+ *
11365
+ * We want the two `ngZone.run()` only trigger one change detection
11366
+ * when shouldCoalesceRunChangeDetection is true.
11367
+ * And because in this case, change detection run in async way(requestAnimationFrame),
11368
+ * so we also need to check the _nesting here to prevent multiple
11369
+ * change detections.
11370
+ */
11371
+ if (zone.isCheckStableRunning || zone.lastRequestAnimationFrameId !== -1) {
11372
+ return;
11373
+ }
11374
+ zone.lastRequestAnimationFrameId = zone.nativeRequestAnimationFrame.call(_global, () => {
11375
+ // This is a work around for https://github.com/angular/angular/issues/36839.
11376
+ // The core issue is that when event coalescing is enabled it is possible for microtasks
11377
+ // to get flushed too early (As is the case with `Promise.then`) between the
11378
+ // coalescing eventTasks.
11379
+ //
11380
+ // To workaround this we schedule a "fake" eventTask before we process the
11381
+ // coalescing eventTasks. The benefit of this is that the "fake" container eventTask
11382
+ // will prevent the microtasks queue from getting drained in between the coalescing
11383
+ // eventTask execution.
11384
+ if (!zone.fakeTopEventTask) {
11385
+ zone.fakeTopEventTask = Zone.root.scheduleEventTask('fakeTopEventTask', () => {
11386
+ zone.lastRequestAnimationFrameId = -1;
11387
+ updateMicroTaskStatus(zone);
11388
+ zone.isCheckStableRunning = true;
11389
+ checkStable(zone);
11390
+ zone.isCheckStableRunning = false;
11391
+ }, undefined, () => { }, () => { });
11392
+ }
11393
+ zone.fakeTopEventTask.invoke();
11394
+ });
11395
+ updateMicroTaskStatus(zone);
11396
+ }
11397
+ function forkInnerZoneWithAngularBehavior(zone) {
11398
+ const delayChangeDetectionForEventsDelegate = () => {
11399
+ delayChangeDetectionForEvents(zone);
11400
+ };
11401
+ zone._inner = zone._inner.fork({
11402
+ name: 'angular',
11403
+ properties: { 'isAngularZone': true },
11404
+ onInvokeTask: (delegate, current, target, task, applyThis, applyArgs) => {
11405
+ try {
11406
+ onEnter(zone);
11407
+ return delegate.invokeTask(target, task, applyThis, applyArgs);
11408
+ }
11409
+ finally {
11410
+ if ((zone.shouldCoalesceEventChangeDetection && task.type === 'eventTask') ||
11411
+ zone.shouldCoalesceRunChangeDetection) {
11412
+ delayChangeDetectionForEventsDelegate();
11413
+ }
11414
+ onLeave(zone);
11415
+ }
11416
+ },
11417
+ onInvoke: (delegate, current, target, callback, applyThis, applyArgs, source) => {
11418
+ try {
11419
+ onEnter(zone);
11420
+ return delegate.invoke(target, callback, applyThis, applyArgs, source);
11421
+ }
11422
+ finally {
11423
+ if (zone.shouldCoalesceRunChangeDetection) {
11424
+ delayChangeDetectionForEventsDelegate();
11425
+ }
11426
+ onLeave(zone);
11427
+ }
11428
+ },
11429
+ onHasTask: (delegate, current, target, hasTaskState) => {
11430
+ delegate.hasTask(target, hasTaskState);
11431
+ if (current === target) {
11432
+ // We are only interested in hasTask events which originate from our zone
11433
+ // (A child hasTask event is not interesting to us)
11434
+ if (hasTaskState.change == 'microTask') {
11435
+ zone._hasPendingMicrotasks = hasTaskState.microTask;
11436
+ updateMicroTaskStatus(zone);
11437
+ checkStable(zone);
11438
+ }
11439
+ else if (hasTaskState.change == 'macroTask') {
11440
+ zone.hasPendingMacrotasks = hasTaskState.macroTask;
11441
+ }
11442
+ }
11443
+ },
11444
+ onHandleError: (delegate, current, target, error) => {
11445
+ delegate.handleError(target, error);
11446
+ zone.runOutsideAngular(() => zone.onError.emit(error));
11447
+ return false;
11448
+ }
11449
+ });
11450
+ }
11451
+ function updateMicroTaskStatus(zone) {
11452
+ if (zone._hasPendingMicrotasks ||
11453
+ ((zone.shouldCoalesceEventChangeDetection || zone.shouldCoalesceRunChangeDetection) &&
11454
+ zone.lastRequestAnimationFrameId !== -1)) {
11455
+ zone.hasPendingMicrotasks = true;
11456
+ }
11457
+ else {
11458
+ zone.hasPendingMicrotasks = false;
11459
+ }
11460
+ }
11461
+ function onEnter(zone) {
11462
+ zone._nesting++;
11463
+ if (zone.isStable) {
11464
+ zone.isStable = false;
11465
+ zone.onUnstable.emit(null);
11466
+ }
11467
+ }
11468
+ function onLeave(zone) {
11469
+ zone._nesting--;
11470
+ checkStable(zone);
11471
+ }
11472
+ /**
11473
+ * Provides a noop implementation of `NgZone` which does nothing. This zone requires explicit calls
11474
+ * to framework to perform rendering.
11475
+ */
11476
+ class NoopNgZone {
11477
+ constructor() {
11478
+ this.hasPendingMicrotasks = false;
11479
+ this.hasPendingMacrotasks = false;
11480
+ this.isStable = true;
11481
+ this.onUnstable = new EventEmitter();
11482
+ this.onMicrotaskEmpty = new EventEmitter();
11483
+ this.onStable = new EventEmitter();
11484
+ this.onError = new EventEmitter();
11485
+ }
11486
+ run(fn, applyThis, applyArgs) {
11487
+ return fn.apply(applyThis, applyArgs);
11488
+ }
11489
+ runGuarded(fn, applyThis, applyArgs) {
11490
+ return fn.apply(applyThis, applyArgs);
11491
+ }
11492
+ runOutsideAngular(fn) {
11493
+ return fn();
11494
+ }
11495
+ runTask(fn, applyThis, applyArgs, name) {
11496
+ return fn.apply(applyThis, applyArgs);
11497
+ }
11498
+ }
11499
+ /**
11500
+ * Token used to drive ApplicationRef.isStable
11501
+ *
11502
+ * TODO: This should be moved entirely to NgZone (as a breaking change) so it can be tree-shakeable
11503
+ * for `NoopNgZone` which is always just an `Observable` of `true`. Additionally, we should consider
11504
+ * whether the property on `NgZone` should be `Observable` or `Signal`.
11505
+ */
11506
+ const ZONE_IS_STABLE_OBSERVABLE = new InjectionToken(ngDevMode ? 'isStable Observable' : '', {
11507
+ providedIn: 'root',
11508
+ // TODO(atscott): Replace this with a suitable default like `new
11509
+ // BehaviorSubject(true).asObservable`. Again, long term this won't exist on ApplicationRef at
11510
+ // all but until we can remove it, we need a default value zoneless.
11511
+ factory: isStableFactory,
11512
+ });
11513
+ function isStableFactory() {
11514
+ const zone = inject$1(NgZone);
11515
+ let _stable = true;
11516
+ const isCurrentlyStable = new Observable((observer) => {
11517
+ _stable = zone.isStable && !zone.hasPendingMacrotasks && !zone.hasPendingMicrotasks;
11518
+ zone.runOutsideAngular(() => {
11519
+ observer.next(_stable);
11520
+ observer.complete();
11521
+ });
11522
+ });
11523
+ const isStable = new Observable((observer) => {
11524
+ // Create the subscription to onStable outside the Angular Zone so that
11525
+ // the callback is run outside the Angular Zone.
11526
+ let stableSub;
11527
+ zone.runOutsideAngular(() => {
11528
+ stableSub = zone.onStable.subscribe(() => {
11529
+ NgZone.assertNotInAngularZone();
11530
+ // Check whether there are no pending macro/micro tasks in the next tick
11531
+ // to allow for NgZone to update the state.
11532
+ queueMicrotask(() => {
11533
+ if (!_stable && !zone.hasPendingMacrotasks && !zone.hasPendingMicrotasks) {
11534
+ _stable = true;
11535
+ observer.next(true);
11536
+ }
11537
+ });
11538
+ });
11539
+ });
11540
+ const unstableSub = zone.onUnstable.subscribe(() => {
11541
+ NgZone.assertInAngularZone();
11542
+ if (_stable) {
11543
+ _stable = false;
11544
+ zone.runOutsideAngular(() => {
11545
+ observer.next(false);
11546
+ });
11547
+ }
11548
+ });
11549
+ return () => {
11550
+ stableSub.unsubscribe();
11551
+ unstableSub.unsubscribe();
11552
+ };
11553
+ });
11554
+ return merge$1(isCurrentlyStable, isStable.pipe(share()));
11555
+ }
11556
+
11557
+ // Public API for Zone
11558
+
10997
11559
  /**
10998
11560
  * Register a callback to be invoked each time the application
10999
11561
  * finishes rendering.
@@ -11044,7 +11606,8 @@ function afterRender(callback, options) {
11044
11606
  let destroy;
11045
11607
  const unregisterFn = injector.get(DestroyRef).onDestroy(() => destroy?.());
11046
11608
  const manager = injector.get(AfterRenderEventManager);
11047
- const instance = new AfterRenderCallback(callback);
11609
+ const ngZone = injector.get(NgZone);
11610
+ const instance = new AfterRenderCallback(() => ngZone.runOutsideAngular(callback));
11048
11611
  destroy = () => {
11049
11612
  manager.unregister(instance);
11050
11613
  unregisterFn();
@@ -11103,9 +11666,10 @@ function afterNextRender(callback, options) {
11103
11666
  let destroy;
11104
11667
  const unregisterFn = injector.get(DestroyRef).onDestroy(() => destroy?.());
11105
11668
  const manager = injector.get(AfterRenderEventManager);
11669
+ const ngZone = injector.get(NgZone);
11106
11670
  const instance = new AfterRenderCallback(() => {
11107
11671
  destroy?.();
11108
- callback();
11672
+ ngZone.runOutsideAngular(callback);
11109
11673
  });
11110
11674
  destroy = () => {
11111
11675
  manager.unregister(instance);
@@ -13116,28 +13680,7 @@ function collectNativeNodes(tView, lView, tNode, result, isProjection = false) {
13116
13680
  // ViewContainerRef). When we find a LContainer we need to descend into it to collect root nodes
13117
13681
  // from the views in this container.
13118
13682
  if (isLContainer(lNode)) {
13119
- for (let i = CONTAINER_HEADER_OFFSET; i < lNode.length; i++) {
13120
- const lViewInAContainer = lNode[i];
13121
- const lViewFirstChildTNode = lViewInAContainer[TVIEW].firstChild;
13122
- if (lViewFirstChildTNode !== null) {
13123
- collectNativeNodes(lViewInAContainer[TVIEW], lViewInAContainer, lViewFirstChildTNode, result);
13124
- }
13125
- }
13126
- // When an LContainer is created, the anchor (comment) node is:
13127
- // - (1) either reused in case of an ElementContainer (<ng-container>)
13128
- // - (2) or a new comment node is created
13129
- // In the first case, the anchor comment node would be added to the final
13130
- // list by the code above (`result.push(unwrapRNode(lNode))`), but the second
13131
- // case requires extra handling: the anchor node needs to be added to the
13132
- // final list manually. See additional information in the `createAnchorNode`
13133
- // function in the `view_container_ref.ts`.
13134
- //
13135
- // In the first case, the same reference would be stored in the `NATIVE`
13136
- // and `HOST` slots in an LContainer. Otherwise, this is the second case and
13137
- // we should add an element to the final list.
13138
- if (lNode[NATIVE] !== lNode[HOST]) {
13139
- result.push(lNode[NATIVE]);
13140
- }
13683
+ collectNativeNodesInLContainer(lNode, result);
13141
13684
  }
13142
13685
  const tNodeType = tNode.type;
13143
13686
  if (tNodeType & 8 /* TNodeType.ElementContainer */) {
@@ -13165,6 +13708,34 @@ function collectNativeNodes(tView, lView, tNode, result, isProjection = false) {
13165
13708
  }
13166
13709
  return result;
13167
13710
  }
13711
+ /**
13712
+ * Collects all root nodes in all views in a given LContainer.
13713
+ */
13714
+ function collectNativeNodesInLContainer(lContainer, result) {
13715
+ for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
13716
+ const lViewInAContainer = lContainer[i];
13717
+ const lViewFirstChildTNode = lViewInAContainer[TVIEW].firstChild;
13718
+ if (lViewFirstChildTNode !== null) {
13719
+ collectNativeNodes(lViewInAContainer[TVIEW], lViewInAContainer, lViewFirstChildTNode, result);
13720
+ }
13721
+ }
13722
+ // When an LContainer is created, the anchor (comment) node is:
13723
+ // - (1) either reused in case of an ElementContainer (<ng-container>)
13724
+ // - (2) or a new comment node is created
13725
+ // In the first case, the anchor comment node would be added to the final
13726
+ // list by the code in the `collectNativeNodes` function
13727
+ // (see the `result.push(unwrapRNode(lNode))` line), but the second
13728
+ // case requires extra handling: the anchor node needs to be added to the
13729
+ // final list manually. See additional information in the `createAnchorNode`
13730
+ // function in the `view_container_ref.ts`.
13731
+ //
13732
+ // In the first case, the same reference would be stored in the `NATIVE`
13733
+ // and `HOST` slots in an LContainer. Otherwise, this is the second case and
13734
+ // we should add an element to the final list.
13735
+ if (lContainer[NATIVE] !== lContainer[HOST]) {
13736
+ result.push(lContainer[NATIVE]);
13737
+ }
13738
+ }
13168
13739
 
13169
13740
  function detectChangesInternal(tView, lView, context, notifyErrorHandler = true) {
13170
13741
  const environment = lView[ENVIRONMENT];
@@ -23551,51 +24122,6 @@ function isPure(lView, index) {
23551
24122
  return lView[TVIEW].data[index].pure;
23552
24123
  }
23553
24124
 
23554
- /// <reference types="rxjs" />
23555
- class EventEmitter_ extends Subject {
23556
- constructor(isAsync = false) {
23557
- super();
23558
- this.__isAsync = isAsync;
23559
- }
23560
- emit(value) {
23561
- super.next(value);
23562
- }
23563
- subscribe(observerOrNext, error, complete) {
23564
- let nextFn = observerOrNext;
23565
- let errorFn = error || (() => null);
23566
- let completeFn = complete;
23567
- if (observerOrNext && typeof observerOrNext === 'object') {
23568
- const observer = observerOrNext;
23569
- nextFn = observer.next?.bind(observer);
23570
- errorFn = observer.error?.bind(observer);
23571
- completeFn = observer.complete?.bind(observer);
23572
- }
23573
- if (this.__isAsync) {
23574
- errorFn = _wrapInTimeout(errorFn);
23575
- if (nextFn) {
23576
- nextFn = _wrapInTimeout(nextFn);
23577
- }
23578
- if (completeFn) {
23579
- completeFn = _wrapInTimeout(completeFn);
23580
- }
23581
- }
23582
- const sink = super.subscribe({ next: nextFn, error: errorFn, complete: completeFn });
23583
- if (observerOrNext instanceof Subscription) {
23584
- observerOrNext.add(sink);
23585
- }
23586
- return sink;
23587
- }
23588
- }
23589
- function _wrapInTimeout(fn) {
23590
- return (value) => {
23591
- setTimeout(fn, undefined, value);
23592
- };
23593
- }
23594
- /**
23595
- * @publicApi
23596
- */
23597
- const EventEmitter = EventEmitter_;
23598
-
23599
24125
  function symbolIterator() {
23600
24126
  // @ts-expect-error accessing a private member
23601
24127
  return this._results[Symbol.iterator]();
@@ -26706,7 +27232,7 @@ class TestBedImpl {
26706
27232
  /**
26707
27233
  * Runs the given function in the `EnvironmentInjector` context of `TestBed`.
26708
27234
  *
26709
- * @see EnvironmentInjector#runInContext
27235
+ * @see {@link EnvironmentInjector#runInContext}
26710
27236
  */
26711
27237
  static runInInjectionContext(fn) {
26712
27238
  return TestBedImpl.INSTANCE.runInInjectionContext(fn);
@@ -26899,7 +27425,7 @@ class TestBedImpl {
26899
27425
  }
26900
27426
  const noNgZone = this.inject(ComponentFixtureNoNgZone, false);
26901
27427
  const autoDetect = this.inject(ComponentFixtureAutoDetect, false);
26902
- const ngZone = noNgZone ? null : this.inject(NgZone, null);
27428
+ const ngZone = noNgZone ? null : this.inject(NgZone$1, null);
26903
27429
  const componentFactory = new ɵRender3ComponentFactory(componentDef);
26904
27430
  const initComponent = () => {
26905
27431
  const componentRef = componentFactory.create(Injector$1.NULL, [], `#${rootElId}`, this.testModuleRef);
@@ -27110,11 +27636,15 @@ function withModule(moduleDef, fn) {
27110
27636
  * allows tests to be asynchronous by either returning a promise or using a 'done' parameter.
27111
27637
  */
27112
27638
  // Reset the test providers and the fake async zone before each test.
27113
- beforeEach(getCleanupHook(false));
27639
+ // We keep a guard because somehow this file can make it into a bundle and be executed
27640
+ // beforeEach is only defined when executing the tests
27641
+ globalThis.beforeEach?.(getCleanupHook(false));
27114
27642
  // We provide both a `beforeEach` and `afterEach`, because the updated behavior for
27115
27643
  // tearing down the module is supposed to run after the test so that we can associate
27116
27644
  // teardown errors with the correct test.
27117
- afterEach(getCleanupHook(true));
27645
+ // We keep a guard because somehow this file can make it into a bundle and be executed
27646
+ // afterEach is only defined when executing the tests
27647
+ globalThis.afterEach?.(getCleanupHook(true));
27118
27648
  function getCleanupHook(expectedTeardownValue) {
27119
27649
  return () => {
27120
27650
  const testBed = TestBedImpl.INSTANCE;