@angular/core 16.0.0-next.5 → 16.0.0-next.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.
Files changed (53) hide show
  1. package/esm2022/rxjs-interop/index.mjs +9 -0
  2. package/esm2022/rxjs-interop/public_api.mjs +15 -0
  3. package/esm2022/rxjs-interop/rxjs-interop.mjs +5 -0
  4. package/esm2022/rxjs-interop/src/from_observable.mjs +46 -0
  5. package/esm2022/rxjs-interop/src/from_signal.mjs +36 -0
  6. package/esm2022/rxjs-interop/src/index.mjs +11 -0
  7. package/esm2022/rxjs-interop/src/take_until_destroyed.mjs +33 -0
  8. package/esm2022/src/application_ref.mjs +78 -17
  9. package/esm2022/src/core.mjs +2 -2
  10. package/esm2022/src/core_private_export.mjs +2 -2
  11. package/esm2022/src/core_reactivity_export_internal.mjs +1 -1
  12. package/esm2022/src/errors.mjs +3 -2
  13. package/esm2022/src/hydration/api.mjs +35 -2
  14. package/esm2022/src/hydration/cleanup.mjs +11 -19
  15. package/esm2022/src/linker/component_factory.mjs +1 -1
  16. package/esm2022/src/linker/template_ref.mjs +2 -2
  17. package/esm2022/src/linker/view_container_ref.mjs +2 -2
  18. package/esm2022/src/linker/view_ref.mjs +2 -2
  19. package/esm2022/src/render3/component_ref.mjs +13 -6
  20. package/esm2022/src/render3/instructions/element.mjs +2 -1
  21. package/esm2022/src/render3/instructions/element_container.mjs +1 -2
  22. package/esm2022/src/render3/instructions/shared.mjs +13 -10
  23. package/esm2022/src/render3/interfaces/view.mjs +16 -17
  24. package/esm2022/src/render3/ng_module_ref.mjs +9 -7
  25. package/esm2022/src/render3/reactive_lview_consumer.mjs +2 -1
  26. package/esm2022/src/render3/reactivity/effect.mjs +55 -45
  27. package/esm2022/src/sanitization/sanitization.mjs +3 -3
  28. package/esm2022/src/signals/index.mjs +2 -1
  29. package/esm2022/src/signals/src/api.mjs +1 -2
  30. package/esm2022/src/signals/src/computed.mjs +2 -1
  31. package/esm2022/src/signals/src/errors.mjs +18 -0
  32. package/esm2022/src/signals/src/graph.mjs +32 -8
  33. package/esm2022/src/signals/src/signal.mjs +12 -1
  34. package/esm2022/src/signals/src/watch.mjs +3 -2
  35. package/esm2022/src/util/ng_dev_mode.mjs +2 -1
  36. package/esm2022/src/version.mjs +1 -1
  37. package/esm2022/testing/src/logger.mjs +3 -3
  38. package/esm2022/testing/src/ng_zone_mock.mjs +3 -3
  39. package/esm2022/testing/src/test_bed_compiler.mjs +3 -4
  40. package/fesm2022/core.mjs +1077 -926
  41. package/fesm2022/core.mjs.map +1 -1
  42. package/fesm2022/rxjs-interop.mjs +104 -0
  43. package/fesm2022/rxjs-interop.mjs.map +1 -0
  44. package/fesm2022/testing.mjs +524 -69
  45. package/fesm2022/testing.mjs.map +1 -1
  46. package/index.d.ts +142 -41
  47. package/package.json +7 -1
  48. package/rxjs-interop/index.d.ts +95 -0
  49. package/schematics/migrations/guard-and-resolve-interfaces/bundle.js +13 -13
  50. package/schematics/migrations/remove-module-id/bundle.js +14 -14
  51. package/schematics/ng-generate/standalone-migration/bundle.js +319 -319
  52. package/schematics/ng-generate/standalone-migration/bundle.js.map +1 -1
  53. package/testing/index.d.ts +1 -1
@@ -1,13 +1,12 @@
1
1
  /**
2
- * @license Angular v16.0.0-next.5
2
+ * @license Angular v16.0.0-next.6
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, NgZone, ɵprovideNgZoneChangeDetection, Compiler, COMPILER_OPTIONS, ɵNgModuleFactory, ɵisEnvironmentProviders, ModuleWithComponentFactories, ɵconvertToBitFlags, Injector as Injector$1, 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, ɵ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, ɵNgModuleFactory, ɵisEnvironmentProviders, ModuleWithComponentFactories, ɵconvertToBitFlags, Injector as Injector$1, 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';
8
8
  import { ResourceLoader } from '@angular/compiler';
9
9
  import { Subject, Subscription } from 'rxjs';
10
- import { first } from 'rxjs/operators';
11
10
 
12
11
  /**
13
12
  * Wraps a test function in an asynchronous test zone. The test will automatically
@@ -838,7 +837,8 @@ const XSS_SECURITY_URL = 'https://g.co/ng/security#xss';
838
837
  *
839
838
  * Note: the `message` argument contains a descriptive error message as a string in development
840
839
  * mode (when the `ngDevMode` is defined). In production mode (after tree-shaking pass), the
841
- * `message` argument becomes `false`, thus we account for it in the typings and the runtime logic.
840
+ * `message` argument becomes `false`, thus we account for it in the typings and the runtime
841
+ * logic.
842
842
  */
