@angular/core 17.0.0-next.7 → 17.0.0-next.8

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 (90) hide show
  1. package/esm2022/primitives/signals/index.mjs +15 -0
  2. package/esm2022/primitives/signals/src/computed.mjs +92 -0
  3. package/esm2022/primitives/signals/src/equality.mjs +14 -0
  4. package/esm2022/primitives/signals/src/errors.mjs +18 -0
  5. package/esm2022/primitives/signals/src/graph.mjs +291 -0
  6. package/esm2022/primitives/signals/src/signal.mjs +78 -0
  7. package/esm2022/primitives/signals/src/watch.mjs +82 -0
  8. package/esm2022/primitives/signals/src/weak_ref.mjs +11 -0
  9. package/esm2022/rxjs-interop/src/to_signal.mjs +45 -14
  10. package/esm2022/src/application_init.mjs +50 -2
  11. package/esm2022/src/application_ref.mjs +7 -2
  12. package/esm2022/src/application_tokens.mjs +16 -1
  13. package/esm2022/src/core_private_export.mjs +4 -4
  14. package/esm2022/src/core_reactivity_export_internal.mjs +6 -2
  15. package/esm2022/src/core_render3_private_export.mjs +2 -2
  16. package/esm2022/src/errors.mjs +1 -1
  17. package/esm2022/src/image_performance_warning.mjs +154 -0
  18. package/esm2022/src/linker/compiler.mjs +1 -1
  19. package/esm2022/src/metadata/directives.mjs +1 -1
  20. package/esm2022/src/render3/after_render_hooks.mjs +5 -1
  21. package/esm2022/src/render3/assert.mjs +16 -1
  22. package/esm2022/src/render3/component_ref.mjs +12 -3
  23. package/esm2022/src/render3/debug/framework_injector_profiler.mjs +33 -4
  24. package/esm2022/src/render3/debug/injector_profiler.mjs +1 -1
  25. package/esm2022/src/render3/debug/set_debug_info.mjs +20 -0
  26. package/esm2022/src/render3/definition.mjs +2 -1
  27. package/esm2022/src/render3/deps_tracker/api.mjs +1 -1
  28. package/esm2022/src/render3/deps_tracker/deps_tracker.mjs +13 -2
  29. package/esm2022/src/render3/features/host_directives_feature.mjs +3 -8
  30. package/esm2022/src/render3/hooks.mjs +5 -5
  31. package/esm2022/src/render3/index.mjs +3 -2
  32. package/esm2022/src/render3/instructions/change_detection.mjs +31 -14
  33. package/esm2022/src/render3/instructions/control_flow.mjs +21 -12
  34. package/esm2022/src/render3/instructions/defer.mjs +156 -22
  35. package/esm2022/src/render3/instructions/defer_events.mjs +13 -3
  36. package/esm2022/src/render3/instructions/shared.mjs +5 -4
  37. package/esm2022/src/render3/interfaces/container.mjs +5 -4
  38. package/esm2022/src/render3/interfaces/defer.mjs +13 -6
  39. package/esm2022/src/render3/interfaces/definition.mjs +1 -1
  40. package/esm2022/src/render3/interfaces/view.mjs +5 -4
  41. package/esm2022/src/render3/jit/environment.mjs +3 -1
  42. package/esm2022/src/render3/node_manipulation.mjs +4 -6
  43. package/esm2022/src/render3/reactive_lview_consumer.mjs +2 -2
  44. package/esm2022/src/render3/reactivity/api.mjs +15 -0
  45. package/esm2022/src/render3/reactivity/asserts.mjs +26 -0
  46. package/esm2022/src/render3/reactivity/computed.mjs +19 -0
  47. package/esm2022/src/render3/reactivity/effect.mjs +7 -6
  48. package/esm2022/src/render3/reactivity/signal.mjs +32 -0
  49. package/esm2022/src/render3/reactivity/untracked.mjs +24 -0
  50. package/esm2022/src/render3/util/injector_discovery_utils.mjs +43 -14
  51. package/esm2022/src/render3/util/stringify_utils.mjs +28 -1
  52. package/esm2022/src/render3/util/view_utils.mjs +41 -25
  53. package/esm2022/src/render3/view_ref.mjs +3 -2
  54. package/esm2022/src/util/stringify.mjs +16 -1
  55. package/esm2022/src/version.mjs +1 -1
  56. package/esm2022/testing/src/logger.mjs +3 -3
  57. package/fesm2022/core.mjs +1787 -1212
  58. package/fesm2022/core.mjs.map +1 -1
  59. package/fesm2022/primitives/signals.mjs +539 -0
  60. package/fesm2022/primitives/signals.mjs.map +1 -0
  61. package/fesm2022/rxjs-interop.mjs +45 -14
  62. package/fesm2022/rxjs-interop.mjs.map +1 -1
  63. package/fesm2022/testing.mjs +1 -1
  64. package/index.d.ts +162 -163
  65. package/package.json +7 -1
  66. package/primitives/signals/index.d.ts +281 -0
  67. package/rxjs-interop/index.d.ts +15 -101
  68. package/schematics/collection.json +12 -2
  69. package/schematics/migrations/block-template-entities/bundle.js +485 -297
  70. package/schematics/migrations/block-template-entities/bundle.js.map +4 -4
  71. package/schematics/migrations/compiler-options/bundle.js +582 -0
  72. package/schematics/migrations/compiler-options/bundle.js.map +7 -0
  73. package/schematics/migrations/transfer-state/bundle.js +592 -0
  74. package/schematics/migrations/transfer-state/bundle.js.map +7 -0
  75. package/schematics/migrations.json +10 -0
  76. package/schematics/ng-generate/control-flow-migration/bundle.js +24097 -0
  77. package/schematics/ng-generate/control-flow-migration/bundle.js.map +7 -0
  78. package/schematics/ng-generate/control-flow-migration/schema.json +7 -0
  79. package/schematics/ng-generate/standalone-migration/bundle.js +1677 -1278
  80. package/schematics/ng-generate/standalone-migration/bundle.js.map +4 -4
  81. package/testing/index.d.ts +1 -1
  82. package/esm2022/src/signals/index.mjs +0 -16
  83. package/esm2022/src/signals/src/api.mjs +0 -39
  84. package/esm2022/src/signals/src/computed.mjs +0 -95
  85. package/esm2022/src/signals/src/errors.mjs +0 -18
  86. package/esm2022/src/signals/src/graph.mjs +0 -280
  87. package/esm2022/src/signals/src/signal.mjs +0 -92
  88. package/esm2022/src/signals/src/untracked.mjs +0 -26
  89. package/esm2022/src/signals/src/watch.mjs +0 -81
  90. package/esm2022/src/signals/src/weak_ref.mjs +0 -11
package/fesm2022/core.mjs CHANGED
@@ -1,9 +1,10 @@
1
1
  /**
2
- * @license Angular v17.0.0-next.7
2
+ * @license Angular v17.0.0-next.8
3
3
  * (c) 2010-2022 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
6
6
 
7
+ import { setActiveConsumer as setActiveConsumer$1, consumerDestroy as consumerDestroy$1, SIGNAL as SIGNAL$1, createComputed as createComputed$1, createSignal as createSignal$1, signalSetFn as signalSetFn$1, signalUpdateFn as signalUpdateFn$1, getActiveConsumer as getActiveConsumer$1, createWatch as createWatch$1, REACTIVE_NODE as REACTIVE_NODE$1, consumerBeforeComputation as consumerBeforeComputation$1, consumerAfterComputation as consumerAfterComputation$1, setThrowInvalidWriteToSignalError as setThrowInvalidWriteToSignalError$1 } from '@angular/core/primitives/signals';
7
8
  import { Subject, Subscription, Observable, merge as merge$1, BehaviorSubject, of } from 'rxjs';
8
9
  import { share, switchMap, distinctUntilChanged, first } from 'rxjs/operators';
9
10
 
@@ -65,6 +66,21 @@ function concatStringsWithSpace(before, after) {
65
66
  (after === null ? '' : after) :
66
67
  ((after == null || after === '') ? before : before + ' ' + after);
67
68
  }
69
+ /**
70
+ * Ellipses the string in the middle when longer than the max length
71
+ *
72
+ * @param string
73
+ * @param maxLength of the output string
74
+ * @returns elispsed string with ... in the middle
75
+ */
76
+ function truncateMiddle(str, maxLength = 100) {
77
+ if (!str || maxLength < 1 || str.length <= maxLength)
78
+ return str;
79
+ if (maxLength == 1)
80
+ return str.substring(0, 1) + '...';
81
+ const halfLimit = Math.round(maxLength / 2);
82
+ return str.substring(0, halfLimit) + '...' + str.substring(str.length - halfLimit);
83
+ }
68
84
 
69
85
  const __forward_ref__ = getClosureSafeProperty({ __forward_ref__: getClosureSafeProperty });
70
86
  /**
@@ -193,6 +209,28 @@ function formatRuntimeError(code, message) {
193
209
  return errorMessage;
194
210
  }
195
211
 
212
+ const NG_COMP_DEF = getClosureSafeProperty({ ɵcmp: getClosureSafeProperty });
213
+ const NG_DIR_DEF = getClosureSafeProperty({ ɵdir: getClosureSafeProperty });
214
+ const NG_PIPE_DEF = getClosureSafeProperty({ ɵpipe: getClosureSafeProperty });
215
+ const NG_MOD_DEF = getClosureSafeProperty({ ɵmod: getClosureSafeProperty });
216
+ const NG_FACTORY_DEF = getClosureSafeProperty({ ɵfac: getClosureSafeProperty });
217
+ /**
218
+ * If a directive is diPublic, bloomAdd sets a property on the type with this constant as
219
+ * the key and the directive's unique ID as the value. This allows us to map directives to their
220
+ * bloom filter bit for DI.
221
+ */
222
+ // TODO(misko): This is wrong. The NG_ELEMENT_ID should never be minified.
223
+ const NG_ELEMENT_ID = getClosureSafeProperty({ __NG_ELEMENT_ID__: getClosureSafeProperty });
224
+ /**
225
+ * The `NG_ENV_ID` field on a DI token indicates special processing in the `EnvironmentInjector`:
226
+ * getting such tokens from the `EnvironmentInjector` will bypass the standard DI resolution
227
+ * strategy and instead will return implementation produced by the `NG_ENV_ID` factory function.
228
+ *
229
+ * This particular retrieval of DI tokens is mostly done to eliminate circular dependencies and
230
+ * improve tree-shaking.
231
+ */
232
+ const NG_ENV_ID = getClosureSafeProperty({ __NG_ENV_ID__: getClosureSafeProperty });
233
+
196
234
  /**
197
235
  * Used for stringify render output in Ivy.
198
236
  * Important! This function is very performance-sensitive and we should
@@ -210,6 +248,7 @@ function renderStringify(value) {
210
248
  }
211
249
  /**
212
250
  * Used to stringify a value so that it can be displayed in an error message.
251
+ *
213
252
  * Important! This function contains a megamorphic read and should only be
214
253
  * used for error messages.
215
254
  */
@@ -221,6 +260,31 @@ function stringifyForError(value) {
221
260
  }
222
261
  return renderStringify(value);
223
262
  }
263
+ /**
264
+ * Used to stringify a `Type` and including the file path and line number in which it is defined, if
265
+ * possible, for better debugging experience.
266
+ *
267
+ * Important! This function contains a megamorphic read and should only be used for error messages.
268
+ */
269
+ function debugStringifyTypeForError(type) {
270
+ // TODO(pmvald): Do some refactoring so that we can use getComponentDef here without creating
271
+ // circular deps.
272
+ let componentDef = type[NG_COMP_DEF] || null;
273
+ if (componentDef !== null && componentDef.debugInfo) {
274
+ return stringifyTypeFromDebugInfo(componentDef.debugInfo);
275
+ }
276
+ return stringifyForError(type);
277
+ }
278
+ // TODO(pmvald): Do some refactoring so that we can use the type ClassDebugInfo for the param
279
+ // debugInfo here without creating circular deps.
280
+ function stringifyTypeFromDebugInfo(debugInfo) {
281
+ if (!debugInfo.filePath || !debugInfo.lineNumber) {
282
+ return debugInfo.className;
283
+ }
284
+ else {
285
+ return `${debugInfo.className} (at ${debugInfo.filePath}:${debugInfo.lineNumber})`;
286
+ }
287
+ }
224
288
 
225
289
  /** Called when directives inject each other (creating a circular dependency) */