843
843
  class RuntimeError extends Error {
844
844
  constructor(code, message) {
@@ -1640,6 +1640,7 @@ function ngDevModeResetPerfCounters() {
1640
1640
  hydratedComponents: 0,
1641
1641
  dehydratedViewsRemoved: 0,
1642
1642
  dehydratedViewsCleanupRuns: 0,
1643
+ componentsSkippedHydration: 0,
1643
1644
  };
1644
1645
  // Make sure to refer to ngDevMode as ['ngDevMode'] for closure.
1645
1646
  const allowNgDevModeTrue = locationString.indexOf('ngDevMode=false') === -1;
@@ -3219,23 +3220,22 @@ const T_HOST = 6;
3219
3220
  const CLEANUP = 7;
3220
3221
  const CONTEXT = 8;
3221
3222
  const INJECTOR$1 = 9;
3222
- const RENDERER_FACTORY = 10;
3223
+ const ENVIRONMENT = 10;
3223
3224
  const RENDERER = 11;
3224
- const SANITIZER = 12;
3225
- const CHILD_HEAD = 13;
3226
- const CHILD_TAIL = 14;
3225
+ const CHILD_HEAD = 12;
3226
+ const CHILD_TAIL = 13;
3227
3227
  // FIXME(misko): Investigate if the three declarations aren't all same thing.
3228
- const DECLARATION_VIEW = 15;
3229
- const DECLARATION_COMPONENT_VIEW = 16;
3230
- const DECLARATION_LCONTAINER = 17;
3231
- const PREORDER_HOOK_FLAGS = 18;
3232
- const QUERIES = 19;
3233
- const ID = 20;
3234
- const EMBEDDED_VIEW_INJECTOR = 21;
3235
- const ON_DESTROY_HOOKS = 22;
3236
- const HYDRATION = 23;
3237
- const REACTIVE_TEMPLATE_CONSUMER = 24;
3238
- const REACTIVE_HOST_BINDING_CONSUMER = 25;
3228
+ const DECLARATION_VIEW = 14;
3229
+ const DECLARATION_COMPONENT_VIEW = 15;
3230
+ const DECLARATION_LCONTAINER = 16;
3231
+ const PREORDER_HOOK_FLAGS = 17;
3232
+ const QUERIES = 18;
3233
+ const ID = 19;
3234
+ const EMBEDDED_VIEW_INJECTOR = 20;
3235
+ const ON_DESTROY_HOOKS = 21;
3236
+ const HYDRATION = 22;
3237
+ const REACTIVE_TEMPLATE_CONSUMER = 23;
3238
+ const REACTIVE_HOST_BINDING_CONSUMER = 24;
3239
3239
  /**
3240
3240
  * Size of LView's header. Necessary to adjust for it when setting slots.
3241
3241
  *
@@ -3243,7 +3243,7 @@ const REACTIVE_HOST_BINDING_CONSUMER = 25;
3243
3243
  * instruction index into `LView` index. All other indexes should be in the `LView` index space and
3244
3244
  * there should be no need to refer to `HEADER_OFFSET` anywhere else.
3245
3245
  */
3246
- const HEADER_OFFSET = 26;
3246
+ const HEADER_OFFSET = 25;
3247
3247
  // Note: This hack is necessary so we don't erroneously get a circular dependency
3248
3248
  // failure based on types.
3249
3249
  const unusedValueExportToPlacateAjd$4 = 1;
@@ -8356,7 +8356,7 @@ function validateAgainstEventAttributes(name) {
8356
8356
  }
8357
8357
  function getSanitizer() {
8358
8358
  const lView = getLView();
8359
- return lView && lView[SANITIZER];
8359
+ return lView && lView[ENVIRONMENT].sanitizer;
8360
8360
  }
8361
8361
 
8362
8362
  /**
@@ -9787,7 +9787,7 @@ class Version {
9787
9787
  /**
9788
9788
  * @publicApi
9789
9789
  */
9790
- const VERSION = new Version('16.0.0-next.5');
9790
+ const VERSION = new Version('16.0.0-next.6');
9791
9791
 
9792
9792
  // This default value is when checking the hierarchy for a token.
9793
9793
  //
@@ -10026,6 +10026,10 @@ let _nextReactiveId = 0;
10026
10026
  * consumer).
10027
10027
  */
10028
10028
  let activeConsumer = null;
10029
+ /**
10030
+ * Whether the graph is currently propagating change notifications.
10031
+ */
10032
+ let inNotificationPhase = false;
10029
10033
  function setActiveConsumer(consumer) {
10030
10034
  const prev = activeConsumer;
10031
10035
  activeConsumer = consumer;
@@ -10116,20 +10120,33 @@ class ReactiveNode {
10116
10120
  * Notify all consumers of this producer that its value may have changed.
10117
10121
  */
10118
10122
  producerMayHaveChanged() {
10119
- for (const [consumerId, edge] of this.consumers) {
10120
- const consumer = edge.consumerNode.deref();
10121
- if (consumer === undefined || consumer.trackingVersion !== edge.atTrackingVersion) {
10122
- this.consumers.delete(consumerId);
10123
- consumer?.producers.delete(this.id);
10124
- continue;
10123
+ // Prevent signal reads when we're updating the graph
10124
+ const prev = inNotificationPhase;
10125
+ inNotificationPhase = true;
10126
+ try {
10127
+ for (const [consumerId, edge] of this.consumers) {
10128
+ const consumer = edge.consumerNode.deref();
10129
+ if (consumer === undefined || consumer.trackingVersion !== edge.atTrackingVersion) {
10130
+ this.consumers.delete(consumerId);
10131
+ consumer?.producers.delete(this.id);
10132
+ continue;
10133
+ }
10134
+ consumer.onConsumerDependencyMayHaveChanged();
10125
10135
  }
10126
- consumer.onConsumerDependencyMayHaveChanged();
10136
+ }
10137
+ finally {
10138
+ inNotificationPhase = prev;
10127
10139
  }
10128
10140
  }
10129
10141
  /**
10130
10142
  * Mark that this producer node has been accessed in the current reactive context.
10131
10143
  */
10132
10144
  producerAccessed() {
10145
+ if (inNotificationPhase) {
10146
+ throw new Error(typeof ngDevMode !== 'undefined' && ngDevMode ?
10147
+ `Assertion error: signal read during notification phase` :
10148
+ '');
10149
+ }
10133
10150
  if (activeConsumer === null) {
10134
10151
  return;
10135
10152
  }
@@ -10156,6 +10173,13 @@ class ReactiveNode {
10156
10173
  get hasProducers() {
10157
10174
  return this.producers.size > 0;
10158
10175
  }
10176
+ /**
10177
+ * Whether this `ReactiveNode` in its producer capacity is currently allowed to initiate updates,
10178
+ * based on the current consumer context.
10179
+ */
10180
+ get producerUpdatesAllowed() {
10181
+ return activeConsumer?.consumerAllowSignalWrites !== false;
10182
+ }
10159
10183
  /**
10160
10184
  * Checks if a `Producer` has a current value which is different than the value
10161
10185
  * last seen at a specific version by a `Consumer` which recorded a dependency on
@@ -10203,6 +10227,7 @@ const NG_DEV_MODE = typeof ngDevMode === 'undefined' || ngDevMode;
10203
10227
  class ReactiveLViewConsumer extends ReactiveNode {
10204
10228
  constructor() {
10205
10229
  super(...arguments);
10230
+ this.consumerAllowSignalWrites = false;
10206
10231
  this._lView = null;
10207
10232
  }
10208
10233
  set lView(lView) {
@@ -11426,7 +11451,7 @@ function renderChildComponents(hostLView, components) {
11426
11451
  renderComponent(hostLView, components[i]);
11427
11452
  }
11428
11453
  }
11429
- function createLView(parentLView, tView, context, flags, host, tHostNode, rendererFactory, renderer, sanitizer, injector, embeddedViewInjector, hydrationInfo) {
11454
+ function createLView(parentLView, tView, context, flags, host, tHostNode, environment, renderer, injector, embeddedViewInjector, hydrationInfo) {
11430
11455
  const lView = tView.blueprint.slice();
11431
11456
  lView[HOST] = host;
11432
11457
  lView[FLAGS] = flags | 4 /* LViewFlags.CreationMode */ | 64 /* LViewFlags.Attached */ | 8 /* LViewFlags.FirstLViewPass */;
@@ -11438,11 +11463,10 @@ function createLView(parentLView, tView, context, flags, host, tHostNode, render
11438
11463
  ngDevMode && tView.declTNode && parentLView && assertTNodeForLView(tView.declTNode, parentLView);
11439
11464
  lView[PARENT] = lView[DECLARATION_VIEW] = parentLView;
11440
11465
  lView[CONTEXT] = context;
11441
- lView[RENDERER_FACTORY] = (rendererFactory || parentLView && parentLView[RENDERER_FACTORY]);
11442
- ngDevMode && assertDefined(lView[RENDERER_FACTORY], 'RendererFactory is required');
11466
+ lView[ENVIRONMENT] = (environment || parentLView && parentLView[ENVIRONMENT]);
11467
+ ngDevMode && assertDefined(lView[ENVIRONMENT], 'LViewEnvironment is required');
11443
11468
  lView[RENDERER] = (renderer || parentLView && parentLView[RENDERER]);
11444
11469
  ngDevMode && assertDefined(lView[RENDERER], 'Renderer is required');
11445
- lView[SANITIZER] = sanitizer || parentLView && parentLView[SANITIZER] || null;
11446
11470
  lView[INJECTOR$1] = injector || parentLView && parentLView[INJECTOR$1] || null;
11447
11471
  lView[T_HOST] = tHostNode;
11448
11472
  lView[ID] = getUniqueLViewId();
@@ -11621,10 +11645,11 @@ function refreshView(tView, lView, templateFn, context) {
11621
11645
  const flags = lView[FLAGS];
11622
11646
  if ((flags & 128 /* LViewFlags.Destroyed */) === 128 /* LViewFlags.Destroyed */)
11623
11647
  return;
11624
- enterView(lView);
11625
11648
  // Check no changes mode is a dev only mode used to verify that bindings have not changed
11626
11649
  // since they were assigned. We do not want to execute lifecycle hooks in that mode.
11627
11650
  const isInCheckNoChangesPass = ngDevMode && isInCheckNoChangesMode();
11651
+ !isInCheckNoChangesPass && lView[ENVIRONMENT].effectManager?.flush();
11652
+ enterView(lView);
11628
11653
  try {
11629
11654
  resetPreOrderHookFlags(lView);
11630
11655
  setBindingIndex(tView.bindingStartIndex);
@@ -12540,8 +12565,8 @@ function addComponentLogic(lView, hostTNode, def) {
12540
12565
  const tView = getOrCreateComponentTView(def);
12541
12566
  // Only component views should be added to the view tree directly. Embedded views are
12542
12567
  // accessed through their containers because they may be removed / re-added later.
12543
- const rendererFactory = lView[RENDERER_FACTORY];
12544
- const componentView = addToViewTree(lView, createLView(lView, tView, null, def.onPush ? 32 /* LViewFlags.Dirty */ : 16 /* LViewFlags.CheckAlways */, native, hostTNode, rendererFactory, rendererFactory.createRenderer(native, def), null, null, null, null));
12568
+ const rendererFactory = lView[ENVIRONMENT].rendererFactory;
12569
+ const componentView = addToViewTree(lView, createLView(lView, tView, null, def.onPush ? 32 /* LViewFlags.Dirty */ : 16 /* LViewFlags.CheckAlways */, native, hostTNode, null, rendererFactory.createRenderer(native, def), null, null, null));
12545
12570
  // Component view will always be created before any injected LContainers,
12546
12571
  // so this is a regular element, wrap it with the component view
12547
12572
  lView[hostTNode.index] = componentView;
@@ -12855,7 +12880,7 @@ function addToViewTree(lView, lViewOrLContainer) {
12855
12880
  //// Change detection
12856
12881
  ///////////////////////////////
12857
12882
  function detectChangesInternal(tView, lView, context, notifyErrorHandler = true) {
12858
- const rendererFactory = lView[RENDERER_FACTORY];
12883
+ const rendererFactory = lView[ENVIRONMENT].rendererFactory;
12859
12884
  // Check no changes mode is a dev only mode used to verify that bindings have not changed
12860
12885
  // since they were assigned. We do not want to invoke renderer factory functions in that mode
12861
12886
  // to avoid any possible side-effects.
@@ -12874,6 +12899,9 @@ function detectChangesInternal(tView, lView, context, notifyErrorHandler = true)
12874
12899
  finally {
12875
12900
  if (!checkNoChangesMode && rendererFactory.end)
12876
12901
  rendererFactory.end();
12902
+ // One final flush of the effects queue to catch any effects created in `ngAfterViewInit` or
12903
+ // other post-order hooks.
12904
+ !checkNoChangesMode && lView[ENVIRONMENT].effectManager?.flush();
12877
12905
  }
12878
12906
  }
12879
12907
  function checkNoChangesInternal(tView, lView, context, notifyErrorHandler = true) {
@@ -12996,6 +13024,433 @@ function textBindingInternal(lView, index, value) {
12996
13024
  updateTextNode(lView[RENDERER], element, value);
12997
13025
  }
12998
13026
 
13027
+ /**
13028
+ * `DestroyRef` lets you set callbacks to run for any cleanup or destruction behavior.
13029
+ * The scope of this destruction depends on where `DestroyRef` is injected. If `DestroyRef`
13030
+ * is injected in a component or directive, the callbacks run when that component or
13031
+ * directive is destroyed. Otherwise the callbacks run when a corresponding injector is destroyed.
13032
+ *
13033
+ * @publicApi
13034
+ */
13035
+ class DestroyRef {
13036
+ /**
13037
+ * @internal
13038
+ * @nocollapse
13039
+ */
13040
+ static { this.__NG_ELEMENT_ID__ = injectDestroyRef; }
13041
+ /**
13042
+ * @internal
13043
+ * @nocollapse
13044
+ */
13045
+ static { this.__NG_ENV_ID__ = (injector) => injector; }
13046
+ }
13047
+ class NodeInjectorDestroyRef extends DestroyRef {
13048
+ constructor(_lView) {
13049
+ super();
13050
+ this._lView = _lView;
13051
+ }
13052
+ onDestroy(callback) {
13053
+ storeLViewOnDestroy(this._lView, callback);
13054
+ return () => removeLViewOnDestroy(this._lView, callback);
13055
+ }
13056
+ }
13057
+ function injectDestroyRef() {
13058
+ return new NodeInjectorDestroyRef(getLView());
13059
+ }
13060
+
13061
+ /**
13062
+ * Symbol used to tell `Signal`s apart from other functions.
13063
+ *
13064
+ * This can be used to auto-unwrap signals in various cases, or to auto-wrap non-signal values.
13065
+ */
13066
+ const SIGNAL = Symbol('SIGNAL');
13067
+ /**
13068
+ * Checks if the given `value` function is a reactive `Signal`.
13069
+ */
13070
+ function isSignal(value) {
13071
+ return value[SIGNAL] !== undefined;
13072
+ }
13073
+ /**
13074
+ * Converts `fn` into a marked signal function (where `isSignal(fn)` will be `true`), and
13075
+ * potentially add some set of extra properties (passed as an object record `extraApi`).
13076
+ */
13077
+ function createSignalFromFunction(node, fn, extraApi = {}) {
13078
+ fn[SIGNAL] = node;
13079
+ // Copy properties from `extraApi` to `fn` to complete the desired API of the `Signal`.
13080
+ return Object.assign(fn, extraApi);
13081
+ }
13082
+ /**
13083
+ * The default equality function used for `signal` and `computed`, which treats objects and arrays
13084
+ * as never equal, and all other primitive values using identity semantics.
13085
+ *
13086
+ * This allows signals to hold non-primitive values (arrays, objects, other collections) and still
13087
+ * propagate change notification upon explicit mutation without identity change.
13088
+ *
13089
+ * @developerPreview
13090
+ */
13091
+ function defaultEquals(a, b) {
13092
+ // `Object.is` compares two values using identity semantics which is desired behavior for
13093
+ // primitive values. If `Object.is` determines two values to be equal we need to make sure that
13094
+ // those don't represent objects (we want to make sure that 2 objects are always considered
13095
+ // "unequal"). The null check is needed for the special case of JavaScript reporting null values
13096
+ // as objects (`typeof null === 'object'`).
13097
+ return (a === null || typeof a !== 'object') && Object.is(a, b);
13098
+ }
13099
+
13100
+ /**
13101
+ * Create a computed `Signal` which derives a reactive value from an expression.
13102
+ *
13103
+ * @developerPreview
13104
+ */
13105
+ function computed(computation, options) {
13106
+ const node = new ComputedImpl(computation, options?.equal ?? defaultEquals);
13107
+ // Casting here is required for g3, as TS inference behavior is slightly different between our
13108
+ // version/options and g3's.
13109
+ return createSignalFromFunction(node, node.signal.bind(node));
13110
+ }
13111
+ /**
13112
+ * A dedicated symbol used before a computed value has been calculated for the first time.
13113
+ * Explicitly typed as `any` so we can use it as signal's value.
13114
+ */
13115
+ const UNSET = Symbol('UNSET');
13116
+ /**
13117
+ * A dedicated symbol used in place of a computed signal value to indicate that a given computation
13118
+ * is in progress. Used to detect cycles in computation chains.
13119
+ * Explicitly typed as `any` so we can use it as signal's value.
13120
+ */
13121
+ const COMPUTING = Symbol('COMPUTING');
13122
+ /**
13123
+ * A dedicated symbol used in place of a computed signal value to indicate that a given computation
13124
+ * failed. The thrown error is cached until the computation gets dirty again.
13125
+ * Explicitly typed as `any` so we can use it as signal's value.
13126
+ */
13127
+ const ERRORED = Symbol('ERRORED');
13128
+ /**
13129
+ * A computation, which derives a value from a declarative reactive expression.
13130
+ *
13131
+ * `Computed`s are both producers and consumers of reactivity.
13132
+ */
13133
+ class ComputedImpl extends ReactiveNode {
13134
+ constructor(computation, equal) {
13135
+ super();
13136
+ this.computation = computation;
13137
+ this.equal = equal;
13138
+ /**
13139
+ * Current value of the computation.
13140
+ *
13141
+ * This can also be one of the special values `UNSET`, `COMPUTING`, or `ERRORED`.
13142
+ */
13143
+ this.value = UNSET;
13144
+ /**
13145
+ * If `value` is `ERRORED`, the error caught from the last computation attempt which will
13146
+ * be re-thrown.
13147
+ */
13148
+ this.error = null;
13149
+ /**
13150
+ * Flag indicating that the computation is currently stale, meaning that one of the
13151
+ * dependencies has notified of a potential change.
13152
+ *
13153
+ * It's possible that no dependency has _actually_ changed, in which case the `stale`
13154
+ * state can be resolved without recomputing the value.
13155
+ */
13156
+ this.stale = true;
13157
+ this.consumerAllowSignalWrites = false;
13158
+ }
13159
+ onConsumerDependencyMayHaveChanged() {
13160
+ if (this.stale) {
13161
+ // We've already notified consumers that this value has potentially changed.
13162
+ return;
13163
+ }
13164
+ // Record that the currently cached value may be stale.
13165
+ this.stale = true;
13166
+ // Notify any consumers about the potential change.
13167
+ this.producerMayHaveChanged();
13168
+ }
13169
+ onProducerUpdateValueVersion() {
13170
+ if (!this.stale) {
13171
+ // The current value and its version are already up to date.
13172
+ return;
13173
+ }
13174
+ // The current value is stale. Check whether we need to produce a new one.
13175
+ if (this.value !== UNSET && this.value !== COMPUTING &&
13176
+ !this.consumerPollProducersForChange()) {
13177
+ // Even though we were previously notified of a potential dependency update, all of
13178
+ // our dependencies report that they have not actually changed in value, so we can
13179
+ // resolve the stale state without needing to recompute the current value.
13180
+ this.stale = false;
13181
+ return;
13182
+ }
13183
+ // The current value is stale, and needs to be recomputed. It still may not change -
13184
+ // that depends on whether the newly computed value is equal to the old.
13185
+ this.recomputeValue();
13186
+ }
13187
+ recomputeValue() {
13188
+ if (this.value === COMPUTING) {
13189
+ // Our computation somehow led to a cyclic read of itself.
13190
+ throw new Error('Detected cycle in computations.');
13191
+ }
13192
+ const oldValue = this.value;
13193
+ this.value = COMPUTING;
13194
+ // As we're re-running the computation, update our dependent tracking version number.
13195
+ this.trackingVersion++;
13196
+ const prevConsumer = setActiveConsumer(this);
13197
+ let newValue;
13198
+ try {
13199
+ newValue = this.computation();
13200
+ }
13201
+ catch (err) {
13202
+ newValue = ERRORED;
13203
+ this.error = err;
13204
+ }
13205
+ finally {
13206
+ setActiveConsumer(prevConsumer);
13207
+ }
13208
+ this.stale = false;
13209
+ if (oldValue !== UNSET && oldValue !== ERRORED && newValue !== ERRORED &&
13210
+ this.equal(oldValue, newValue)) {
13211
+ // No change to `valueVersion` - old and new values are
13212
+ // semantically equivalent.
13213
+ this.value = oldValue;
13214
+ return;
13215
+ }
13216
+ this.value = newValue;
13217
+ this.valueVersion++;
13218
+ }
13219
+ signal() {
13220
+ // Check if the value needs updating before returning it.
13221
+ this.onProducerUpdateValueVersion();
13222
+ // Record that someone looked at this signal.
13223
+ this.producerAccessed();
13224
+ if (this.value === ERRORED) {
13225
+ throw this.error;
13226
+ }
13227
+ return this.value;
13228
+ }
13229
+ }
13230
+
13231
+ function defaultThrowError() {
13232
+ throw new Error();
13233
+ }
13234
+ let throwInvalidWriteToSignalErrorFn = defaultThrowError;
13235
+ function throwInvalidWriteToSignalError() {
13236
+ throwInvalidWriteToSignalErrorFn();
13237
+ }
13238
+ function setThrowInvalidWriteToSignalError(fn) {
13239
+ throwInvalidWriteToSignalErrorFn = fn;
13240
+ }
13241
+
13242
+ class WritableSignalImpl extends ReactiveNode {
13243
+ constructor(value, equal) {
13244
+ super();
13245
+ this.value = value;
13246
+ this.equal = equal;
13247
+ this.consumerAllowSignalWrites = false;
13248
+ }
13249
+ onConsumerDependencyMayHaveChanged() {
13250
+ // This never happens for writable signals as they're not consumers.
13251
+ }
13252
+ onProducerUpdateValueVersion() {
13253
+ // Writable signal value versions are always up to date.
13254
+ }
13255
+ /**
13256
+ * Directly update the value of the signal to a new value, which may or may not be
13257
+ * equal to the previous.
13258
+ *
13259
+ * In the event that `newValue` is semantically equal to the current value, `set` is
13260
+ * a no-op.
13261
+ */
13262
+ set(newValue) {
13263
+ if (!this.producerUpdatesAllowed) {
13264
+ throwInvalidWriteToSignalError();
13265
+ }
13266
+ if (!this.equal(this.value, newValue)) {
13267
+ this.value = newValue;
13268
+ this.valueVersion++;
13269
+ this.producerMayHaveChanged();
13270
+ }
13271
+ }
13272
+ /**
13273
+ * Derive a new value for the signal from its current value using the `updater` function.
13274
+ *
13275
+ * This is equivalent to calling `set` on the result of running `updater` on the current
13276
+ * value.
13277
+ */
13278
+ update(updater) {
13279
+ if (!this.producerUpdatesAllowed) {
13280
+ throwInvalidWriteToSignalError();
13281
+ }
13282
+ this.set(updater(this.value));
13283
+ }
13284
+ /**
13285
+ * Calls `mutator` on the current value and assumes that it has been mutated.
13286
+ */
13287
+ mutate(mutator) {
13288
+ if (!this.producerUpdatesAllowed) {
13289
+ throwInvalidWriteToSignalError();
13290
+ }
13291
+ // Mutate bypasses equality checks as it's by definition changing the value.
13292
+ mutator(this.value);
13293
+ this.valueVersion++;
13294
+ this.producerMayHaveChanged();
13295
+ }
13296
+ signal() {
13297
+ this.producerAccessed();
13298
+ return this.value;
13299
+ }
13300
+ }
13301
+ /**
13302
+ * Create a `Signal` that can be set or updated directly.
13303
+ *
13304
+ * @developerPreview
13305
+ */
13306
+ function signal(initialValue, options) {
13307
+ const signalNode = new WritableSignalImpl(initialValue, options?.equal ?? defaultEquals);
13308
+ // Casting here is required for g3, as TS inference behavior is slightly different between our
13309
+ // version/options and g3's.
13310
+ const signalFn = createSignalFromFunction(signalNode, signalNode.signal.bind(signalNode), {
13311
+ set: signalNode.set.bind(signalNode),
13312
+ update: signalNode.update.bind(signalNode),
13313
+ mutate: signalNode.mutate.bind(signalNode),
13314
+ });
13315
+ return signalFn;
13316
+ }
13317
+
13318
+ /**
13319
+ * Execute an arbitrary function in a non-reactive (non-tracking) context. The executed function
13320
+ * can, optionally, return a value.
13321
+ *
13322
+ * @developerPreview
13323
+ */
13324
+ function untracked(nonReactiveReadsFn) {
13325
+ const prevConsumer = setActiveConsumer(null);
13326
+ // We are not trying to catch any particular errors here, just making sure that the consumers
13327
+ // stack is restored in case of errors.
13328
+ try {
13329
+ return nonReactiveReadsFn();
13330
+ }
13331
+ finally {
13332
+ setActiveConsumer(prevConsumer);
13333
+ }
13334
+ }
13335
+
13336
+ const NOOP_CLEANUP_FN = () => { };
13337
+ /**
13338
+ * Watches a reactive expression and allows it to be scheduled to re-run
13339
+ * when any dependencies notify of a change.
13340
+ *
13341
+ * `Watch` doesn't run reactive expressions itself, but relies on a consumer-
13342
+ * provided scheduling operation to coordinate calling `Watch.run()`.
13343
+ */
13344
+ class Watch extends ReactiveNode {
13345
+ constructor(watch, schedule, allowSignalWrites) {
13346
+ super();
13347
+ this.watch = watch;
13348
+ this.schedule = schedule;
13349
+ this.dirty = false;
13350
+ this.cleanupFn = NOOP_CLEANUP_FN;
13351
+ this.consumerAllowSignalWrites = allowSignalWrites;
13352
+ }
13353
+ notify() {
13354
+ if (!this.dirty) {
13355
+ this.schedule(this);
13356
+ }
13357
+ this.dirty = true;
13358
+ }
13359
+ onConsumerDependencyMayHaveChanged() {
13360
+ this.notify();
13361
+ }
13362
+ onProducerUpdateValueVersion() {
13363
+ // Watches are not producers.
13364
+ }
13365
+ /**
13366
+ * Execute the reactive expression in the context of this `Watch` consumer.
13367
+ *
13368
+ * Should be called by the user scheduling algorithm when the provided
13369
+ * `schedule` hook is called by `Watch`.
13370
+ */
13371
+ run() {
13372
+ this.dirty = false;
13373
+ if (this.trackingVersion !== 0 && !this.consumerPollProducersForChange()) {
13374
+ return;
13375
+ }
13376
+ const prevConsumer = setActiveConsumer(this);
13377
+ this.trackingVersion++;
13378
+ try {
13379
+ this.cleanupFn();
13380
+ this.cleanupFn = this.watch() ?? NOOP_CLEANUP_FN;
13381
+ }
13382
+ finally {
13383
+ setActiveConsumer(prevConsumer);
13384
+ }
13385
+ }
13386
+ cleanup() {
13387
+ this.cleanupFn();
13388
+ }
13389
+ }
13390
+
13391
+ /**
13392
+ * Tracks all effects registered within a given application and runs them via `flush`.
13393
+ */
13394
+ class EffectManager {
13395
+ constructor() {
13396
+ this.all = new Set();
13397
+ this.queue = new Map();
13398
+ }
13399
+ create(effectFn, destroyRef, allowSignalWrites) {
13400
+ const zone = Zone.current;
13401
+ const watch = new Watch(effectFn, (watch) => {
13402
+ if (!this.all.has(watch)) {
13403
+ return;
13404
+ }
13405
+ this.queue.set(watch, zone);
13406
+ }, allowSignalWrites);
13407
+ this.all.add(watch);
13408
+ // Effects start dirty.
13409
+ watch.notify();
13410
+ let unregisterOnDestroy;
13411
+ const destroy = () => {
13412
+ watch.cleanup();
13413
+ unregisterOnDestroy?.();
13414
+ this.all.delete(watch);
13415
+ this.queue.delete(watch);
13416
+ };
13417
+ unregisterOnDestroy = destroyRef?.onDestroy(destroy);
13418
+ return {
13419
+ destroy,
13420
+ };
13421
+ }
13422
+ flush() {
13423
+ if (this.queue.size === 0) {
13424
+ return;
13425
+ }
13426
+ for (const [watch, zone] of this.queue) {
13427
+ this.queue.delete(watch);
13428
+ zone.run(() => watch.run());
13429
+ }
13430
+ }
13431
+ get isQueueEmpty() {
13432
+ return this.queue.size === 0;
13433
+ }
13434
+ /** @nocollapse */
13435
+ static { this.ɵprov = ɵɵdefineInjectable({
13436
+ token: EffectManager,
13437
+ providedIn: 'root',
13438
+ factory: () => new EffectManager(),
13439
+ }); }
13440
+ }
13441
+ /**
13442
+ * Create a global `Effect` for the given reactive function.
13443
+ *
13444
+ * @developerPreview
13445
+ */
13446
+ function effect(effectFn, options) {
13447
+ !options?.injector && assertInInjectionContext(effect);
13448
+ const injector = options?.injector ?? inject$1(Injector);
13449
+ const effectManager = injector.get(EffectManager);
13450
+ const destroyRef = options?.manualCleanup !== true ? injector.get(DestroyRef) : null;
13451
+ return effectManager.create(effectFn, destroyRef, !!options?.allowSignalWrites);
13452
+ }
13453
+
12999
13454
  /**
13000
13455
  * Compute the static styling (class/style) from `TAttributes`.
13001
13456
  *
@@ -13463,6 +13918,12 @@ class ComponentFactory extends ComponentFactory$1 {
13463
13918
  'Make sure that any injector used to create this component has a correct parent.');
13464
13919
  }
13465
13920
  const sanitizer = rootViewInjector.get(Sanitizer, null);
13921
+ const effectManager = rootViewInjector.get(EffectManager, null);
13922
+ const environment = {
13923
+ rendererFactory,
13924
+ sanitizer,
13925
+ effectManager,
13926
+ };
13466
13927
  const hostRenderer = rendererFactory.createRenderer(null, this.componentDef);
13467
13928
  // Determine a tag name used for creating host elements when this component is created
13468
13929
  // dynamically. Default to 'div' if this component did not specify any tag name in its selector.
@@ -13474,7 +13935,7 @@ class ComponentFactory extends ComponentFactory$1 {
13474
13935
  16 /* LViewFlags.CheckAlways */ | 256 /* LViewFlags.IsRoot */;
13475
13936
  // Create the root view. Uses empty TView and ContentTemplate.
13476
13937
  const rootTView = createTView(0 /* TViewType.Root */, null, null, 1, 0, null, null, null, null, null, null);
13477
- const rootLView = createLView(null, rootTView, null, rootFlags, null, null, rendererFactory, hostRenderer, sanitizer, rootViewInjector, null, null);
13938
+ const rootLView = createLView(null, rootTView, null, rootFlags, null, null, environment, hostRenderer, rootViewInjector, null, null);
13478
13939
  // rootView is the parent when bootstrapping
13479
13940
  // TODO(misko): it looks like we are entering view here but we don't really need to as
13480
13941
  // `renderView` does that. However as the code is written it is needed because
@@ -13497,7 +13958,7 @@ class ComponentFactory extends ComponentFactory$1 {
13497
13958
  rootDirectives = [rootComponentDef];
13498
13959
  }
13499
13960
  const hostTNode = createRootComponentTNode(rootLView, hostRNode);
13500
- const componentView = createRootComponentView(hostTNode, hostRNode, rootComponentDef, rootDirectives, rootLView, rendererFactory, hostRenderer);
13961
+ const componentView = createRootComponentView(hostTNode, hostRNode, rootComponentDef, rootDirectives, rootLView, environment, hostRenderer);
13501
13962
  tElementNode = getTNode(rootTView, HEADER_OFFSET);
13502
13963
  // TODO(crisbeto): in practice `hostRNode` should always be defined, but there are some tests
13503
13964
  // where the renderer is mocked out and `undefined` is returned. We should update the tests so
@@ -13603,7 +14064,7 @@ function createRootComponentTNode(lView, rNode) {
13603
14064
  *
13604
14065
  * @returns Component view created
13605
14066
  */
13606
- function createRootComponentView(tNode, hostRNode, rootComponentDef, rootDirectives, rootView, rendererFactory, hostRenderer, sanitizer) {
14067
+ function createRootComponentView(tNode, hostRNode, rootComponentDef, rootDirectives, rootView, environment, hostRenderer) {
13607
14068
  const tView = rootView[TVIEW];
13608
14069
  applyRootComponentStyling(rootDirectives, tNode, hostRNode, hostRenderer);
13609
14070
  // Hydration info is on the host element and needs to be retreived
@@ -13612,8 +14073,8 @@ function createRootComponentView(tNode, hostRNode, rootComponentDef, rootDirecti
13612
14073
  if (hostRNode !== null) {
13613
14074
  hydrationInfo = retrieveHydrationInfo(hostRNode, rootView[INJECTOR$1]);
13614
14075
  }
13615
- const viewRenderer = rendererFactory.createRenderer(hostRNode, rootComponentDef);
13616
- const componentView = createLView(rootView, getOrCreateComponentTView(rootComponentDef), null, rootComponentDef.onPush ? 32 /* LViewFlags.Dirty */ : 16 /* LViewFlags.CheckAlways */, rootView[tNode.index], tNode, rendererFactory, viewRenderer, sanitizer || null, null, null, hydrationInfo);
14076
+ const viewRenderer = environment.rendererFactory.createRenderer(hostRNode, rootComponentDef);
14077
+ const componentView = createLView(rootView, getOrCreateComponentTView(rootComponentDef), null, rootComponentDef.onPush ? 32 /* LViewFlags.Dirty */ : 16 /* LViewFlags.CheckAlways */, rootView[tNode.index], tNode, environment, viewRenderer, null, null, hydrationInfo);
13617
14078
  if (tView.firstCreatePass) {
13618
14079
  markAsComponentHost(tView, tNode, rootDirectives.length - 1);
13619
14080
  }
@@ -15822,6 +16283,7 @@ function locateOrCreateElementNodeImpl(tView, lView, tNode, renderer, name, inde
15822
16283
  // Since this isn't hydratable, we need to empty the node
15823
16284
  // so there's no duplicate content after render
15824
16285
  clearElementContents(native);
16286
+ ngDevMode && ngDevMode.componentsSkippedHydration++;
15825
16287
  }
15826
16288
  else if (ngDevMode) {
15827
16289
  // If this is not a component host, throw an error.
@@ -15878,7 +16340,6 @@ function ɵɵelementContainerStart(index, attrsIndex, localRefsIndex) {
15878
16340
  elementContainerStartFirstCreatePass(adjustedIndex, tView, lView, attrsIndex, localRefsIndex) :
15879
16341
  tView.data[adjustedIndex];
15880
16342
  setCurrentTNode(tNode, true);
15881
- ngDevMode && ngDevMode.rendererCreateComment++;
15882
16343
  const comment = _locateOrCreateElementContainerNode(tView, lView, tNode, index);
15883
16344
  lView[adjustedIndex] = comment;
15884
16345
  if (wasLastNodeCreated()) {
@@ -22066,17 +22527,19 @@ function createNgModuleRefWithProviders(moduleType, parentInjector, additionalPr
22066
22527
  return new NgModuleRef(moduleType, parentInjector, additionalProviders);
22067
22528
  }
22068
22529
  class EnvironmentNgModuleRefAdapter extends NgModuleRef$1 {
22069
- constructor(providers, parent, source) {
22530
+ constructor(config) {
22070
22531
  super();
22071
22532
  this.componentFactoryResolver = new ComponentFactoryResolver(this);
22072
22533
  this.instance = null;
22073
22534
  const injector = new R3Injector([
22074
- ...providers,
22535
+ ...config.providers,
22075
22536
  { provide: NgModuleRef$1, useValue: this },
22076
22537
  { provide: ComponentFactoryResolver$1, useValue: this.componentFactoryResolver },
22077
- ], parent || getNullInjector(), source, new Set(['environment']));
22538
+ ], config.parent || getNullInjector(), config.debugName, new Set(['environment']));
22078
22539
  this.injector = injector;
22079
- injector.resolveInjectorInitializers();
22540
+ if (config.runEnvironmentInitializers) {
22541
+ injector.resolveInjectorInitializers();
22542
+ }
22080
22543
  }
22081
22544
  destroy() {
22082
22545
  this.injector.destroy();
@@ -22099,7 +22562,7 @@ class EnvironmentNgModuleRefAdapter extends NgModuleRef$1 {
22099
22562
  * @publicApi
22100
22563
  */
22101
22564
  function createEnvironmentInjector(providers, parent, debugName = null) {
22102
- const adapter = new EnvironmentNgModuleRefAdapter(providers, parent, debugName);
22565
+ const adapter = new EnvironmentNgModuleRefAdapter({ providers, parent, debugName, runEnvironmentInitializers: true });
22103
22566
  return adapter.injector;
22104
22567
  }
22105
22568
 
@@ -23367,7 +23830,7 @@ const R3TemplateRef = class TemplateRef extends ViewEngineTemplateRef {
23367
23830
  */
23368
23831
  createEmbeddedViewImpl(context, injector, hydrationInfo) {
23369
23832
  const embeddedTView = this._declarationTContainer.tView;
23370
- const embeddedLView = createLView(this._declarationLView, embeddedTView, context, 16 /* LViewFlags.CheckAlways */, null, embeddedTView.declTNode, null, null, null, null, injector || null, hydrationInfo || null);
23833
+ const embeddedLView = createLView(this._declarationLView, embeddedTView, context, 16 /* LViewFlags.CheckAlways */, null, embeddedTView.declTNode, null, null, null, injector || null, hydrationInfo || null);
23371
23834
  const declarationLContainer = this._declarationLView[this._declarationTContainer.index];
23372
23835
  ngDevMode && assertLContainer(declarationLContainer);
23373
23836
  embeddedLView[DECLARATION_LCONTAINER] = declarationLContainer;
@@ -23469,24 +23932,17 @@ function cleanupLView(lView) {
23469
23932
  * Walks over all views registered within the ApplicationRef and removes
23470
23933
  * all dehydrated views from all `LContainer`s along the way.
23471
23934
  */
23472
- function cleanupDehydratedViews(appRef, pendingTasks) {
23473
- // Wait once an app becomes stable and cleanup all views that
23474
- // were not claimed during the application bootstrap process.
23475
- // The timing is similar to when we kick off serialization on the server.
23476
- const isStablePromise = appRef.isStable.pipe(first((isStable) => isStable)).toPromise();
23477
- const pendingTasksPromise = pendingTasks.whenAllTasksComplete;
23478
- return Promise.allSettled([isStablePromise, pendingTasksPromise]).then(() => {
23479
- const viewRefs = appRef._views;
23480
- for (const viewRef of viewRefs) {
23481
- const lView = getComponentLViewForHydration(viewRef);
23482
- // An `lView` might be `null` if a `ViewRef` represents
23483
- // an embedded view (not a component view).
23484
- if (lView !== null && lView[HOST] !== null) {
23485
- cleanupLView(lView);
23486
- ngDevMode && ngDevMode.dehydratedViewsCleanupRuns++;
23487
- }
23935
+ function cleanupDehydratedViews(appRef) {
23936
+ const viewRefs = appRef._views;
23937
+ for (const viewRef of viewRefs) {
23938
+ const lView = getComponentLViewForHydration(viewRef);
23939
+ // An `lView` might be `null` if a `ViewRef` represents
23940
+ // an embedded view (not a component view).
23941
+ if (lView !== null && lView[HOST] !== null) {
23942
+ cleanupLView(lView);
23943
+ ngDevMode && ngDevMode.dehydratedViewsCleanupRuns++;
23488
23944
  }
23489
- });
23945
+ }
23490
23946
  }
23491
23947
 
23492
23948
  /**
@@ -23570,7 +24026,7 @@ function findMatchingDehydratedView(lContainer, template) {
23570
24026
  * (created by instantiating a `TemplateRef` with the `createEmbeddedView()` method).
23571
24027
  *
23572
24028
  * A view container instance can contain other view containers,
23573
- * creating a [view hierarchy](guide/glossary#view-tree).
24029
+ * creating a [view hierarchy](guide/glossary#view-hierarchy).
23574
24030
  *
23575
24031
  * @see `ComponentRef`
23576
24032
  * @see `EmbeddedViewRef`
@@ -25903,9 +26359,8 @@ class TestBedCompiler {
25903
26359
  ɵcompileNgModuleDefs(RootScopeModule, {
25904
26360
  providers: [...this.rootProviderOverrides],
25905
26361
  });
25906
- const ngZone = new NgZone({ enableLongStackTrace: true });
25907
26362
  const providers = [
25908
- ɵprovideNgZoneChangeDetection(ngZone),
26363
+ provideZoneChangeDetection(),
25909
26364
  { provide: Compiler, useFactory: () => new R3TestCompiler(this) },
25910
26365
  ...this.providers,
25911
26366
  ...this.providerOverrides,