226
290
  function throwCyclicDependencyError(token, path) {
@@ -1027,28 +1091,6 @@ if ((typeof ngDevMode === 'undefined' || ngDevMode) && initNgDevMode()) {
1027
1091
  Object.freeze(EMPTY_ARRAY);
1028
1092
  }
1029
1093
 
1030
- const NG_COMP_DEF = getClosureSafeProperty({ ɵcmp: getClosureSafeProperty });
1031
- const NG_DIR_DEF = getClosureSafeProperty({ ɵdir: getClosureSafeProperty });
1032
- const NG_PIPE_DEF = getClosureSafeProperty({ ɵpipe: getClosureSafeProperty });
1033
- const NG_MOD_DEF = getClosureSafeProperty({ ɵmod: getClosureSafeProperty });
1034
- const NG_FACTORY_DEF = getClosureSafeProperty({ ɵfac: getClosureSafeProperty });
1035
- /**
1036
- * If a directive is diPublic, bloomAdd sets a property on the type with this constant as
1037
- * the key and the directive's unique ID as the value. This allows us to map directives to their
1038
- * bloom filter bit for DI.
1039
- */
1040
- // TODO(misko): This is wrong. The NG_ELEMENT_ID should never be minified.
1041
- const NG_ELEMENT_ID = getClosureSafeProperty({ __NG_ELEMENT_ID__: getClosureSafeProperty });
1042
- /**
1043
- * The `NG_ENV_ID` field on a DI token indicates special processing in the `EnvironmentInjector`:
1044
- * getting such tokens from the `EnvironmentInjector` will bypass the standard DI resolution
1045
- * strategy and instead will return implementation produced by the `NG_ENV_ID` factory function.
1046
- *
1047
- * This particular retrieval of DI tokens is mostly done to eliminate circular dependencies and
1048
- * improve tree-shaking.
1049
- */
1050
- const NG_ENV_ID = getClosureSafeProperty({ __NG_ENV_ID__: getClosureSafeProperty });
1051
-
1052
1094
  /**
1053
1095
  * Returns an index of `classToSearch` in `className` taking token boundaries into account.
1054
1096
  *
@@ -1951,6 +1993,7 @@ function getNgDirectiveDef(directiveDefinition) {
1951
1993
  hostDirectives: null,
1952
1994
  inputs: invertObject(directiveDefinition.inputs, declaredInputs),
1953
1995
  outputs: invertObject(directiveDefinition.outputs),
1996
+ debugInfo: null,
1954
1997
  };
1955
1998
  }
1956
1999
  function initFeatures(definition) {
@@ -2032,10 +2075,12 @@ function getComponentId(componentDef) {
2032
2075
  const HOST = 0;
2033
2076
  const TVIEW = 1;
2034
2077
  const FLAGS = 2;
2078
+ // Shared with LContainer
2035
2079
  const PARENT = 3;
2036
2080
  const NEXT = 4;
2037
- const DESCENDANT_VIEWS_TO_REFRESH = 5;
2038
- const T_HOST = 6;
2081
+ const T_HOST = 5;
2082
+ // End shared with LContainer
2083
+ const HYDRATION = 6;
2039
2084
  const CLEANUP = 7;
2040
2085
  const CONTEXT = 8;
2041
2086
  const INJECTOR$1 = 9;
@@ -2052,7 +2097,6 @@ const QUERIES = 18;
2052
2097
  const ID = 19;
2053
2098
  const EMBEDDED_VIEW_INJECTOR = 20;
2054
2099
  const ON_DESTROY_HOOKS = 21;
2055
- const HYDRATION = 22;
2056
2100
  const REACTIVE_TEMPLATE_CONSUMER = 23;
2057
2101
  const REACTIVE_HOST_BINDING_CONSUMER = 24;
2058
2102
  /**
@@ -2087,10 +2131,11 @@ const TYPE = 1;
2087
2131
  * that the `MOVED_VIEWS` are transplanted and on-push.
2088
2132
  */
2089
2133
  const HAS_TRANSPLANTED_VIEWS = 2;
2090
- // PARENT, NEXT, DESCENDANT_VIEWS_TO_REFRESH are indices 3, 4, and 5
2134
+ // PARENT and NEXT are indices 3 and 4
2091
2135
  // As we already have these constants in LView, we don't need to re-create them.
2092
- // T_HOST is index 6
2136
+ // T_HOST is index 5
2093
2137
  // We already have this constants in LView, we don't need to re-create it.
2138
+ const HAS_CHILD_VIEWS_TO_REFRESH = 6;
2094
2139
  const NATIVE = 7;
2095
2140
  const VIEW_REFS = 8;
2096
2141
  const MOVED_VIEWS = 9;
@@ -2235,6 +2280,20 @@ function assertProjectionSlots(lView, errMessage) {
2235
2280
  function assertParentView(lView, errMessage) {
2236
2281
  assertDefined(lView, errMessage || 'Component views should always have a parent view (component\'s host view)');
2237
2282
  }
2283
+ function assertNoDuplicateDirectives(directives) {
2284
+ // The array needs at least two elements in order to have duplicates.
2285
+ if (directives.length < 2) {
2286
+ return;
2287
+ }
2288
+ const seenDirectives = new Set();
2289
+ for (const current of directives) {
2290
+ if (seenDirectives.has(current)) {
2291
+ throw new RuntimeError(309 /* RuntimeErrorCode.DUPLICATE_DIRECTITVE */, `Directive ${current.type.name} matches multiple times on the same element. ` +
2292
+ `Directives can only match an element once.`);
2293
+ }
2294
+ seenDirectives.add(current);
2295
+ }
2296
+ }
2238
2297
  /**
2239
2298
  * This is a basic sanity check that the `injectorIndex` seems to point to what looks like a
2240
2299
  * NodeInjector data structure.
@@ -2265,906 +2324,345 @@ function getFactoryDef(type, throwNotFound) {
2265
2324
  }
2266
2325
 
2267
2326
  /**
2268
- * Symbol used to tell `Signal`s apart from other functions.
2327
+ * Represents a basic change from a previous to a new value for a single
2328
+ * property on a directive instance. Passed as a value in a
2329
+ * {@link SimpleChanges} object to the `ngOnChanges` hook.
2269
2330
  *
2270
- * This can be used to auto-unwrap signals in various cases, or to auto-wrap non-signal values.
2331
+ * @see {@link OnChanges}
2332
+ *
2333
+ * @publicApi
2271
2334
  */
2272
- const SIGNAL = /* @__PURE__ */ Symbol('SIGNAL');
2335
+ class SimpleChange {
2336
+ constructor(previousValue, currentValue, firstChange) {
2337
+ this.previousValue = previousValue;
2338
+ this.currentValue = currentValue;
2339
+ this.firstChange = firstChange;
2340
+ }
2341
+ /**
2342
+ * Check whether the new value is the first value assigned.
2343
+ */
2344
+ isFirstChange() {
2345
+ return this.firstChange;
2346
+ }
2347
+ }
2348
+
2273
2349
  /**
2274
- * Checks if the given `value` is a reactive `Signal`.
2350
+ * The NgOnChangesFeature decorates a component with support for the ngOnChanges
2351
+ * lifecycle hook, so it should be included in any component that implements
2352
+ * that hook.
2275
2353
  *
2276
- * @developerPreview
2354
+ * If the component or directive uses inheritance, the NgOnChangesFeature MUST
2355
+ * be included as a feature AFTER {@link InheritDefinitionFeature}, otherwise
2356
+ * inherited properties will not be propagated to the ngOnChanges lifecycle
2357
+ * hook.
2358
+ *
2359
+ * Example usage:
2360
+ *
2361
+ * ```
2362
+ * static ɵcmp = defineComponent({
2363
+ * ...
2364
+ * inputs: {name: 'publicName'},
2365
+ * features: [NgOnChangesFeature]
2366
+ * });
2367
+ * ```
2368
+ *
2369
+ * @codeGenApi
2277
2370
  */
2278
- function isSignal(value) {
2279
- return typeof value === 'function' && value[SIGNAL] !== undefined;
2371
+ function ɵɵNgOnChangesFeature() {
2372
+ return NgOnChangesFeatureImpl;
2373
+ }
2374
+ function NgOnChangesFeatureImpl(definition) {
2375
+ if (definition.type.prototype.ngOnChanges) {
2376
+ definition.setInput = ngOnChangesSetInput;
2377
+ }
2378
+ return rememberChangeHistoryAndInvokeOnChangesHook;
2280
2379
  }
2380
+ // This option ensures that the ngOnChanges lifecycle hook will be inherited
2381
+ // from superclasses (in InheritDefinitionFeature).
2382
+ /** @nocollapse */
2383
+ // tslint:disable-next-line:no-toplevel-property-access
2384
+ ɵɵNgOnChangesFeature.ngInherit = true;
2281
2385
  /**
2282
- * The default equality function used for `signal` and `computed`, which treats objects and arrays
2283
- * as never equal, and all other primitive values using identity semantics.
2386
+ * This is a synthetic lifecycle hook which gets inserted into `TView.preOrderHooks` to simulate
2387
+ * `ngOnChanges`.
2284
2388
  *
2285
- * This allows signals to hold non-primitive values (arrays, objects, other collections) and still
2286
- * propagate change notification upon explicit mutation without identity change.
2389
+ * The hook reads the `NgSimpleChangesStore` data from the component instance and if changes are
2390
+ * found it invokes `ngOnChanges` on the component instance.
2287
2391
  *
2288
- * @developerPreview
2392
+ * @param this Component instance. Because this function gets inserted into `TView.preOrderHooks`,
2393
+ * it is guaranteed to be called with component instance.
2289
2394
  */
2290
- function defaultEquals(a, b) {
2291
- // `Object.is` compares two values using identity semantics which is desired behavior for
2292
- // primitive values. If `Object.is` determines two values to be equal we need to make sure that
2293
- // those don't represent objects (we want to make sure that 2 objects are always considered
2294
- // "unequal"). The null check is needed for the special case of JavaScript reporting null values
2295
- // as objects (`typeof null === 'object'`).
2296
- return (a === null || typeof a !== 'object') && Object.is(a, b);
2395
+ function rememberChangeHistoryAndInvokeOnChangesHook() {
2396
+ const simpleChangesStore = getSimpleChangesStore(this);
2397
+ const current = simpleChangesStore?.current;
2398
+ if (current) {
2399
+ const previous = simpleChangesStore.previous;
2400
+ if (previous === EMPTY_OBJ) {
2401
+ simpleChangesStore.previous = current;
2402
+ }
2403
+ else {
2404
+ // New changes are copied to the previous store, so that we don't lose history for inputs
2405
+ // which were not changed this time
2406
+ for (let key in current) {
2407
+ previous[key] = current[key];
2408
+ }
2409
+ }
2410
+ simpleChangesStore.current = null;
2411
+ this.ngOnChanges(current);
2412
+ }
2413
+ }
2414
+ function ngOnChangesSetInput(instance, value, publicName, privateName) {
2415
+ const declaredName = this.declaredInputs[publicName];
2416
+ ngDevMode && assertString(declaredName, 'Name of input in ngOnChanges has to be a string');
2417
+ const simpleChangesStore = getSimpleChangesStore(instance) ||
2418
+ setSimpleChangesStore(instance, { previous: EMPTY_OBJ, current: null });
2419
+ const current = simpleChangesStore.current || (simpleChangesStore.current = {});
2420
+ const previous = simpleChangesStore.previous;
2421
+ const previousChange = previous[declaredName];
2422
+ current[declaredName] = new SimpleChange(previousChange && previousChange.currentValue, value, previous === EMPTY_OBJ);
2423
+ instance[privateName] = value;
2424
+ }
2425
+ const SIMPLE_CHANGES_STORE = '__ngSimpleChanges__';
2426
+ function getSimpleChangesStore(instance) {
2427
+ return instance[SIMPLE_CHANGES_STORE] || null;
2428
+ }
2429
+ function setSimpleChangesStore(instance, store) {
2430
+ return instance[SIMPLE_CHANGES_STORE] = store;
2297
2431
  }
2298
2432
 
2299
- // Required as the signals library is in a separate package, so we need to explicitly ensure the
2433
+ let profilerCallback = null;
2300
2434
  /**
2301
- * The currently active consumer `ReactiveNode`, if running code in a reactive context.
2435
+ * Sets the callback function which will be invoked before and after performing certain actions at
2436
+ * runtime (for example, before and after running change detection).
2302
2437
  *
2303
- * Change this via `setActiveConsumer`.
2438
+ * Warning: this function is *INTERNAL* and should not be relied upon in application's code.
2439
+ * The contract of the function might be changed in any release and/or the function can be removed
2440
+ * completely.
2441
+ *
2442
+ * @param profiler function provided by the caller or null value to disable profiling.
2304
2443
  */
2305
- let activeConsumer = null;
2306
- let inNotificationPhase = false;
2307
- function setActiveConsumer(consumer) {
2308
- const prev = activeConsumer;
2309
- activeConsumer = consumer;
2310
- return prev;
2311
- }
2312
- function isInNotificationPhase() {
2313
- return inNotificationPhase;
2314
- }
2315
- const REACTIVE_NODE = {
2316
- version: 0,
2317
- dirty: false,
2318
- producerNode: undefined,
2319
- producerLastReadVersion: undefined,
2320
- producerIndexOfThis: undefined,
2321
- nextProducerIndex: 0,
2322
- liveConsumerNode: undefined,
2323
- liveConsumerIndexOfThis: undefined,
2324
- consumerAllowSignalWrites: false,
2325
- consumerIsAlwaysLive: false,
2326
- producerMustRecompute: () => false,
2327
- producerRecomputeValue: () => { },
2328
- consumerMarkedDirty: () => { },
2444
+ const setProfiler = (profiler) => {
2445
+ profilerCallback = profiler;
2329
2446
  };
2330
2447
  /**
2331
- * Called by implementations when a producer's signal is read.
2448
+ * Profiler function which wraps user code executed by the runtime.
2449
+ *
2450
+ * @param event ProfilerEvent corresponding to the execution context
2451
+ * @param instance component instance
2452
+ * @param hookOrListener lifecycle hook function or output listener. The value depends on the
2453
+ * execution context
2454
+ * @returns
2332
2455
  */
2333
- function producerAccessed(node) {
2334
- if (inNotificationPhase) {
2335
- throw new Error(typeof ngDevMode !== 'undefined' && ngDevMode ?
2336
- `Assertion error: signal read during notification phase` :
2337
- '');
2338
- }
2339
- if (activeConsumer === null) {
2340
- // Accessed outside of a reactive context, so nothing to record.
2341
- return;
2342
- }
2343
- // This producer is the `idx`th dependency of `activeConsumer`.
2344
- const idx = activeConsumer.nextProducerIndex++;
2345
- assertConsumerNode(activeConsumer);
2346
- if (idx < activeConsumer.producerNode.length && activeConsumer.producerNode[idx] !== node) {
2347
- // There's been a change in producers since the last execution of `activeConsumer`.
2348
- // `activeConsumer.producerNode[idx]` holds a stale dependency which will be be removed and
2349
- // replaced with `this`.
2350
- //
2351
- // If `activeConsumer` isn't live, then this is a no-op, since we can replace the producer in
2352
- // `activeConsumer.producerNode` directly. However, if `activeConsumer` is live, then we need
2353
- // to remove it from the stale producer's `liveConsumer`s.
2354
- if (consumerIsLive(activeConsumer)) {
2355
- const staleProducer = activeConsumer.producerNode[idx];
2356
- producerRemoveLiveConsumerAtIndex(staleProducer, activeConsumer.producerIndexOfThis[idx]);
2357
- // At this point, the only record of `staleProducer` is the reference at
2358
- // `activeConsumer.producerNode[idx]` which will be overwritten below.
2359
- }
2360
- }
2361
- if (activeConsumer.producerNode[idx] !== node) {
2362
- // We're a new dependency of the consumer (at `idx`).
2363
- activeConsumer.producerNode[idx] = node;
2364
- // If the active consumer is live, then add it as a live consumer. If not, then use 0 as a
2365
- // placeholder value.
2366
- activeConsumer.producerIndexOfThis[idx] =
2367
- consumerIsLive(activeConsumer) ? producerAddLiveConsumer(node, activeConsumer, idx) : 0;
2456
+ const profiler = function (event, instance, hookOrListener) {
2457
+ if (profilerCallback != null /* both `null` and `undefined` */) {
2458
+ profilerCallback(event, instance, hookOrListener);
2368
2459
  }
2369
- activeConsumer.producerLastReadVersion[idx] = node.version;
2370
- }
2460
+ };
2461
+
2462
+ const SVG_NAMESPACE = 'svg';
2463
+ const MATH_ML_NAMESPACE = 'math';
2464
+
2371
2465
  /**
2372
- * Ensure this producer's `version` is up-to-date.
2466
+ * For efficiency reasons we often put several different data types (`RNode`, `LView`, `LContainer`)
2467
+ * in same location in `LView`. This is because we don't want to pre-allocate space for it
2468
+ * because the storage is sparse. This file contains utilities for dealing with such data types.
2469
+ *
2470
+ * How do we know what is stored at a given location in `LView`.
2471
+ * - `Array.isArray(value) === false` => `RNode` (The normal storage value)
2472
+ * - `Array.isArray(value) === true` => then the `value[0]` represents the wrapped value.
2473
+ * - `typeof value[TYPE] === 'object'` => `LView`
2474
+ * - This happens when we have a component at a given location
2475
+ * - `typeof value[TYPE] === true` => `LContainer`
2476
+ * - This happens when we have `LContainer` binding at a given location.
2477
+ *
2478
+ *
2479
+ * NOTE: it is assumed that `Array.isArray` and `typeof` operations are very efficient.
2373
2480
  */
2374
- function producerUpdateValueVersion(node) {
2375
- if (consumerIsLive(node) && !node.dirty) {
2376
- // A live consumer will be marked dirty by producers, so a clean state means that its version
2377
- // is guaranteed to be up-to-date.
2378
- return;
2379
- }
2380
- if (!node.producerMustRecompute(node) && !consumerPollProducersForChange(node)) {
2381
- // None of our producers report a change since the last time they were read, so no
2382
- // recomputation of our value is necessary, and we can consider ourselves clean.
2383
- node.dirty = false;
2384
- return;
2481
+ /**
2482
+ * Returns `RNode`.
2483
+ * @param value wrapped value of `RNode`, `LView`, `LContainer`
2484
+ */
2485
+ function unwrapRNode(value) {
2486
+ while (Array.isArray(value)) {
2487
+ value = value[HOST];
2385
2488
  }
2386
- node.producerRecomputeValue(node);
2387
- // After recomputing the value, we're no longer dirty.
2388
- node.dirty = false;
2489
+ return value;
2389
2490
  }
2390
2491
  /**
2391
- * Propagate a dirty notification to live consumers of this producer.
2492
+ * Returns `LView` or `null` if not found.
2493
+ * @param value wrapped value of `RNode`, `LView`, `LContainer`
2392
2494
  */
2393
- function producerNotifyConsumers(node) {
2394
- if (node.liveConsumerNode === undefined) {
2395
- return;
2396
- }
2397
- // Prevent signal reads when we're updating the graph
2398
- const prev = inNotificationPhase;
2399
- inNotificationPhase = true;
2400
- try {
2401
- for (const consumer of node.liveConsumerNode) {
2402
- if (!consumer.dirty) {
2403
- consumerMarkDirty(consumer);
2404
- }
2405
- }
2406
- }
2407
- finally {
2408
- inNotificationPhase = prev;
2495
+ function unwrapLView(value) {
2496
+ while (Array.isArray(value)) {
2497
+ // This check is same as `isLView()` but we don't call at as we don't want to call
2498
+ // `Array.isArray()` twice and give JITer more work for inlining.
2499
+ if (typeof value[TYPE] === 'object')
2500
+ return value;
2501
+ value = value[HOST];
2409
2502
  }
2503
+ return null;
2410
2504
  }
2411
2505
  /**
2412
- * Whether this `ReactiveNode` in its producer capacity is currently allowed to initiate updates,
2413
- * based on the current consumer context.
2506
+ * Retrieves an element value from the provided `viewData`, by unwrapping
2507
+ * from any containers, component views, or style contexts.
2414
2508
  */
2415
- function producerUpdatesAllowed() {
2416
- return activeConsumer?.consumerAllowSignalWrites !== false;
2509
+ function getNativeByIndex(index, lView) {
2510
+ ngDevMode && assertIndexInRange(lView, index);
2511
+ ngDevMode && assertGreaterThanOrEqual(index, HEADER_OFFSET, 'Expected to be past HEADER_OFFSET');
2512
+ return unwrapRNode(lView[index]);
2417
2513
  }
2418
- function consumerMarkDirty(node) {
2419
- node.dirty = true;
2420
- producerNotifyConsumers(node);
2421
- node.consumerMarkedDirty?.(node);
2514
+ /**
2515
+ * Retrieve an `RNode` for a given `TNode` and `LView`.
2516
+ *
2517
+ * This function guarantees in dev mode to retrieve a non-null `RNode`.
2518
+ *
2519
+ * @param tNode
2520
+ * @param lView
2521
+ */
2522
+ function getNativeByTNode(tNode, lView) {
2523
+ ngDevMode && assertTNodeForLView(tNode, lView);
2524
+ ngDevMode && assertIndexInRange(lView, tNode.index);
2525
+ const node = unwrapRNode(lView[tNode.index]);
2526
+ return node;
2422
2527
  }
2423
2528
  /**
2424
- * Prepare this consumer to run a computation in its reactive context.
2529
+ * Retrieve an `RNode` or `null` for a given `TNode` and `LView`.
2425
2530
  *
2426
- * Must be called by subclasses which represent reactive computations, before those computations
2427
- * begin.
2531
+ * Some `TNode`s don't have associated `RNode`s. For example `Projection`
2532
+ *
2533
+ * @param tNode
2534
+ * @param lView
2428
2535
  */
2429
- function consumerBeforeComputation(node) {
2430
- node && (node.nextProducerIndex = 0);
2431
- return setActiveConsumer(node);
2536
+ function getNativeByTNodeOrNull(tNode, lView) {
2537
+ const index = tNode === null ? -1 : tNode.index;
2538
+ if (index !== -1) {
2539
+ ngDevMode && assertTNodeForLView(tNode, lView);
2540
+ const node = unwrapRNode(lView[index]);
2541
+ return node;
2542
+ }
2543
+ return null;
2544
+ }
2545
+ // fixme(misko): The return Type should be `TNode|null`
2546
+ function getTNode(tView, index) {
2547
+ ngDevMode && assertGreaterThan(index, -1, 'wrong index for TNode');
2548
+ ngDevMode && assertLessThan(index, tView.data.length, 'wrong index for TNode');
2549
+ const tNode = tView.data[index];
2550
+ ngDevMode && tNode !== null && assertTNode(tNode);
2551
+ return tNode;
2552
+ }
2553
+ /** Retrieves a value from any `LView` or `TData`. */
2554
+ function load(view, index) {
2555
+ ngDevMode && assertIndexInRange(view, index);
2556
+ return view[index];
2557
+ }
2558
+ function getComponentLViewByIndex(nodeIndex, hostView) {
2559
+ // Could be an LView or an LContainer. If LContainer, unwrap to find LView.
2560
+ ngDevMode && assertIndexInRange(hostView, nodeIndex);
2561
+ const slotValue = hostView[nodeIndex];
2562
+ const lView = isLView(slotValue) ? slotValue : slotValue[HOST];
2563
+ return lView;
2564
+ }
2565
+ /** Checks whether a given view is in creation mode */
2566
+ function isCreationMode(view) {
2567
+ return (view[FLAGS] & 4 /* LViewFlags.CreationMode */) === 4 /* LViewFlags.CreationMode */;
2432
2568
  }
2433
2569
  /**
2434
- * Finalize this consumer's state after a reactive computation has run.
2570
+ * Returns a boolean for whether the view is attached to the change detection tree.
2435
2571
  *
2436
- * Must be called by subclasses which represent reactive computations, after those computations
2437
- * have finished.
2572
+ * Note: This determines whether a view should be checked, not whether it's inserted
2573
+ * into a container. For that, you'll want `viewAttachedToContainer` below.
2438
2574
  */
2439
- function consumerAfterComputation(node, prevConsumer) {
2440
- setActiveConsumer(prevConsumer);
2441
- if (!node || node.producerNode === undefined || node.producerIndexOfThis === undefined ||
2442
- node.producerLastReadVersion === undefined) {
2575
+ function viewAttachedToChangeDetector(view) {
2576
+ return (view[FLAGS] & 128 /* LViewFlags.Attached */) === 128 /* LViewFlags.Attached */;
2577
+ }
2578
+ /** Returns a boolean for whether the view is attached to a container. */
2579
+ function viewAttachedToContainer(view) {
2580
+ return isLContainer(view[PARENT]);
2581
+ }
2582
+ function getConstant(consts, index) {
2583
+ if (index === null || index === undefined)
2584
+ return null;
2585
+ ngDevMode && assertIndexInRange(consts, index);
2586
+ return consts[index];
2587
+ }
2588
+ /**
2589
+ * Resets the pre-order hook flags of the view.
2590
+ * @param lView the LView on which the flags are reset
2591
+ */
2592
+ function resetPreOrderHookFlags(lView) {
2593
+ lView[PREORDER_HOOK_FLAGS] = 0;
2594
+ }
2595
+ /**
2596
+ * Adds the `RefreshView` flag from the lView and updates HAS_CHILD_VIEWS_TO_REFRESH flag of
2597
+ * parents.
2598
+ */
2599
+ function markViewForRefresh(lView) {
2600
+ if (lView[FLAGS] & 1024 /* LViewFlags.RefreshView */) {
2443
2601
  return;
2444
2602
  }
2445
- if (consumerIsLive(node)) {
2446
- // For live consumers, we need to remove the producer -> consumer edge for any stale producers
2447
- // which weren't dependencies after the recomputation.
2448
- for (let i = node.nextProducerIndex; i < node.producerNode.length; i++) {
2449
- producerRemoveLiveConsumerAtIndex(node.producerNode[i], node.producerIndexOfThis[i]);
2450
- }
2451
- }
2452
- // Truncate the producer tracking arrays.
2453
- // Perf note: this is essentially truncating the length to `node.nextProducerIndex`, but
2454
- // benchmarking has shown that individual pop operations are faster.
2455
- while (node.producerNode.length > node.nextProducerIndex) {
2456
- node.producerNode.pop();
2457
- node.producerLastReadVersion.pop();
2458
- node.producerIndexOfThis.pop();
2603
+ lView[FLAGS] |= 1024 /* LViewFlags.RefreshView */;
2604
+ if (viewAttachedToChangeDetector(lView)) {
2605
+ markAncestorsForTraversal(lView);
2459
2606
  }
2460
2607
  }
2461
2608
  /**
2462
- * Determine whether this consumer has any dependencies which have changed since the last time
2463
- * they were read.
2609
+ * Walks up the LView hierarchy.
2610
+ * @param nestingLevel Number of times to walk up in hierarchy.
2611
+ * @param currentView View from which to start the lookup.
2464
2612
  */
2465
- function consumerPollProducersForChange(node) {
2466
- assertConsumerNode(node);
2467
- // Poll producers for change.
2468
- for (let i = 0; i < node.producerNode.length; i++) {
2469
- const producer = node.producerNode[i];
2470
- const seenVersion = node.producerLastReadVersion[i];
2471
- // First check the versions. A mismatch means that the producer's value is known to have
2472
- // changed since the last time we read it.
2473
- if (seenVersion !== producer.version) {
2474
- return true;
2475
- }
2476
- // The producer's version is the same as the last time we read it, but it might itself be
2477
- // stale. Force the producer to recompute its version (calculating a new value if necessary).
2478
- producerUpdateValueVersion(producer);
2479
- // Now when we do this check, `producer.version` is guaranteed to be up to date, so if the
2480
- // versions still match then it has not changed since the last time we read it.
2481
- if (seenVersion !== producer.version) {
2482
- return true;
2483
- }
2613
+ function walkUpViews(nestingLevel, currentView) {
2614
+ while (nestingLevel > 0) {
2615
+ ngDevMode &&
2616
+ assertDefined(currentView[DECLARATION_VIEW], 'Declaration view should be defined if nesting level is greater than 0.');
2617
+ currentView = currentView[DECLARATION_VIEW];
2618
+ nestingLevel--;
2484
2619
  }
2485
- return false;
2620
+ return currentView;
2486
2621
  }
2487
2622
  /**
2488
- * Disconnect this consumer from the graph.
2623
+ * Updates the `DESCENDANT_VIEWS_TO_REFRESH` counter on the parents of the `LView` as well as the
2624
+ * parents above that whose
2625
+ * 1. counter goes from 0 to 1, indicating that there is a new child that has a view to refresh
2626
+ * or
2627
+ * 2. counter goes from 1 to 0, indicating there are no more descendant views to refresh
2628
+ * When attaching/re-attaching an `LView` to the change detection tree, we need to ensure that the
2629
+ * views above it are traversed during change detection if this one is marked for refresh or has
2630
+ * some child or descendant that needs to be refreshed.
2489
2631
  */
2490
- function consumerDestroy(node) {
2491
- assertConsumerNode(node);
2492
- if (consumerIsLive(node)) {
2493
- // Drop all connections from the graph to this node.
2494
- for (let i = 0; i < node.producerNode.length; i++) {
2495
- producerRemoveLiveConsumerAtIndex(node.producerNode[i], node.producerIndexOfThis[i]);
2496
- }
2497
- }
2498
- // Truncate all the arrays to drop all connection from this node to the graph.
2499
- node.producerNode.length = node.producerLastReadVersion.length = node.producerIndexOfThis.length =
2500
- 0;
2501
- if (node.liveConsumerNode) {
2502
- node.liveConsumerNode.length = node.liveConsumerIndexOfThis.length = 0;
2632
+ function updateAncestorTraversalFlagsOnAttach(lView) {
2633
+ if (lView[FLAGS] & (1024 /* LViewFlags.RefreshView */ | 8192 /* LViewFlags.HasChildViewsToRefresh */)) {
2634
+ markAncestorsForTraversal(lView);
2503
2635
  }
2504
2636
  }
2505
2637
  /**
2506
- * Add `consumer` as a live consumer of this node.
2638
+ * Ensures views above the given `lView` are traversed during change detection even when they are
2639
+ * not dirty.
2507
2640
  *
2508
- * Note that this operation is potentially transitive. If this node becomes live, then it becomes
2509
- * a live consumer of all of its current producers.
2641
+ * This is done by setting the `HAS_CHILD_VIEWS_TO_REFRESH` flag up to the root, stopping when the
2642
+ * flag is already `true` or the `lView` is detached.
2510
2643
  */
2511
- function producerAddLiveConsumer(node, consumer, indexOfThis) {
2512
- assertProducerNode(node);
2513
- assertConsumerNode(node);
2514
- if (node.liveConsumerNode.length === 0) {
2515
- // When going from 0 to 1 live consumers, we become a live consumer to our producers.
2516
- for (let i = 0; i < node.producerNode.length; i++) {
2517
- node.producerIndexOfThis[i] = producerAddLiveConsumer(node.producerNode[i], node, i);
2644
+ function markAncestorsForTraversal(lView) {
2645
+ let parent = lView[PARENT];
2646
+ if (parent === null) {
2647
+ return;
2648
+ }
2649
+ while (parent !== null) {
2650
+ // We stop adding markers to the ancestors once we reach one that already has the marker. This
2651
+ // is to avoid needlessly traversing all the way to the root when the marker already exists.
2652
+ if ((isLContainer(parent) && parent[HAS_CHILD_VIEWS_TO_REFRESH] ||
2653
+ (isLView(parent) && parent[FLAGS] & 8192 /* LViewFlags.HasChildViewsToRefresh */))) {
2654
+ break;
2655
+ }
2656
+ if (isLContainer(parent)) {
2657
+ parent[HAS_CHILD_VIEWS_TO_REFRESH] = true;
2518
2658
  }
2519
- }
2520
- node.liveConsumerIndexOfThis.push(indexOfThis);
2521
- return node.liveConsumerNode.push(consumer) - 1;
2522
- }
2523
- /**
2524
- * Remove the live consumer at `idx`.
2525
- */
2526
- function producerRemoveLiveConsumerAtIndex(node, idx) {
2527
- assertProducerNode(node);
2528
- assertConsumerNode(node);
2529
- if (typeof ngDevMode !== 'undefined' && ngDevMode && idx >= node.liveConsumerNode.length) {
2530
- throw new Error(`Assertion error: active consumer index ${idx} is out of bounds of ${node.liveConsumerNode.length} consumers)`);
2531
- }
2532
- if (node.liveConsumerNode.length === 1) {
2533
- // When removing the last live consumer, we will no longer be live. We need to remove
2534
- // ourselves from our producers' tracking (which may cause consumer-producers to lose
2535
- // liveness as well).
2536
- for (let i = 0; i < node.producerNode.length; i++) {
2537
- producerRemoveLiveConsumerAtIndex(node.producerNode[i], node.producerIndexOfThis[i]);
2538
- }
2539
- }
2540
- // Move the last value of `liveConsumers` into `idx`. Note that if there's only a single
2541
- // live consumer, this is a no-op.
2542
- const lastIdx = node.liveConsumerNode.length - 1;
2543
- node.liveConsumerNode[idx] = node.liveConsumerNode[lastIdx];
2544
- node.liveConsumerIndexOfThis[idx] = node.liveConsumerIndexOfThis[lastIdx];
2545
- // Truncate the array.
2546
- node.liveConsumerNode.length--;
2547
- node.liveConsumerIndexOfThis.length--;
2548
- // If the index is still valid, then we need to fix the index pointer from the producer to this
2549
- // consumer, and update it from `lastIdx` to `idx` (accounting for the move above).
2550
- if (idx < node.liveConsumerNode.length) {
2551
- const idxProducer = node.liveConsumerIndexOfThis[idx];
2552
- const consumer = node.liveConsumerNode[idx];
2553
- assertConsumerNode(consumer);
2554
- consumer.producerIndexOfThis[idxProducer] = idx;
2555
- }
2556
- }
2557
- function consumerIsLive(node) {
2558
- return node.consumerIsAlwaysLive || (node?.liveConsumerNode?.length ?? 0) > 0;
2559
- }
2560
- function assertConsumerNode(node) {
2561
- node.producerNode ??= [];
2562
- node.producerIndexOfThis ??= [];
2563
- node.producerLastReadVersion ??= [];
2564
- }
2565
- function assertProducerNode(node) {
2566
- node.liveConsumerNode ??= [];
2567
- node.liveConsumerIndexOfThis ??= [];
2568
- }
2569
-
2570
- /**
2571
- * Create a computed `Signal` which derives a reactive value from an expression.
2572
- *
2573
- * @developerPreview
2574
- */
2575
- function computed(computation, options) {
2576
- const node = Object.create(COMPUTED_NODE);
2577
- node.computation = computation;
2578
- options?.equal && (node.equal = options.equal);
2579
- const computed = () => {
2580
- // Check if the value needs updating before returning it.
2581
- producerUpdateValueVersion(node);
2582
- // Record that someone looked at this signal.
2583
- producerAccessed(node);
2584
- if (node.value === ERRORED) {
2585
- throw node.error;
2586
- }
2587
- return node.value;
2588
- };
2589
- computed[SIGNAL] = node;
2590
- return computed;
2591
- }
2592
- /**
2593
- * A dedicated symbol used before a computed value has been calculated for the first time.
2594
- * Explicitly typed as `any` so we can use it as signal's value.
2595
- */
2596
- const UNSET = /* @__PURE__ */ Symbol('UNSET');
2597
- /**
2598
- * A dedicated symbol used in place of a computed signal value to indicate that a given computation
2599
- * is in progress. Used to detect cycles in computation chains.
2600
- * Explicitly typed as `any` so we can use it as signal's value.
2601
- */
2602
- const COMPUTING = /* @__PURE__ */ Symbol('COMPUTING');
2603
- /**
2604
- * A dedicated symbol used in place of a computed signal value to indicate that a given computation
2605
- * failed. The thrown error is cached until the computation gets dirty again.
2606
- * Explicitly typed as `any` so we can use it as signal's value.
2607
- */
2608
- const ERRORED = /* @__PURE__ */ Symbol('ERRORED');
2609
- // Note: Using an IIFE here to ensure that the spread assignment is not considered
2610
- // a side-effect, ending up preserving `COMPUTED_NODE` and `REACTIVE_NODE`.
2611
- // TODO: remove when https://github.com/evanw/esbuild/issues/3392 is resolved.
2612
- const COMPUTED_NODE = /* @__PURE__ */ (() => {
2613
- return {
2614
- ...REACTIVE_NODE,
2615
- value: UNSET,
2616
- dirty: true,
2617
- error: null,
2618
- equal: defaultEquals,
2619
- producerMustRecompute(node) {
2620
- // Force a recomputation if there's no current value, or if the current value is in the
2621
- // process of being calculated (which should throw an error).
2622
- return node.value === UNSET || node.value === COMPUTING;
2623
- },
2624
- producerRecomputeValue(node) {
2625
- if (node.value === COMPUTING) {
2626
- // Our computation somehow led to a cyclic read of itself.
2627
- throw new Error('Detected cycle in computations.');
2628
- }
2629
- const oldValue = node.value;
2630
- node.value = COMPUTING;
2631
- const prevConsumer = consumerBeforeComputation(node);
2632
- let newValue;
2633
- try {
2634
- newValue = node.computation();
2635
- }
2636
- catch (err) {
2637
- newValue = ERRORED;
2638
- node.error = err;
2639
- }
2640
- finally {
2641
- consumerAfterComputation(node, prevConsumer);
2642
- }
2643
- if (oldValue !== UNSET && oldValue !== ERRORED && newValue !== ERRORED &&
2644
- node.equal(oldValue, newValue)) {
2645
- // No change to `valueVersion` - old and new values are
2646
- // semantically equivalent.
2647
- node.value = oldValue;
2648
- return;
2649
- }
2650
- node.value = newValue;
2651
- node.version++;
2652
- },
2653
- };
2654
- })();
2655
-
2656
- function defaultThrowError() {
2657
- throw new Error();
2658
- }
2659
- let throwInvalidWriteToSignalErrorFn = defaultThrowError;
2660
- function throwInvalidWriteToSignalError() {
2661
- throwInvalidWriteToSignalErrorFn();
2662
- }
2663
- function setThrowInvalidWriteToSignalError(fn) {
2664
- throwInvalidWriteToSignalErrorFn = fn;
2665
- }
2666
-
2667
- /**
2668
- * If set, called after `WritableSignal`s are updated.
2669
- *
2670
- * This hook can be used to achieve various effects, such as running effects synchronously as part
2671
- * of setting a signal.
2672
- */
2673
- let postSignalSetFn = null;
2674
- /**
2675
- * Create a `Signal` that can be set or updated directly.
2676
- *
2677
- * @developerPreview
2678
- */
2679
- function signal(initialValue, options) {
2680
- const node = Object.create(SIGNAL_NODE);
2681
- node.value = initialValue;
2682
- options?.equal && (node.equal = options.equal);
2683
- function signalFn() {
2684
- producerAccessed(node);
2685
- return node.value;
2686
- }
2687
- signalFn.set = signalSetFn;
2688
- signalFn.update = signalUpdateFn;
2689
- signalFn.mutate = signalMutateFn;
2690
- signalFn.asReadonly = signalAsReadonlyFn;
2691
- signalFn[SIGNAL] = node;
2692
- return signalFn;
2693
- }
2694
- function setPostSignalSetFn(fn) {
2695
- const prev = postSignalSetFn;
2696
- postSignalSetFn = fn;
2697
- return prev;
2698
- }
2699
- // Note: Using an IIFE here to ensure that the spread assignment is not considered
2700
- // a side-effect, ending up preserving `COMPUTED_NODE` and `REACTIVE_NODE`.
2701
- // TODO: remove when https://github.com/evanw/esbuild/issues/3392 is resolved.
2702
- const SIGNAL_NODE = /* @__PURE__ */ (() => {
2703
- return {
2704
- ...REACTIVE_NODE,
2705
- equal: defaultEquals,
2706
- readonlyFn: undefined,
2707
- };
2708
- })();
2709
- function signalValueChanged(node) {
2710
- node.version++;
2711
- producerNotifyConsumers(node);
2712
- postSignalSetFn?.();
2713
- }
2714
- function signalSetFn(newValue) {
2715
- const node = this[SIGNAL];
2716
- if (!producerUpdatesAllowed()) {
2717
- throwInvalidWriteToSignalError();
2718
- }
2719
- if (!node.equal(node.value, newValue)) {
2720
- node.value = newValue;
2721
- signalValueChanged(node);
2722
- }
2723
- }
2724
- function signalUpdateFn(updater) {
2725
- if (!producerUpdatesAllowed()) {
2726
- throwInvalidWriteToSignalError();
2727
- }
2728
- signalSetFn.call(this, updater(this[SIGNAL].value));
2729
- }
2730
- function signalMutateFn(mutator) {
2731
- const node = this[SIGNAL];
2732
- if (!producerUpdatesAllowed()) {
2733
- throwInvalidWriteToSignalError();
2734
- }
2735
- // Mutate bypasses equality checks as it's by definition changing the value.
2736
- mutator(node.value);
2737
- signalValueChanged(node);
2738
- }
2739
- function signalAsReadonlyFn() {
2740
- const node = this[SIGNAL];
2741
- if (node.readonlyFn === undefined) {
2742
- const readonlyFn = () => this();
2743
- readonlyFn[SIGNAL] = node;
2744
- node.readonlyFn = readonlyFn;
2745
- }
2746
- return node.readonlyFn;
2747
- }
2748
-
2749
- /**
2750
- * Execute an arbitrary function in a non-reactive (non-tracking) context. The executed function
2751
- * can, optionally, return a value.
2752
- *
2753
- * @developerPreview
2754
- */
2755
- function untracked(nonReactiveReadsFn) {
2756
- const prevConsumer = setActiveConsumer(null);
2757
- // We are not trying to catch any particular errors here, just making sure that the consumers
2758
- // stack is restored in case of errors.
2759
- try {
2760
- return nonReactiveReadsFn();
2761
- }
2762
- finally {
2763
- setActiveConsumer(prevConsumer);
2764
- }
2765
- }
2766
-
2767
- function watch(fn, schedule, allowSignalWrites) {
2768
- const node = Object.create(WATCH_NODE);
2769
- if (allowSignalWrites) {
2770
- node.consumerAllowSignalWrites = true;
2771
- }
2772
- node.fn = fn;
2773
- node.schedule = schedule;
2774
- const registerOnCleanup = (cleanupFn) => {
2775
- node.cleanupFn = cleanupFn;
2776
- };
2777
- function isWatchNodeDestroyed(node) {
2778
- return node.fn === null && node.schedule === null;
2779
- }
2780
- function destroyWatchNode(node) {
2781
- if (!isWatchNodeDestroyed(node)) {
2782
- consumerDestroy(node); // disconnect watcher from the reactive graph
2783
- node.cleanupFn();
2784
- // nullify references to the integration functions to mark node as destroyed
2785
- node.fn = null;
2786
- node.schedule = null;
2787
- node.cleanupFn = NOOP_CLEANUP_FN;
2788
- }
2789
- }
2790
- const run = () => {
2791
- if (node.fn === null) {
2792
- // trying to run a destroyed watch is noop
2793
- return;
2794
- }
2795
- if (isInNotificationPhase()) {
2796
- throw new Error(`Schedulers cannot synchronously execute watches while scheduling.`);
2797
- }
2798
- node.dirty = false;
2799
- if (node.hasRun && !consumerPollProducersForChange(node)) {
2800
- return;
2801
- }
2802
- node.hasRun = true;
2803
- const prevConsumer = consumerBeforeComputation(node);
2804
- try {
2805
- node.cleanupFn();
2806
- node.cleanupFn = NOOP_CLEANUP_FN;
2807
- node.fn(registerOnCleanup);
2808
- }
2809
- finally {
2810
- consumerAfterComputation(node, prevConsumer);
2811
- }
2812
- };
2813
- node.ref = {
2814
- notify: () => consumerMarkDirty(node),
2815
- run,
2816
- cleanup: () => node.cleanupFn(),
2817
- destroy: () => destroyWatchNode(node),
2818
- };
2819
- return node.ref;
2820
- }
2821
- const NOOP_CLEANUP_FN = () => { };
2822
- // Note: Using an IIFE here to ensure that the spread assignment is not considered
2823
- // a side-effect, ending up preserving `COMPUTED_NODE` and `REACTIVE_NODE`.
2824
- // TODO: remove when https://github.com/evanw/esbuild/issues/3392 is resolved.
2825
- const WATCH_NODE = /* @__PURE__ */ (() => {
2826
- return {
2827
- ...REACTIVE_NODE,
2828
- consumerIsAlwaysLive: true,
2829
- consumerAllowSignalWrites: false,
2830
- consumerMarkedDirty: (node) => {
2831
- if (node.schedule !== null) {
2832
- node.schedule(node.ref);
2833
- }
2834
- },
2835
- hasRun: false,
2836
- cleanupFn: NOOP_CLEANUP_FN,
2837
- };
2838
- })();
2839
-
2840
- function setAlternateWeakRefImpl(impl) {
2841
- // TODO: remove this function
2842
- }
2843
-
2844
- /**
2845
- * Represents a basic change from a previous to a new value for a single
2846
- * property on a directive instance. Passed as a value in a
2847
- * {@link SimpleChanges} object to the `ngOnChanges` hook.
2848
- *
2849
- * @see {@link OnChanges}
2850
- *
2851
- * @publicApi
2852
- */
2853
- class SimpleChange {
2854
- constructor(previousValue, currentValue, firstChange) {
2855
- this.previousValue = previousValue;
2856
- this.currentValue = currentValue;
2857
- this.firstChange = firstChange;
2858
- }
2859
- /**
2860
- * Check whether the new value is the first value assigned.
2861
- */
2862
- isFirstChange() {
2863
- return this.firstChange;
2864
- }
2865
- }
2866
-
2867
- /**
2868
- * The NgOnChangesFeature decorates a component with support for the ngOnChanges
2869
- * lifecycle hook, so it should be included in any component that implements
2870
- * that hook.
2871
- *
2872
- * If the component or directive uses inheritance, the NgOnChangesFeature MUST
2873
- * be included as a feature AFTER {@link InheritDefinitionFeature}, otherwise
2874
- * inherited properties will not be propagated to the ngOnChanges lifecycle
2875
- * hook.
2876
- *
2877
- * Example usage:
2878
- *
2879
- * ```
2880
- * static ɵcmp = defineComponent({
2881
- * ...
2882
- * inputs: {name: 'publicName'},
2883
- * features: [NgOnChangesFeature]
2884
- * });
2885
- * ```
2886
- *
2887
- * @codeGenApi
2888
- */
2889
- function ɵɵNgOnChangesFeature() {
2890
- return NgOnChangesFeatureImpl;
2891
- }
2892
- function NgOnChangesFeatureImpl(definition) {
2893
- if (definition.type.prototype.ngOnChanges) {
2894
- definition.setInput = ngOnChangesSetInput;
2895
- }
2896
- return rememberChangeHistoryAndInvokeOnChangesHook;
2897
- }
2898
- // This option ensures that the ngOnChanges lifecycle hook will be inherited
2899
- // from superclasses (in InheritDefinitionFeature).
2900
- /** @nocollapse */
2901
- // tslint:disable-next-line:no-toplevel-property-access
2902
- ɵɵNgOnChangesFeature.ngInherit = true;
2903
- /**
2904
- * This is a synthetic lifecycle hook which gets inserted into `TView.preOrderHooks` to simulate
2905
- * `ngOnChanges`.
2906
- *
2907
- * The hook reads the `NgSimpleChangesStore` data from the component instance and if changes are
2908
- * found it invokes `ngOnChanges` on the component instance.
2909
- *
2910
- * @param this Component instance. Because this function gets inserted into `TView.preOrderHooks`,
2911
- * it is guaranteed to be called with component instance.
2912
- */
2913
- function rememberChangeHistoryAndInvokeOnChangesHook() {
2914
- const simpleChangesStore = getSimpleChangesStore(this);
2915
- const current = simpleChangesStore?.current;
2916
- if (current) {
2917
- const previous = simpleChangesStore.previous;
2918
- if (previous === EMPTY_OBJ) {
2919
- simpleChangesStore.previous = current;
2920
- }
2921
- else {
2922
- // New changes are copied to the previous store, so that we don't lose history for inputs
2923
- // which were not changed this time
2924
- for (let key in current) {
2925
- previous[key] = current[key];
2926
- }
2927
- }
2928
- simpleChangesStore.current = null;
2929
- this.ngOnChanges(current);
2930
- }
2931
- }
2932
- function ngOnChangesSetInput(instance, value, publicName, privateName) {
2933
- const declaredName = this.declaredInputs[publicName];
2934
- ngDevMode && assertString(declaredName, 'Name of input in ngOnChanges has to be a string');
2935
- const simpleChangesStore = getSimpleChangesStore(instance) ||
2936
- setSimpleChangesStore(instance, { previous: EMPTY_OBJ, current: null });
2937
- const current = simpleChangesStore.current || (simpleChangesStore.current = {});
2938
- const previous = simpleChangesStore.previous;
2939
- const previousChange = previous[declaredName];
2940
- current[declaredName] = new SimpleChange(previousChange && previousChange.currentValue, value, previous === EMPTY_OBJ);
2941
- instance[privateName] = value;
2942
- }
2943
- const SIMPLE_CHANGES_STORE = '__ngSimpleChanges__';
2944
- function getSimpleChangesStore(instance) {
2945
- return instance[SIMPLE_CHANGES_STORE] || null;
2946
- }
2947
- function setSimpleChangesStore(instance, store) {
2948
- return instance[SIMPLE_CHANGES_STORE] = store;
2949
- }
2950
-
2951
- let profilerCallback = null;
2952
- /**
2953
- * Sets the callback function which will be invoked before and after performing certain actions at
2954
- * runtime (for example, before and after running change detection).
2955
- *
2956
- * Warning: this function is *INTERNAL* and should not be relied upon in application's code.
2957
- * The contract of the function might be changed in any release and/or the function can be removed
2958
- * completely.
2959
- *
2960
- * @param profiler function provided by the caller or null value to disable profiling.
2961
- */
2962
- const setProfiler = (profiler) => {
2963
- profilerCallback = profiler;
2964
- };
2965
- /**
2966
- * Profiler function which wraps user code executed by the runtime.
2967
- *
2968
- * @param event ProfilerEvent corresponding to the execution context
2969
- * @param instance component instance
2970
- * @param hookOrListener lifecycle hook function or output listener. The value depends on the
2971
- * execution context
2972
- * @returns
2973
- */
2974
- const profiler = function (event, instance, hookOrListener) {
2975
- if (profilerCallback != null /* both `null` and `undefined` */) {
2976
- profilerCallback(event, instance, hookOrListener);
2977
- }
2978
- };
2979
-
2980
- const SVG_NAMESPACE = 'svg';
2981
- const MATH_ML_NAMESPACE = 'math';
2982
-
2983
- /**
2984
- * For efficiency reasons we often put several different data types (`RNode`, `LView`, `LContainer`)
2985
- * in same location in `LView`. This is because we don't want to pre-allocate space for it
2986
- * because the storage is sparse. This file contains utilities for dealing with such data types.
2987
- *
2988
- * How do we know what is stored at a given location in `LView`.
2989
- * - `Array.isArray(value) === false` => `RNode` (The normal storage value)
2990
- * - `Array.isArray(value) === true` => then the `value[0]` represents the wrapped value.
2991
- * - `typeof value[TYPE] === 'object'` => `LView`
2992
- * - This happens when we have a component at a given location
2993
- * - `typeof value[TYPE] === true` => `LContainer`
2994
- * - This happens when we have `LContainer` binding at a given location.
2995
- *
2996
- *
2997
- * NOTE: it is assumed that `Array.isArray` and `typeof` operations are very efficient.
2998
- */
2999
- /**
3000
- * Returns `RNode`.
3001
- * @param value wrapped value of `RNode`, `LView`, `LContainer`
3002
- */
3003
- function unwrapRNode(value) {
3004
- while (Array.isArray(value)) {
3005
- value = value[HOST];
3006
- }
3007
- return value;
3008
- }
3009
- /**
3010
- * Returns `LView` or `null` if not found.
3011
- * @param value wrapped value of `RNode`, `LView`, `LContainer`
3012
- */
3013
- function unwrapLView(value) {
3014
- while (Array.isArray(value)) {
3015
- // This check is same as `isLView()` but we don't call at as we don't want to call
3016
- // `Array.isArray()` twice and give JITer more work for inlining.
3017
- if (typeof value[TYPE] === 'object')
3018
- return value;
3019
- value = value[HOST];
3020
- }
3021
- return null;
3022
- }
3023
- /**
3024
- * Retrieves an element value from the provided `viewData`, by unwrapping
3025
- * from any containers, component views, or style contexts.
3026
- */
3027
- function getNativeByIndex(index, lView) {
3028
- ngDevMode && assertIndexInRange(lView, index);
3029
- ngDevMode && assertGreaterThanOrEqual(index, HEADER_OFFSET, 'Expected to be past HEADER_OFFSET');
3030
- return unwrapRNode(lView[index]);
3031
- }
3032
- /**
3033
- * Retrieve an `RNode` for a given `TNode` and `LView`.
3034
- *
3035
- * This function guarantees in dev mode to retrieve a non-null `RNode`.
3036
- *
3037
- * @param tNode
3038
- * @param lView
3039
- */
3040
- function getNativeByTNode(tNode, lView) {
3041
- ngDevMode && assertTNodeForLView(tNode, lView);
3042
- ngDevMode && assertIndexInRange(lView, tNode.index);
3043
- const node = unwrapRNode(lView[tNode.index]);
3044
- return node;
3045
- }
3046
- /**
3047
- * Retrieve an `RNode` or `null` for a given `TNode` and `LView`.
3048
- *
3049
- * Some `TNode`s don't have associated `RNode`s. For example `Projection`
3050
- *
3051
- * @param tNode
3052
- * @param lView
3053
- */
3054
- function getNativeByTNodeOrNull(tNode, lView) {
3055
- const index = tNode === null ? -1 : tNode.index;
3056
- if (index !== -1) {
3057
- ngDevMode && assertTNodeForLView(tNode, lView);
3058
- const node = unwrapRNode(lView[index]);
3059
- return node;
3060
- }
3061
- return null;
3062
- }
3063
- // fixme(misko): The return Type should be `TNode|null`
3064
- function getTNode(tView, index) {
3065
- ngDevMode && assertGreaterThan(index, -1, 'wrong index for TNode');
3066
- ngDevMode && assertLessThan(index, tView.data.length, 'wrong index for TNode');
3067
- const tNode = tView.data[index];
3068
- ngDevMode && tNode !== null && assertTNode(tNode);
3069
- return tNode;
3070
- }
3071
- /** Retrieves a value from any `LView` or `TData`. */
3072
- function load(view, index) {
3073
- ngDevMode && assertIndexInRange(view, index);
3074
- return view[index];
3075
- }
3076
- function getComponentLViewByIndex(nodeIndex, hostView) {
3077
- // Could be an LView or an LContainer. If LContainer, unwrap to find LView.
3078
- ngDevMode && assertIndexInRange(hostView, nodeIndex);
3079
- const slotValue = hostView[nodeIndex];
3080
- const lView = isLView(slotValue) ? slotValue : slotValue[HOST];
3081
- return lView;
3082
- }
3083
- /** Checks whether a given view is in creation mode */
3084
- function isCreationMode(view) {
3085
- return (view[FLAGS] & 4 /* LViewFlags.CreationMode */) === 4 /* LViewFlags.CreationMode */;
3086
- }
3087
- /**
3088
- * Returns a boolean for whether the view is attached to the change detection tree.
3089
- *
3090
- * Note: This determines whether a view should be checked, not whether it's inserted
3091
- * into a container. For that, you'll want `viewAttachedToContainer` below.
3092
- */
3093
- function viewAttachedToChangeDetector(view) {
3094
- return (view[FLAGS] & 128 /* LViewFlags.Attached */) === 128 /* LViewFlags.Attached */;
3095
- }
3096
- /** Returns a boolean for whether the view is attached to a container. */
3097
- function viewAttachedToContainer(view) {
3098
- return isLContainer(view[PARENT]);
3099
- }
3100
- function getConstant(consts, index) {
3101
- if (index === null || index === undefined)
3102
- return null;
3103
- ngDevMode && assertIndexInRange(consts, index);
3104
- return consts[index];
3105
- }
3106
- /**
3107
- * Resets the pre-order hook flags of the view.
3108
- * @param lView the LView on which the flags are reset
3109
- */
3110
- function resetPreOrderHookFlags(lView) {
3111
- lView[PREORDER_HOOK_FLAGS] = 0;
3112
- }
3113
- /**
3114
- * Adds the `RefreshView` flag from the lView and updates DESCENDANT_VIEWS_TO_REFRESH counters of
3115
- * parents.
3116
- */
3117
- function markViewForRefresh(lView) {
3118
- if ((lView[FLAGS] & 1024 /* LViewFlags.RefreshView */) === 0) {
3119
- lView[FLAGS] |= 1024 /* LViewFlags.RefreshView */;
3120
- updateViewsToRefresh(lView, 1);
3121
- }
3122
- }
3123
- /**
3124
- * Removes the `RefreshView` flag from the lView and updates DESCENDANT_VIEWS_TO_REFRESH counters of
3125
- * parents.
3126
- */
3127
- function clearViewRefreshFlag(lView) {
3128
- if (lView[FLAGS] & 1024 /* LViewFlags.RefreshView */) {
3129
- lView[FLAGS] &= ~1024 /* LViewFlags.RefreshView */;
3130
- updateViewsToRefresh(lView, -1);
3131
- }
3132
- }
3133
- /**
3134
- * Walks up the LView hierarchy.
3135
- * @param nestingLevel Number of times to walk up in hierarchy.
3136
- * @param currentView View from which to start the lookup.
3137
- */
3138
- function walkUpViews(nestingLevel, currentView) {
3139
- while (nestingLevel > 0) {
3140
- ngDevMode &&
3141
- assertDefined(currentView[DECLARATION_VIEW], 'Declaration view should be defined if nesting level is greater than 0.');
3142
- currentView = currentView[DECLARATION_VIEW];
3143
- nestingLevel--;
3144
- }
3145
- return currentView;
3146
- }
3147
- /**
3148
- * Updates the `DESCENDANT_VIEWS_TO_REFRESH` counter on the parents of the `LView` as well as the
3149
- * parents above that whose
3150
- * 1. counter goes from 0 to 1, indicating that there is a new child that has a view to refresh
3151
- * or
3152
- * 2. counter goes from 1 to 0, indicating there are no more descendant views to refresh
3153
- */
3154
- function updateViewsToRefresh(lView, amount) {
3155
- let parent = lView[PARENT];
3156
- if (parent === null) {
3157
- return;
3158
- }
3159
- parent[DESCENDANT_VIEWS_TO_REFRESH] += amount;
3160
- let viewOrContainer = parent;
3161
- parent = parent[PARENT];
3162
- while (parent !== null &&
3163
- ((amount === 1 && viewOrContainer[DESCENDANT_VIEWS_TO_REFRESH] === 1) ||
3164
- (amount === -1 && viewOrContainer[DESCENDANT_VIEWS_TO_REFRESH] === 0))) {
3165
- parent[DESCENDANT_VIEWS_TO_REFRESH] += amount;
3166
- viewOrContainer = parent;
3167
- parent = parent[PARENT];
2659
+ else {
2660
+ parent[FLAGS] |= 8192 /* LViewFlags.HasChildViewsToRefresh */;
2661
+ if (!viewAttachedToChangeDetector(parent)) {
2662
+ break;
2663
+ }
2664
+ }
2665
+ parent = parent[PARENT];
3168
2666
  }
3169
2667
  }
3170
2668
  /**
@@ -3863,7 +3361,7 @@ function incrementInitPhaseFlags(lView, initPhase) {
3863
3361
  assertNotEqual(initPhase, 3 /* InitPhaseState.InitPhaseCompleted */, 'Init hooks phase should not be incremented after all init hooks have been run.');
3864
3362
  let flags = lView[FLAGS];
3865
3363
  if ((flags & 3 /* LViewFlags.InitPhaseStateMask */) === initPhase) {
3866
- flags &= 8191 /* LViewFlags.IndexWithinInitPhaseReset */;
3364
+ flags &= 16383 /* LViewFlags.IndexWithinInitPhaseReset */;
3867
3365
  flags += 1 /* LViewFlags.InitPhaseStateIncrementer */;
3868
3366
  lView[FLAGS] = flags;
3869
3367
  }
@@ -3921,12 +3419,12 @@ function callHooks(currentView, arr, initPhase, currentNodeIndex) {
3921
3419
  */
3922
3420
  function callHookInternal(directive, hook) {
3923
3421
  profiler(4 /* ProfilerEvent.LifecycleHookStart */, directive, hook);
3924
- const prevConsumer = setActiveConsumer(null);
3422
+ const prevConsumer = setActiveConsumer$1(null);
3925
3423
  try {
3926
3424
  hook.call(directive);
3927
3425
  }
3928
3426
  finally {
3929
- setActiveConsumer(prevConsumer);
3427
+ setActiveConsumer$1(prevConsumer);
3930
3428
  profiler(5 /* ProfilerEvent.LifecycleHookEnd */, directive, hook);
3931
3429
  }
3932
3430
  }
@@ -3944,12 +3442,12 @@ function callHook(currentView, initPhase, arr, i) {
3944
3442
  const directiveIndex = isInitHook ? -arr[i] : arr[i];
3945
3443
  const directive = currentView[directiveIndex];
3946
3444
  if (isInitHook) {
3947
- const indexWithintInitPhase = currentView[FLAGS] >> 13 /* LViewFlags.IndexWithinInitPhaseShift */;
3445
+ const indexWithintInitPhase = currentView[FLAGS] >> 14 /* LViewFlags.IndexWithinInitPhaseShift */;
3948
3446
  // The init phase state must be always checked here as it may have been recursively updated.
3949
3447
  if (indexWithintInitPhase <
3950
3448
  (currentView[PREORDER_HOOK_FLAGS] >> 16 /* PreOrderHookFlags.NumberOfInitHooksCalledShift */) &&
3951
3449
  (currentView[FLAGS] & 3 /* LViewFlags.InitPhaseStateMask */) === initPhase) {
3952
- currentView[FLAGS] += 8192 /* LViewFlags.IndexWithinInitPhaseIncrementer */;
3450
+ currentView[FLAGS] += 16384 /* LViewFlags.IndexWithinInitPhaseIncrementer */;
3953
3451
  callHookInternal(directive, hook);
3954
3452
  }
3955
3453
  }
@@ -7261,6 +6759,21 @@ const ENABLED_SSR_FEATURES = new InjectionToken((typeof ngDevMode === 'undefined
7261
6759
  providedIn: 'root',
7262
6760
  factory: () => new Set(),
7263
6761
  });
6762
+ const IMAGE_CONFIG_DEFAULTS = {
6763
+ breakpoints: [16, 32, 48, 64, 96, 128, 256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840],
6764
+ disableImageSizeWarning: false,
6765
+ disableImageLazyLoadWarning: false,
6766
+ };
6767
+ /**
6768
+ * Injection token that configures the image optimized image functionality.
6769
+ * See {@link ImageConfig} for additional information about parameters that
6770
+ * can be used.
6771
+ *
6772
+ * @see {@link NgOptimizedImage}
6773
+ * @see {@link ImageConfig}
6774
+ * @publicApi
6775
+ */
6776
+ const IMAGE_CONFIG = new InjectionToken('ImageConfig', { providedIn: 'root', factory: () => IMAGE_CONFIG_DEFAULTS });
7264
6777
 
7265
6778
  /**
7266
6779
  *
@@ -7379,7 +6892,9 @@ class DepsTracker {
7379
6892
  }
7380
6893
  else {
7381
6894
  if (!this.ownerNgModule.has(type)) {
7382
- throw new RuntimeError(1001 /* RuntimeErrorCode.RUNTIME_DEPS_ORPHAN_COMPONENT */, `Orphan component found! Trying to render the component ${type.name} without first loading the NgModule that declares it. Make sure that you import the component's NgModule in the NgModule or the standalone component in which you are trying to render this component. Also make sure the way the app is bundled and served always includes the component's NgModule before the component.`);
6895
+ // This component is orphan! No need to handle the error since the component rendering
6896
+ // pipeline (e.g., view_container_ref) will check for this error based on configs.
6897
+ return { dependencies: [] };
7383
6898
  }
7384
6899
  const scope = this.getNgModuleScope(this.ownerNgModule.get(type));
7385
6900
  if (scope.compilation.isPoisoned) {
@@ -7552,6 +7067,15 @@ class DepsTracker {
7552
7067
  }
7553
7068
  return ans;
7554
7069
  }
7070
+ /** @override */
7071
+ isOrphanComponent(cmp) {
7072
+ const def = getComponentDef(cmp);
7073
+ if (!def || def.standalone) {
7074
+ return false;
7075
+ }
7076
+ this.resolveNgModulesDecls();
7077
+ return !this.ownerNgModule.has(cmp);
7078
+ }
7555
7079
  }
7556
7080
  function addSet(sourceSet, targetSet) {
7557
7081
  for (const m of sourceSet) {
@@ -8654,6 +8178,7 @@ function insertView(tView, lView, lContainer, index) {
8654
8178
  if (lQueries !== null) {
8655
8179
  lQueries.insertView(tView);
8656
8180
  }
8181
+ updateAncestorTraversalFlagsOnAttach(lView);
8657
8182
  // Sets the attached flag
8658
8183
  lView[FLAGS] |= 128 /* LViewFlags.Attached */;
8659
8184
  }
@@ -8692,9 +8217,6 @@ function detachMovedView(declarationContainer, lView) {
8692
8217
  const declarationViewIndex = movedViews.indexOf(lView);
8693
8218
  const insertionLContainer = lView[PARENT];
8694
8219
  ngDevMode && assertLContainer(insertionLContainer);
8695
- // If the view was marked for refresh but then detached before it was checked (where the flag
8696
- // would be cleared and the counter decremented), we need to update the status here.
8697
- clearViewRefreshFlag(lView);
8698
8220
  movedViews.splice(declarationViewIndex, 1);
8699
8221
  }
8700
8222
  /**
@@ -8744,8 +8266,8 @@ function detachView(lContainer, removeIndex) {
8744
8266
  function destroyLView(tView, lView) {
8745
8267
  if (!(lView[FLAGS] & 256 /* LViewFlags.Destroyed */)) {
8746
8268
  const renderer = lView[RENDERER];
8747
- lView[REACTIVE_TEMPLATE_CONSUMER] && consumerDestroy(lView[REACTIVE_TEMPLATE_CONSUMER]);
8748
- lView[REACTIVE_HOST_BINDING_CONSUMER] && consumerDestroy(lView[REACTIVE_HOST_BINDING_CONSUMER]);
8269
+ lView[REACTIVE_TEMPLATE_CONSUMER] && consumerDestroy$1(lView[REACTIVE_TEMPLATE_CONSUMER]);
8270
+ lView[REACTIVE_HOST_BINDING_CONSUMER] && consumerDestroy$1(lView[REACTIVE_HOST_BINDING_CONSUMER]);
8749
8271
  if (renderer.destroyNode) {
8750
8272
  applyView(tView, lView, renderer, 3 /* WalkTNodeTreeAction.Destroy */, null, null);
8751
8273
  }
@@ -10907,7 +10429,7 @@ class Version {
10907
10429
  /**
10908
10430
  * @publicApi
10909
10431
  */
10910
- const VERSION = new Version('17.0.0-next.7');
10432
+ const VERSION = new Version('17.0.0-next.8');
10911
10433
 
10912
10434
  // This default value is when checking the hierarchy for a token.
10913
10435
  //
@@ -10928,6 +10450,64 @@ const VERSION = new Version('17.0.0-next.7');
10928
10450
  // - mod2.injector.get(token, default)
10929
10451
  const NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR = {};
10930
10452
 
10453
+ /**
10454
+ * Checks if the given `value` is a reactive `Signal`.
10455
+ */
10456
+ function isSignal(value) {
10457
+ return typeof value === 'function' && value[SIGNAL$1] !== undefined;
10458
+ }
10459
+
10460
+ /**
10461
+ * Create a computed `Signal` which derives a reactive value from an expression.
10462
+ */
10463
+ function computed(computation, options) {
10464
+ const getter = createComputed$1(computation);
10465
+ if (options?.equal) {
10466
+ getter[SIGNAL$1].equal = options.equal;
10467
+ }
10468
+ return getter;
10469
+ }
10470
+
10471
+ /**
10472
+ * Create a `Signal` that can be set or updated directly.
10473
+ */
10474
+ function signal(initialValue, options) {
10475
+ const signalFn = createSignal$1(initialValue);
10476
+ const node = signalFn[SIGNAL$1];
10477
+ if (options?.equal) {
10478
+ node.equal = options.equal;
10479
+ }
10480
+ signalFn.set = (newValue) => signalSetFn$1(node, newValue);
10481
+ signalFn.update = (updateFn) => signalUpdateFn$1(node, updateFn);
10482
+ signalFn.asReadonly = signalAsReadonlyFn.bind(signalFn);
10483
+ return signalFn;
10484
+ }
10485
+ function signalAsReadonlyFn() {
10486
+ const node = this[SIGNAL$1];
10487
+ if (node.readonlyFn === undefined) {
10488
+ const readonlyFn = () => this();
10489
+ readonlyFn[SIGNAL$1] = node;
10490
+ node.readonlyFn = readonlyFn;
10491
+ }
10492
+ return node.readonlyFn;
10493
+ }
10494
+
10495
+ /**
10496
+ * Execute an arbitrary function in a non-reactive (non-tracking) context. The executed function
10497
+ * can, optionally, return a value.
10498
+ */
10499
+ function untracked(nonReactiveReadsFn) {
10500
+ const prevConsumer = setActiveConsumer$1(null);
10501
+ // We are not trying to catch any particular errors here, just making sure that the consumers
10502
+ // stack is restored in case of errors.
10503
+ try {
10504
+ return nonReactiveReadsFn();
10505
+ }
10506
+ finally {
10507
+ setActiveConsumer$1(prevConsumer);
10508
+ }
10509
+ }
10510
+
10931
10511
  const ERROR_ORIGINAL_ERROR = 'ngOriginalError';
10932
10512
  function wrappedError(message, originalError) {
10933
10513
  const msg = `${message} caused by: ${originalError instanceof Error ? originalError.message : originalError}`;
@@ -11022,6 +10602,183 @@ function injectDestroyRef() {
11022
10602
  return new NodeInjectorDestroyRef(getLView());
11023
10603
  }
11024
10604
 
10605
+ /**
10606
+ * Asserts that the current stack frame is not within a reactive context. Useful
10607
+ * to disallow certain code from running inside a reactive context (see {@link toSignal}).
10608
+ *
10609
+ * @param debugFn a reference to the function making the assertion (used for the error message).
10610
+ *
10611
+ * @publicApi
10612
+ */
10613
+ function assertNotInReactiveContext(debugFn, extraContext) {
10614
+ // Taking a `Function` instead of a string name here prevents the un-minified name of the function
10615
+ // from being retained in the bundle regardless of minification.
10616
+ if (getActiveConsumer$1() !== null) {
10617
+ throw new RuntimeError(-602 /* RuntimeErrorCode.ASSERTION_NOT_INSIDE_REACTIVE_CONTEXT */, ngDevMode &&
10618
+ `${debugFn.name}() cannot be called from within a reactive context.${extraContext ? ` ${extraContext}` : ''}`);
10619
+ }
10620
+ }
10621
+
10622
+ /**
10623
+ * Not public API, which guarantees `EffectScheduler` only ever comes from the application root
10624
+ * injector.
10625
+ */
10626
+ const APP_EFFECT_SCHEDULER = new InjectionToken('', {
10627
+ providedIn: 'root',
10628
+ factory: () => inject(EffectScheduler),
10629
+ });
10630
+ /**
10631
+ * A scheduler which manages the execution of effects.
10632
+ */
10633
+ class EffectScheduler {
10634
+ /** @nocollapse */
10635
+ static { this.ɵprov = ɵɵdefineInjectable({
10636
+ token: EffectScheduler,
10637
+ providedIn: 'root',
10638
+ factory: () => new ZoneAwareMicrotaskScheduler(),
10639
+ }); }
10640
+ }
10641
+ /**
10642
+ * An `EffectScheduler` which is capable of queueing scheduled effects per-zone, and flushing them
10643
+ * as an explicit operation.
10644
+ */
10645
+ class ZoneAwareQueueingScheduler {
10646
+ constructor() {
10647
+ this.queuedEffectCount = 0;
10648
+ this.queues = new Map();
10649
+ }
10650
+ scheduleEffect(handle) {
10651
+ const zone = handle.creationZone;
10652
+ if (!this.queues.has(zone)) {
10653
+ this.queues.set(zone, new Set());
10654
+ }
10655
+ const queue = this.queues.get(zone);
10656
+ if (queue.has(handle)) {
10657
+ return;
10658
+ }
10659
+ this.queuedEffectCount++;
10660
+ queue.add(handle);
10661
+ }
10662
+ /**
10663
+ * Run all scheduled effects.
10664
+ *
10665
+ * Execution order of effects within the same zone is guaranteed to be FIFO, but there is no
10666
+ * ordering guarantee between effects scheduled in different zones.
10667
+ */
10668
+ flush() {
10669
+ while (this.queuedEffectCount > 0) {
10670
+ for (const [zone, queue] of this.queues) {
10671
+ // `zone` here must be defined.
10672
+ if (zone === null) {
10673
+ this.flushQueue(queue);
10674
+ }
10675
+ else {
10676
+ zone.run(() => this.flushQueue(queue));
10677
+ }
10678
+ }
10679
+ }
10680
+ }
10681
+ flushQueue(queue) {
10682
+ for (const handle of queue) {
10683
+ queue.delete(handle);
10684
+ this.queuedEffectCount--;
10685
+ // TODO: what happens if this throws an error?
10686
+ handle.run();
10687
+ }
10688
+ }
10689
+ /** @nocollapse */
10690
+ static { this.ɵprov = ɵɵdefineInjectable({
10691
+ token: ZoneAwareQueueingScheduler,
10692
+ providedIn: 'root',
10693
+ factory: () => new ZoneAwareQueueingScheduler(),
10694
+ }); }
10695
+ }
10696
+ /**
10697
+ * A wrapper around `ZoneAwareQueueingScheduler` that schedules flushing via the microtask queue
10698
+ * when.
10699
+ */
10700
+ class ZoneAwareMicrotaskScheduler {
10701
+ constructor() {
10702
+ this.hasQueuedFlush = false;
10703
+ this.delegate = new ZoneAwareQueueingScheduler();
10704
+ this.flushTask = () => {
10705
+ // Leave `hasQueuedFlush` as `true` so we don't queue another microtask if more effects are
10706
+ // scheduled during flushing. The flush of the `ZoneAwareQueueingScheduler` delegate is
10707
+ // guaranteed to empty the queue.
10708
+ this.delegate.flush();
10709
+ this.hasQueuedFlush = false;
10710
+ // This is a variable initialization, not a method.
10711
+ // tslint:disable-next-line:semicolon
10712
+ };
10713
+ }
10714
+ scheduleEffect(handle) {
10715
+ this.delegate.scheduleEffect(handle);
10716
+ if (!this.hasQueuedFlush) {
10717
+ queueMicrotask(this.flushTask);
10718
+ this.hasQueuedFlush = true;
10719
+ }
10720
+ }
10721
+ }
10722
+ /**
10723
+ * Core reactive node for an Angular effect.
10724
+ *
10725
+ * `EffectHandle` combines the reactive graph's `Watch` base node for effects with the framework's
10726
+ * scheduling abstraction (`EffectScheduler`) as well as automatic cleanup via `DestroyRef` if
10727
+ * available/requested.
10728
+ */
10729
+ class EffectHandle {
10730
+ constructor(scheduler, effectFn, creationZone, destroyRef, errorHandler, allowSignalWrites) {
10731
+ this.scheduler = scheduler;
10732
+ this.effectFn = effectFn;
10733
+ this.creationZone = creationZone;
10734
+ this.errorHandler = errorHandler;
10735
+ this.watcher = createWatch$1((onCleanup) => this.runEffect(onCleanup), () => this.schedule(), allowSignalWrites);
10736
+ this.unregisterOnDestroy = destroyRef?.onDestroy(() => this.destroy());
10737
+ }
10738
+ runEffect(onCleanup) {
10739
+ try {
10740
+ this.effectFn(onCleanup);
10741
+ }
10742
+ catch (err) {
10743
+ this.errorHandler?.handleError(err);
10744
+ }
10745
+ }
10746
+ run() {
10747
+ this.watcher.run();
10748
+ }
10749
+ schedule() {
10750
+ this.scheduler.scheduleEffect(this);
10751
+ }
10752
+ notify() {
10753
+ this.watcher.notify();
10754
+ }
10755
+ destroy() {
10756
+ this.watcher.destroy();
10757
+ this.unregisterOnDestroy?.();
10758
+ // Note: if the effect is currently scheduled, it's not un-scheduled, and so the scheduler will
10759
+ // retain a reference to it. Attempting to execute it will be a no-op.
10760
+ }
10761
+ }
10762
+ /**
10763
+ * Create a global `Effect` for the given reactive function.
10764
+ */
10765
+ function effect(effectFn, options) {
10766
+ ngDevMode &&
10767
+ assertNotInReactiveContext(effect, 'Call `effect` outside of a reactive context. For example, schedule the ' +
10768
+ 'effect inside the component constructor.');
10769
+ !options?.injector && assertInInjectionContext(effect);
10770
+ const injector = options?.injector ?? inject(Injector);
10771
+ const errorHandler = injector.get(ErrorHandler, null, { optional: true });
10772
+ const destroyRef = options?.manualCleanup !== true ? injector.get(DestroyRef) : null;
10773
+ const handle = new EffectHandle(injector.get(APP_EFFECT_SCHEDULER), effectFn, (typeof Zone === 'undefined') ? null : Zone.current, destroyRef, errorHandler, options?.allowSignalWrites ?? false);
10774
+ // Effects start dirty.
10775
+ handle.notify();
10776
+ return handle;
10777
+ }
10778
+
10779
+ // clang-format off
10780
+ // clang-format on
10781
+
11025
10782
  /// <reference types="rxjs" />
11026
10783
  class EventEmitter_ extends Subject {
11027
10784
  constructor(isAsync = false) {
@@ -11702,6 +11459,9 @@ var AfterRenderPhase;
11702
11459
  * @developerPreview
11703
11460
  */
11704
11461
  function afterRender(callback, options) {
11462
+ ngDevMode &&
11463
+ assertNotInReactiveContext(afterRender, 'Call `afterRender` outside of a reactive context. For example, schedule the render ' +
11464
+ 'callback inside the component constructor`.');
11705
11465
  !options && assertInInjectionContext(afterRender);
11706
11466
  const injector = options?.injector ?? inject(Injector);
11707
11467
  if (!isPlatformBrowser(injector)) {
@@ -12113,7 +11873,7 @@ function commitLViewConsumerIfHasProducers(lView, slot) {
12113
11873
  currentConsumer = createLViewConsumer();
12114
11874
  }
12115
11875
  const REACTIVE_LVIEW_CONSUMER_NODE = {
12116
- ...REACTIVE_NODE,
11876
+ ...REACTIVE_NODE$1,
12117
11877
  consumerIsAlwaysLive: true,
12118
11878
  consumerMarkedDirty: (node) => {
12119
11879
  (typeof ngDevMode === 'undefined' || ngDevMode) &&
@@ -12245,13 +12005,13 @@ function processHostBindingOpCodes(tView, lView) {
12245
12005
  const hostBindingFn = hostBindingOpCodes[++i];
12246
12006
  setBindingRootForHostBindings(bindingRootIndx, directiveIdx);
12247
12007
  consumer.dirty = false;
12248
- const prevConsumer = consumerBeforeComputation(consumer);
12008
+ const prevConsumer = consumerBeforeComputation$1(consumer);
12249
12009
  try {
12250
12010
  const context = lView[directiveIdx];
12251
12011
  hostBindingFn(2 /* RenderFlags.Update */, context);
12252
12012
  }
12253
12013
  finally {
12254
- consumerAfterComputation(consumer, prevConsumer);
12014
+ consumerAfterComputation$1(consumer, prevConsumer);
12255
12015
  }
12256
12016
  }
12257
12017
  }
@@ -12393,7 +12153,7 @@ function executeTemplate(tView, lView, templateFn, rf, context) {
12393
12153
  const preHookType = isUpdatePhase ? 2 /* ProfilerEvent.TemplateUpdateStart */ : 0 /* ProfilerEvent.TemplateCreateStart */;
12394
12154
  profiler(preHookType, context);
12395
12155
  const effectiveConsumer = isUpdatePhase ? consumer : null;
12396
- const prevConsumer = consumerBeforeComputation(effectiveConsumer);
12156
+ const prevConsumer = consumerBeforeComputation$1(effectiveConsumer);
12397
12157
  try {
12398
12158
  if (effectiveConsumer !== null) {
12399
12159
  effectiveConsumer.dirty = false;
@@ -12401,7 +12161,7 @@ function executeTemplate(tView, lView, templateFn, rf, context) {
12401
12161
  templateFn(rf, context);
12402
12162
  }
12403
12163
  finally {
12404
- consumerAfterComputation(effectiveConsumer, prevConsumer);
12164
+ consumerAfterComputation$1(effectiveConsumer, prevConsumer);
12405
12165
  }
12406
12166
  }
12407
12167
  finally {
@@ -12418,7 +12178,7 @@ function executeTemplate(tView, lView, templateFn, rf, context) {
12418
12178
  //////////////////////////
12419
12179
  function executeContentQueries(tView, tNode, lView) {
12420
12180
  if (isContentQueryHost(tNode)) {
12421
- const prevConsumer = setActiveConsumer(null);
12181
+ const prevConsumer = setActiveConsumer$1(null);
12422
12182
  try {
12423
12183
  const start = tNode.directiveStart;
12424
12184
  const end = tNode.directiveEnd;
@@ -12430,7 +12190,7 @@ function executeContentQueries(tView, tNode, lView) {
12430
12190
  }
12431
12191
  }
12432
12192
  finally {
12433
- setActiveConsumer(prevConsumer);
12193
+ setActiveConsumer$1(prevConsumer);
12434
12194
  }
12435
12195
  }
12436
12196
  }
@@ -13128,6 +12888,7 @@ function findDirectiveDefMatches(tView, tNode) {
13128
12888
  }
13129
12889
  }
13130
12890
  }
12891
+ ngDevMode && matches !== null && assertNoDuplicateDirectives(matches);
13131
12892
  return matches === null ? null : [matches, hostDirectiveDefs];
13132
12893
  }
13133
12894
  /**
@@ -13274,7 +13035,7 @@ function setInputsFromAttrs(lView, directiveIndex, instance, def, tNode, initial
13274
13035
  }
13275
13036
  }
13276
13037
  function writeToDirectiveInput(def, instance, publicName, privateName, value) {
13277
- const prevConsumer = setActiveConsumer(null);
13038
+ const prevConsumer = setActiveConsumer$1(null);
13278
13039
  try {
13279
13040
  const inputTransforms = def.inputTransforms;
13280
13041
  if (inputTransforms !== null && inputTransforms.hasOwnProperty(privateName)) {
@@ -13288,7 +13049,7 @@ function writeToDirectiveInput(def, instance, publicName, privateName, value) {
13288
13049
  }
13289
13050
  }
13290
13051
  finally {
13291
- setActiveConsumer(prevConsumer);
13052
+ setActiveConsumer$1(prevConsumer);
13292
13053
  }
13293
13054
  }
13294
13055
  /**
@@ -13364,8 +13125,8 @@ function createLContainer(hostNative, currentView, native, tNode) {
13364
13125
  false,
13365
13126
  currentView,
13366
13127
  null,
13367
- 0,
13368
13128
  tNode,
13129
+ false,
13369
13130
  native,
13370
13131
  null,
13371
13132
  null,
@@ -13424,12 +13185,12 @@ function addToViewTree(lView, lViewOrLContainer) {
13424
13185
  function executeViewQueryFn(flags, viewQueryFn, component) {
13425
13186
  ngDevMode && assertDefined(viewQueryFn, 'View queries function to execute must be defined.');
13426
13187
  setCurrentQueryIndex(0);
13427
- const prevConsumer = setActiveConsumer(null);
13188
+ const prevConsumer = setActiveConsumer$1(null);
13428
13189
  try {
13429
13190
  viewQueryFn(flags, component);
13430
13191
  }
13431
13192
  finally {
13432
- setActiveConsumer(prevConsumer);
13193
+ setActiveConsumer$1(prevConsumer);
13433
13194
  }
13434
13195
  }
13435
13196
  ///////////////////////////////
@@ -13919,7 +13680,15 @@ function refreshView(tView, lView, templateFn, context) {
13919
13680
  if (!isInCheckNoChangesPass) {
13920
13681
  lView[FLAGS] &= ~(64 /* LViewFlags.Dirty */ | 8 /* LViewFlags.FirstLViewPass */);
13921
13682
  }
13922
- clearViewRefreshFlag(lView);
13683
+ lView[FLAGS] &= ~1024 /* LViewFlags.RefreshView */;
13684
+ }
13685
+ catch (e) {
13686
+ // If refreshing a view causes an error, we need to remark the ancestors as needing traversal
13687
+ // because the error might have caused a situation where views below the current location are
13688
+ // dirty but will be unreachable because the "has dirty children" flag in the ancestors has been
13689
+ // cleared during change detection and we failed to run to completion.
13690
+ markAncestorsForTraversal(lView);
13691
+ throw e;
13923
13692
  }
13924
13693
  finally {
13925
13694
  leaveView();
@@ -13931,9 +13700,10 @@ function refreshView(tView, lView, templateFn, context) {
13931
13700
  */
13932
13701
  function detectChangesInEmbeddedViews(lView, mode) {
13933
13702
  for (let lContainer = getFirstLContainer(lView); lContainer !== null; lContainer = getNextLContainer(lContainer)) {
13703
+ lContainer[HAS_CHILD_VIEWS_TO_REFRESH] = false;
13934
13704
  for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
13935
13705
  const embeddedLView = lContainer[i];
13936
- detectChangesInView(embeddedLView, mode);
13706
+ detectChangesInViewIfAttached(embeddedLView, mode);
13937
13707
  }
13938
13708
  }
13939
13709
  }
@@ -13965,33 +13735,41 @@ function markTransplantedViewsForRefresh(lView) {
13965
13735
  function detectChangesInComponent(hostLView, componentHostIdx, mode) {
13966
13736
  ngDevMode && assertEqual(isCreationMode(hostLView), false, 'Should be run in update mode');
13967
13737
  const componentView = getComponentLViewByIndex(componentHostIdx, hostLView);
13968
- detectChangesInView(componentView, mode);
13738
+ detectChangesInViewIfAttached(componentView, mode);
13969
13739
  }
13970
13740
  /**
13971
13741
  * Visits a view as part of change detection traversal.
13972
13742
  *
13973
- * - If the view is detached, no additional traversal happens.
13743
+ * If the view is detached, no additional traversal happens.
13744
+ */
13745
+ function detectChangesInViewIfAttached(lView, mode) {
13746
+ if (!viewAttachedToChangeDetector(lView)) {
13747
+ return;
13748
+ }
13749
+ detectChangesInView(lView, mode);
13750
+ }
13751
+ /**
13752
+ * Visits a view as part of change detection traversal.
13974
13753
  *
13975
13754
  * The view is refreshed if:
13976
13755
  * - If the view is CheckAlways or Dirty and ChangeDetectionMode is `Global`
13977
13756
  * - If the view has the `RefreshTransplantedView` flag
13978
13757
  *
13979
13758
  * The view is not refreshed, but descendants are traversed in `ChangeDetectionMode.Targeted` if the
13980
- * view has a non-zero TRANSPLANTED_VIEWS_TO_REFRESH counter.
13981
- *
13759
+ * view HasChildViewsToRefresh flag is set.
13982
13760
  */
13983
13761
  function detectChangesInView(lView, mode) {
13984
- if (!viewAttachedToChangeDetector(lView)) {
13985
- return;
13986
- }
13987
13762
  const tView = lView[TVIEW];
13988
13763
  const flags = lView[FLAGS];
13764
+ // Flag cleared before change detection runs so that the view can be re-marked for traversal if
13765
+ // necessary.
13766
+ lView[FLAGS] &= ~8192 /* LViewFlags.HasChildViewsToRefresh */;
13989
13767
  if ((flags & (16 /* LViewFlags.CheckAlways */ | 64 /* LViewFlags.Dirty */) &&
13990
13768
  mode === 0 /* ChangeDetectionMode.Global */) ||
13991
13769
  flags & 1024 /* LViewFlags.RefreshView */) {
13992
13770
  refreshView(tView, lView, tView.template, lView[CONTEXT]);
13993
13771
  }
13994
- else if (lView[DESCENDANT_VIEWS_TO_REFRESH] > 0) {
13772
+ else if (flags & 8192 /* LViewFlags.HasChildViewsToRefresh */) {
13995
13773
  detectChangesInEmbeddedViews(lView, 1 /* ChangeDetectionMode.Targeted */);
13996
13774
  const components = tView.components;
13997
13775
  if (components !== null) {
@@ -14226,6 +14004,7 @@ class ViewRef$1 {
14226
14004
  * ```
14227
14005
  */
14228
14006
  reattach() {
14007
+ updateAncestorTraversalFlagsOnAttach(this._lView);
14229
14008
  this._lView[FLAGS] |= 128 /* LViewFlags.Attached */;
14230
14009
  }
14231
14010
  /**
@@ -14392,6 +14171,13 @@ class ComponentFactory extends ComponentFactory$1 {
14392
14171
  this.isBoundToModule = !!ngModule;
14393
14172
  }
14394
14173
  create(injector, projectableNodes, rootSelectorOrNode, environmentInjector) {
14174
+ // Check if the component is orphan
14175
+ if (ngDevMode && (typeof ngJitMode === 'undefined' || ngJitMode) &&
14176
+ this.componentDef.debugInfo?.forbidOrphanRendering) {
14177
+ if (depsTracker.isOrphanComponent(this.componentType)) {
14178
+ throw new RuntimeError(1001 /* RuntimeErrorCode.RUNTIME_DEPS_ORPHAN_COMPONENT */, `Orphan component found! Trying to render the component ${debugStringifyTypeForError(this.componentType)} without first loading the NgModule that declares it. It is recommended to make this component standalone in order to avoid this error. If this is not possible now, import the component's NgModule in the appropriate NgModule, or the standalone component in which you are trying to render this component. If this is a lazy import, load the NgModule lazily as well and use its module injector.`);
14179
+ }
14180
+ }
14395
14181
  environmentInjector = environmentInjector || this.ngModule;
14396
14182
  let realEnvironmentInjector = environmentInjector instanceof EnvironmentInjector ?
14397
14183
  environmentInjector :
@@ -14454,6 +14240,7 @@ class ComponentFactory extends ComponentFactory$1 {
14454
14240
  hostDirectiveDefs = new Map();
14455
14241
  rootComponentDef.findHostDirectiveDefs(rootComponentDef, rootDirectives, hostDirectiveDefs);
14456
14242
  rootDirectives.push(rootComponentDef);
14243
+ ngDevMode && assertNoDuplicateDirectives(rootDirectives);
14457
14244
  }
14458
14245
  else {
14459
14246
  rootDirectives = [rootComponentDef];
@@ -14952,7 +14739,7 @@ function findHostDirectiveDefs(currentDef, matchedDefs, hostDirectiveDefs) {
14952
14739
  for (const hostDirectiveConfig of currentDef.hostDirectives) {
14953
14740
  const hostDirectiveDef = getDirectiveDef(hostDirectiveConfig.directive);
14954
14741
  if (typeof ngDevMode === 'undefined' || ngDevMode) {
14955
- validateHostDirective(hostDirectiveConfig, hostDirectiveDef, matchedDefs);
14742
+ validateHostDirective(hostDirectiveConfig, hostDirectiveDef);
14956
14743
  }
14957
14744
  // We need to patch the `declaredInputs` so that
14958
14745
  // `ngOnChanges` can map the properties correctly.
@@ -15018,9 +14805,8 @@ function patchDeclaredInputs(declaredInputs, exposedInputs) {
15018
14805
  * Verifies that the host directive has been configured correctly.
15019
14806
  * @param hostDirectiveConfig Host directive configuration object.
15020
14807
  * @param directiveDef Directive definition of the host directive.
15021
- * @param matchedDefs Directives that have been matched so far.
15022
14808
  */
15023
- function validateHostDirective(hostDirectiveConfig, directiveDef, matchedDefs) {
14809
+ function validateHostDirective(hostDirectiveConfig, directiveDef) {
15024
14810
  const type = hostDirectiveConfig.directive;
15025
14811
  if (directiveDef === null) {
15026
14812
  if (getComponentDef(type) !== null) {
@@ -15032,10 +14818,6 @@ function validateHostDirective(hostDirectiveConfig, directiveDef, matchedDefs) {
15032
14818
  if (!directiveDef.standalone) {
15033
14819
  throw new RuntimeError(308 /* RuntimeErrorCode.HOST_DIRECTIVE_NOT_STANDALONE */, `Host directive ${directiveDef.type.name} must be standalone.`);
15034
14820
  }
15035
- if (matchedDefs.indexOf(directiveDef) > -1) {
15036
- throw new RuntimeError(309 /* RuntimeErrorCode.DUPLICATE_DIRECTITVE */, `Directive ${directiveDef.type.name} matches multiple times on the same element. ` +
15037
- `Directives can only match an element once.`);
15038
- }
15039
14821
  validateMappings('input', directiveDef, hostDirectiveConfig.inputs);
15040
14822
  validateMappings('output', directiveDef, hostDirectiveConfig.outputs);
15041
14823
  }
@@ -19421,6 +19203,12 @@ class LiveCollectionLContainerImpl extends LiveCollection {
19421
19203
  this.hostLView = hostLView;
19422
19204
  this.templateTNode = templateTNode;
19423
19205
  this.trackByFn = trackByFn;
19206
+ /**
19207
+ Property indicating if indexes in the repeater context need to be updated following the live
19208
+ collection changes. Index updates are necessary if and only if views are inserted / removed in
19209
+ the middle of LContainer. Adds and removals at the end don't require index updates.
19210
+ */
19211
+ this.needsIndexUpdate = false;
19424
19212
  }
19425
19213
  get length() {
19426
19214
  return this.lContainer.length - CONTAINER_HEADER_OFFSET;
@@ -19433,9 +19221,11 @@ class LiveCollectionLContainerImpl extends LiveCollection {
19433
19221
  }
19434
19222
  attach(index, lView) {
19435
19223
  const dehydratedView = lView[HYDRATION];
19224
+ this.needsIndexUpdate ||= index !== this.length;
19436
19225
  addLViewToLContainer(this.lContainer, lView, index, shouldAddViewToDom(this.templateTNode, dehydratedView));
19437
19226
  }
19438
19227
  detach(index) {
19228
+ this.needsIndexUpdate ||= index !== this.length - 1;
19439
19229
  return detachExistingView(this.lContainer, index);
19440
19230
  }
19441
19231
  create(index, value) {
@@ -19449,6 +19239,13 @@ class LiveCollectionLContainerImpl extends LiveCollection {
19449
19239
  updateValue(index, value) {
19450
19240
  this.at(index)[CONTEXT].$implicit = value;
19451
19241
  }
19242
+ updateIndexes() {
19243
+ if (this.needsIndexUpdate) {
19244
+ for (let i = 0; i < this.length; i++) {
19245
+ this.at(i)[CONTEXT].$index = i;
19246
+ }
19247
+ }
19248
+ }
19452
19249
  }
19453
19250
  /**
19454
19251
  * The repeater instruction does update-time diffing of a provided collection (against the
@@ -19467,19 +19264,13 @@ function ɵɵrepeater(metadataSlotIdx, collection) {
19467
19264
  const containerIndex = metadataSlotIdx + 1;
19468
19265
  const lContainer = getLContainer(hostLView, HEADER_OFFSET + containerIndex);
19469
19266
  const itemTemplateTNode = getExistingTNode(hostTView, containerIndex);
19470
- reconcile(new LiveCollectionLContainerImpl(lContainer, hostLView, itemTemplateTNode, metadata.trackByFn), collection, metadata.trackByFn);
19471
- // moves in the container might caused context's index to get out of order, re-adjust
19472
- // PERF: we could try to book-keep moves and do this index re-adjust as need, at the cost of the
19473
- // additional code complexity
19474
- for (let i = 0; i < lContainer.length - CONTAINER_HEADER_OFFSET; i++) {
19475
- const lView = getExistingLViewFromLContainer(lContainer, i);
19476
- lView[CONTEXT].$index = i;
19477
- }
19267
+ const liveCollection = new LiveCollectionLContainerImpl(lContainer, hostLView, itemTemplateTNode, metadata.trackByFn);
19268
+ reconcile(liveCollection, collection, metadata.trackByFn);
19269
+ // moves in the container might caused context's index to get out of order, re-adjust if needed
19270
+ liveCollection.updateIndexes();
19478
19271
  // handle empty blocks
19479
- // PERF: maybe I could skip allocation of memory for the empty block? Isn't it the "fix" on the
19480
- // compiler side that we've been discussing? Talk to K & D!
19481
- const bindingIndex = nextBindingIndex();
19482
19272
  if (metadata.hasEmptyBlock) {
19273
+ const bindingIndex = nextBindingIndex();
19483
19274
  const isCollectionEmpty = lContainer.length - CONTAINER_HEADER_OFFSET === 0;
19484
19275
  if (bindingUpdated(hostLView, bindingIndex, isCollectionEmpty)) {
19485
19276
  const emptyTemplateIndex = metadataSlotIdx + 2;
@@ -19531,6 +19322,10 @@ var DeferDependenciesLoadingState;
19531
19322
  /** Dependency loading has failed */
19532
19323
  DeferDependenciesLoadingState[DeferDependenciesLoadingState["FAILED"] = 3] = "FAILED";
19533
19324
  })(DeferDependenciesLoadingState || (DeferDependenciesLoadingState = {}));
19325
+ /** Slot index where `minimum` parameter value is stored. */
19326
+ const MINIMUM_SLOT = 0;
19327
+ /** Slot index where `after` parameter value is stored. */
19328
+ const LOADING_AFTER_SLOT = 1;
19534
19329
  /**
19535
19330
  * Describes the current state of this defer block instance.
19536
19331
  *
@@ -19559,11 +19354,14 @@ var DeferBlockInternalState;
19559
19354
  /** Initial state. Nothing is rendered yet. */
19560
19355
  DeferBlockInternalState[DeferBlockInternalState["Initial"] = -1] = "Initial";
19561
19356
  })(DeferBlockInternalState || (DeferBlockInternalState = {}));
19562
- /**
19563
- * A slot in the `LDeferBlockDetails` array that contains a number
19564
- * that represent a current block state that is being rendered.
19565
- */
19566
- const DEFER_BLOCK_STATE = 0;
19357
+ const NEXT_DEFER_BLOCK_STATE = 0;
19358
+ // Note: it's *important* to keep the state in this slot, because this slot
19359
+ // is used by runtime logic to differentiate between LViews, LContainers and
19360
+ // other types (see `isLView` and `isLContainer` functions). In case of defer
19361
+ // blocks, this slot would always be a number.
19362
+ const DEFER_BLOCK_STATE = 1;
19363
+ const STATE_IS_FROZEN_UNTIL = 2;
19364
+ const LOADING_AFTER_CLEANUP_FN = 3;
19567
19365
  /**
19568
19366
  * Options for configuring defer blocks behavior.
19569
19367
  * @publicApi
@@ -19600,6 +19398,8 @@ const hoverTriggers = new WeakMap();
19600
19398
  const interactionTriggers = new WeakMap();
19601
19399
  /** Names of the events considered as interaction events. */
19602
19400
  const interactionEventNames = ['click', 'keydown'];
19401
+ /** Names of the events considered as hover events. */
19402
+ const hoverEventNames = ['mouseenter', 'focusin'];
19603
19403
  /** Object keeping track of registered callbacks for a deferred block trigger. */
19604
19404
  class DeferEventEntry {
19605
19405
  constructor() {
@@ -19669,7 +19469,9 @@ function onHover(trigger, callback, injector) {
19669
19469
  // Ensure that the handler runs in the NgZone since it gets
19670
19470
  // registered in `afterRender` which runs outside.
19671
19471
  injector.get(NgZone).run(() => {
19672
- trigger.addEventListener('mouseenter', entry.listener, eventListenerOptions);
19472
+ for (const name of hoverEventNames) {
19473
+ trigger.addEventListener(name, entry.listener, eventListenerOptions);
19474
+ }
19673
19475
  });
19674
19476
  }
19675
19477
  entry.callbacks.add(callback);
@@ -19677,7 +19479,9 @@ function onHover(trigger, callback, injector) {
19677
19479
  const { callbacks, listener } = entry;
19678
19480
  callbacks.delete(callback);
19679
19481
  if (callbacks.size === 0) {
19680
- trigger.removeEventListener('mouseenter', listener, eventListenerOptions);
19482
+ for (const name of hoverEventNames) {
19483
+ trigger.removeEventListener(name, listener, eventListenerOptions);
19484
+ }
19681
19485
  hoverTriggers.delete(trigger);
19682
19486
  }
19683
19487
  };
@@ -19730,6 +19534,10 @@ class DeferIntersectionManager {
19730
19534
  }
19731
19535
  entry.callbacks.add(callback);
19732
19536
  return () => {
19537
+ // It's possible that a different cleanup callback fully removed this element already.
19538
+ if (!this.viewportTriggers.has(trigger)) {
19539
+ return;
19540
+ }
19733
19541
  entry.callbacks.delete(callback);
19734
19542
  if (entry.callbacks.size === 0) {
19735
19543
  this.intersectionObserver?.unobserve(trigger);
@@ -19757,6 +19565,33 @@ function shouldTriggerDeferBlock(injector) {
19757
19565
  }
19758
19566
  return isPlatformBrowser(injector);
19759
19567
  }
19568
+ /**
19569
+ * Reference to the timer-based scheduler implementation of defer block state
19570
+ * rendering method. It's used to make timer-based scheduling tree-shakable.
19571
+ * If `minimum` or `after` parameters are used, compiler generates an extra
19572
+ * argument for the `ɵɵdefer` instruction, which references a timer-based
19573
+ * implementation.
19574
+ */
19575
+ let applyDeferBlockStateWithSchedulingImpl = null;
19576
+ /**
19577
+ * Enables timer-related scheduling if `after` or `minimum` parameters are setup
19578
+ * on the `@loading` or `@placeholder` blocks.
19579
+ */
19580
+ function ɵɵdeferEnableTimerScheduling(tView, tDetails, placeholderConfigIndex, loadingConfigIndex) {
19581
+ const tViewConsts = tView.consts;
19582
+ if (placeholderConfigIndex != null) {
19583
+ tDetails.placeholderBlockConfig =
19584
+ getConstant(tViewConsts, placeholderConfigIndex);
19585
+ }
19586
+ if (loadingConfigIndex != null) {
19587
+ tDetails.loadingBlockConfig =
19588
+ getConstant(tViewConsts, loadingConfigIndex);
19589
+ }
19590
+ // Enable implementation that supports timer-based scheduling.
19591
+ if (applyDeferBlockStateWithSchedulingImpl === null) {
19592
+ applyDeferBlockStateWithSchedulingImpl = applyDeferBlockStateWithScheduling;
19593
+ }
19594
+ }
19760
19595
  /**
19761
19596
  * Creates runtime data structures for defer blocks.
19762
19597
  *
@@ -19770,32 +19605,30 @@ function shouldTriggerDeferBlock(injector) {
19770
19605
  * block.
19771
19606
  * @param placeholderConfigIndex Index in the constants array of the configuration of the
19772
19607
  * placeholder block.
19608
+ * @param enableTimerScheduling Function that enables timer-related scheduling if `after`
19609
+ * or `minimum` parameters are setup on the `@loading` or `@placeholder` blocks.
19773
19610
  *
19774
19611
  * @codeGenApi
19775
19612
  */
19776
- function ɵɵdefer(index, primaryTmplIndex, dependencyResolverFn, loadingTmplIndex, placeholderTmplIndex, errorTmplIndex, loadingConfigIndex, placeholderConfigIndex) {
19613
+ function ɵɵdefer(index, primaryTmplIndex, dependencyResolverFn, loadingTmplIndex, placeholderTmplIndex, errorTmplIndex, loadingConfigIndex, placeholderConfigIndex, enableTimerScheduling) {
19777
19614
  const lView = getLView();
19778
19615
  const tView = getTView();
19779
- const tViewConsts = tView.consts;
19780
19616
  const adjustedIndex = index + HEADER_OFFSET;
19781
19617
  ɵɵtemplate(index, null, 0, 0);
19782
19618
  if (tView.firstCreatePass) {
19783
- const deferBlockConfig = {
19619
+ const tDetails = {
19784
19620
  primaryTmplIndex,
19785
19621
  loadingTmplIndex: loadingTmplIndex ?? null,
19786
19622
  placeholderTmplIndex: placeholderTmplIndex ?? null,
19787
19623
  errorTmplIndex: errorTmplIndex ?? null,
19788
- placeholderBlockConfig: placeholderConfigIndex != null ?
19789
- getConstant(tViewConsts, placeholderConfigIndex) :
19790
- null,
19791
- loadingBlockConfig: loadingConfigIndex != null ?
19792
- getConstant(tViewConsts, loadingConfigIndex) :
19793
- null,
19624
+ placeholderBlockConfig: null,
19625
+ loadingBlockConfig: null,
19794
19626
  dependencyResolverFn: dependencyResolverFn ?? null,
19795
19627
  loadingState: DeferDependenciesLoadingState.NOT_STARTED,
19796
19628
  loadingPromise: null,
19797
19629
  };
19798
- setTDeferBlockDetails(tView, adjustedIndex, deferBlockConfig);
19630
+ enableTimerScheduling?.(tView, tDetails, placeholderConfigIndex, loadingConfigIndex);
19631
+ setTDeferBlockDetails(tView, adjustedIndex, tDetails);
19799
19632
  }
19800
19633
  const tNode = getCurrentTNode();
19801
19634
  const lContainer = lView[adjustedIndex];
@@ -19804,8 +19637,12 @@ function ɵɵdefer(index, primaryTmplIndex, dependencyResolverFn, loadingTmplInd
19804
19637
  // In client-only mode, this function is a noop.
19805
19638
  populateDehydratedViewsInLContainer(lContainer, tNode, lView);
19806
19639
  // Init instance-specific defer details and store it.
19807
- const lDetails = [];
19808
- lDetails[DEFER_BLOCK_STATE] = DeferBlockInternalState.Initial;
19640
+ const lDetails = [
19641
+ null,
19642
+ DeferBlockInternalState.Initial,
19643
+ null,
19644
+ null // LOADING_AFTER_CLEANUP_FN
19645
+ ];
19809
19646
  setLDeferBlockDetails(lView, adjustedIndex, lDetails);
19810
19647
  }
19811
19648
  /**
@@ -20231,6 +20068,24 @@ function getTemplateIndexForState(newState, hostLView, tNode) {
20231
20068
  return null;
20232
20069
  }
20233
20070
  }
20071
+ /**
20072
+ * Returns a minimum amount of time that a given state should be rendered for,
20073
+ * taking into account `minimum` parameter value. If the `minimum` value is
20074
+ * not specified - returns `null`.
20075
+ */
20076
+ function getMinimumDurationForState(tDetails, currentState) {
20077
+ if (currentState === DeferBlockState.Placeholder) {
20078
+ return tDetails.placeholderBlockConfig?.[MINIMUM_SLOT] ?? null;
20079
+ }
20080
+ else if (currentState === DeferBlockState.Loading) {
20081
+ return tDetails.loadingBlockConfig?.[MINIMUM_SLOT] ?? null;
20082
+ }
20083
+ return null;
20084
+ }
20085
+ /** Retrieves the value of the `after` parameter on the @loading block. */
20086
+ function getLoadingBlockAfter(tDetails) {
20087
+ return tDetails.loadingBlockConfig?.[LOADING_AFTER_SLOT] ?? null;
20088
+ }
20234
20089
  /**
20235
20090
  * Transitions a defer block to the new state. Updates the necessary
20236
20091
  * data structures and renders corresponding block.
@@ -20241,6 +20096,7 @@ function getTemplateIndexForState(newState, hostLView, tNode) {
20241
20096
  */
20242
20097
  function renderDeferBlockState(newState, tNode, lContainer) {
20243
20098
  const hostLView = lContainer[PARENT];
20099
+ const hostTView = hostLView[TVIEW];
20244
20100
  // Check if this view is not destroyed. Since the loading process was async,
20245
20101
  // the view might end up being destroyed by the time rendering happens.
20246
20102
  if (isDestroyed(hostLView))
@@ -20249,12 +20105,26 @@ function renderDeferBlockState(newState, tNode, lContainer) {
20249
20105
  ngDevMode && assertTNodeForLView(tNode, hostLView);
20250
20106
  const lDetails = getLDeferBlockDetails(hostLView, tNode);
20251
20107
  ngDevMode && assertDefined(lDetails, 'Expected a defer block state defined');
20108
+ const currentState = lDetails[DEFER_BLOCK_STATE];
20109
+ if (isValidStateChange(currentState, newState) &&
20110
+ isValidStateChange(lDetails[NEXT_DEFER_BLOCK_STATE] ?? -1, newState)) {
20111
+ const tDetails = getTDeferBlockDetails(hostTView, tNode);
20112
+ const needsScheduling = getLoadingBlockAfter(tDetails) !== null ||
20113
+ getMinimumDurationForState(tDetails, DeferBlockState.Loading) !== null ||
20114
+ getMinimumDurationForState(tDetails, DeferBlockState.Placeholder);
20115
+ if (ngDevMode && needsScheduling) {
20116
+ assertDefined(applyDeferBlockStateWithSchedulingImpl, 'Expected scheduling function to be defined');
20117
+ }
20118
+ const applyStateFn = needsScheduling ? applyDeferBlockStateWithSchedulingImpl : applyDeferBlockState;
20119
+ applyStateFn(newState, lDetails, lContainer, tNode, hostLView);
20120
+ }
20121
+ }
20122
+ /**
20123
+ * Applies changes to the DOM to reflect a given state.
20124
+ */
20125
+ function applyDeferBlockState(newState, lDetails, lContainer, tNode, hostLView) {
20252
20126
  const stateTmplIndex = getTemplateIndexForState(newState, hostLView, tNode);
20253
- // Note: we transition to the next state if the previous state was represented
20254
- // with a number that is less than the next state. For example, if the current
20255
- // state is "loading" (represented as `2`), we should not show a placeholder
20256
- // (represented as `1`).
20257
- if (lDetails[DEFER_BLOCK_STATE] < newState && stateTmplIndex !== null) {
20127
+ if (stateTmplIndex !== null) {
20258
20128
  lDetails[DEFER_BLOCK_STATE] = newState;
20259
20129
  const hostTView = hostLView[TVIEW];
20260
20130
  const adjustedIndex = stateTmplIndex + HEADER_OFFSET;
@@ -20266,8 +20136,80 @@ function renderDeferBlockState(newState, tNode, lContainer) {
20266
20136
  const dehydratedView = findMatchingDehydratedView(lContainer, tNode.tView.ssrId);
20267
20137
  const embeddedLView = createAndRenderEmbeddedLView(hostLView, tNode, null, { dehydratedView });
20268
20138
  addLViewToLContainer(lContainer, embeddedLView, viewIndex, shouldAddViewToDom(tNode, dehydratedView));
20139
+ markViewDirty(embeddedLView);
20269
20140
  }
20270
20141
  }
20142
+ /**
20143
+ * Extends the `applyDeferBlockState` with timer-based scheduling.
20144
+ * This function becomes available on a page if there are defer blocks
20145
+ * that use `after` or `minimum` parameters in the `@loading` or
20146
+ * `@placeholder` blocks.
20147
+ */
20148
+ function applyDeferBlockStateWithScheduling(newState, lDetails, lContainer, tNode, hostLView) {
20149
+ const now = Date.now();
20150
+ const hostTView = hostLView[TVIEW];
20151
+ const tDetails = getTDeferBlockDetails(hostTView, tNode);
20152
+ if (lDetails[STATE_IS_FROZEN_UNTIL] === null || lDetails[STATE_IS_FROZEN_UNTIL] <= now) {
20153
+ lDetails[STATE_IS_FROZEN_UNTIL] = null;
20154
+ const loadingAfter = getLoadingBlockAfter(tDetails);
20155
+ const inLoadingAfterPhase = lDetails[LOADING_AFTER_CLEANUP_FN] !== null;
20156
+ if (newState === DeferBlockState.Loading && loadingAfter !== null && !inLoadingAfterPhase) {
20157
+ // Trying to render loading, but it has an `after` config,
20158
+ // so schedule an update action after a timeout.
20159
+ lDetails[NEXT_DEFER_BLOCK_STATE] = newState;
20160
+ const cleanupFn = scheduleDeferBlockUpdate(loadingAfter, lDetails, tNode, lContainer, hostLView);
20161
+ lDetails[LOADING_AFTER_CLEANUP_FN] = cleanupFn;
20162
+ }
20163
+ else {
20164
+ // If we transition to a complete or an error state and there is a pending
20165
+ // operation to render loading after a timeout - invoke a cleanup operation,
20166
+ // which stops the timer.
20167
+ if (newState > DeferBlockState.Loading && inLoadingAfterPhase) {
20168
+ lDetails[LOADING_AFTER_CLEANUP_FN]();
20169
+ lDetails[LOADING_AFTER_CLEANUP_FN] = null;
20170
+ lDetails[NEXT_DEFER_BLOCK_STATE] = null;
20171
+ }
20172
+ applyDeferBlockState(newState, lDetails, lContainer, tNode, hostLView);
20173
+ const duration = getMinimumDurationForState(tDetails, newState);
20174
+ if (duration !== null) {
20175
+ lDetails[STATE_IS_FROZEN_UNTIL] = now + duration;
20176
+ scheduleDeferBlockUpdate(duration, lDetails, tNode, lContainer, hostLView);
20177
+ }
20178
+ }
20179
+ }
20180
+ else {
20181
+ // We are still rendering the previous state.
20182
+ // Update the `NEXT_DEFER_BLOCK_STATE`, which would be
20183
+ // picked up once it's time to transition to the next state.
20184
+ lDetails[NEXT_DEFER_BLOCK_STATE] = newState;
20185
+ }
20186
+ }
20187
+ /**
20188
+ * Schedules an update operation after a specified timeout.
20189
+ */
20190
+ function scheduleDeferBlockUpdate(timeout, lDetails, tNode, lContainer, hostLView) {
20191
+ const callback = () => {
20192
+ const nextState = lDetails[NEXT_DEFER_BLOCK_STATE];
20193
+ lDetails[STATE_IS_FROZEN_UNTIL] = null;
20194
+ lDetails[NEXT_DEFER_BLOCK_STATE] = null;
20195
+ if (nextState !== null) {
20196
+ renderDeferBlockState(nextState, tNode, lContainer);
20197
+ }
20198
+ };
20199
+ return scheduleTimerTrigger(timeout, callback, hostLView, true);
20200
+ }
20201
+ /**
20202
+ * Checks whether we can transition to the next state.
20203
+ *
20204
+ * We transition to the next state if the previous state was represented
20205
+ * with a number that is less than the next state. For example, if the current
20206
+ * state is "loading" (represented as `1`), we should not show a placeholder
20207
+ * (represented as `0`), but we can show a completed state (represented as `2`)
20208
+ * or an error state (represented as `3`).
20209
+ */
20210
+ function isValidStateChange(currentState, newState) {
20211
+ return currentState < newState;
20212
+ }
20271
20213
  /**
20272
20214
  * Trigger prefetching of dependencies for a defer block.
20273
20215
  *
@@ -20419,11 +20361,9 @@ function triggerDeferBlock(lView, tNode) {
20419
20361
  if (!shouldTriggerDeferBlock(injector))
20420
20362
  return;
20421
20363
  const tDetails = getTDeferBlockDetails(tView, tNode);
20422
- // Condition is triggered, try to render loading state and start downloading.
20423
- // Note: if a block is in a loading, completed or an error state, this call would be a noop.
20424
- renderDeferBlockState(DeferBlockState.Loading, tNode, lContainer);
20425
20364
  switch (tDetails.loadingState) {
20426
20365
  case DeferDependenciesLoadingState.NOT_STARTED:
20366
+ renderDeferBlockState(DeferBlockState.Loading, tNode, lContainer);
20427
20367
  triggerResourceLoading(tDetails, lView);
20428
20368
  // The `loadingState` might have changed to "loading".
20429
20369
  if (tDetails.loadingState ===
@@ -20432,6 +20372,7 @@ function triggerDeferBlock(lView, tNode) {
20432
20372
  }
20433
20373
  break;
20434
20374
  case DeferDependenciesLoadingState.IN_PROGRESS:
20375
+ renderDeferBlockState(DeferBlockState.Loading, tNode, lContainer);
20435
20376
  renderDeferStateAfterResourceLoading(tDetails, tNode, lContainer);
20436
20377
  break;
20437
20378
  case DeferDependenciesLoadingState.COMPLETE:
@@ -27359,6 +27300,18 @@ function ɵɵgetComponentDepsFactory(type, rawImports) {
27359
27300
  };
27360
27301
  }
27361
27302
 
27303
+ /**
27304
+ * Sets the debug info for an Angular class.
27305
+ *
27306
+ * This runtime is guarded by ngDevMode flag.
27307
+ */
27308
+ function ɵsetClassDebugInfo(type, debugInfo) {
27309
+ const def = getComponentDef(type);
27310
+ if (def !== null) {
27311
+ def.debugInfo = debugInfo;
27312
+ }
27313
+ }
27314
+
27362
27315
  /**
27363
27316
  * A mapping of the @angular/core API surface used in generated expressions to the actual symbols.
27364
27317
  *
@@ -27497,6 +27450,7 @@ const angularCoreEnv = (() => ({
27497
27450
  'ɵɵdeferPrefetchOnHover': ɵɵdeferPrefetchOnHover,
27498
27451
  'ɵɵdeferPrefetchOnInteraction': ɵɵdeferPrefetchOnInteraction,
27499
27452
  'ɵɵdeferPrefetchOnViewport': ɵɵdeferPrefetchOnViewport,
27453
+ 'ɵɵdeferEnableTimerScheduling': ɵɵdeferEnableTimerScheduling,
27500
27454
  'ɵɵrepeater': ɵɵrepeater,
27501
27455
  'ɵɵrepeaterCreate': ɵɵrepeaterCreate,
27502
27456
  'ɵɵrepeaterTrackByIndex': ɵɵrepeaterTrackByIndex,
@@ -27527,6 +27481,7 @@ const angularCoreEnv = (() => ({
27527
27481
  'ɵɵsetNgModuleScope': ɵɵsetNgModuleScope,
27528
27482
  'ɵɵregisterNgModuleType': registerNgModuleType,
27529
27483
  'ɵɵgetComponentDepsFactory': ɵɵgetComponentDepsFactory,
27484
+ 'ɵsetClassDebugInfo': ɵsetClassDebugInfo,
27530
27485
  'ɵɵsanitizeHtml': ɵɵsanitizeHtml,
27531
27486
  'ɵɵsanitizeStyle': ɵɵsanitizeStyle,
27532
27487
  'ɵɵsanitizeResourceUrl': ɵɵsanitizeResourceUrl,
@@ -28743,7 +28698,7 @@ const ITS_JUST_ANGULAR = true;
28743
28698
  *
28744
28699
  * The following example illustrates how to configure a multi-provider using `APP_INITIALIZER` token
28745
28700
  * and a function returning a promise.
28746
- *
28701
+ * ### Example with NgModule-based application
28747
28702
  * ```
28748
28703
  * function initializeApp(): Promise<any> {
28749
28704
  * return new Promise((resolve, reject) => {
@@ -28765,11 +28720,38 @@ const ITS_JUST_ANGULAR = true;
28765
28720
  * export class AppModule {}
28766
28721
  * ```
28767
28722
  *
28723
+ * ### Example with standalone application
28724
+ * ```
28725
+ * export function initializeApp(http: HttpClient) {
28726
+ * return (): Promise<any> =>
28727
+ * firstValueFrom(
28728
+ * http
28729
+ * .get("https://someUrl.com/api/user")
28730
+ * .pipe(tap(user => { ... }))
28731
+ * );
28732
+ * }
28733
+ *
28734
+ * bootstrapApplication(App, {
28735
+ * providers: [
28736
+ * provideHttpClient(),
28737
+ * {
28738
+ * provide: APP_INITIALIZER,
28739
+ * useFactory: initializeApp,
28740
+ * multi: true,
28741
+ * deps: [HttpClient],
28742
+ * },
28743
+ * ],
28744
+ * });
28745
+
28746
+ * ```
28747
+ *
28748
+ *
28768
28749
  * It's also possible to configure a multi-provider using `APP_INITIALIZER` token and a function
28769
28750
  * returning an observable, see an example below. Note: the `HttpClient` in this example is used for
28770
28751
  * demo purposes to illustrate how the factory function can work with other providers available
28771
28752
  * through DI.
28772
28753
  *
28754
+ * ### Example with NgModule-based application
28773
28755
  * ```
28774
28756
  * function initializeAppFactory(httpClient: HttpClient): () => Observable<any> {
28775
28757
  * return () => httpClient.get("https://someUrl.com/api/user")
@@ -28792,6 +28774,27 @@ const ITS_JUST_ANGULAR = true;
28792
28774
  * export class AppModule {}
28793
28775
  * ```
28794
28776
  *
28777
+ * ### Example with standalone application
28778
+ *
28779
+ * function initializeAppFactory(httpClient: HttpClient): () => Observable<any> {
28780
+ * return () => httpClient.get("https://someUrl.com/api/user")
28781
+ * .pipe(
28782
+ * tap(user => { ... })
28783
+ * );
28784
+ * }
28785
+ *
28786
+ * bootstrapApplication(App, {
28787
+ * providers: [
28788
+ * provideHttpClient(),
28789
+ * {
28790
+ * provide: APP_INITIALIZER,
28791
+ * useFactory: initializeApp,
28792
+ * multi: true,
28793
+ * deps: [HttpClient],
28794
+ * },
28795
+ * ],
28796
+ * });
28797
+ *
28795
28798
  * @publicApi
28796
28799
  */
28797
28800
  const APP_INITIALIZER = new InjectionToken('Application Initializer');
@@ -29049,6 +29052,147 @@ var MissingTranslationStrategy;
29049
29052
  MissingTranslationStrategy[MissingTranslationStrategy["Ignore"] = 2] = "Ignore";
29050
29053
  })(MissingTranslationStrategy || (MissingTranslationStrategy = {}));
29051
29054
 
29055
+ // A delay in milliseconds before the scan is run after onLoad, to avoid any
29056
+ // potential race conditions with other LCP-related functions. This delay
29057
+ // happens outside of the main JavaScript execution and will only effect the timing
29058
+ // on when the warning becomes visible in the console.
29059
+ const SCAN_DELAY = 200;
29060
+ const OVERSIZED_IMAGE_TOLERANCE = 1200;
29061
+ class ImagePerformanceWarning {
29062
+ constructor() {
29063
+ // Map of full image URLs -> original `ngSrc` values.
29064
+ this.window = null;
29065
+ this.observer = null;
29066
+ this.options = inject(IMAGE_CONFIG);
29067
+ }
29068
+ start() {
29069
+ if (typeof PerformanceObserver === 'undefined' ||
29070
+ (this.options?.disableImageSizeWarning && this.options?.disableImageLazyLoadWarning)) {
29071
+ return;
29072
+ }
29073
+ this.observer = this.initPerformanceObserver();
29074
+ const win = getDocument().defaultView;
29075
+ if (typeof win !== 'undefined') {
29076
+ this.window = win;
29077
+ // Wait to avoid race conditions where LCP image triggers
29078
+ // load event before it's recorded by the performance observer
29079
+ const waitToScan = () => {
29080
+ setTimeout(this.scanImages.bind(this), SCAN_DELAY);
29081
+ };
29082
+ this.window?.addEventListener('load', waitToScan);
29083
+ }
29084
+ }
29085
+ ngOnDestroy() {
29086
+ this.observer?.disconnect();
29087
+ }
29088
+ initPerformanceObserver() {
29089
+ if (typeof PerformanceObserver === 'undefined') {
29090
+ return null;
29091
+ }
29092
+ const observer = new PerformanceObserver((entryList) => {
29093
+ const entries = entryList.getEntries();
29094
+ if (entries.length === 0)
29095
+ return;
29096
+ // We use the latest entry produced by the `PerformanceObserver` as the best
29097
+ // signal on which element is actually an LCP one. As an example, the first image to load on
29098
+ // a page, by virtue of being the only thing on the page so far, is often a LCP candidate
29099
+ // and gets reported by PerformanceObserver, but isn't necessarily the LCP element.
29100
+ const lcpElement = entries[entries.length - 1];
29101
+ // Cast to `any` due to missing `element` on the `LargestContentfulPaint` type of entry.
29102
+ // See https://developer.mozilla.org/en-US/docs/Web/API/LargestContentfulPaint
29103
+ const imgSrc = lcpElement.element?.src ?? '';
29104
+ // Exclude `data:` and `blob:` URLs, since they are fetched resources.
29105
+ if (imgSrc.startsWith('data:') || imgSrc.startsWith('blob:'))
29106
+ return;
29107
+ this.lcpImageUrl = imgSrc;
29108
+ });
29109
+ observer.observe({ type: 'largest-contentful-paint', buffered: true });
29110
+ return observer;
29111
+ }
29112
+ scanImages() {
29113
+ const images = getDocument().querySelectorAll('img');
29114
+ let lcpElementFound, lcpElementLoadedCorrectly = false;
29115
+ images.forEach(image => {
29116
+ if (!this.options?.disableImageSizeWarning) {
29117
+ for (const image of images) {
29118
+ // Image elements using the NgOptimizedImage directive are excluded,
29119
+ // as that directive has its own version of this check.
29120
+ if (!image.getAttribute('ng-img') && this.isOversized(image)) {
29121
+ logOversizedImageWarning(image.src);
29122
+ }
29123
+ }
29124
+ }
29125
+ if (!this.options?.disableImageLazyLoadWarning && this.lcpImageUrl) {
29126
+ if (image.src === this.lcpImageUrl) {
29127
+ lcpElementFound = true;
29128
+ if (image.loading !== 'lazy' || image.getAttribute('ng-img')) {
29129
+ // This variable is set to true and never goes back to false to account
29130
+ // for the case where multiple images have the same src url, and some
29131
+ // have lazy loading while others don't.
29132
+ // Also ignore NgOptimizedImage because there's a different warning for that.
29133
+ lcpElementLoadedCorrectly = true;
29134
+ }
29135
+ }
29136
+ }
29137
+ });
29138
+ if (lcpElementFound && !lcpElementLoadedCorrectly && this.lcpImageUrl &&
29139
+ !this.options?.disableImageLazyLoadWarning) {
29140
+ logLazyLCPWarning(this.lcpImageUrl);
29141
+ }
29142
+ }
29143
+ isOversized(image) {
29144
+ if (!this.window) {
29145
+ return false;
29146
+ }
29147
+ const computedStyle = this.window.getComputedStyle(image);
29148
+ let renderedWidth = parseFloat(computedStyle.getPropertyValue('width'));
29149
+ let renderedHeight = parseFloat(computedStyle.getPropertyValue('height'));
29150
+ const boxSizing = computedStyle.getPropertyValue('box-sizing');
29151
+ const objectFit = computedStyle.getPropertyValue('object-fit');
29152
+ if (objectFit === `cover`) {
29153
+ // Object fit cover may indicate a use case such as a sprite sheet where
29154
+ // this warning does not apply.
29155
+ return false;
29156
+ }
29157
+ if (boxSizing === 'border-box') {
29158
+ const paddingTop = computedStyle.getPropertyValue('padding-top');
29159
+ const paddingRight = computedStyle.getPropertyValue('padding-right');
29160
+ const paddingBottom = computedStyle.getPropertyValue('padding-bottom');
29161
+ const paddingLeft = computedStyle.getPropertyValue('padding-left');
29162
+ renderedWidth -= parseFloat(paddingRight) + parseFloat(paddingLeft);
29163
+ renderedHeight -= parseFloat(paddingTop) + parseFloat(paddingBottom);
29164
+ }
29165
+ const intrinsicWidth = image.naturalWidth;
29166
+ const intrinsicHeight = image.naturalHeight;
29167
+ const recommendedWidth = this.window.devicePixelRatio * renderedWidth;
29168
+ const recommendedHeight = this.window.devicePixelRatio * renderedHeight;
29169
+ const oversizedWidth = (intrinsicWidth - recommendedWidth) >= OVERSIZED_IMAGE_TOLERANCE;
29170
+ const oversizedHeight = (intrinsicHeight - recommendedHeight) >= OVERSIZED_IMAGE_TOLERANCE;
29171
+ return oversizedWidth || oversizedHeight;
29172
+ }
29173
+ static { this.ɵfac = function ImagePerformanceWarning_Factory(t) { return new (t || ImagePerformanceWarning)(); }; }
29174
+ static { this.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: ImagePerformanceWarning, factory: ImagePerformanceWarning.ɵfac, providedIn: 'root' }); }
29175
+ }
29176
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ImagePerformanceWarning, [{
29177
+ type: Injectable,
29178
+ args: [{ providedIn: 'root' }]
29179
+ }], () => [], null); })();
29180
+ function logLazyLCPWarning(src) {
29181
+ console.warn(formatRuntimeError(-913 /* RuntimeErrorCode.IMAGE_PERFORMANCE_WARNING */, `An image with src ${src} is the Largest Contentful Paint (LCP) element ` +
29182
+ `but was given a "loading" value of "lazy", which can negatively impact` +
29183
+ `application loading performance. This warning can be addressed by ` +
29184
+ `changing the loading value of the LCP image to "eager", or by using the ` +
29185
+ `NgOptimizedImage directive's prioritization utilities. For more ` +
29186
+ `information about addressing or disabling this warning, see ` +
29187
+ `https://angular.io/errors/NG2965`));
29188
+ }
29189
+ function logOversizedImageWarning(src) {
29190
+ console.warn(formatRuntimeError(-913 /* RuntimeErrorCode.IMAGE_PERFORMANCE_WARNING */, `An image with src ${src} has intrinsic file dimensions much larger than its ` +
29191
+ `rendered size. This can negatively impact application loading performance. ` +
29192
+ `For more information about addressing or disabling this warning, see ` +
29193
+ `https://angular.io/errors/NG2965`));
29194
+ }
29195
+
29052
29196
  /**
29053
29197
  * *Internal* service that keeps track of pending tasks happening in the system
29054
29198
  * during the initial rendering. No tasks are tracked after an initial
@@ -29299,7 +29443,35 @@ function handleInjectEvent(context, data) {
29299
29443
  instantiatedTokenToDependencies.set(context.token, []);
29300
29444
  }
29301
29445
  const { token, value, flags } = data;
29302
- instantiatedTokenToDependencies.get(context.token).push({ token, value, flags });
29446
+ assertDefined(context.token, 'Injector profiler context token is undefined.');
29447
+ const dependencies = instantiatedTokenToDependencies.get(context.token);
29448
+ assertDefined(dependencies, 'Could not resolve dependencies for token.');
29449
+ if (context.injector instanceof NodeInjector) {
29450
+ dependencies.push({ token, value, flags, injectedIn: getNodeInjectorContext(context.injector) });
29451
+ }
29452
+ else {
29453
+ dependencies.push({ token, value, flags });
29454
+ }
29455
+ }
29456
+ /**
29457
+ *
29458
+ * Returns the LView and TNode associated with a NodeInjector. Returns undefined if the injector
29459
+ * is not a NodeInjector.
29460
+ *
29461
+ * @param injector
29462
+ * @returns {lView: LView, tNode: TNode}|undefined
29463
+ */
29464
+ function getNodeInjectorContext(injector) {
29465
+ if (!(injector instanceof NodeInjector)) {
29466
+ throwError('getNodeInjectorContext must be called with a NodeInjector');
29467
+ }
29468
+ const lView = getNodeInjectorLView(injector);
29469
+ const tNode = getNodeInjectorTNode(injector);
29470
+ if (tNode === null) {
29471
+ return;
29472
+ }
29473
+ assertTNodeForLView(tNode, lView);
29474
+ return { lView, tNode };
29303
29475
  }
29304
29476
  /**
29305
29477
  *
@@ -29428,14 +29600,10 @@ function getDependenciesFromInjectable(injector, token) {
29428
29600
  if (instance === null) {
29429
29601
  throw new Error(`Unable to determine instance of ${token} in given injector`);
29430
29602
  }
29431
- let diResolver = injector;
29432
- if (injector instanceof NodeInjector) {
29433
- diResolver = getNodeInjectorLView(injector);
29434
- }
29435
- const { resolverToTokenToDependencies } = getFrameworkDIDebugData();
29436
- let dependencies = resolverToTokenToDependencies.get(diResolver)?.get?.(token) ?? [];
29603
+ const unformattedDependencies = getDependenciesForTokenInInjector(token, injector);
29437
29604
  const resolutionPath = getInjectorResolutionPath(injector);
29438
- dependencies = dependencies.map(dep => {
29605
+ const dependencies = unformattedDependencies.map(dep => {
29606
+ // convert injection flags to booleans
29439
29607
  const flags = dep.flags;
29440
29608
  dep.flags = {
29441
29609
  optional: (8 /* InternalInjectFlags.Optional */ & flags) === 8 /* InternalInjectFlags.Optional */,
@@ -29443,6 +29611,7 @@ function getDependenciesFromInjectable(injector, token) {
29443
29611
  self: (2 /* InternalInjectFlags.Self */ & flags) === 2 /* InternalInjectFlags.Self */,
29444
29612
  skipSelf: (4 /* InternalInjectFlags.SkipSelf */ & flags) === 4 /* InternalInjectFlags.SkipSelf */,
29445
29613
  };
29614
+ // find the injector that provided the dependency
29446
29615
  for (let i = 0; i < resolutionPath.length; i++) {
29447
29616
  const injectorToCheck = resolutionPath[i];
29448
29617
  // if skipSelf is true we skip the first injector
@@ -29475,10 +29644,42 @@ function getDependenciesFromInjectable(injector, token) {
29475
29644
  break;
29476
29645
  }
29477
29646
  }
29478
- return dep;
29647
+ // injectedIn contains private fields, so we omit it from the response
29648
+ const formattedDependency = {
29649
+ value: dep.value,
29650
+ };
29651
+ if (dep.token)
29652
+ formattedDependency.token = dep.token;
29653
+ if (dep.flags)
29654
+ formattedDependency.flags = dep.flags;
29655
+ if (dep.providedIn)
29656
+ formattedDependency.providedIn = dep.providedIn;
29657
+ return formattedDependency;
29479
29658
  });
29480
29659
  return { instance, dependencies };
29481
29660
  }
29661
+ function getDependenciesForTokenInInjector(token, injector) {
29662
+ const { resolverToTokenToDependencies } = getFrameworkDIDebugData();
29663
+ if (!(injector instanceof NodeInjector)) {
29664
+ return resolverToTokenToDependencies.get(injector)?.get?.(token) ?? [];
29665
+ }
29666
+ const lView = getNodeInjectorLView(injector);
29667
+ const tokenDependencyMap = resolverToTokenToDependencies.get(lView);
29668
+ const dependencies = tokenDependencyMap?.get(token) ?? [];
29669
+ // In the NodeInjector case, all injections for every node are stored in the same lView.
29670
+ // We use the injectedIn field of the dependency to filter out the dependencies that
29671
+ // do not come from the same node as the instance we're looking at.
29672
+ return dependencies.filter(dependency => {
29673
+ const dependencyNode = dependency.injectedIn?.tNode;
29674
+ if (dependencyNode === undefined) {
29675
+ return false;
29676
+ }
29677
+ const instanceNode = getNodeInjectorTNode(injector);
29678
+ assertTNode(dependencyNode);
29679
+ assertTNode(instanceNode);
29680
+ return dependencyNode === instanceNode;
29681
+ });
29682
+ }
29482
29683
  /**
29483
29684
  * Gets the class associated with an injector that contains a provider `imports` array in it's
29484
29685
  * definition
@@ -29741,8 +29942,7 @@ function getInjectorMetadata(injector) {
29741
29942
  const lView = getNodeInjectorLView(injector);
29742
29943
  const tNode = getNodeInjectorTNode(injector);
29743
29944
  assertTNodeForLView(tNode, lView);
29744
- assertDefined(lView[tNode.index][HOST], 'Could not find node in element view.');
29745
- return { type: 'element', source: lView[tNode.index][HOST] };
29945
+ return { type: 'element', source: getNativeByTNode(tNode, lView) };
29746
29946
  }
29747
29947
  if (injector instanceof R3Injector) {
29748
29948
  return { type: 'environment', source: injector.source ?? null };
@@ -30316,7 +30516,7 @@ function publishDefaultGlobalUtils() {
30316
30516
  * Sets the error for an invalid write to a signal to be an Angular `RuntimeError`.
30317
30517
  */
30318
30518
  function publishSignalConfiguration() {
30319
- setThrowInvalidWriteToSignalError(() => {
30519
+ setThrowInvalidWriteToSignalError$1(() => {
30320
30520
  throw new RuntimeError(600 /* RuntimeErrorCode.SIGNAL_WRITE_FROM_ILLEGAL_CONTEXT */, ngDevMode &&
30321
30521
  'Writing to signals is not allowed in a `computed` or an `effect` by default. ' +
30322
30522
  'Use `allowSignalWrites` in the `CreateEffectOptions` to enable this inside effects.');
@@ -30443,6 +30643,10 @@ function internalCreateApplication(config) {
30443
30643
  if (rootComponent !== undefined) {
30444
30644
  appRef.bootstrap(rootComponent);
30445
30645
  }
30646
+ if (typeof ngDevMode === 'undefined' || ngDevMode) {
30647
+ const imagePerformanceService = envInjector.get(ImagePerformanceWarning);
30648
+ imagePerformanceService.start();
30649
+ }
30446
30650
  return appRef;
30447
30651
  });
30448
30652
  });
@@ -32939,114 +33143,645 @@ class IterableDiffers {
32939
33143
  }
32940
33144
  }
32941
33145
  }
32942
- function getTypeNameForDebugging(type) {
32943
- return type['name'] || typeof type;
32944
- }
32945
-
32946
- function defaultKeyValueDiffersFactory() {
32947
- return new KeyValueDiffers([new DefaultKeyValueDifferFactory()]);
32948
- }
33146
+ function getTypeNameForDebugging(type) {
33147
+ return type['name'] || typeof type;
33148
+ }
33149
+
33150
+ function defaultKeyValueDiffersFactory() {
33151
+ return new KeyValueDiffers([new DefaultKeyValueDifferFactory()]);
33152
+ }
33153
+ /**
33154
+ * A repository of different Map diffing strategies used by NgClass, NgStyle, and others.
33155
+ *
33156
+ * @publicApi
33157
+ */
33158
+ class KeyValueDiffers {
33159
+ /** @nocollapse */
33160
+ static { this.ɵprov = ɵɵdefineInjectable({ token: KeyValueDiffers, providedIn: 'root', factory: defaultKeyValueDiffersFactory }); }
33161
+ constructor(factories) {
33162
+ this.factories = factories;
33163
+ }
33164
+ static create(factories, parent) {
33165
+ if (parent) {
33166
+ const copied = parent.factories.slice();
33167
+ factories = factories.concat(copied);
33168
+ }
33169
+ return new KeyValueDiffers(factories);
33170
+ }
33171
+ /**
33172
+ * Takes an array of {@link KeyValueDifferFactory} and returns a provider used to extend the
33173
+ * inherited {@link KeyValueDiffers} instance with the provided factories and return a new
33174
+ * {@link KeyValueDiffers} instance.
33175
+ *
33176
+ * @usageNotes
33177
+ * ### Example
33178
+ *
33179
+ * The following example shows how to extend an existing list of factories,
33180
+ * which will only be applied to the injector for this component and its children.
33181
+ * This step is all that's required to make a new {@link KeyValueDiffer} available.
33182
+ *
33183
+ * ```
33184
+ * @Component({
33185
+ * viewProviders: [
33186
+ * KeyValueDiffers.extend([new ImmutableMapDiffer()])
33187
+ * ]
33188
+ * })
33189
+ * ```
33190
+ */
33191
+ static extend(factories) {
33192
+ return {
33193
+ provide: KeyValueDiffers,
33194
+ useFactory: (parent) => {
33195
+ // if parent is null, it means that we are in the root injector and we have just overridden
33196
+ // the default injection mechanism for KeyValueDiffers, in such a case just assume
33197
+ // `defaultKeyValueDiffersFactory`.
33198
+ return KeyValueDiffers.create(factories, parent || defaultKeyValueDiffersFactory());
33199
+ },
33200
+ // Dependency technically isn't optional, but we can provide a better error message this way.
33201
+ deps: [[KeyValueDiffers, new SkipSelf(), new Optional()]]
33202
+ };
33203
+ }
33204
+ find(kv) {
33205
+ const factory = this.factories.find(f => f.supports(kv));
33206
+ if (factory) {
33207
+ return factory;
33208
+ }
33209
+ throw new RuntimeError(901 /* RuntimeErrorCode.NO_SUPPORTING_DIFFER_FACTORY */, ngDevMode && `Cannot find a differ supporting object '${kv}'`);
33210
+ }
33211
+ }
33212
+
33213
+ /**
33214
+ * Structural diffing for `Object`s and `Map`s.
33215
+ */
33216
+ const keyValDiff = [new DefaultKeyValueDifferFactory()];
33217
+ /**
33218
+ * Structural diffing for `Iterable` types such as `Array`s.
33219
+ */
33220
+ const iterableDiff = [new DefaultIterableDifferFactory()];
33221
+ const defaultIterableDiffers = new IterableDiffers(iterableDiff);
33222
+ const defaultKeyValueDiffers = new KeyValueDiffers(keyValDiff);
33223
+
33224
+ /**
33225
+ * @module
33226
+ * @description
33227
+ * Change detection enables data binding in Angular.
33228
+ */
33229
+
33230
+ /**
33231
+ * This platform has to be included in any other platform
33232
+ *
33233
+ * @publicApi
33234
+ */
33235
+ const platformCore = createPlatformFactory(null, 'core', []);
33236
+
33237
+ /**
33238
+ * Re-exported by `BrowserModule`, which is included automatically in the root
33239
+ * `AppModule` when you create a new app with the CLI `new` command. Eagerly injects
33240
+ * `ApplicationRef` to instantiate it.
33241
+ *
33242
+ * @publicApi
33243
+ */
33244
+ class ApplicationModule {
33245
+ // Inject ApplicationRef to make it eager...
33246
+ constructor(appRef) { }
33247
+ static { this.ɵfac = function ApplicationModule_Factory(t) { return new (t || ApplicationModule)(ɵɵinject(ApplicationRef)); }; }
33248
+ static { this.ɵmod = /*@__PURE__*/ ɵɵdefineNgModule({ type: ApplicationModule }); }
33249
+ static { this.ɵinj = /*@__PURE__*/ ɵɵdefineInjector({}); }
33250
+ }
33251
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ApplicationModule, [{
33252
+ type: NgModule
33253
+ }], () => [{ type: ApplicationRef }], null); })();
33254
+
33255
+ /**
33256
+ * The default equality function used for `signal` and `computed`, which uses referential equality.
33257
+ */
33258
+ function defaultEquals(a, b) {
33259
+ return Object.is(a, b);
33260
+ }
33261
+
33262
+ /**
33263
+ * The currently active consumer `ReactiveNode`, if running code in a reactive context.
33264
+ *
33265
+ * Change this via `setActiveConsumer`.
33266
+ */
33267
+ let activeConsumer = null;
33268
+ let inNotificationPhase = false;
33269
+ /**
33270
+ * Symbol used to tell `Signal`s apart from other functions.
33271
+ *
33272
+ * This can be used to auto-unwrap signals in various cases, or to auto-wrap non-signal values.
33273
+ */
33274
+ const SIGNAL = /* @__PURE__ */ Symbol('SIGNAL');
33275
+ function setActiveConsumer(consumer) {
33276
+ const prev = activeConsumer;
33277
+ activeConsumer = consumer;
33278
+ return prev;
33279
+ }
33280
+ function getActiveConsumer() {
33281
+ return activeConsumer;
33282
+ }
33283
+ function isInNotificationPhase() {
33284
+ return inNotificationPhase;
33285
+ }
33286
+ function isReactive(value) {
33287
+ return value[SIGNAL] !== undefined;
33288
+ }
33289
+ const REACTIVE_NODE = {
33290
+ version: 0,
33291
+ dirty: false,
33292
+ producerNode: undefined,
33293
+ producerLastReadVersion: undefined,
33294
+ producerIndexOfThis: undefined,
33295
+ nextProducerIndex: 0,
33296
+ liveConsumerNode: undefined,
33297
+ liveConsumerIndexOfThis: undefined,
33298
+ consumerAllowSignalWrites: false,
33299
+ consumerIsAlwaysLive: false,
33300
+ producerMustRecompute: () => false,
33301
+ producerRecomputeValue: () => { },
33302
+ consumerMarkedDirty: () => { },
33303
+ consumerOnSignalRead: () => { },
33304
+ };
33305
+ /**
33306
+ * Called by implementations when a producer's signal is read.
33307
+ */
33308
+ function producerAccessed(node) {
33309
+ if (inNotificationPhase) {
33310
+ throw new Error(typeof ngDevMode !== 'undefined' && ngDevMode ?
33311
+ `Assertion error: signal read during notification phase` :
33312
+ '');
33313
+ }
33314
+ if (activeConsumer === null) {
33315
+ // Accessed outside of a reactive context, so nothing to record.
33316
+ return;
33317
+ }
33318
+ activeConsumer.consumerOnSignalRead(node);
33319
+ // This producer is the `idx`th dependency of `activeConsumer`.
33320
+ const idx = activeConsumer.nextProducerIndex++;
33321
+ assertConsumerNode(activeConsumer);
33322
+ if (idx < activeConsumer.producerNode.length && activeConsumer.producerNode[idx] !== node) {
33323
+ // There's been a change in producers since the last execution of `activeConsumer`.
33324
+ // `activeConsumer.producerNode[idx]` holds a stale dependency which will be be removed and
33325
+ // replaced with `this`.
33326
+ //
33327
+ // If `activeConsumer` isn't live, then this is a no-op, since we can replace the producer in
33328
+ // `activeConsumer.producerNode` directly. However, if `activeConsumer` is live, then we need
33329
+ // to remove it from the stale producer's `liveConsumer`s.
33330
+ if (consumerIsLive(activeConsumer)) {
33331
+ const staleProducer = activeConsumer.producerNode[idx];
33332
+ producerRemoveLiveConsumerAtIndex(staleProducer, activeConsumer.producerIndexOfThis[idx]);
33333
+ // At this point, the only record of `staleProducer` is the reference at
33334
+ // `activeConsumer.producerNode[idx]` which will be overwritten below.
33335
+ }
33336
+ }
33337
+ if (activeConsumer.producerNode[idx] !== node) {
33338
+ // We're a new dependency of the consumer (at `idx`).
33339
+ activeConsumer.producerNode[idx] = node;
33340
+ // If the active consumer is live, then add it as a live consumer. If not, then use 0 as a
33341
+ // placeholder value.
33342
+ activeConsumer.producerIndexOfThis[idx] =
33343
+ consumerIsLive(activeConsumer) ? producerAddLiveConsumer(node, activeConsumer, idx) : 0;
33344
+ }
33345
+ activeConsumer.producerLastReadVersion[idx] = node.version;
33346
+ }
33347
+ /**
33348
+ * Ensure this producer's `version` is up-to-date.
33349
+ */
33350
+ function producerUpdateValueVersion(node) {
33351
+ if (consumerIsLive(node) && !node.dirty) {
33352
+ // A live consumer will be marked dirty by producers, so a clean state means that its version
33353
+ // is guaranteed to be up-to-date.
33354
+ return;
33355
+ }
33356
+ if (!node.producerMustRecompute(node) && !consumerPollProducersForChange(node)) {
33357
+ // None of our producers report a change since the last time they were read, so no
33358
+ // recomputation of our value is necessary, and we can consider ourselves clean.
33359
+ node.dirty = false;
33360
+ return;
33361
+ }
33362
+ node.producerRecomputeValue(node);
33363
+ // After recomputing the value, we're no longer dirty.
33364
+ node.dirty = false;
33365
+ }
33366
+ /**
33367
+ * Propagate a dirty notification to live consumers of this producer.
33368
+ */
33369
+ function producerNotifyConsumers(node) {
33370
+ if (node.liveConsumerNode === undefined) {
33371
+ return;
33372
+ }
33373
+ // Prevent signal reads when we're updating the graph
33374
+ const prev = inNotificationPhase;
33375
+ inNotificationPhase = true;
33376
+ try {
33377
+ for (const consumer of node.liveConsumerNode) {
33378
+ if (!consumer.dirty) {
33379
+ consumerMarkDirty(consumer);
33380
+ }
33381
+ }
33382
+ }
33383
+ finally {
33384
+ inNotificationPhase = prev;
33385
+ }
33386
+ }
33387
+ /**
33388
+ * Whether this `ReactiveNode` in its producer capacity is currently allowed to initiate updates,
33389
+ * based on the current consumer context.
33390
+ */
33391
+ function producerUpdatesAllowed() {
33392
+ return activeConsumer?.consumerAllowSignalWrites !== false;
33393
+ }
33394
+ function consumerMarkDirty(node) {
33395
+ node.dirty = true;
33396
+ producerNotifyConsumers(node);
33397
+ node.consumerMarkedDirty?.(node);
33398
+ }
33399
+ /**
33400
+ * Prepare this consumer to run a computation in its reactive context.
33401
+ *
33402
+ * Must be called by subclasses which represent reactive computations, before those computations
33403
+ * begin.
33404
+ */
33405
+ function consumerBeforeComputation(node) {
33406
+ node && (node.nextProducerIndex = 0);
33407
+ return setActiveConsumer(node);
33408
+ }
33409
+ /**
33410
+ * Finalize this consumer's state after a reactive computation has run.
33411
+ *
33412
+ * Must be called by subclasses which represent reactive computations, after those computations
33413
+ * have finished.
33414
+ */
33415
+ function consumerAfterComputation(node, prevConsumer) {
33416
+ setActiveConsumer(prevConsumer);
33417
+ if (!node || node.producerNode === undefined || node.producerIndexOfThis === undefined ||
33418
+ node.producerLastReadVersion === undefined) {
33419
+ return;
33420
+ }
33421
+ if (consumerIsLive(node)) {
33422
+ // For live consumers, we need to remove the producer -> consumer edge for any stale producers
33423
+ // which weren't dependencies after the recomputation.
33424
+ for (let i = node.nextProducerIndex; i < node.producerNode.length; i++) {
33425
+ producerRemoveLiveConsumerAtIndex(node.producerNode[i], node.producerIndexOfThis[i]);
33426
+ }
33427
+ }
33428
+ // Truncate the producer tracking arrays.
33429
+ // Perf note: this is essentially truncating the length to `node.nextProducerIndex`, but
33430
+ // benchmarking has shown that individual pop operations are faster.
33431
+ while (node.producerNode.length > node.nextProducerIndex) {
33432
+ node.producerNode.pop();
33433
+ node.producerLastReadVersion.pop();
33434
+ node.producerIndexOfThis.pop();
33435
+ }
33436
+ }
33437
+ /**
33438
+ * Determine whether this consumer has any dependencies which have changed since the last time
33439
+ * they were read.
33440
+ */
33441
+ function consumerPollProducersForChange(node) {
33442
+ assertConsumerNode(node);
33443
+ // Poll producers for change.
33444
+ for (let i = 0; i < node.producerNode.length; i++) {
33445
+ const producer = node.producerNode[i];
33446
+ const seenVersion = node.producerLastReadVersion[i];
33447
+ // First check the versions. A mismatch means that the producer's value is known to have
33448
+ // changed since the last time we read it.
33449
+ if (seenVersion !== producer.version) {
33450
+ return true;
33451
+ }
33452
+ // The producer's version is the same as the last time we read it, but it might itself be
33453
+ // stale. Force the producer to recompute its version (calculating a new value if necessary).
33454
+ producerUpdateValueVersion(producer);
33455
+ // Now when we do this check, `producer.version` is guaranteed to be up to date, so if the
33456
+ // versions still match then it has not changed since the last time we read it.
33457
+ if (seenVersion !== producer.version) {
33458
+ return true;
33459
+ }
33460
+ }
33461
+ return false;
33462
+ }
33463
+ /**
33464
+ * Disconnect this consumer from the graph.
33465
+ */
33466
+ function consumerDestroy(node) {
33467
+ assertConsumerNode(node);
33468
+ if (consumerIsLive(node)) {
33469
+ // Drop all connections from the graph to this node.
33470
+ for (let i = 0; i < node.producerNode.length; i++) {
33471
+ producerRemoveLiveConsumerAtIndex(node.producerNode[i], node.producerIndexOfThis[i]);
33472
+ }
33473
+ }
33474
+ // Truncate all the arrays to drop all connection from this node to the graph.
33475
+ node.producerNode.length = node.producerLastReadVersion.length = node.producerIndexOfThis.length =
33476
+ 0;
33477
+ if (node.liveConsumerNode) {
33478
+ node.liveConsumerNode.length = node.liveConsumerIndexOfThis.length = 0;
33479
+ }
33480
+ }
32949
33481
  /**
32950
- * A repository of different Map diffing strategies used by NgClass, NgStyle, and others.
33482
+ * Add `consumer` as a live consumer of this node.
32951
33483
  *
32952
- * @publicApi
33484
+ * Note that this operation is potentially transitive. If this node becomes live, then it becomes
33485
+ * a live consumer of all of its current producers.
32953
33486
  */
32954
- class KeyValueDiffers {
32955
- /** @nocollapse */
32956
- static { this.ɵprov = ɵɵdefineInjectable({ token: KeyValueDiffers, providedIn: 'root', factory: defaultKeyValueDiffersFactory }); }
32957
- constructor(factories) {
32958
- this.factories = factories;
32959
- }
32960
- static create(factories, parent) {
32961
- if (parent) {
32962
- const copied = parent.factories.slice();
32963
- factories = factories.concat(copied);
33487
+ function producerAddLiveConsumer(node, consumer, indexOfThis) {
33488
+ assertProducerNode(node);
33489
+ assertConsumerNode(node);
33490
+ if (node.liveConsumerNode.length === 0) {
33491
+ // When going from 0 to 1 live consumers, we become a live consumer to our producers.
33492
+ for (let i = 0; i < node.producerNode.length; i++) {
33493
+ node.producerIndexOfThis[i] = producerAddLiveConsumer(node.producerNode[i], node, i);
32964
33494
  }
32965
- return new KeyValueDiffers(factories);
32966
33495
  }
32967
- /**
32968
- * Takes an array of {@link KeyValueDifferFactory} and returns a provider used to extend the
32969
- * inherited {@link KeyValueDiffers} instance with the provided factories and return a new
32970
- * {@link KeyValueDiffers} instance.
32971
- *
32972
- * @usageNotes
32973
- * ### Example
32974
- *
32975
- * The following example shows how to extend an existing list of factories,
32976
- * which will only be applied to the injector for this component and its children.
32977
- * This step is all that's required to make a new {@link KeyValueDiffer} available.
32978
- *
32979
- * ```
32980
- * @Component({
32981
- * viewProviders: [
32982
- * KeyValueDiffers.extend([new ImmutableMapDiffer()])
32983
- * ]
32984
- * })
32985
- * ```
32986
- */
32987
- static extend(factories) {
32988
- return {
32989
- provide: KeyValueDiffers,
32990
- useFactory: (parent) => {
32991
- // if parent is null, it means that we are in the root injector and we have just overridden
32992
- // the default injection mechanism for KeyValueDiffers, in such a case just assume
32993
- // `defaultKeyValueDiffersFactory`.
32994
- return KeyValueDiffers.create(factories, parent || defaultKeyValueDiffersFactory());
32995
- },
32996
- // Dependency technically isn't optional, but we can provide a better error message this way.
32997
- deps: [[KeyValueDiffers, new SkipSelf(), new Optional()]]
32998
- };
33496
+ node.liveConsumerIndexOfThis.push(indexOfThis);
33497
+ return node.liveConsumerNode.push(consumer) - 1;
33498
+ }
33499
+ /**
33500
+ * Remove the live consumer at `idx`.
33501
+ */
33502
+ function producerRemoveLiveConsumerAtIndex(node, idx) {
33503
+ assertProducerNode(node);
33504
+ assertConsumerNode(node);
33505
+ if (typeof ngDevMode !== 'undefined' && ngDevMode && idx >= node.liveConsumerNode.length) {
33506
+ throw new Error(`Assertion error: active consumer index ${idx} is out of bounds of ${node.liveConsumerNode.length} consumers)`);
32999
33507
  }
33000
- find(kv) {
33001
- const factory = this.factories.find(f => f.supports(kv));
33002
- if (factory) {
33003
- return factory;
33508
+ if (node.liveConsumerNode.length === 1) {
33509
+ // When removing the last live consumer, we will no longer be live. We need to remove
33510
+ // ourselves from our producers' tracking (which may cause consumer-producers to lose
33511
+ // liveness as well).
33512
+ for (let i = 0; i < node.producerNode.length; i++) {
33513
+ producerRemoveLiveConsumerAtIndex(node.producerNode[i], node.producerIndexOfThis[i]);
33004
33514
  }
33005
- throw new RuntimeError(901 /* RuntimeErrorCode.NO_SUPPORTING_DIFFER_FACTORY */, ngDevMode && `Cannot find a differ supporting object '${kv}'`);
33006
33515
  }
33516
+ // Move the last value of `liveConsumers` into `idx`. Note that if there's only a single
33517
+ // live consumer, this is a no-op.
33518
+ const lastIdx = node.liveConsumerNode.length - 1;
33519
+ node.liveConsumerNode[idx] = node.liveConsumerNode[lastIdx];
33520
+ node.liveConsumerIndexOfThis[idx] = node.liveConsumerIndexOfThis[lastIdx];
33521
+ // Truncate the array.
33522
+ node.liveConsumerNode.length--;
33523
+ node.liveConsumerIndexOfThis.length--;
33524
+ // If the index is still valid, then we need to fix the index pointer from the producer to this
33525
+ // consumer, and update it from `lastIdx` to `idx` (accounting for the move above).
33526
+ if (idx < node.liveConsumerNode.length) {
33527
+ const idxProducer = node.liveConsumerIndexOfThis[idx];
33528
+ const consumer = node.liveConsumerNode[idx];
33529
+ assertConsumerNode(consumer);
33530
+ consumer.producerIndexOfThis[idxProducer] = idx;
33531
+ }
33532
+ }
33533
+ function consumerIsLive(node) {
33534
+ return node.consumerIsAlwaysLive || (node?.liveConsumerNode?.length ?? 0) > 0;
33535
+ }
33536
+ function assertConsumerNode(node) {
33537
+ node.producerNode ??= [];
33538
+ node.producerIndexOfThis ??= [];
33539
+ node.producerLastReadVersion ??= [];
33540
+ }
33541
+ function assertProducerNode(node) {
33542
+ node.liveConsumerNode ??= [];
33543
+ node.liveConsumerIndexOfThis ??= [];
33007
33544
  }
33008
33545
 
33009
33546
  /**
33010
- * Structural diffing for `Object`s and `Map`s.
33547
+ * Create a computed signal which derives a reactive value from an expression.
33011
33548
  */
33012
- const keyValDiff = [new DefaultKeyValueDifferFactory()];
33549
+ function createComputed(computation) {
33550
+ const node = Object.create(COMPUTED_NODE);
33551
+ node.computation = computation;
33552
+ const computed = () => {
33553
+ // Check if the value needs updating before returning it.
33554
+ producerUpdateValueVersion(node);
33555
+ // Record that someone looked at this signal.
33556
+ producerAccessed(node);
33557
+ if (node.value === ERRORED) {
33558
+ throw node.error;
33559
+ }
33560
+ return node.value;
33561
+ };
33562
+ computed[SIGNAL] = node;
33563
+ return computed;
33564
+ }
33013
33565
  /**
33014
- * Structural diffing for `Iterable` types such as `Array`s.
33566
+ * A dedicated symbol used before a computed value has been calculated for the first time.
33567
+ * Explicitly typed as `any` so we can use it as signal's value.
33015
33568
  */
33016
- const iterableDiff = [new DefaultIterableDifferFactory()];
33017
- const defaultIterableDiffers = new IterableDiffers(iterableDiff);
33018
- const defaultKeyValueDiffers = new KeyValueDiffers(keyValDiff);
33019
-
33569
+ const UNSET = /* @__PURE__ */ Symbol('UNSET');
33020
33570
  /**
33021
- * @module
33022
- * @description
33023
- * Change detection enables data binding in Angular.
33571
+ * A dedicated symbol used in place of a computed signal value to indicate that a given computation
33572
+ * is in progress. Used to detect cycles in computation chains.
33573
+ * Explicitly typed as `any` so we can use it as signal's value.
33024
33574
  */
33025
-
33575
+ const COMPUTING = /* @__PURE__ */ Symbol('COMPUTING');
33026
33576
  /**
33027
- * This platform has to be included in any other platform
33028
- *
33029
- * @publicApi
33577
+ * A dedicated symbol used in place of a computed signal value to indicate that a given computation
33578
+ * failed. The thrown error is cached until the computation gets dirty again.
33579
+ * Explicitly typed as `any` so we can use it as signal's value.
33030
33580
  */
33031
- const platformCore = createPlatformFactory(null, 'core', []);
33581
+ const ERRORED = /* @__PURE__ */ Symbol('ERRORED');
33582
+ // Note: Using an IIFE here to ensure that the spread assignment is not considered
33583
+ // a side-effect, ending up preserving `COMPUTED_NODE` and `REACTIVE_NODE`.
33584
+ // TODO: remove when https://github.com/evanw/esbuild/issues/3392 is resolved.
33585
+ const COMPUTED_NODE = /* @__PURE__ */ (() => {
33586
+ return {
33587
+ ...REACTIVE_NODE,
33588
+ value: UNSET,
33589
+ dirty: true,
33590
+ error: null,
33591
+ equal: defaultEquals,
33592
+ producerMustRecompute(node) {
33593
+ // Force a recomputation if there's no current value, or if the current value is in the
33594
+ // process of being calculated (which should throw an error).
33595
+ return node.value === UNSET || node.value === COMPUTING;
33596
+ },
33597
+ producerRecomputeValue(node) {
33598
+ if (node.value === COMPUTING) {
33599
+ // Our computation somehow led to a cyclic read of itself.
33600
+ throw new Error('Detected cycle in computations.');
33601
+ }
33602
+ const oldValue = node.value;
33603
+ node.value = COMPUTING;
33604
+ const prevConsumer = consumerBeforeComputation(node);
33605
+ let newValue;
33606
+ try {
33607
+ newValue = node.computation();
33608
+ }
33609
+ catch (err) {
33610
+ newValue = ERRORED;
33611
+ node.error = err;
33612
+ }
33613
+ finally {
33614
+ consumerAfterComputation(node, prevConsumer);
33615
+ }
33616
+ if (oldValue !== UNSET && oldValue !== ERRORED && newValue !== ERRORED &&
33617
+ node.equal(oldValue, newValue)) {
33618
+ // No change to `valueVersion` - old and new values are
33619
+ // semantically equivalent.
33620
+ node.value = oldValue;
33621
+ return;
33622
+ }
33623
+ node.value = newValue;
33624
+ node.version++;
33625
+ },
33626
+ };
33627
+ })();
33628
+
33629
+ function defaultThrowError() {
33630
+ throw new Error();
33631
+ }
33632
+ let throwInvalidWriteToSignalErrorFn = defaultThrowError;
33633
+ function throwInvalidWriteToSignalError() {
33634
+ throwInvalidWriteToSignalErrorFn();
33635
+ }
33636
+ function setThrowInvalidWriteToSignalError(fn) {
33637
+ throwInvalidWriteToSignalErrorFn = fn;
33638
+ }
33032
33639
 
33033
33640
  /**
33034
- * Re-exported by `BrowserModule`, which is included automatically in the root
33035
- * `AppModule` when you create a new app with the CLI `new` command. Eagerly injects
33036
- * `ApplicationRef` to instantiate it.
33641
+ * If set, called after `WritableSignal`s are updated.
33037
33642
  *
33038
- * @publicApi
33643
+ * This hook can be used to achieve various effects, such as running effects synchronously as part
33644
+ * of setting a signal.
33039
33645
  */
33040
- class ApplicationModule {
33041
- // Inject ApplicationRef to make it eager...
33042
- constructor(appRef) { }
33043
- static { this.ɵfac = function ApplicationModule_Factory(t) { return new (t || ApplicationModule)(ɵɵinject(ApplicationRef)); }; }
33044
- static { this.ɵmod = /*@__PURE__*/ ɵɵdefineNgModule({ type: ApplicationModule }); }
33045
- static { this.ɵinj = /*@__PURE__*/ ɵɵdefineInjector({}); }
33646
+ let postSignalSetFn = null;
33647
+ /**
33648
+ * Create a `Signal` that can be set or updated directly.
33649
+ */
33650
+ function createSignal(initialValue) {
33651
+ const node = Object.create(SIGNAL_NODE);
33652
+ node.value = initialValue;
33653
+ const getter = (() => {
33654
+ producerAccessed(node);
33655
+ return node.value;
33656
+ });
33657
+ getter[SIGNAL] = node;
33658
+ return getter;
33659
+ }
33660
+ function setPostSignalSetFn(fn) {
33661
+ const prev = postSignalSetFn;
33662
+ postSignalSetFn = fn;
33663
+ return prev;
33664
+ }
33665
+ function signalGetFn() {
33666
+ producerAccessed(this);
33667
+ return this.value;
33668
+ }
33669
+ function signalSetFn(node, newValue) {
33670
+ if (!producerUpdatesAllowed()) {
33671
+ throwInvalidWriteToSignalError();
33672
+ }
33673
+ if (!node.equal(node.value, newValue)) {
33674
+ node.value = newValue;
33675
+ signalValueChanged(node);
33676
+ }
33677
+ }
33678
+ function signalUpdateFn(node, updater) {
33679
+ if (!producerUpdatesAllowed()) {
33680
+ throwInvalidWriteToSignalError();
33681
+ }
33682
+ signalSetFn(node, updater(node.value));
33683
+ }
33684
+ function signalMutateFn(node, mutator) {
33685
+ if (!producerUpdatesAllowed()) {
33686
+ throwInvalidWriteToSignalError();
33687
+ }
33688
+ // Mutate bypasses equality checks as it's by definition changing the value.
33689
+ mutator(node.value);
33690
+ signalValueChanged(node);
33691
+ }
33692
+ // Note: Using an IIFE here to ensure that the spread assignment is not considered
33693
+ // a side-effect, ending up preserving `COMPUTED_NODE` and `REACTIVE_NODE`.
33694
+ // TODO: remove when https://github.com/evanw/esbuild/issues/3392 is resolved.
33695
+ const SIGNAL_NODE = /* @__PURE__ */ (() => {
33696
+ return {
33697
+ ...REACTIVE_NODE,
33698
+ equal: defaultEquals,
33699
+ value: undefined,
33700
+ };
33701
+ })();
33702
+ function signalValueChanged(node) {
33703
+ node.version++;
33704
+ producerNotifyConsumers(node);
33705
+ postSignalSetFn?.();
33706
+ }
33707
+
33708
+ function createWatch(fn, schedule, allowSignalWrites) {
33709
+ const node = Object.create(WATCH_NODE);
33710
+ if (allowSignalWrites) {
33711
+ node.consumerAllowSignalWrites = true;
33712
+ }
33713
+ node.fn = fn;
33714
+ node.schedule = schedule;
33715
+ const registerOnCleanup = (cleanupFn) => {
33716
+ node.cleanupFn = cleanupFn;
33717
+ };
33718
+ function isWatchNodeDestroyed(node) {
33719
+ return node.fn === null && node.schedule === null;
33720
+ }
33721
+ function destroyWatchNode(node) {
33722
+ if (!isWatchNodeDestroyed(node)) {
33723
+ consumerDestroy(node); // disconnect watcher from the reactive graph
33724
+ node.cleanupFn();
33725
+ // nullify references to the integration functions to mark node as destroyed
33726
+ node.fn = null;
33727
+ node.schedule = null;
33728
+ node.cleanupFn = NOOP_CLEANUP_FN;
33729
+ }
33730
+ }
33731
+ const run = () => {
33732
+ if (node.fn === null) {
33733
+ // trying to run a destroyed watch is noop
33734
+ return;
33735
+ }
33736
+ if (isInNotificationPhase()) {
33737
+ throw new Error(`Schedulers cannot synchronously execute watches while scheduling.`);
33738
+ }
33739
+ node.dirty = false;
33740
+ if (node.hasRun && !consumerPollProducersForChange(node)) {
33741
+ return;
33742
+ }
33743
+ node.hasRun = true;
33744
+ const prevConsumer = consumerBeforeComputation(node);
33745
+ try {
33746
+ node.cleanupFn();
33747
+ node.cleanupFn = NOOP_CLEANUP_FN;
33748
+ node.fn(registerOnCleanup);
33749
+ }
33750
+ finally {
33751
+ consumerAfterComputation(node, prevConsumer);
33752
+ }
33753
+ };
33754
+ node.ref = {
33755
+ notify: () => consumerMarkDirty(node),
33756
+ run,
33757
+ cleanup: () => node.cleanupFn(),
33758
+ destroy: () => destroyWatchNode(node),
33759
+ [SIGNAL]: node,
33760
+ };
33761
+ return node.ref;
33762
+ }
33763
+ const NOOP_CLEANUP_FN = () => { };
33764
+ // Note: Using an IIFE here to ensure that the spread assignment is not considered
33765
+ // a side-effect, ending up preserving `COMPUTED_NODE` and `REACTIVE_NODE`.
33766
+ // TODO: remove when https://github.com/evanw/esbuild/issues/3392 is resolved.
33767
+ const WATCH_NODE = /* @__PURE__ */ (() => {
33768
+ return {
33769
+ ...REACTIVE_NODE,
33770
+ consumerIsAlwaysLive: true,
33771
+ consumerAllowSignalWrites: false,
33772
+ consumerMarkedDirty: (node) => {
33773
+ if (node.schedule !== null) {
33774
+ node.schedule(node.ref);
33775
+ }
33776
+ },
33777
+ hasRun: false,
33778
+ cleanupFn: NOOP_CLEANUP_FN,
33779
+ };
33780
+ })();
33781
+
33782
+ function setAlternateWeakRefImpl(impl) {
33783
+ // TODO: remove this function
33046
33784
  }
33047
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ApplicationModule, [{
33048
- type: NgModule
33049
- }], () => [{ type: ApplicationRef }], null); })();
33050
33785
 
33051
33786
  /**
33052
33787
  * A collection that tracks all serialized views (`ngh` DOM annotations)
@@ -33868,166 +34603,6 @@ function ɵɵngDeclarePipe(decl) {
33868
34603
  // clang-format off
33869
34604
  // clang-format on
33870
34605
 
33871
- /**
33872
- * Not public API, which guarantees `EffectScheduler` only ever comes from the application root
33873
- * injector.
33874
- */
33875
- const APP_EFFECT_SCHEDULER = new InjectionToken('', {
33876
- providedIn: 'root',
33877
- factory: () => inject(EffectScheduler),
33878
- });
33879
- /**
33880
- * A scheduler which manages the execution of effects.
33881
- */
33882
- class EffectScheduler {
33883
- /** @nocollapse */
33884
- static { this.ɵprov = ɵɵdefineInjectable({
33885
- token: EffectScheduler,
33886
- providedIn: 'root',
33887
- factory: () => new ZoneAwareMicrotaskScheduler(),
33888
- }); }
33889
- }
33890
- /**
33891
- * An `EffectScheduler` which is capable of queueing scheduled effects per-zone, and flushing them
33892
- * as an explicit operation.
33893
- */
33894
- class ZoneAwareQueueingScheduler {
33895
- constructor() {
33896
- this.queuedEffectCount = 0;
33897
- this.queues = new Map();
33898
- }
33899
- scheduleEffect(handle) {
33900
- const zone = handle.creationZone;
33901
- if (!this.queues.has(zone)) {
33902
- this.queues.set(zone, new Set());
33903
- }
33904
- const queue = this.queues.get(zone);
33905
- if (queue.has(handle)) {
33906
- return;
33907
- }
33908
- this.queuedEffectCount++;
33909
- queue.add(handle);
33910
- }
33911
- /**
33912
- * Run all scheduled effects.
33913
- *
33914
- * Execution order of effects within the same zone is guaranteed to be FIFO, but there is no
33915
- * ordering guarantee between effects scheduled in different zones.
33916
- */
33917
- flush() {
33918
- while (this.queuedEffectCount > 0) {
33919
- for (const [zone, queue] of this.queues) {
33920
- // `zone` here must be defined.
33921
- if (zone === null) {
33922
- this.flushQueue(queue);
33923
- }
33924
- else {
33925
- zone.run(() => this.flushQueue(queue));
33926
- }
33927
- }
33928
- }
33929
- }
33930
- flushQueue(queue) {
33931
- for (const handle of queue) {
33932
- queue.delete(handle);
33933
- this.queuedEffectCount--;
33934
- // TODO: what happens if this throws an error?
33935
- handle.run();
33936
- }
33937
- }
33938
- /** @nocollapse */
33939
- static { this.ɵprov = ɵɵdefineInjectable({
33940
- token: ZoneAwareQueueingScheduler,
33941
- providedIn: 'root',
33942
- factory: () => new ZoneAwareQueueingScheduler(),
33943
- }); }
33944
- }
33945
- /**
33946
- * A wrapper around `ZoneAwareQueueingScheduler` that schedules flushing via the microtask queue
33947
- * when.
33948
- */
33949
- class ZoneAwareMicrotaskScheduler {
33950
- constructor() {
33951
- this.hasQueuedFlush = false;
33952
- this.delegate = new ZoneAwareQueueingScheduler();
33953
- this.flushTask = () => {
33954
- // Leave `hasQueuedFlush` as `true` so we don't queue another microtask if more effects are
33955
- // scheduled during flushing. The flush of the `ZoneAwareQueueingScheduler` delegate is
33956
- // guaranteed to empty the queue.
33957
- this.delegate.flush();
33958
- this.hasQueuedFlush = false;
33959
- // This is a variable initialization, not a method.
33960
- // tslint:disable-next-line:semicolon
33961
- };
33962
- }
33963
- scheduleEffect(handle) {
33964
- this.delegate.scheduleEffect(handle);
33965
- if (!this.hasQueuedFlush) {
33966
- queueMicrotask(this.flushTask);
33967
- this.hasQueuedFlush = true;
33968
- }
33969
- }
33970
- }
33971
- /**
33972
- * Core reactive node for an Angular effect.
33973
- *
33974
- * `EffectHandle` combines the reactive graph's `Watch` base node for effects with the framework's
33975
- * scheduling abstraction (`EffectScheduler`) as well as automatic cleanup via `DestroyRef` if
33976
- * available/requested.
33977
- */
33978
- class EffectHandle {
33979
- constructor(scheduler, effectFn, creationZone, destroyRef, errorHandler, allowSignalWrites) {
33980
- this.scheduler = scheduler;
33981
- this.effectFn = effectFn;
33982
- this.creationZone = creationZone;
33983
- this.errorHandler = errorHandler;
33984
- this.watcher =
33985
- watch((onCleanup) => this.runEffect(onCleanup), () => this.schedule(), allowSignalWrites);
33986
- this.unregisterOnDestroy = destroyRef?.onDestroy(() => this.destroy());
33987
- }
33988
- runEffect(onCleanup) {
33989
- try {
33990
- this.effectFn(onCleanup);
33991
- }
33992
- catch (err) {
33993
- this.errorHandler?.handleError(err);
33994
- }
33995
- }
33996
- run() {
33997
- this.watcher.run();
33998
- }
33999
- schedule() {
34000
- this.scheduler.scheduleEffect(this);
34001
- }
34002
- notify() {
34003
- this.watcher.notify();
34004
- }
34005
- destroy() {
34006
- this.watcher.destroy();
34007
- this.unregisterOnDestroy?.();
34008
- // Note: if the effect is currently scheduled, it's not un-scheduled, and so the scheduler will
34009
- // retain a reference to it. Attempting to execute it will be a no-op.
34010
- }
34011
- }
34012
- /**
34013
- * Create a global `Effect` for the given reactive function.
34014
- *
34015
- * @developerPreview
34016
- */
34017
- function effect(effectFn, options) {
34018
- !options?.injector && assertInInjectionContext(effect);
34019
- const injector = options?.injector ?? inject(Injector);
34020
- const errorHandler = injector.get(ErrorHandler, null, { optional: true });
34021
- const destroyRef = options?.manualCleanup !== true ? injector.get(DestroyRef) : null;
34022
- const handle = new EffectHandle(injector.get(APP_EFFECT_SCHEDULER), effectFn, (typeof Zone === 'undefined') ? null : Zone.current, destroyRef, errorHandler, options?.allowSignalWrites ?? false);
34023
- // Effects start dirty.
34024
- handle.notify();
34025
- return handle;
34026
- }
34027
-
34028
- // clang-format off
34029
- // clang-format on
34030
-
34031
34606
  // This file exists to allow the set of reactivity exports to be modified in g3, as these APIs are
34032
34607
 
34033
34608
  /**
@@ -34215,5 +34790,5 @@ if (typeof ngDevMode !== 'undefined' && ngDevMode) {
34215
34790
  * Generated bundle index. Do not edit.
34216
34791
  */
34217
34792
 
34218
- export { ANIMATION_MODULE_TYPE, APP_BOOTSTRAP_LISTENER, APP_ID, APP_INITIALIZER, AfterRenderPhase, ApplicationInitStatus, ApplicationModule, ApplicationRef, Attribute, COMPILER_OPTIONS, CSP_NONCE, CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, ChangeDetectorRef, Compiler, CompilerFactory, Component, ComponentFactory$1 as ComponentFactory, ComponentFactoryResolver$1 as ComponentFactoryResolver, ComponentRef$1 as ComponentRef, ContentChild, ContentChildren, DEFAULT_CURRENCY_CODE, DebugElement, DebugEventListener, DebugNode, DefaultIterableDiffer, DestroyRef, Directive, ENVIRONMENT_INITIALIZER, ElementRef, EmbeddedViewRef, EnvironmentInjector, ErrorHandler, EventEmitter, Host, HostBinding, HostListener, INJECTOR, Inject, InjectFlags, Injectable, InjectionToken, Injector, Input, IterableDiffers, KeyValueDiffers, LOCALE_ID, MissingTranslationStrategy, ModuleWithComponentFactories, NO_ERRORS_SCHEMA, NgModule, NgModuleFactory$1 as NgModuleFactory, NgModuleRef$1 as NgModuleRef, NgProbeToken, NgZone, Optional, Output, PACKAGE_ROOT_URL, PLATFORM_ID, PLATFORM_INITIALIZER, Pipe, PlatformRef, Query, QueryList, Renderer2, RendererFactory2, RendererStyleFlags2, Sanitizer, SecurityContext, Self, SimpleChange, SkipSelf, TRANSLATIONS, TRANSLATIONS_FORMAT, TemplateRef, Testability, TestabilityRegistry, TransferState, Type, VERSION, Version, ViewChild, ViewChildren, ViewContainerRef, ViewEncapsulation$1 as ViewEncapsulation, ViewRef, afterNextRender, afterRender, asNativeElements, assertInInjectionContext, assertPlatform, booleanAttribute, computed, createComponent, createEnvironmentInjector, createNgModule, createNgModuleRef, createPlatform, createPlatformFactory, defineInjectable, destroyPlatform, effect, enableProdMode, forwardRef, getDebugNode, getModuleFactory, getNgModuleById, getPlatform, importProvidersFrom, inject, isDevMode, isSignal, isStandalone, makeEnvironmentProviders, makeStateKey, mergeApplicationConfig, numberAttribute, platformCore, provideZoneChangeDetection, reflectComponentType, resolveForwardRef, runInInjectionContext, setTestabilityGetter, signal, untracked, ALLOW_MULTIPLE_PLATFORMS as ɵALLOW_MULTIPLE_PLATFORMS, AfterRenderEventManager as ɵAfterRenderEventManager, CONTAINER_HEADER_OFFSET as ɵCONTAINER_HEADER_OFFSET, ComponentFactory$1 as ɵComponentFactory, Console as ɵConsole, DEFAULT_LOCALE_ID as ɵDEFAULT_LOCALE_ID, DEFER_BLOCK_CONFIG as ɵDEFER_BLOCK_CONFIG, DEFER_BLOCK_DEPENDENCY_INTERCEPTOR as ɵDEFER_BLOCK_DEPENDENCY_INTERCEPTOR, DeferBlockBehavior as ɵDeferBlockBehavior, DeferBlockState as ɵDeferBlockState, ENABLED_SSR_FEATURES as ɵENABLED_SSR_FEATURES, EffectScheduler as ɵEffectScheduler, INJECTOR_SCOPE as ɵINJECTOR_SCOPE, IS_HYDRATION_DOM_REUSE_ENABLED as ɵIS_HYDRATION_DOM_REUSE_ENABLED, InitialRenderPendingTasks as ɵInitialRenderPendingTasks, LContext as ɵLContext, LifecycleHooksFeature as ɵLifecycleHooksFeature, LocaleDataIndex as ɵLocaleDataIndex, NG_COMP_DEF as ɵNG_COMP_DEF, NG_DIR_DEF as ɵNG_DIR_DEF, NG_ELEMENT_ID as ɵNG_ELEMENT_ID, NG_INJ_DEF as ɵNG_INJ_DEF, NG_MOD_DEF as ɵNG_MOD_DEF, NG_PIPE_DEF as ɵNG_PIPE_DEF, NG_PROV_DEF as ɵNG_PROV_DEF, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR as ɵNOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR, NO_CHANGE as ɵNO_CHANGE, NgModuleFactory as ɵNgModuleFactory, NoopNgZone as ɵNoopNgZone, ReflectionCapabilities as ɵReflectionCapabilities, ComponentFactory as ɵRender3ComponentFactory, ComponentRef as ɵRender3ComponentRef, NgModuleRef as ɵRender3NgModuleRef, RuntimeError as ɵRuntimeError, SSR_CONTENT_INTEGRITY_MARKER as ɵSSR_CONTENT_INTEGRITY_MARKER, TESTABILITY as ɵTESTABILITY, TESTABILITY_GETTER as ɵTESTABILITY_GETTER, USE_RUNTIME_DEPS_TRACKER_FOR_JIT as ɵUSE_RUNTIME_DEPS_TRACKER_FOR_JIT, ViewRef$1 as ɵViewRef, XSS_SECURITY_URL as ɵXSS_SECURITY_URL, ZoneAwareQueueingScheduler as ɵZoneAwareQueueingScheduler, _sanitizeHtml as ɵ_sanitizeHtml, _sanitizeUrl as ɵ_sanitizeUrl, allowSanitizationBypassAndThrow as ɵallowSanitizationBypassAndThrow, annotateForHydration as ɵannotateForHydration, bypassSanitizationTrustHtml as ɵbypassSanitizationTrustHtml, bypassSanitizationTrustResourceUrl as ɵbypassSanitizationTrustResourceUrl, bypassSanitizationTrustScript as ɵbypassSanitizationTrustScript, bypassSanitizationTrustStyle as ɵbypassSanitizationTrustStyle, bypassSanitizationTrustUrl as ɵbypassSanitizationTrustUrl, clearResolutionOfComponentResourcesQueue as ɵclearResolutionOfComponentResourcesQueue, compileComponent as ɵcompileComponent, compileDirective as ɵcompileDirective, compileNgModule as ɵcompileNgModule, compileNgModuleDefs as ɵcompileNgModuleDefs, compileNgModuleFactory as ɵcompileNgModuleFactory, compilePipe as ɵcompilePipe, convertToBitFlags as ɵconvertToBitFlags, createInjector as ɵcreateInjector, defaultIterableDiffers as ɵdefaultIterableDiffers, defaultKeyValueDiffers as ɵdefaultKeyValueDiffers, depsTracker as ɵdepsTracker, detectChanges as ɵdetectChanges, devModeEqual as ɵdevModeEqual, findLocaleData as ɵfindLocaleData, flushModuleScopingQueueAsMuchAsPossible as ɵflushModuleScopingQueueAsMuchAsPossible, formatRuntimeError as ɵformatRuntimeError, generateStandaloneInDeclarationsError as ɵgenerateStandaloneInDeclarationsError, getAsyncClassMetadata as ɵgetAsyncClassMetadata, getDebugNode as ɵgetDebugNode, getDeferBlocks as ɵgetDeferBlocks, getDirectives as ɵgetDirectives, getHostElement as ɵgetHostElement, getInjectableDef as ɵgetInjectableDef, getLContext as ɵgetLContext, getLocaleCurrencyCode as ɵgetLocaleCurrencyCode, getLocalePluralCase as ɵgetLocalePluralCase, getSanitizationBypassType as ɵgetSanitizationBypassType, ɵgetUnknownElementStrictMode, ɵgetUnknownPropertyStrictMode, _global as ɵglobal, injectChangeDetectorRef as ɵinjectChangeDetectorRef, internalCreateApplication as ɵinternalCreateApplication, isBoundToModule as ɵisBoundToModule, isComponentDefPendingResolution as ɵisComponentDefPendingResolution, isEnvironmentProviders as ɵisEnvironmentProviders, isInjectable as ɵisInjectable, isNgModule as ɵisNgModule, isPromise as ɵisPromise, isSubscribable as ɵisSubscribable, noSideEffects as ɵnoSideEffects, patchComponentDefWithScope as ɵpatchComponentDefWithScope, publishDefaultGlobalUtils$1 as ɵpublishDefaultGlobalUtils, publishGlobalUtil as ɵpublishGlobalUtil, registerLocaleData as ɵregisterLocaleData, renderDeferBlockState as ɵrenderDeferBlockState, resetCompiledComponents as ɵresetCompiledComponents, resetJitOptions as ɵresetJitOptions, resolveComponentResources as ɵresolveComponentResources, restoreComponentResolutionQueue as ɵrestoreComponentResolutionQueue, setAllowDuplicateNgModuleIdsForTest as ɵsetAllowDuplicateNgModuleIdsForTest, setAlternateWeakRefImpl as ɵsetAlternateWeakRefImpl, setClassMetadata as ɵsetClassMetadata, setClassMetadataAsync as ɵsetClassMetadataAsync, setCurrentInjector as ɵsetCurrentInjector, setDocument as ɵsetDocument, setInjectorProfilerContext as ɵsetInjectorProfilerContext, setLocaleId as ɵsetLocaleId, ɵsetUnknownElementStrictMode, ɵsetUnknownPropertyStrictMode, store as ɵstore, stringify as ɵstringify, transitiveScopesFor as ɵtransitiveScopesFor, triggerResourceLoading as ɵtriggerResourceLoading, unregisterAllLocaleData as ɵunregisterLocaleData, unwrapSafeValue as ɵunwrapSafeValue, whenStable as ɵwhenStable, withDomHydration as ɵwithDomHydration, ɵɵCopyDefinitionFeature, FactoryTarget as ɵɵFactoryTarget, ɵɵHostDirectivesFeature, ɵɵInheritDefinitionFeature, ɵɵInputTransformsFeature, ɵɵNgOnChangesFeature, ɵɵProvidersFeature, ɵɵStandaloneFeature, ɵɵadvance, ɵɵattribute, ɵɵattributeInterpolate1, ɵɵattributeInterpolate2, ɵɵattributeInterpolate3, ɵɵattributeInterpolate4, ɵɵattributeInterpolate5, ɵɵattributeInterpolate6, ɵɵattributeInterpolate7, ɵɵattributeInterpolate8, ɵɵattributeInterpolateV, ɵɵclassMap, ɵɵclassMapInterpolate1, ɵɵclassMapInterpolate2, ɵɵclassMapInterpolate3, ɵɵclassMapInterpolate4, ɵɵclassMapInterpolate5, ɵɵclassMapInterpolate6, ɵɵclassMapInterpolate7, ɵɵclassMapInterpolate8, ɵɵclassMapInterpolateV, ɵɵclassProp, ɵɵcomponentInstance, ɵɵconditional, ɵɵcontentQuery, ɵɵdefer, ɵɵdeferOnHover, ɵɵdeferOnIdle, ɵɵdeferOnImmediate, ɵɵdeferOnInteraction, ɵɵdeferOnTimer, ɵɵdeferOnViewport, ɵɵdeferPrefetchOnHover, ɵɵdeferPrefetchOnIdle, ɵɵdeferPrefetchOnImmediate, ɵɵdeferPrefetchOnInteraction, ɵɵdeferPrefetchOnTimer, ɵɵdeferPrefetchOnViewport, ɵɵdeferPrefetchWhen, ɵɵdeferWhen, ɵɵdefineComponent, ɵɵdefineDirective, ɵɵdefineInjectable, ɵɵdefineInjector, ɵɵdefineNgModule, ɵɵdefinePipe, ɵɵdirectiveInject, ɵɵdisableBindings, ɵɵelement, ɵɵelementContainer, ɵɵelementContainerEnd, ɵɵelementContainerStart, ɵɵelementEnd, ɵɵelementStart, ɵɵenableBindings, ɵɵgetComponentDepsFactory, ɵɵgetCurrentView, ɵɵgetInheritedFactory, ɵɵhostProperty, ɵɵi18n, ɵɵi18nApply, ɵɵi18nAttributes, ɵɵi18nEnd, ɵɵi18nExp, ɵɵi18nPostprocess, ɵɵi18nStart, ɵɵinject, ɵɵinjectAttribute, ɵɵinvalidFactory, ɵɵinvalidFactoryDep, ɵɵlistener, ɵɵloadQuery, ɵɵnamespaceHTML, ɵɵnamespaceMathML, ɵɵnamespaceSVG, ɵɵnextContext, ɵɵngDeclareClassMetadata, ɵɵngDeclareComponent, ɵɵngDeclareDirective, ɵɵngDeclareFactory, ɵɵngDeclareInjectable, ɵɵngDeclareInjector, ɵɵngDeclareNgModule, ɵɵngDeclarePipe, ɵɵpipe, ɵɵpipeBind1, ɵɵpipeBind2, ɵɵpipeBind3, ɵɵpipeBind4, ɵɵpipeBindV, ɵɵprojection, ɵɵprojectionDef, ɵɵproperty, ɵɵpropertyInterpolate, ɵɵpropertyInterpolate1, ɵɵpropertyInterpolate2, ɵɵpropertyInterpolate3, ɵɵpropertyInterpolate4, ɵɵpropertyInterpolate5, ɵɵpropertyInterpolate6, ɵɵpropertyInterpolate7, ɵɵpropertyInterpolate8, ɵɵpropertyInterpolateV, ɵɵpureFunction0, ɵɵpureFunction1, ɵɵpureFunction2, ɵɵpureFunction3, ɵɵpureFunction4, ɵɵpureFunction5, ɵɵpureFunction6, ɵɵpureFunction7, ɵɵpureFunction8, ɵɵpureFunctionV, ɵɵqueryRefresh, ɵɵreference, registerNgModuleType as ɵɵregisterNgModuleType, ɵɵrepeater, ɵɵrepeaterCreate, ɵɵrepeaterTrackByIdentity, ɵɵrepeaterTrackByIndex, ɵɵresetView, ɵɵresolveBody, ɵɵresolveDocument, ɵɵresolveWindow, ɵɵrestoreView, ɵɵsanitizeHtml, ɵɵsanitizeResourceUrl, ɵɵsanitizeScript, ɵɵsanitizeStyle, ɵɵsanitizeUrl, ɵɵsanitizeUrlOrResourceUrl, ɵɵsetComponentScope, ɵɵsetNgModuleScope, ɵɵstyleMap, ɵɵstyleMapInterpolate1, ɵɵstyleMapInterpolate2, ɵɵstyleMapInterpolate3, ɵɵstyleMapInterpolate4, ɵɵstyleMapInterpolate5, ɵɵstyleMapInterpolate6, ɵɵstyleMapInterpolate7, ɵɵstyleMapInterpolate8, ɵɵstyleMapInterpolateV, ɵɵstyleProp, ɵɵstylePropInterpolate1, ɵɵstylePropInterpolate2, ɵɵstylePropInterpolate3, ɵɵstylePropInterpolate4, ɵɵstylePropInterpolate5, ɵɵstylePropInterpolate6, ɵɵstylePropInterpolate7, ɵɵstylePropInterpolate8, ɵɵstylePropInterpolateV, ɵɵsyntheticHostListener, ɵɵsyntheticHostProperty, ɵɵtemplate, ɵɵtemplateRefExtractor, ɵɵtext, ɵɵtextInterpolate, ɵɵtextInterpolate1, ɵɵtextInterpolate2, ɵɵtextInterpolate3, ɵɵtextInterpolate4, ɵɵtextInterpolate5, ɵɵtextInterpolate6, ɵɵtextInterpolate7, ɵɵtextInterpolate8, ɵɵtextInterpolateV, ɵɵtrustConstantHtml, ɵɵtrustConstantResourceUrl, ɵɵvalidateIframeAttribute, ɵɵviewQuery };
34793
+ export { ANIMATION_MODULE_TYPE, APP_BOOTSTRAP_LISTENER, APP_ID, APP_INITIALIZER, AfterRenderPhase, ApplicationInitStatus, ApplicationModule, ApplicationRef, Attribute, COMPILER_OPTIONS, CSP_NONCE, CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, ChangeDetectorRef, Compiler, CompilerFactory, Component, ComponentFactory$1 as ComponentFactory, ComponentFactoryResolver$1 as ComponentFactoryResolver, ComponentRef$1 as ComponentRef, ContentChild, ContentChildren, DEFAULT_CURRENCY_CODE, DebugElement, DebugEventListener, DebugNode, DefaultIterableDiffer, DestroyRef, Directive, ENVIRONMENT_INITIALIZER, ElementRef, EmbeddedViewRef, EnvironmentInjector, ErrorHandler, EventEmitter, Host, HostBinding, HostListener, INJECTOR, Inject, InjectFlags, Injectable, InjectionToken, Injector, Input, IterableDiffers, KeyValueDiffers, LOCALE_ID, MissingTranslationStrategy, ModuleWithComponentFactories, NO_ERRORS_SCHEMA, NgModule, NgModuleFactory$1 as NgModuleFactory, NgModuleRef$1 as NgModuleRef, NgProbeToken, NgZone, Optional, Output, PACKAGE_ROOT_URL, PLATFORM_ID, PLATFORM_INITIALIZER, Pipe, PlatformRef, Query, QueryList, Renderer2, RendererFactory2, RendererStyleFlags2, Sanitizer, SecurityContext, Self, SimpleChange, SkipSelf, TRANSLATIONS, TRANSLATIONS_FORMAT, TemplateRef, Testability, TestabilityRegistry, TransferState, Type, VERSION, Version, ViewChild, ViewChildren, ViewContainerRef, ViewEncapsulation$1 as ViewEncapsulation, ViewRef, afterNextRender, afterRender, asNativeElements, assertInInjectionContext, assertNotInReactiveContext, assertPlatform, booleanAttribute, computed, createComponent, createEnvironmentInjector, createNgModule, createNgModuleRef, createPlatform, createPlatformFactory, defineInjectable, destroyPlatform, effect, enableProdMode, forwardRef, getDebugNode, getModuleFactory, getNgModuleById, getPlatform, importProvidersFrom, inject, isDevMode, isSignal, isStandalone, makeEnvironmentProviders, makeStateKey, mergeApplicationConfig, numberAttribute, platformCore, provideZoneChangeDetection, reflectComponentType, resolveForwardRef, runInInjectionContext, setTestabilityGetter, signal, untracked, ALLOW_MULTIPLE_PLATFORMS as ɵALLOW_MULTIPLE_PLATFORMS, AfterRenderEventManager as ɵAfterRenderEventManager, CONTAINER_HEADER_OFFSET as ɵCONTAINER_HEADER_OFFSET, ComponentFactory$1 as ɵComponentFactory, Console as ɵConsole, DEFAULT_LOCALE_ID as ɵDEFAULT_LOCALE_ID, DEFER_BLOCK_CONFIG as ɵDEFER_BLOCK_CONFIG, DEFER_BLOCK_DEPENDENCY_INTERCEPTOR as ɵDEFER_BLOCK_DEPENDENCY_INTERCEPTOR, DeferBlockBehavior as ɵDeferBlockBehavior, DeferBlockState as ɵDeferBlockState, ENABLED_SSR_FEATURES as ɵENABLED_SSR_FEATURES, EffectScheduler as ɵEffectScheduler, IMAGE_CONFIG as ɵIMAGE_CONFIG, IMAGE_CONFIG_DEFAULTS as ɵIMAGE_CONFIG_DEFAULTS, INJECTOR_SCOPE as ɵINJECTOR_SCOPE, IS_HYDRATION_DOM_REUSE_ENABLED as ɵIS_HYDRATION_DOM_REUSE_ENABLED, InitialRenderPendingTasks as ɵInitialRenderPendingTasks, LContext as ɵLContext, LifecycleHooksFeature as ɵLifecycleHooksFeature, LocaleDataIndex as ɵLocaleDataIndex, NG_COMP_DEF as ɵNG_COMP_DEF, NG_DIR_DEF as ɵNG_DIR_DEF, NG_ELEMENT_ID as ɵNG_ELEMENT_ID, NG_INJ_DEF as ɵNG_INJ_DEF, NG_MOD_DEF as ɵNG_MOD_DEF, NG_PIPE_DEF as ɵNG_PIPE_DEF, NG_PROV_DEF as ɵNG_PROV_DEF, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR as ɵNOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR, NO_CHANGE as ɵNO_CHANGE, NgModuleFactory as ɵNgModuleFactory, NoopNgZone as ɵNoopNgZone, ReflectionCapabilities as ɵReflectionCapabilities, ComponentFactory as ɵRender3ComponentFactory, ComponentRef as ɵRender3ComponentRef, NgModuleRef as ɵRender3NgModuleRef, RuntimeError as ɵRuntimeError, SSR_CONTENT_INTEGRITY_MARKER as ɵSSR_CONTENT_INTEGRITY_MARKER, TESTABILITY as ɵTESTABILITY, TESTABILITY_GETTER as ɵTESTABILITY_GETTER, USE_RUNTIME_DEPS_TRACKER_FOR_JIT as ɵUSE_RUNTIME_DEPS_TRACKER_FOR_JIT, ViewRef$1 as ɵViewRef, XSS_SECURITY_URL as ɵXSS_SECURITY_URL, ZoneAwareQueueingScheduler as ɵZoneAwareQueueingScheduler, _sanitizeHtml as ɵ_sanitizeHtml, _sanitizeUrl as ɵ_sanitizeUrl, allowSanitizationBypassAndThrow as ɵallowSanitizationBypassAndThrow, annotateForHydration as ɵannotateForHydration, bypassSanitizationTrustHtml as ɵbypassSanitizationTrustHtml, bypassSanitizationTrustResourceUrl as ɵbypassSanitizationTrustResourceUrl, bypassSanitizationTrustScript as ɵbypassSanitizationTrustScript, bypassSanitizationTrustStyle as ɵbypassSanitizationTrustStyle, bypassSanitizationTrustUrl as ɵbypassSanitizationTrustUrl, clearResolutionOfComponentResourcesQueue as ɵclearResolutionOfComponentResourcesQueue, compileComponent as ɵcompileComponent, compileDirective as ɵcompileDirective, compileNgModule as ɵcompileNgModule, compileNgModuleDefs as ɵcompileNgModuleDefs, compileNgModuleFactory as ɵcompileNgModuleFactory, compilePipe as ɵcompilePipe, convertToBitFlags as ɵconvertToBitFlags, createInjector as ɵcreateInjector, defaultIterableDiffers as ɵdefaultIterableDiffers, defaultKeyValueDiffers as ɵdefaultKeyValueDiffers, depsTracker as ɵdepsTracker, detectChanges as ɵdetectChanges, devModeEqual as ɵdevModeEqual, findLocaleData as ɵfindLocaleData, flushModuleScopingQueueAsMuchAsPossible as ɵflushModuleScopingQueueAsMuchAsPossible, formatRuntimeError as ɵformatRuntimeError, generateStandaloneInDeclarationsError as ɵgenerateStandaloneInDeclarationsError, getAsyncClassMetadata as ɵgetAsyncClassMetadata, getDebugNode as ɵgetDebugNode, getDeferBlocks as ɵgetDeferBlocks, getDirectives as ɵgetDirectives, getHostElement as ɵgetHostElement, getInjectableDef as ɵgetInjectableDef, getLContext as ɵgetLContext, getLocaleCurrencyCode as ɵgetLocaleCurrencyCode, getLocalePluralCase as ɵgetLocalePluralCase, getSanitizationBypassType as ɵgetSanitizationBypassType, ɵgetUnknownElementStrictMode, ɵgetUnknownPropertyStrictMode, _global as ɵglobal, injectChangeDetectorRef as ɵinjectChangeDetectorRef, internalCreateApplication as ɵinternalCreateApplication, isBoundToModule as ɵisBoundToModule, isComponentDefPendingResolution as ɵisComponentDefPendingResolution, isEnvironmentProviders as ɵisEnvironmentProviders, isInjectable as ɵisInjectable, isNgModule as ɵisNgModule, isPromise as ɵisPromise, isSubscribable as ɵisSubscribable, noSideEffects as ɵnoSideEffects, patchComponentDefWithScope as ɵpatchComponentDefWithScope, publishDefaultGlobalUtils$1 as ɵpublishDefaultGlobalUtils, publishGlobalUtil as ɵpublishGlobalUtil, registerLocaleData as ɵregisterLocaleData, renderDeferBlockState as ɵrenderDeferBlockState, resetCompiledComponents as ɵresetCompiledComponents, resetJitOptions as ɵresetJitOptions, resolveComponentResources as ɵresolveComponentResources, restoreComponentResolutionQueue as ɵrestoreComponentResolutionQueue, setAllowDuplicateNgModuleIdsForTest as ɵsetAllowDuplicateNgModuleIdsForTest, setAlternateWeakRefImpl as ɵsetAlternateWeakRefImpl, ɵsetClassDebugInfo, setClassMetadata as ɵsetClassMetadata, setClassMetadataAsync as ɵsetClassMetadataAsync, setCurrentInjector as ɵsetCurrentInjector, setDocument as ɵsetDocument, setInjectorProfilerContext as ɵsetInjectorProfilerContext, setLocaleId as ɵsetLocaleId, ɵsetUnknownElementStrictMode, ɵsetUnknownPropertyStrictMode, store as ɵstore, stringify as ɵstringify, transitiveScopesFor as ɵtransitiveScopesFor, triggerResourceLoading as ɵtriggerResourceLoading, truncateMiddle as ɵtruncateMiddle, unregisterAllLocaleData as ɵunregisterLocaleData, unwrapSafeValue as ɵunwrapSafeValue, whenStable as ɵwhenStable, withDomHydration as ɵwithDomHydration, ɵɵCopyDefinitionFeature, FactoryTarget as ɵɵFactoryTarget, ɵɵHostDirectivesFeature, ɵɵInheritDefinitionFeature, ɵɵInputTransformsFeature, ɵɵNgOnChangesFeature, ɵɵProvidersFeature, ɵɵStandaloneFeature, ɵɵadvance, ɵɵattribute, ɵɵattributeInterpolate1, ɵɵattributeInterpolate2, ɵɵattributeInterpolate3, ɵɵattributeInterpolate4, ɵɵattributeInterpolate5, ɵɵattributeInterpolate6, ɵɵattributeInterpolate7, ɵɵattributeInterpolate8, ɵɵattributeInterpolateV, ɵɵclassMap, ɵɵclassMapInterpolate1, ɵɵclassMapInterpolate2, ɵɵclassMapInterpolate3, ɵɵclassMapInterpolate4, ɵɵclassMapInterpolate5, ɵɵclassMapInterpolate6, ɵɵclassMapInterpolate7, ɵɵclassMapInterpolate8, ɵɵclassMapInterpolateV, ɵɵclassProp, ɵɵcomponentInstance, ɵɵconditional, ɵɵcontentQuery, ɵɵdefer, ɵɵdeferEnableTimerScheduling, ɵɵdeferOnHover, ɵɵdeferOnIdle, ɵɵdeferOnImmediate, ɵɵdeferOnInteraction, ɵɵdeferOnTimer, ɵɵdeferOnViewport, ɵɵdeferPrefetchOnHover, ɵɵdeferPrefetchOnIdle, ɵɵdeferPrefetchOnImmediate, ɵɵdeferPrefetchOnInteraction, ɵɵdeferPrefetchOnTimer, ɵɵdeferPrefetchOnViewport, ɵɵdeferPrefetchWhen, ɵɵdeferWhen, ɵɵdefineComponent, ɵɵdefineDirective, ɵɵdefineInjectable, ɵɵdefineInjector, ɵɵdefineNgModule, ɵɵdefinePipe, ɵɵdirectiveInject, ɵɵdisableBindings, ɵɵelement, ɵɵelementContainer, ɵɵelementContainerEnd, ɵɵelementContainerStart, ɵɵelementEnd, ɵɵelementStart, ɵɵenableBindings, ɵɵgetComponentDepsFactory, ɵɵgetCurrentView, ɵɵgetInheritedFactory, ɵɵhostProperty, ɵɵi18n, ɵɵi18nApply, ɵɵi18nAttributes, ɵɵi18nEnd, ɵɵi18nExp, ɵɵi18nPostprocess, ɵɵi18nStart, ɵɵinject, ɵɵinjectAttribute, ɵɵinvalidFactory, ɵɵinvalidFactoryDep, ɵɵlistener, ɵɵloadQuery, ɵɵnamespaceHTML, ɵɵnamespaceMathML, ɵɵnamespaceSVG, ɵɵnextContext, ɵɵngDeclareClassMetadata, ɵɵngDeclareComponent, ɵɵngDeclareDirective, ɵɵngDeclareFactory, ɵɵngDeclareInjectable, ɵɵngDeclareInjector, ɵɵngDeclareNgModule, ɵɵngDeclarePipe, ɵɵpipe, ɵɵpipeBind1, ɵɵpipeBind2, ɵɵpipeBind3, ɵɵpipeBind4, ɵɵpipeBindV, ɵɵprojection, ɵɵprojectionDef, ɵɵproperty, ɵɵpropertyInterpolate, ɵɵpropertyInterpolate1, ɵɵpropertyInterpolate2, ɵɵpropertyInterpolate3, ɵɵpropertyInterpolate4, ɵɵpropertyInterpolate5, ɵɵpropertyInterpolate6, ɵɵpropertyInterpolate7, ɵɵpropertyInterpolate8, ɵɵpropertyInterpolateV, ɵɵpureFunction0, ɵɵpureFunction1, ɵɵpureFunction2, ɵɵpureFunction3, ɵɵpureFunction4, ɵɵpureFunction5, ɵɵpureFunction6, ɵɵpureFunction7, ɵɵpureFunction8, ɵɵpureFunctionV, ɵɵqueryRefresh, ɵɵreference, registerNgModuleType as ɵɵregisterNgModuleType, ɵɵrepeater, ɵɵrepeaterCreate, ɵɵrepeaterTrackByIdentity, ɵɵrepeaterTrackByIndex, ɵɵresetView, ɵɵresolveBody, ɵɵresolveDocument, ɵɵresolveWindow, ɵɵrestoreView, ɵɵsanitizeHtml, ɵɵsanitizeResourceUrl, ɵɵsanitizeScript, ɵɵsanitizeStyle, ɵɵsanitizeUrl, ɵɵsanitizeUrlOrResourceUrl, ɵɵsetComponentScope, ɵɵsetNgModuleScope, ɵɵstyleMap, ɵɵstyleMapInterpolate1, ɵɵstyleMapInterpolate2, ɵɵstyleMapInterpolate3, ɵɵstyleMapInterpolate4, ɵɵstyleMapInterpolate5, ɵɵstyleMapInterpolate6, ɵɵstyleMapInterpolate7, ɵɵstyleMapInterpolate8, ɵɵstyleMapInterpolateV, ɵɵstyleProp, ɵɵstylePropInterpolate1, ɵɵstylePropInterpolate2, ɵɵstylePropInterpolate3, ɵɵstylePropInterpolate4, ɵɵstylePropInterpolate5, ɵɵstylePropInterpolate6, ɵɵstylePropInterpolate7, ɵɵstylePropInterpolate8, ɵɵstylePropInterpolateV, ɵɵsyntheticHostListener, ɵɵsyntheticHostProperty, ɵɵtemplate, ɵɵtemplateRefExtractor, ɵɵtext, ɵɵtextInterpolate, ɵɵtextInterpolate1, ɵɵtextInterpolate2, ɵɵtextInterpolate3, ɵɵtextInterpolate4, ɵɵtextInterpolate5, ɵɵtextInterpolate6, ɵɵtextInterpolate7, ɵɵtextInterpolate8, ɵɵtextInterpolateV, ɵɵtrustConstantHtml, ɵɵtrustConstantResourceUrl, ɵɵvalidateIframeAttribute, ɵɵviewQuery };
34219
34794
  //# sourceMappingURL=core.mjs.map