@angular/core 16.0.0-next.3 → 16.0.0-next.4

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 (59) hide show
  1. package/esm2020/src/application_tokens.mjs +33 -1
  2. package/esm2020/src/change_detection/change_detector_ref.mjs +4 -4
  3. package/esm2020/src/compiler/compiler_facade_interface.mjs +1 -1
  4. package/esm2020/src/core.mjs +2 -2
  5. package/esm2020/src/core_private_export.mjs +2 -1
  6. package/esm2020/src/core_reactivity_export_internal.mjs +1 -1
  7. package/esm2020/src/core_render3_private_export.mjs +1 -2
  8. package/esm2020/src/di/r3_injector.mjs +8 -1
  9. package/esm2020/src/errors.mjs +1 -1
  10. package/esm2020/src/hydration/annotate.mjs +118 -5
  11. package/esm2020/src/hydration/api.mjs +14 -1
  12. package/esm2020/src/hydration/cleanup.mjs +54 -3
  13. package/esm2020/src/hydration/compression.mjs +69 -0
  14. package/esm2020/src/hydration/error_handling.mjs +357 -15
  15. package/esm2020/src/hydration/interfaces.mjs +17 -1
  16. package/esm2020/src/hydration/node_lookup_utils.mjs +199 -7
  17. package/esm2020/src/hydration/utils.mjs +16 -3
  18. package/esm2020/src/hydration/views.mjs +19 -15
  19. package/esm2020/src/linker/destroy_ref.mjs +5 -2
  20. package/esm2020/src/linker/view_container_ref.mjs +8 -7
  21. package/esm2020/src/metadata/directives.mjs +8 -3
  22. package/esm2020/src/render3/instructions/element.mjs +16 -9
  23. package/esm2020/src/render3/instructions/element_container.mjs +2 -5
  24. package/esm2020/src/render3/instructions/element_validation.mjs +2 -2
  25. package/esm2020/src/render3/instructions/projection.mjs +7 -4
  26. package/esm2020/src/render3/instructions/template.mjs +4 -7
  27. package/esm2020/src/render3/instructions/text.mjs +6 -6
  28. package/esm2020/src/render3/interfaces/public_definitions.mjs +1 -1
  29. package/esm2020/src/render3/interfaces/type_checks.mjs +4 -1
  30. package/esm2020/src/render3/node_manipulation.mjs +2 -2
  31. package/esm2020/src/render3/node_selector_matcher.mjs +17 -5
  32. package/esm2020/src/render3/util/view_utils.mjs +12 -1
  33. package/esm2020/src/render3/view_ref.mjs +1 -1
  34. package/esm2020/src/signals/index.mjs +2 -1
  35. package/esm2020/src/signals/src/computed.mjs +3 -3
  36. package/esm2020/src/signals/src/effect.mjs +1 -3
  37. package/esm2020/src/signals/src/signal.mjs +3 -3
  38. package/esm2020/src/signals/src/watch.mjs +3 -3
  39. package/esm2020/src/signals/src/weak_ref.mjs +18 -2
  40. package/esm2020/src/util/ng_dev_mode.mjs +2 -1
  41. package/esm2020/src/version.mjs +1 -1
  42. package/esm2020/testing/src/logger.mjs +3 -3
  43. package/esm2020/testing/src/ng_zone_mock.mjs +3 -3
  44. package/esm2020/testing/src/test_bed_compiler.mjs +12 -7
  45. package/fesm2015/core.mjs +1066 -178
  46. package/fesm2015/core.mjs.map +1 -1
  47. package/fesm2015/testing.mjs +816 -68
  48. package/fesm2015/testing.mjs.map +1 -1
  49. package/fesm2020/core.mjs +1051 -170
  50. package/fesm2020/core.mjs.map +1 -1
  51. package/fesm2020/testing.mjs +810 -67
  52. package/fesm2020/testing.mjs.map +1 -1
  53. package/index.d.ts +128 -216
  54. package/package.json +1 -1
  55. package/schematics/migrations/relative-link-resolution/bundle.js +7 -7
  56. package/schematics/migrations/router-link-with-href/bundle.js +10 -10
  57. package/schematics/ng-generate/standalone-migration/bundle.js +473 -376
  58. package/schematics/ng-generate/standalone-migration/bundle.js.map +2 -2
  59. package/testing/index.d.ts +1 -1
package/fesm2020/core.mjs CHANGED
@@ -1,11 +1,11 @@
1
1
  /**
2
- * @license Angular v16.0.0-next.3
2
+ * @license Angular v16.0.0-next.4
3
3
  * (c) 2010-2022 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
6
6
 
7
7
  import { Subject, Subscription, Observable, merge as merge$1 } from 'rxjs';
8
- import { share } from 'rxjs/operators';
8
+ import { first, share } from 'rxjs/operators';
9
9
 
10
10
  function getClosureSafeProperty(objWithPropertyToExtract) {
11
11
  for (let key in objWithPropertyToExtract) {
@@ -558,6 +558,7 @@ function ngDevModeResetPerfCounters() {
558
558
  hydratedNodes: 0,
559
559
  hydratedComponents: 0,
560
560
  dehydratedViewsRemoved: 0,
561
+ dehydratedViewsCleanupRuns: 0,
561
562
  };
562
563
  // Make sure to refer to ngDevMode as ['ngDevMode'] for closure.
563
564
  const allowNgDevModeTrue = locationString.indexOf('ngDevMode=false') === -1;
@@ -1187,12 +1188,19 @@ function isCssClassMatching(attrs, cssClassToMatch, isProjectionMode) {
1187
1188
  ngDevMode &&
1188
1189
  assertEqual(cssClassToMatch, cssClassToMatch.toLowerCase(), 'Class name expected to be lowercase.');
1189
1190
  let i = 0;
1191
+ // Indicates whether we are processing value from the implicit
1192
+ // attribute section (i.e. before the first marker in the array).
1193
+ let isImplicitAttrsSection = true;
1190
1194
  while (i < attrs.length) {
1191
1195
  let item = attrs[i++];
1192
- if (isProjectionMode && item === 'class') {
1193
- item = attrs[i];
1194
- if (classIndexOf(item.toLowerCase(), cssClassToMatch, 0) !== -1) {
1195
- return true;
1196
+ if (typeof item === 'string' && isImplicitAttrsSection) {
1197
+ const value = attrs[i++];
1198
+ if (isProjectionMode && item === 'class') {
1199
+ // We found a `class` attribute in the implicit attribute section,
1200
+ // check if it matches the value of the `cssClassToMatch` argument.
1201
+ if (classIndexOf(value.toLowerCase(), cssClassToMatch, 0) !== -1) {
1202
+ return true;
1203
+ }
1196
1204
  }
1197
1205
  }
1198
1206
  else if (item === 1 /* AttributeMarker.Classes */) {
@@ -1204,6 +1212,11 @@ function isCssClassMatching(attrs, cssClassToMatch, isProjectionMode) {
1204
1212
  }
1205
1213
  return false;
1206
1214
  }
1215
+ else if (typeof item === 'number') {
1216
+ // We've came across a first marker, which indicates
1217
+ // that the implicit attribute section is over.
1218
+ isImplicitAttrsSection = false;
1219
+ }
1207
1220
  }
1208
1221
  return false;
1209
1222
  }
@@ -2038,6 +2051,9 @@ function isComponentDef(def) {
2038
2051
  function isRootView(target) {
2039
2052
  return (target[FLAGS] & 256 /* LViewFlags.IsRoot */) !== 0;
2040
2053
  }
2054
+ function isProjectionTNode(tNode) {
2055
+ return (tNode.type & 16 /* TNodeType.Projection */) === 16 /* TNodeType.Projection */;
2056
+ }
2041
2057
 
2042
2058
  // [Assert functions do not constraint type when they are guarded by a truthy
2043
2059
  // expression.](https://github.com/microsoft/TypeScript/issues/37295)
@@ -2451,6 +2467,17 @@ function storeLViewOnDestroy(lView, onDestroyCallback) {
2451
2467
  }
2452
2468
  lView[ON_DESTROY_HOOKS].push(onDestroyCallback);
2453
2469
  }
2470
+ /**
2471
+ * Removes previously registered LView-specific destroy callback.
2472
+ */
2473
+ function removeLViewOnDestroy(lView, onDestroyCallback) {
2474
+ if (lView[ON_DESTROY_HOOKS] === null)
2475
+ return;
2476
+ const destroyCBIdx = lView[ON_DESTROY_HOOKS].indexOf(onDestroyCallback);
2477
+ if (destroyCBIdx !== -1) {
2478
+ lView[ON_DESTROY_HOOKS].splice(destroyCBIdx, 1);
2479
+ }
2480
+ }
2454
2481
 
2455
2482
  const instructionState = {
2456
2483
  lFrame: createLFrame(null),
@@ -8447,6 +8474,7 @@ class R3Injector extends EnvironmentInjector {
8447
8474
  }
8448
8475
  onDestroy(callback) {
8449
8476
  this._onDestroyHooks.push(callback);
8477
+ return () => this.removeOnDestroy(callback);
8450
8478
  }
8451
8479
  runInContext(fn) {
8452
8480
  this.assertNotDestroyed();
@@ -8621,6 +8649,12 @@ class R3Injector extends EnvironmentInjector {
8621
8649
  return this.injectorDefTypes.has(providedIn);
8622
8650
  }
8623
8651
  }
8652
+ removeOnDestroy(callback) {
8653
+ const destroyCBIdx = this._onDestroyHooks.indexOf(callback);
8654
+ if (destroyCBIdx !== -1) {
8655
+ this._onDestroyHooks.splice(destroyCBIdx, 1);
8656
+ }
8657
+ }
8624
8658
  }
8625
8659
  function injectableDefOrInjectorDefFactory(token) {
8626
8660
  // Most tokens will have an injectable def directly on them, which specifies a factory directly.
@@ -8806,6 +8840,37 @@ const PACKAGE_ROOT_URL = new InjectionToken('Application Packages Root URL');
8806
8840
  * @publicApi
8807
8841
  */
8808
8842
  const ANIMATION_MODULE_TYPE = new InjectionToken('AnimationModuleType');
8843
+ // TODO(crisbeto): link to CSP guide here.
8844
+ /**
8845
+ * Token used to configure the [Content Security Policy](https://web.dev/strict-csp/) nonce that
8846
+ * Angular will apply when inserting inline styles. If not provided, Angular will look up its value
8847
+ * from the `ngCspNonce` attribute of the application root node.
8848
+ *
8849
+ * @publicApi
8850
+ */
8851
+ const CSP_NONCE = new InjectionToken('CSP nonce', {
8852
+ providedIn: 'root',
8853
+ factory: () => {
8854
+ // Ideally we wouldn't have to use `querySelector` here since we know that the nonce will be on
8855
+ // the root node, but because the token value is used in renderers, it has to be available
8856
+ // *very* early in the bootstrapping process. This should be a fairly shallow search, because
8857
+ // the app won't have been added to the DOM yet. Some approaches that were considered:
8858
+ // 1. Find the root node through `ApplicationRef.components[i].location` - normally this would
8859
+ // be enough for our purposes, but the token is injected very early so the `components` array
8860
+ // isn't populated yet.
8861
+ // 2. Find the root `LView` through the current `LView` - renderers are a prerequisite to
8862
+ // creating the `LView`. This means that no `LView` will have been entered when this factory is
8863
+ // invoked for the root component.
8864
+ // 3. Have the token factory return `() => string` which is invoked when a nonce is requested -
8865
+ // the slightly later execution does allow us to get an `LView` reference, but the fact that
8866
+ // it is a function means that it could be executed at *any* time (including immediately) which
8867
+ // may lead to weird bugs.
8868
+ // 4. Have the `ComponentFactory` read the attribute and provide it to the injector under the
8869
+ // hood - has the same problem as #1 and #2 in that the renderer is used to query for the root
8870
+ // node and the nonce value needs to be available when the renderer is created.
8871
+ return getDocument().body.querySelector('[ngCspNonce]')?.getAttribute('ngCspNonce') || null;
8872
+ },
8873
+ });
8809
8874
 
8810
8875
  function escapeTransferStateContent(text) {
8811
8876
  const escapedText = {
@@ -8948,6 +9013,19 @@ function retrieveTransferredState(doc, appId) {
8948
9013
  return initialState;
8949
9014
  }
8950
9015
 
9016
+ /** Encodes that the node lookup should start from the host node of this component. */
9017
+ const REFERENCE_NODE_HOST = 'h';
9018
+ /** Encodes that the node lookup should start from the document body node. */
9019
+ const REFERENCE_NODE_BODY = 'b';
9020
+ /**
9021
+ * Describes navigation steps that the runtime logic need to perform,
9022
+ * starting from a given (known) element.
9023
+ */
9024
+ var NodeNavigationStep;
9025
+ (function (NodeNavigationStep) {
9026
+ NodeNavigationStep["FirstChild"] = "f";
9027
+ NodeNavigationStep["NextSibling"] = "n";
9028
+ })(NodeNavigationStep || (NodeNavigationStep = {}));
8951
9029
  /**
8952
9030
  * Keys within serialized view data structure to represent various
8953
9031
  * parts. See the `SerializedView` interface below for additional information.
@@ -8955,8 +9033,11 @@ function retrieveTransferredState(doc, appId) {
8955
9033
  const ELEMENT_CONTAINERS = 'e';
8956
9034
  const TEMPLATES = 't';
8957
9035
  const CONTAINERS = 'c';
9036
+ const MULTIPLIER = 'x';
8958
9037
  const NUM_ROOT_NODES = 'r';
8959
9038
  const TEMPLATE_ID = 'i'; // as it's also an "id"
9039
+ const NODES = 'n';
9040
+ const DISCONNECTED_NODES = 'd';
8960
9041
 
8961
9042
  /**
8962
9043
  * The name of the key used in the TransferState collection,
@@ -9146,10 +9227,23 @@ function calcSerializedContainerSize(hydrationInfo, index) {
9146
9227
  const views = getSerializedContainerViews(hydrationInfo, index) ?? [];
9147
9228
  let numNodes = 0;
9148
9229
  for (let view of views) {
9149
- numNodes += view[NUM_ROOT_NODES];
9230
+ numNodes += view[NUM_ROOT_NODES] * (view[MULTIPLIER] ?? 1);
9150
9231
  }
9151
9232
  return numNodes;
9152
9233
  }
9234
+ /**
9235
+ * Checks whether a node is annotated as "disconnected", i.e. not present
9236
+ * in the DOM at serialization time. We should not attempt hydration for
9237
+ * such nodes and instead, use a regular "creation mode".
9238
+ */
9239
+ function isDisconnectedNode(hydrationInfo, index) {
9240
+ // Check if we are processing disconnected info for the first time.
9241
+ if (typeof hydrationInfo.disconnectedNodes === 'undefined') {
9242
+ const nodeIds = hydrationInfo.data[DISCONNECTED_NODES];
9243
+ hydrationInfo.disconnectedNodes = nodeIds ? (new Set(nodeIds)) : null;
9244
+ }
9245
+ return !!hydrationInfo.disconnectedNodes?.has(index);
9246
+ }
9153
9247
 
9154
9248
  /**
9155
9249
  * Represents a component created by a `ComponentFactory`.
@@ -9330,7 +9424,7 @@ class Version {
9330
9424
  /**
9331
9425
  * @publicApi
9332
9426
  */
9333
- const VERSION = new Version('16.0.0-next.3');
9427
+ const VERSION = new Version('16.0.0-next.4');
9334
9428
 
9335
9429
  // This default value is when checking the hierarchy for a token.
9336
9430
  //
@@ -14070,40 +14164,443 @@ function detectChanges(component) {
14070
14164
  detectChangesInternal(view[TVIEW], view, component);
14071
14165
  }
14072
14166
 
14167
+ const AT_THIS_LOCATION = '<-- AT THIS LOCATION';
14073
14168
  /**
14074
- * Verifies whether a given node matches an expected criteria,
14075
- * based on internal data structure state.
14169
+ * Retrieves a user friendly string for a given TNodeType for use in
14170
+ * friendly error messages
14171
+ *
14172
+ * @param tNodeType
14173
+ * @returns
14076
14174
  */
14077
- function validateMatchingNode(node, nodeType, tagName, lView, tNode) {
14078
- validateNodeExists(node);
14079
- if (node.nodeType !== nodeType ||
14080
- node.nodeType === Node.ELEMENT_NODE &&
14081
- node.tagName.toLowerCase() !== tagName?.toLowerCase()) {
14082
- // TODO: improve error message and use RuntimeError instead.
14083
- throw new Error(`Unexpected node found during hydration.`);
14175
+ function getFriendlyStringFromTNodeType(tNodeType) {
14176
+ switch (tNodeType) {
14177
+ case 4 /* TNodeType.Container */:
14178
+ return 'view container';
14179
+ case 2 /* TNodeType.Element */:
14180
+ return 'element';
14181
+ case 8 /* TNodeType.ElementContainer */:
14182
+ return 'ng-container';
14183
+ case 32 /* TNodeType.Icu */:
14184
+ return 'icu';
14185
+ case 64 /* TNodeType.Placeholder */:
14186
+ return 'i18n';
14187
+ case 16 /* TNodeType.Projection */:
14188
+ return 'projection';
14189
+ case 1 /* TNodeType.Text */:
14190
+ return 'text';
14191
+ default:
14192
+ // This should not happen as we cover all possible TNode types above.
14193
+ return '<unknown>';
14194
+ }
14195
+ }
14196
+ /**
14197
+ * Validates that provided nodes match during the hydration process.
14198
+ */
14199
+ function validateMatchingNode(node, nodeType, tagName, lView, tNode, isViewContainerAnchor = false) {
14200
+ if (!node ||
14201
+ (node.nodeType !== nodeType ||
14202
+ (node.nodeType === Node.ELEMENT_NODE &&
14203
+ node.tagName.toLowerCase() !== tagName?.toLowerCase()))) {
14204
+ const expectedNode = shortRNodeDescription(nodeType, tagName, null);
14205
+ let header = `During hydration Angular expected ${expectedNode} but `;
14206
+ const hostComponentDef = getDeclarationComponentDef(lView);
14207
+ const componentClassName = hostComponentDef?.type?.name;
14208
+ const expected = `Angular expected this DOM:\n\n${describeExpectedDom(lView, tNode, isViewContainerAnchor)}\n\n`;
14209
+ let actual = '';
14210
+ if (!node) {
14211
+ // No node found during hydration.
14212
+ header += `the node was not found.\n\n`;
14213
+ }
14214
+ else {
14215
+ const actualNode = shortRNodeDescription(node.nodeType, node.tagName ?? null, node.textContent ?? null);
14216
+ header += `found ${actualNode}.\n\n`;
14217
+ actual = `Actual DOM is:\n\n${describeDomFromNode(node)}\n\n`;
14218
+ }
14219
+ const footer = getHydrationErrorFooter(componentClassName);
14220
+ const message = header + expected + actual + getHydrationAttributeNote() + footer;
14221
+ throw new RuntimeError(500 /* RuntimeErrorCode.HYDRATION_NODE_MISMATCH */, message);
14084
14222
  }
14085
14223
  }
14086
14224
  /**
14087
- * Verifies whether next sibling node exists.
14225
+ * Validates that a given node has sibling nodes
14088
14226
  */
14089
14227
  function validateSiblingNodeExists(node) {
14090
14228
  validateNodeExists(node);
14091
14229
  if (!node.nextSibling) {
14092
- // TODO: improve error message and use RuntimeError instead.
14093
- throw new Error(`Unexpected state: insufficient number of sibling nodes.`);
14230
+ const header = 'During hydration Angular expected more sibling nodes to be present.\n\n';
14231
+ const actual = `Actual DOM is:\n\n${describeDomFromNode(node)}\n\n`;
14232
+ const footer = getHydrationErrorFooter();
14233
+ const message = header + actual + footer;
14234
+ throw new RuntimeError(501 /* RuntimeErrorCode.HYDRATION_MISSING_SIBLINGS */, message);
14094
14235
  }
14095
14236
  }
14237
+ /**
14238
+ * Validates that a node exists or throws
14239
+ */
14096
14240
  function validateNodeExists(node) {
14097
14241
  if (!node) {
14098
- // TODO: improve error message and use RuntimeError instead.
14099
- throw new Error(`Hydration expected an element to be present at this location.`);
14242
+ throw new RuntimeError(502 /* RuntimeErrorCode.HYDRATION_MISSING_NODE */, `Hydration expected an element to be present at this location.`);
14100
14243
  }
14101
14244
  }
14245
+ /**
14246
+ * Builds the hydration error message when a node is not found
14247
+ *
14248
+ * @param lView the LView where the node exists
14249
+ * @param tNode the TNode
14250
+ */
14251
+ function nodeNotFoundError(lView, tNode) {
14252
+ const header = 'During serialization, Angular was unable to find an element in the DOM:\n\n';
14253
+ const expected = `${describeExpectedDom(lView, tNode, false)}\n\n`;
14254
+ const footer = getHydrationErrorFooter();
14255
+ throw new RuntimeError(502 /* RuntimeErrorCode.HYDRATION_MISSING_NODE */, header + expected + footer);
14256
+ }
14257
+ /**
14258
+ * Builds a hydration error message when a node is not found at a path location
14259
+ *
14260
+ * @param host the Host Node
14261
+ * @param path the path to the node
14262
+ */
14263
+ function nodeNotFoundAtPathError(host, path) {
14264
+ const header = `During hydration Angular was unable to locate a node ` +
14265
+ `using the "${path}" path, starting from the ${describeRNode(host)} node.\n\n`;
14266
+ const footer = getHydrationErrorFooter();
14267
+ throw new RuntimeError(502 /* RuntimeErrorCode.HYDRATION_MISSING_NODE */, header + footer);
14268
+ }
14269
+ /**
14270
+ * Builds the hydration error message in the case that dom nodes are created outside of
14271
+ * the Angular context and are being used as projected nodes
14272
+ *
14273
+ * @param lView the LView
14274
+ * @param tNode the TNode
14275
+ * @returns an error
14276
+ */
14277
+ function unsupportedProjectionOfDomNodes(rNode) {
14278
+ const header = 'During serialization, Angular detected DOM nodes ' +
14279
+ 'that were created outside of Angular context and provided as projectable nodes ' +
14280
+ '(likely via `ViewContainerRef.createComponent` or `createComponent` APIs). ' +
14281
+ 'Hydration is not supported for such cases, consider refactoring the code to avoid ' +
14282
+ 'this pattern or using `ngSkipHydration` on the host element of the component.\n\n';
14283
+ const actual = `${describeDomFromNode(rNode)}\n\n`;
14284
+ const message = header + actual + getHydrationAttributeNote();
14285
+ return new RuntimeError(503 /* RuntimeErrorCode.UNSUPPORTED_PROJECTION_DOM_NODES */, message);
14286
+ }
14287
+ /**
14288
+ * Builds the hydration error message in the case that ngSkipHydration was used on a
14289
+ * node that is not a component host element or host binding
14290
+ *
14291
+ * @param rNode the HTML Element
14292
+ * @returns an error
14293
+ */
14294
+ function invalidSkipHydrationHost(rNode) {
14295
+ const header = 'The `ngSkipHydration` flag is applied on a node ' +
14296
+ 'that doesn\'t act as a component host. Hydration can be ' +
14297
+ 'skipped only on per-component basis.\n\n';
14298
+ const actual = `${describeDomFromNode(rNode)}\n\n`;
14299
+ const footer = 'Please move the `ngSkipHydration` attribute to the component host element.';
14300
+ const message = header + actual + footer;
14301
+ return new RuntimeError(504 /* RuntimeErrorCode.INVALID_SKIP_HYDRATION_HOST */, message);
14302
+ }
14303
+ /**
14304
+ * Builds the hydration error message in the case that a user is attempting to enable
14305
+ * hydration on internationalized nodes, which is not yet supported.
14306
+ *
14307
+ * @param rNode the HTML Element
14308
+ * @returns an error
14309
+ */
14310
+ function notYetSupportedI18nBlockError(rNode) {
14311
+ const header = 'Hydration for nodes marked with `i18n` is not yet supported. ' +
14312
+ 'You can opt-out a component that uses `i18n` in a template using ' +
14313
+ 'the `ngSkipHydration` attribute or fall back to the previous ' +
14314
+ 'hydration logic (which re-creates the application structure).\n\n';
14315
+ const actual = `${describeDomFromNode(rNode)}\n\n`;
14316
+ const message = header + actual;
14317
+ return new RuntimeError(518 /* RuntimeErrorCode.HYDRATION_I18N_NOT_YET_SUPPORTED */, message);
14318
+ }
14319
+ // Stringification methods
14320
+ /**
14321
+ * Stringifies a given TNode's attributes
14322
+ *
14323
+ * @param tNode a provided TNode
14324
+ * @returns string
14325
+ */
14326
+ function stringifyTNodeAttrs(tNode) {
14327
+ const results = [];
14328
+ if (tNode.attrs) {
14329
+ for (let i = 0; i < tNode.attrs.length;) {
14330
+ const attrName = tNode.attrs[i++];
14331
+ // Once we reach the first flag, we know that the list of
14332
+ // attributes is over.
14333
+ if (typeof attrName == 'number') {
14334
+ break;
14335
+ }
14336
+ const attrValue = tNode.attrs[i++];
14337
+ results.push(`${attrName}="${shorten(attrValue)}"`);
14338
+ }
14339
+ }
14340
+ return results.join(' ');
14341
+ }
14342
+ /**
14343
+ * The list of internal attributes that should be filtered out while
14344
+ * producing an error message.
14345
+ */
14346
+ const internalAttrs = new Set(['ngh', 'ng-version', 'ng-server-context']);
14347
+ /**
14348
+ * Stringifies an HTML Element's attributes
14349
+ *
14350
+ * @param rNode an HTML Element
14351
+ * @returns string
14352
+ */
14353
+ function stringifyRNodeAttrs(rNode) {
14354
+ const results = [];
14355
+ for (let i = 0; i < rNode.attributes.length; i++) {
14356
+ const attr = rNode.attributes[i];
14357
+ if (internalAttrs.has(attr.name))
14358
+ continue;
14359
+ results.push(`${attr.name}="${shorten(attr.value)}"`);
14360
+ }
14361
+ return results.join(' ');
14362
+ }
14363
+ // Methods for Describing the DOM
14364
+ /**
14365
+ * Converts a tNode to a helpful readable string value for use in error messages
14366
+ *
14367
+ * @param tNode a given TNode
14368
+ * @param innerContent the content of the node
14369
+ * @returns string
14370
+ */
14371
+ function describeTNode(tNode, innerContent = '…') {
14372
+ switch (tNode.type) {
14373
+ case 1 /* TNodeType.Text */:
14374
+ const content = tNode.value ? `(${tNode.value})` : '';
14375
+ return `#text${content}`;
14376
+ case 2 /* TNodeType.Element */:
14377
+ const attrs = stringifyTNodeAttrs(tNode);
14378
+ const tag = tNode.value.toLowerCase();
14379
+ return `<${tag}${attrs ? ' ' + attrs : ''}>${innerContent}</${tag}>`;
14380
+ case 8 /* TNodeType.ElementContainer */:
14381
+ return '<!-- ng-container -->';
14382
+ case 4 /* TNodeType.Container */:
14383
+ return '<!-- container -->';
14384
+ default:
14385
+ const typeAsString = getFriendlyStringFromTNodeType(tNode.type);
14386
+ return `#node(${typeAsString})`;
14387
+ }
14388
+ }
14389
+ /**
14390
+ * Converts an RNode to a helpful readable string value for use in error messages
14391
+ *
14392
+ * @param rNode a given RNode
14393
+ * @param innerContent the content of the node
14394
+ * @returns string
14395
+ */
14396
+ function describeRNode(rNode, innerContent = '…') {
14397
+ const node = rNode;
14398
+ switch (node.nodeType) {
14399
+ case Node.ELEMENT_NODE:
14400
+ const tag = node.tagName.toLowerCase();
14401
+ const attrs = stringifyRNodeAttrs(node);
14402
+ return `<${tag}${attrs ? ' ' + attrs : ''}>${innerContent}</${tag}>`;
14403
+ case Node.TEXT_NODE:
14404
+ const content = node.textContent ? shorten(node.textContent) : '';
14405
+ return `#text${content ? `(${content})` : ''}`;
14406
+ case Node.COMMENT_NODE:
14407
+ return `<!-- ${shorten(node.textContent ?? '')} -->`;
14408
+ default:
14409
+ return `#node(${node.nodeType})`;
14410
+ }
14411
+ }
14412
+ /**
14413
+ * Builds the string containing the expected DOM present given the LView and TNode
14414
+ * values for a readable error message
14415
+ *
14416
+ * @param lView the lView containing the DOM
14417
+ * @param tNode the tNode
14418
+ * @param isViewContainerAnchor boolean
14419
+ * @returns string
14420
+ */
14421
+ function describeExpectedDom(lView, tNode, isViewContainerAnchor) {
14422
+ const spacer = ' ';
14423
+ let content = '';
14424
+ if (tNode.prev) {
14425
+ content += spacer + '…\n';
14426
+ content += spacer + describeTNode(tNode.prev) + '\n';
14427
+ }
14428
+ else if (tNode.type && tNode.type & 12 /* TNodeType.AnyContainer */) {
14429
+ content += spacer + '…\n';
14430
+ }
14431
+ if (isViewContainerAnchor) {
14432
+ content += spacer + describeTNode(tNode) + '\n';
14433
+ content += spacer + `<!-- container --> ${AT_THIS_LOCATION}\n`;
14434
+ }
14435
+ else {
14436
+ content += spacer + describeTNode(tNode) + ` ${AT_THIS_LOCATION}\n`;
14437
+ }
14438
+ content += spacer + '…\n';
14439
+ const parentRNode = tNode.type ? getParentRElement(lView[TVIEW], tNode, lView) : null;
14440
+ if (parentRNode) {
14441
+ content = describeRNode(parentRNode, '\n' + content);
14442
+ }
14443
+ return content;
14444
+ }
14445
+ /**
14446
+ * Builds the string containing the DOM present around a given RNode for a
14447
+ * readable error message
14448
+ *
14449
+ * @param node the RNode
14450
+ * @returns string
14451
+ */
14452
+ function describeDomFromNode(node) {
14453
+ const spacer = ' ';
14454
+ let content = '';
14455
+ const currentNode = node;
14456
+ if (currentNode.previousSibling) {
14457
+ content += spacer + '…\n';
14458
+ content += spacer + describeRNode(currentNode.previousSibling) + '\n';
14459
+ }
14460
+ content += spacer + describeRNode(currentNode) + ` ${AT_THIS_LOCATION}\n`;
14461
+ if (node.nextSibling) {
14462
+ content += spacer + '…\n';
14463
+ }
14464
+ if (node.parentNode) {
14465
+ content = describeRNode(currentNode.parentNode, '\n' + content);
14466
+ }
14467
+ return content;
14468
+ }
14469
+ /**
14470
+ * Shortens the description of a given RNode by its type for readability
14471
+ *
14472
+ * @param nodeType the type of node
14473
+ * @param tagName the node tag name
14474
+ * @param textContent the text content in the node
14475
+ * @returns string
14476
+ */
14477
+ function shortRNodeDescription(nodeType, tagName, textContent) {
14478
+ switch (nodeType) {
14479
+ case Node.ELEMENT_NODE:
14480
+ return `<${tagName.toLowerCase()}>`;
14481
+ case Node.TEXT_NODE:
14482
+ const content = textContent ? ` (with the "${shorten(textContent)}" content)` : '';
14483
+ return `a text node${content}`;
14484
+ case Node.COMMENT_NODE:
14485
+ return 'a comment node';
14486
+ default:
14487
+ return `#node(nodeType=${nodeType})`;
14488
+ }
14489
+ }
14490
+ /**
14491
+ * Builds the footer hydration error message
14492
+ *
14493
+ * @param componentClassName the name of the component class
14494
+ * @returns string
14495
+ */
14496
+ function getHydrationErrorFooter(componentClassName) {
14497
+ const componentInfo = componentClassName ? `the "${componentClassName}"` : 'corresponding';
14498
+ return `To fix this problem:\n` +
14499
+ ` * check ${componentInfo} component for hydration-related issues\n` +
14500
+ ` * or skip hydration by adding the \`ngSkipHydration\` attribute ` +
14501
+ `to its host node in a template`;
14502
+ }
14503
+ /**
14504
+ * An attribute related note for hydration errors
14505
+ */
14506
+ function getHydrationAttributeNote() {
14507
+ return 'Note: attributes are only displayed to better represent the DOM' +
14508
+ ' but have no effect on hydration mismatches.\n\n';
14509
+ }
14510
+ // Node string utility functions
14511
+ /**
14512
+ * Strips all newlines out of a given string
14513
+ *
14514
+ * @param input a string to be cleared of new line characters
14515
+ * @returns
14516
+ */
14517
+ function stripNewlines(input) {
14518
+ return input.replace(/\s+/gm, '');
14519
+ }
14520
+ /**
14521
+ * Reduces a string down to a maximum length of characters with ellipsis for readability
14522
+ *
14523
+ * @param input a string input
14524
+ * @param maxLength a maximum length in characters
14525
+ * @returns string
14526
+ */
14527
+ function shorten(input, maxLength = 50) {
14528
+ if (!input) {
14529
+ return '';
14530
+ }
14531
+ input = stripNewlines(input);
14532
+ return input.length > maxLength ? `${input.substring(0, maxLength - 1)}…` : input;
14533
+ }
14534
+
14535
+ /**
14536
+ * Regexp that extracts a reference node information from the compressed node location.
14537
+ * The reference node is represented as either:
14538
+ * - a number which points to an LView slot
14539
+ * - the `b` char which indicates that the lookup should start from the `document.body`
14540
+ * - the `h` char to start lookup from the component host node (`lView[HOST]`)
14541
+ */
14542
+ const REF_EXTRACTOR_REGEXP = new RegExp(`^(\\d+)*(${REFERENCE_NODE_BODY}|${REFERENCE_NODE_HOST})*(.*)`);
14543
+ /**
14544
+ * Helper function that takes a reference node location and a set of navigation steps
14545
+ * (from the reference node) to a target node and outputs a string that represents
14546
+ * a location.
14547
+ *
14548
+ * For example, given: referenceNode = 'b' (body) and path = ['firstChild', 'firstChild',
14549
+ * 'nextSibling'], the function returns: `bf2n`.
14550
+ */
14551
+ function compressNodeLocation(referenceNode, path) {
14552
+ const result = [referenceNode];
14553
+ for (const segment of path) {
14554
+ const lastIdx = result.length - 1;
14555
+ if (lastIdx > 0 && result[lastIdx - 1] === segment) {
14556
+ // An empty string in a count slot represents 1 occurrence of an instruction.
14557
+ const value = (result[lastIdx] || 1);
14558
+ result[lastIdx] = value + 1;
14559
+ }
14560
+ else {
14561
+ // Adding a new segment to the path.
14562
+ // Using an empty string in a counter field to avoid encoding `1`s
14563
+ // into the path, since they are implicit (e.g. `f1n1` vs `fn`), so
14564
+ // it's enough to have a single char in this case.
14565
+ result.push(segment, '');
14566
+ }
14567
+ }
14568
+ return result.join('');
14569
+ }
14570
+ /**
14571
+ * Helper function that reverts the `compressNodeLocation` and transforms a given
14572
+ * string into an array where at 0th position there is a reference node info and
14573
+ * after that it contains information (in pairs) about a navigation step and the
14574
+ * number of repetitions.
14575
+ *
14576
+ * For example, the path like 'bf2n' will be transformed to:
14577
+ * ['b', 'firstChild', 2, 'nextSibling', 1].
14578
+ *
14579
+ * This information is later consumed by the code that navigates the DOM to find
14580
+ * a given node by its location.
14581
+ */
14582
+ function decompressNodeLocation(path) {
14583
+ const matches = path.match(REF_EXTRACTOR_REGEXP);
14584
+ const [_, refNodeId, refNodeName, rest] = matches;
14585
+ // If a reference node is represented by an index, transform it to a number.
14586
+ const ref = refNodeId ? parseInt(refNodeId, 10) : refNodeName;
14587
+ const steps = [];
14588
+ // Match all segments in a path.
14589
+ for (const [_, step, count] of rest.matchAll(/(f|n)(\d*)/g)) {
14590
+ const repeat = parseInt(count, 10) || 1;
14591
+ steps.push(step, repeat);
14592
+ }
14593
+ return [ref, ...steps];
14594
+ }
14102
14595
 
14103
14596
  /** Whether current TNode is a first node in an <ng-container>. */
14104
14597
  function isFirstElementInNgContainer(tNode) {
14105
14598
  return !tNode.prev && tNode.parent?.type === 8 /* TNodeType.ElementContainer */;
14106
14599
  }
14600
+ /** Returns an instruction index (subtracting HEADER_OFFSET). */
14601
+ function getNoOffsetIndex(tNode) {
14602
+ return tNode.index - HEADER_OFFSET;
14603
+ }
14107
14604
  /**
14108
14605
  * Locate a node in DOM tree that corresponds to a given TNode.
14109
14606
  *
@@ -14115,7 +14612,13 @@ function isFirstElementInNgContainer(tNode) {
14115
14612
  */
14116
14613
  function locateNextRNode(hydrationInfo, tView, lView, tNode) {
14117
14614
  let native = null;
14118
- if (tView.firstChild === tNode) {
14615
+ const noOffsetIndex = getNoOffsetIndex(tNode);
14616
+ const nodes = hydrationInfo.data[NODES];
14617
+ if (nodes?.[noOffsetIndex]) {
14618
+ // We know the exact location of the node.
14619
+ native = locateRNodeByPath(nodes[noOffsetIndex], lView);
14620
+ }
14621
+ else if (tView.firstChild === tNode) {
14119
14622
  // We create a first node in this view, so we use a reference
14120
14623
  // to the first child in this DOM segment.
14121
14624
  native = hydrationInfo.firstChild;
@@ -14128,7 +14631,7 @@ function locateNextRNode(hydrationInfo, tView, lView, tNode) {
14128
14631
  assertDefined(previousTNode, 'Unexpected state: current TNode does not have a connection ' +
14129
14632
  'to the previous node or a parent node.');
14130
14633
  if (isFirstElementInNgContainer(tNode)) {
14131
- const noOffsetParentIndex = tNode.parent.index - HEADER_OFFSET;
14634
+ const noOffsetParentIndex = getNoOffsetIndex(tNode.parent);
14132
14635
  native = getSegmentHead(hydrationInfo, noOffsetParentIndex);
14133
14636
  }
14134
14637
  else {
@@ -14142,7 +14645,7 @@ function locateNextRNode(hydrationInfo, tView, lView, tNode) {
14142
14645
  // represented in the DOM as `<div></div>...<!--container-->`.
14143
14646
  // In this case, there are nodes *after* this element and we need to skip
14144
14647
  // all of them to reach an element that we are looking for.
14145
- const noOffsetPrevSiblingIndex = previousTNode.index - HEADER_OFFSET;
14648
+ const noOffsetPrevSiblingIndex = getNoOffsetIndex(previousTNode);
14146
14649
  const segmentHead = getSegmentHead(hydrationInfo, noOffsetPrevSiblingIndex);
14147
14650
  if (previousTNode.type === 2 /* TNodeType.Element */ && segmentHead) {
14148
14651
  const numRootNodesToSkip = calcSerializedContainerSize(hydrationInfo, noOffsetPrevSiblingIndex);
@@ -14170,6 +14673,183 @@ function siblingAfter(skip, from) {
14170
14673
  }
14171
14674
  return currentNode;
14172
14675
  }
14676
+ /**
14677
+ * Helper function to produce a string representation of the navigation steps
14678
+ * (in terms of `nextSibling` and `firstChild` navigations). Used in error
14679
+ * messages in dev mode.
14680
+ */
14681
+ function stringifyNavigationInstructions(instructions) {
14682
+ const container = [];
14683
+ let i = 0;
14684
+ while (i < instructions.length) {
14685
+ const step = instructions[i++];
14686
+ const repeat = instructions[i++];
14687
+ for (let r = 0; r < repeat; r++) {
14688
+ container.push(step === NodeNavigationStep.FirstChild ? 'firstChild' : 'nextSibling');
14689
+ }
14690
+ }
14691
+ return container.join('.');
14692
+ }
14693
+ /**
14694
+ * Helper function that navigates from a starting point node (the `from` node)
14695
+ * using provided set of navigation instructions (within `path` argument).
14696
+ */
14697
+ function navigateToNode(from, instructions) {
14698
+ let node = from;
14699
+ let i = 0;
14700
+ while (i < instructions.length) {
14701
+ const step = instructions[i++];
14702
+ const repeat = instructions[i++];
14703
+ for (let r = 0; r < repeat; r++) {
14704
+ if (ngDevMode && !node) {
14705
+ throw nodeNotFoundAtPathError(from, stringifyNavigationInstructions(instructions));
14706
+ }
14707
+ switch (step) {
14708
+ case NodeNavigationStep.FirstChild:
14709
+ node = node.firstChild;
14710
+ break;
14711
+ case NodeNavigationStep.NextSibling:
14712
+ node = node.nextSibling;
14713
+ break;
14714
+ }
14715
+ }
14716
+ }
14717
+ if (ngDevMode && !node) {
14718
+ throw nodeNotFoundAtPathError(from, stringifyNavigationInstructions(instructions));
14719
+ }
14720
+ return node;
14721
+ }
14722
+ /**
14723
+ * Locates an RNode given a set of navigation instructions (which also contains
14724
+ * a starting point node info).
14725
+ */
14726
+ function locateRNodeByPath(path, lView) {
14727
+ const [referenceNode, ...navigationInstructions] = decompressNodeLocation(path);
14728
+ let ref;
14729
+ if (referenceNode === REFERENCE_NODE_HOST) {
14730
+ ref = lView[0];
14731
+ }
14732
+ else if (referenceNode === REFERENCE_NODE_BODY) {
14733
+ ref = ɵɵresolveBody(lView[0]);
14734
+ }
14735
+ else {
14736
+ const parentElementId = Number(referenceNode);
14737
+ ref = unwrapRNode(lView[parentElementId + HEADER_OFFSET]);
14738
+ }
14739
+ return navigateToNode(ref, navigationInstructions);
14740
+ }
14741
+ /**
14742
+ * Generate a list of DOM navigation operations to get from node `start` to node `finish`.
14743
+ *
14744
+ * Note: assumes that node `start` occurs before node `finish` in an in-order traversal of the DOM
14745
+ * tree. That is, we should be able to get from `start` to `finish` purely by using `.firstChild`
14746
+ * and `.nextSibling` operations.
14747
+ */
14748
+ function navigateBetween(start, finish) {
14749
+ if (start === finish) {
14750
+ return [];
14751
+ }
14752
+ else if (start.parentElement == null || finish.parentElement == null) {
14753
+ return null;
14754
+ }
14755
+ else if (start.parentElement === finish.parentElement) {
14756
+ return navigateBetweenSiblings(start, finish);
14757
+ }
14758
+ else {
14759
+ // `finish` is a child of its parent, so the parent will always have a child.
14760
+ const parent = finish.parentElement;
14761
+ const parentPath = navigateBetween(start, parent);
14762
+ const childPath = navigateBetween(parent.firstChild, finish);
14763
+ if (!parentPath || !childPath)
14764
+ return null;
14765
+ return [
14766
+ // First navigate to `finish`'s parent
14767
+ ...parentPath,
14768
+ // Then to its first child.
14769
+ NodeNavigationStep.FirstChild,
14770
+ // And finally from that node to `finish` (maybe a no-op if we're already there).
14771
+ ...childPath,
14772
+ ];
14773
+ }
14774
+ }
14775
+ /**
14776
+ * Calculates a path between 2 sibling nodes (generates a number of `NextSibling` navigations).
14777
+ */
14778
+ function navigateBetweenSiblings(start, finish) {
14779
+ const nav = [];
14780
+ let node = null;
14781
+ for (node = start; node != null && node !== finish; node = node.nextSibling) {
14782
+ nav.push(NodeNavigationStep.NextSibling);
14783
+ }
14784
+ return node === null ? [] : nav;
14785
+ }
14786
+ /**
14787
+ * Calculates a path between 2 nodes in terms of `nextSibling` and `firstChild`
14788
+ * navigations:
14789
+ * - the `from` node is a known node, used as an starting point for the lookup
14790
+ * (the `fromNodeName` argument is a string representation of the node).
14791
+ * - the `to` node is a node that the runtime logic would be looking up,
14792
+ * using the path generated by this function.
14793
+ */
14794
+ function calcPathBetween(from, to, fromNodeName) {
14795
+ const path = navigateBetween(from, to);
14796
+ return path === null ? null : compressNodeLocation(fromNodeName, path);
14797
+ }
14798
+ /**
14799
+ * Invoked at serialization time (on the server) when a set of navigation
14800
+ * instructions needs to be generated for a TNode.
14801
+ */
14802
+ function calcPathForNode(tNode, lView) {
14803
+ const parentTNode = tNode.parent;
14804
+ let parentIndex;
14805
+ let parentRNode;
14806
+ let referenceNodeName;
14807
+ if (parentTNode === null) {
14808
+ // No parent TNode - use host element as a reference node.
14809
+ parentIndex = referenceNodeName = REFERENCE_NODE_HOST;
14810
+ parentRNode = lView[HOST];
14811
+ }
14812
+ else {
14813
+ // Use parent TNode as a reference node.
14814
+ parentIndex = parentTNode.index;
14815
+ parentRNode = unwrapRNode(lView[parentIndex]);
14816
+ referenceNodeName = renderStringify(parentIndex - HEADER_OFFSET);
14817
+ }
14818
+ let rNode = unwrapRNode(lView[tNode.index]);
14819
+ if (tNode.type & 12 /* TNodeType.AnyContainer */) {
14820
+ // For <ng-container> nodes, instead of serializing a reference
14821
+ // to the anchor comment node, serialize a location of the first
14822
+ // DOM element. Paired with the container size (serialized as a part
14823
+ // of `ngh.containers`), it should give enough information for runtime
14824
+ // to hydrate nodes in this container.
14825
+ const firstRNode = getFirstNativeNode(lView, tNode);
14826
+ // If container is not empty, use a reference to the first element,
14827
+ // otherwise, rNode would point to an anchor comment node.
14828
+ if (firstRNode) {
14829
+ rNode = firstRNode;
14830
+ }
14831
+ }
14832
+ let path = calcPathBetween(parentRNode, rNode, referenceNodeName);
14833
+ if (path === null && parentRNode !== rNode) {
14834
+ // Searching for a path between elements within a host node failed.
14835
+ // Trying to find a path to an element starting from the `document.body` instead.
14836
+ //
14837
+ // Important note: this type of reference is relatively unstable, since Angular
14838
+ // may not be able to control parts of the page that the runtime logic navigates
14839
+ // through. This is mostly needed to cover "portals" use-case (like menus, dialog boxes,
14840
+ // etc), where nodes are content-projected (including direct DOM manipulations) outside
14841
+ // of the host node. The better solution is to provide APIs to work with "portals",
14842
+ // at which point this code path would not be needed.
14843
+ const body = parentRNode.ownerDocument.body;
14844
+ path = calcPathBetween(body, rNode, REFERENCE_NODE_BODY);
14845
+ if (path === null) {
14846
+ // If the path is still empty, it's likely that this node is detached and
14847
+ // won't be found during hydration.
14848
+ throw nodeNotFoundError(lView, tNode);
14849
+ }
14850
+ }
14851
+ return path;
14852
+ }
14173
14853
 
14174
14854
  function templateFirstCreatePass(index, tView, lView, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex) {
14175
14855
  ngDevMode && assertFirstCreatePass(tView);
@@ -14246,7 +14926,7 @@ function createContainerAnchorImpl(tView, lView, tNode, index) {
14246
14926
  */
14247
14927
  function locateOrCreateContainerAnchorImpl(tView, lView, tNode, index) {
14248
14928
  const hydrationInfo = lView[HYDRATION];
14249
- const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock$1();
14929
+ const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock$1() || isDisconnectedNode(hydrationInfo, index);
14250
14930
  lastNodeWasCreated(isNodeCreationMode);
14251
14931
  // Regular creation mode.
14252
14932
  if (isNodeCreationMode) {
@@ -14255,11 +14935,8 @@ function locateOrCreateContainerAnchorImpl(tView, lView, tNode, index) {
14255
14935
  // Hydration mode, looking up existing elements in DOM.
14256
14936
  const currentRNode = locateNextRNode(hydrationInfo, tView, lView, tNode);
14257
14937
  ngDevMode && validateNodeExists(currentRNode);
14938
+ setSegmentHead(hydrationInfo, index, currentRNode);
14258
14939
  const viewContainerSize = calcSerializedContainerSize(hydrationInfo, index);
14259
- // If this container is non-empty, store the first node as a segment head,
14260
- // otherwise, this node is an anchor and segment head doesn't exist (thus `null`).
14261
- const segmentHead = viewContainerSize > 0 ? currentRNode : null;
14262
- setSegmentHead(hydrationInfo, index, segmentHead);
14263
14940
  const comment = siblingAfter(viewContainerSize, currentRNode);
14264
14941
  if (ngDevMode) {
14265
14942
  validateMatchingNode(comment, Node.COMMENT_NODE, null, lView, tNode);
@@ -14515,7 +15192,7 @@ let _locateOrCreateElementNode = (tView, lView, tNode, renderer, name, index) =>
14515
15192
  */
14516
15193
  function locateOrCreateElementNodeImpl(tView, lView, tNode, renderer, name, index) {
14517
15194
  const hydrationInfo = lView[HYDRATION];
14518
- const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock$1();
15195
+ const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock$1() || isDisconnectedNode(hydrationInfo, index);
14519
15196
  lastNodeWasCreated(isNodeCreationMode);
14520
15197
  // Regular creation mode.
14521
15198
  if (isNodeCreationMode) {
@@ -14539,10 +15216,17 @@ function locateOrCreateElementNodeImpl(tView, lView, tNode, renderer, name, inde
14539
15216
  // Checks if the skip hydration attribute is present during hydration so we know to
14540
15217
  // skip attempting to hydrate this block.
14541
15218
  if (hydrationInfo && hasNgSkipHydrationAttr(tNode)) {
14542
- enterSkipHydrationBlock(tNode);
14543
- // Since this isn't hydratable, we need to empty the node
14544
- // so there's no duplicate content after render
14545
- clearElementContents(renderer, native);
15219
+ if (isComponentHost(tNode)) {
15220
+ enterSkipHydrationBlock(tNode);
15221
+ // Since this isn't hydratable, we need to empty the node
15222
+ // so there's no duplicate content after render
15223
+ clearElementContents(renderer, native);
15224
+ }
15225
+ else if (ngDevMode) {
15226
+ // If this is not a component host, throw an error.
15227
+ // Hydration can be skipped on per-component basis only.
15228
+ throw invalidSkipHydrationHost(native);
15229
+ }
14546
15230
  }
14547
15231
  return native;
14548
15232
  }
@@ -14676,10 +15360,7 @@ function locateOrCreateElementContainerNode(tView, lView, tNode, index) {
14676
15360
  ngDevMode &&
14677
15361
  assertNumber(ngContainerSize, 'Unexpected state: hydrating an <ng-container>, ' +
14678
15362
  'but no hydration info is available.');
14679
- // If this container is non-empty, store the first node as a segment head,
14680
- // otherwise, this node is an anchor and segment head doesn't exist (thus `null`).
14681
- const segmentHead = ngContainerSize > 0 ? currentRNode : null;
14682
- setSegmentHead(hydrationInfo, index, segmentHead);
15363
+ setSegmentHead(hydrationInfo, index, currentRNode);
14683
15364
  comment = siblingAfter(ngContainerSize, currentRNode);
14684
15365
  if (ngDevMode) {
14685
15366
  validateMatchingNode(comment, Node.COMMENT_NODE, null, lView, tNode);
@@ -15061,7 +15742,10 @@ function ɵɵprojection(nodeIndex, selectorIndex = 0, attrs) {
15061
15742
  tProjectionNode.projection = selectorIndex;
15062
15743
  // `<ng-content>` has no content
15063
15744
  setCurrentTNodeAsNotParent();
15064
- if ((tProjectionNode.flags & 32 /* TNodeFlags.isDetached */) !== 32 /* TNodeFlags.isDetached */) {
15745
+ const hydrationInfo = lView[HYDRATION];
15746
+ const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock$1();
15747
+ if (isNodeCreationMode &&
15748
+ (tProjectionNode.flags & 32 /* TNodeFlags.isDetached */) !== 32 /* TNodeFlags.isDetached */) {
15065
15749
  // re-distribution of projectable nodes is stored on a component's view level
15066
15750
  applyProjection(tView, lView, tProjectionNode);
15067
15751
  }
@@ -17024,7 +17708,7 @@ function ɵɵtext(index, value = '') {
17024
17708
  const tNode = tView.firstCreatePass ?
17025
17709
  getOrCreateTNode(tView, adjustedIndex, 1 /* TNodeType.Text */, value, null) :
17026
17710
  tView.data[adjustedIndex];
17027
- const textNative = _locateOrCreateTextNode(tView, lView, tNode, value);
17711
+ const textNative = _locateOrCreateTextNode(tView, lView, tNode, value, index);
17028
17712
  lView[adjustedIndex] = textNative;
17029
17713
  if (wasLastNodeCreated()) {
17030
17714
  appendChild(tView, lView, textNative, tNode);
@@ -17032,7 +17716,7 @@ function ɵɵtext(index, value = '') {
17032
17716
  // Text nodes are self closing.
17033
17717
  setCurrentTNode(tNode, false);
17034
17718
  }
17035
- let _locateOrCreateTextNode = (tView, lView, tNode, value) => {
17719
+ let _locateOrCreateTextNode = (tView, lView, tNode, value, index) => {
17036
17720
  lastNodeWasCreated(true);
17037
17721
  return createTextNode(lView[RENDERER], value);
17038
17722
  };
@@ -17040,9 +17724,9 @@ let _locateOrCreateTextNode = (tView, lView, tNode, value) => {
17040
17724
  * Enables hydration code path (to lookup existing elements in DOM)
17041
17725
  * in addition to the regular creation mode of text nodes.
17042
17726
  */
17043
- function locateOrCreateTextNodeImpl(tView, lView, tNode, value) {
17727
+ function locateOrCreateTextNodeImpl(tView, lView, tNode, value, index) {
17044
17728
  const hydrationInfo = lView[HYDRATION];
17045
- const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock$1();
17729
+ const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock$1() || isDisconnectedNode(hydrationInfo, index);
17046
17730
  lastNodeWasCreated(isNodeCreationMode);
17047
17731
  // Regular creation mode.
17048
17732
  if (isNodeCreationMode) {
@@ -22150,6 +22834,54 @@ function removeDehydratedView(dehydratedView, renderer) {
22150
22834
  }
22151
22835
  }
22152
22836
  }
22837
+ /**
22838
+ * Walks over all views within this LContainer invokes dehydrated views
22839
+ * cleanup function for each one.
22840
+ */
22841
+ function cleanupLContainer(lContainer) {
22842
+ removeDehydratedViews(lContainer);
22843
+ for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
22844
+ cleanupLView(lContainer[i]);
22845
+ }
22846
+ }
22847
+ /**
22848
+ * Walks over `LContainer`s and components registered within
22849
+ * this LView and invokes dehydrated views cleanup function for each one.
22850
+ */
22851
+ function cleanupLView(lView) {
22852
+ const tView = lView[TVIEW];
22853
+ for (let i = HEADER_OFFSET; i < tView.bindingStartIndex; i++) {
22854
+ if (isLContainer(lView[i])) {
22855
+ const lContainer = lView[i];
22856
+ cleanupLContainer(lContainer);
22857
+ }
22858
+ else if (Array.isArray(lView[i])) {
22859
+ // This is a component, enter the `cleanupLView` recursively.
22860
+ cleanupLView(lView[i]);
22861
+ }
22862
+ }
22863
+ }
22864
+ /**
22865
+ * Walks over all views registered within the ApplicationRef and removes
22866
+ * all dehydrated views from all `LContainer`s along the way.
22867
+ */
22868
+ function cleanupDehydratedViews(appRef) {
22869
+ // Wait once an app becomes stable and cleanup all views that
22870
+ // were not claimed during the application bootstrap process.
22871
+ // The timing is similar to when we kick off serialization on the server.
22872
+ return appRef.isStable.pipe(first((isStable) => isStable)).toPromise().then(() => {
22873
+ const viewRefs = appRef._views;
22874
+ for (const viewRef of viewRefs) {
22875
+ const lView = getComponentLViewForHydration(viewRef);
22876
+ // An `lView` might be `null` if a `ViewRef` represents
22877
+ // an embedded view (not a component view).
22878
+ if (lView !== null && lView[HOST] !== null) {
22879
+ cleanupLView(lView);
22880
+ ngDevMode && ngDevMode.dehydratedViewsCleanupRuns++;
22881
+ }
22882
+ }
22883
+ });
22884
+ }
22153
22885
 
22154
22886
  /**
22155
22887
  * Given a current DOM node and a serialized information about the views
@@ -22159,20 +22891,24 @@ function removeDehydratedView(dehydratedView, renderer) {
22159
22891
  function locateDehydratedViewsInContainer(currentRNode, serializedViews) {
22160
22892
  const dehydratedViews = [];
22161
22893
  for (const serializedView of serializedViews) {
22162
- const view = {
22163
- data: serializedView,
22164
- firstChild: null,
22165
- };
22166
- if (serializedView[NUM_ROOT_NODES] > 0) {
22167
- // Keep reference to the first node in this view,
22168
- // so it can be accessed while invoking template instructions.
22169
- view.firstChild = currentRNode;
22170
- // Move over to the next node after this view, which can
22171
- // either be a first node of the next view or an anchor comment
22172
- // node after the last view in a container.
22173
- currentRNode = siblingAfter(serializedView[NUM_ROOT_NODES], currentRNode);
22894
+ // Repeats a view multiple times as needed, based on the serialized information
22895
+ // (for example, for *ngFor-produced views).
22896
+ for (let i = 0; i < (serializedView[MULTIPLIER] ?? 1); i++) {
22897
+ const view = {
22898
+ data: serializedView,
22899
+ firstChild: null,
22900
+ };
22901
+ if (serializedView[NUM_ROOT_NODES] > 0) {
22902
+ // Keep reference to the first node in this view,
22903
+ // so it can be accessed while invoking template instructions.
22904
+ view.firstChild = currentRNode;
22905
+ // Move over to the next node after this view, which can
22906
+ // either be a first node of the next view or an anchor comment
22907
+ // node after the last view in a container.
22908
+ currentRNode = siblingAfter(serializedView[NUM_ROOT_NODES], currentRNode);
22909
+ }
22910
+ dehydratedViews.push(view);
22174
22911
  }
22175
- dehydratedViews.push(view);
22176
22912
  }
22177
22913
  return [currentRNode, dehydratedViews];
22178
22914
  }
@@ -22553,21 +23289,22 @@ function locateOrCreateAnchorNode(lContainer, hostLView, hostTNode, slotValue) {
22553
23289
  if (lContainer[NATIVE] && lContainer[DEHYDRATED_VIEWS])
22554
23290
  return;
22555
23291
  const hydrationInfo = hostLView[HYDRATION];
22556
- const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock(hostTNode);
23292
+ const noOffsetIndex = hostTNode.index - HEADER_OFFSET;
23293
+ const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock(hostTNode) ||
23294
+ isDisconnectedNode(hydrationInfo, noOffsetIndex);
22557
23295
  // Regular creation mode.
22558
23296
  if (isNodeCreationMode) {
22559
23297
  return createAnchorNode(lContainer, hostLView, hostTNode, slotValue);
22560
23298
  }
22561
23299
  // Hydration mode, looking up an anchor node and dehydrated views in DOM.
22562
- const index = hostTNode.index - HEADER_OFFSET;
22563
- const currentRNode = getSegmentHead(hydrationInfo, index);
22564
- const serializedViews = hydrationInfo.data[CONTAINERS]?.[index];
23300
+ const currentRNode = getSegmentHead(hydrationInfo, noOffsetIndex);
23301
+ const serializedViews = hydrationInfo.data[CONTAINERS]?.[noOffsetIndex];
22565
23302
  ngDevMode &&
22566
23303
  assertDefined(serializedViews, 'Unexpected state: no hydration info available for a given TNode, ' +
22567
23304
  'which represents a view container.');
22568
23305
  const [commentNode, dehydratedViews] = locateDehydratedViewsInContainer(currentRNode, serializedViews);
22569
23306
  if (ngDevMode) {
22570
- validateMatchingNode(commentNode, Node.COMMENT_NODE, null, hostLView, hostTNode);
23307
+ validateMatchingNode(commentNode, Node.COMMENT_NODE, null, hostLView, hostTNode, true);
22571
23308
  // Do not throw in case this node is already claimed (thus `false` as a second
22572
23309
  // argument). If this container is created based on an `<ng-template>`, the comment
22573
23310
  // node would be already claimed from the `template` instruction. If an element acts
@@ -24276,12 +25013,17 @@ const Pipe = makeDecorator('Pipe', (p) => ({ pure: true, ...p }), undefined, und
24276
25013
  * @Annotation
24277
25014
  * @publicApi
24278
25015
  */
24279
- const Input = makePropDecorator('Input', (bindingPropertyName) => ({ bindingPropertyName }));
25016
+ const Input = makePropDecorator('Input', (arg) => {
25017
+ if (!arg) {
25018
+ return {};
25019
+ }
25020
+ return typeof arg === 'string' ? { alias: arg } : arg;
25021
+ });
24280
25022
  /**
24281
25023
  * @Annotation
24282
25024
  * @publicApi
24283
25025
  */
24284
- const Output = makePropDecorator('Output', (bindingPropertyName) => ({ bindingPropertyName }));
25026
+ const Output = makePropDecorator('Output', (alias) => ({ alias }));
24285
25027
  /**
24286
25028
  * @Annotation
24287
25029
  * @publicApi
@@ -26604,6 +27346,8 @@ function enableProdMode() {
26604
27346
  * The scope of this destruction depends on where `DestroyRef` is injected. If `DestroyRef`
26605
27347
  * is injected in a component or directive, the callbacks run when that component or
26606
27348
  * directive is destroyed. Otherwise the callbacks run when a corresponding injector is destroyed.
27349
+ *
27350
+ * @publicApi
26607
27351
  */
26608
27352
  class DestroyRef {
26609
27353
  }
@@ -26624,6 +27368,7 @@ class NodeInjectorDestroyRef extends DestroyRef {
26624
27368
  }
26625
27369
  onDestroy(callback) {
26626
27370
  storeLViewOnDestroy(this._lView, callback);
27371
+ return () => removeLViewOnDestroy(this._lView, callback);
26627
27372
  }
26628
27373
  }
26629
27374
  function injectDestroyRef() {
@@ -28549,6 +29294,7 @@ function annotateForHydration(appRef, doc) {
28549
29294
  */
28550
29295
  function serializeLContainer(lContainer, context) {
28551
29296
  const views = [];
29297
+ let lastViewAsString = '';
28552
29298
  for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
28553
29299
  let childLView = lContainer[i];
28554
29300
  // If this is a root view, get an LView for the underlying component,
@@ -28574,10 +29320,42 @@ function serializeLContainer(lContainer, context) {
28574
29320
  [NUM_ROOT_NODES]: numRootNodes,
28575
29321
  ...serializeLView(lContainer[i], context),
28576
29322
  };
28577
- views.push(view);
29323
+ // Check if the previous view has the same shape (for example, it was
29324
+ // produced by the *ngFor), in which case bump the counter on the previous
29325
+ // view instead of including the same information again.
29326
+ const currentViewAsString = JSON.stringify(view);
29327
+ if (views.length > 0 && currentViewAsString === lastViewAsString) {
29328
+ const previousView = views[views.length - 1];
29329
+ previousView[MULTIPLIER] ?? (previousView[MULTIPLIER] = 1);
29330
+ previousView[MULTIPLIER]++;
29331
+ }
29332
+ else {
29333
+ // Record this view as most recently added.
29334
+ lastViewAsString = currentViewAsString;
29335
+ views.push(view);
29336
+ }
28578
29337
  }
28579
29338
  return views;
28580
29339
  }
29340
+ /**
29341
+ * Helper function to produce a node path (which navigation steps runtime logic
29342
+ * needs to take to locate a node) and stores it in the `NODES` section of the
29343
+ * current serialized view.
29344
+ */
29345
+ function appendSerializedNodePath(ngh, tNode, lView) {
29346
+ const noOffsetIndex = tNode.index - HEADER_OFFSET;
29347
+ ngh[NODES] ?? (ngh[NODES] = {});
29348
+ ngh[NODES][noOffsetIndex] = calcPathForNode(tNode, lView);
29349
+ }
29350
+ /**
29351
+ * There is no special TNode type for an i18n block, so we verify
29352
+ * whether the structure that we store at the `TView.data[idx]` position
29353
+ * has the `TI18n` shape.
29354
+ */
29355
+ function isTI18nNode(obj) {
29356
+ const tI18n = obj;
29357
+ return tI18n.hasOwnProperty('create') && tI18n.hasOwnProperty('update');
29358
+ }
28581
29359
  /**
28582
29360
  * Serializes the lView data into a SerializedView object that will later be added
28583
29361
  * to the TransferState storage and referenced using the `ngh` attribute on a host
@@ -28601,6 +29379,51 @@ function serializeLView(lView, context) {
28601
29379
  if (!tNode) {
28602
29380
  continue;
28603
29381
  }
29382
+ // Check if a native node that represents a given TNode is disconnected from the DOM tree.
29383
+ // Such nodes must be excluded from the hydration (since the hydration won't be able to
29384
+ // find them), so the TNode ids are collected and used at runtime to skip the hydration.
29385
+ //
29386
+ // This situation may happen during the content projection, when some nodes don't make it
29387
+ // into one of the content projection slots (for example, when there is no default
29388
+ // <ng-content /> slot in projector component's template).
29389
+ //
29390
+ // Note: we leverage the fact that we have this information available in the DOM emulation
29391
+ // layer (in Domino) for now. Longer-term solution should not rely on the DOM emulation and
29392
+ // only use internal data structures and state to compute this information.
29393
+ if (!(tNode.type & 16 /* TNodeType.Projection */) && !!lView[i] &&
29394
+ !unwrapRNode(lView[i]).isConnected) {
29395
+ ngh[DISCONNECTED_NODES] ?? (ngh[DISCONNECTED_NODES] = []);
29396
+ ngh[DISCONNECTED_NODES].push(noOffsetIndex);
29397
+ continue;
29398
+ }
29399
+ if (Array.isArray(tNode.projection)) {
29400
+ for (const projectionHeadTNode of tNode.projection) {
29401
+ // We may have `null`s in slots with no projected content.
29402
+ if (!projectionHeadTNode)
29403
+ continue;
29404
+ if (!Array.isArray(projectionHeadTNode)) {
29405
+ // If we process re-projected content (i.e. `<ng-content>`
29406
+ // appears at projection location), skip annotations for this content
29407
+ // since all DOM nodes in this projection were handled while processing
29408
+ // a parent lView, which contains those nodes.
29409
+ if (!isProjectionTNode(projectionHeadTNode) &&
29410
+ !isInSkipHydrationBlock(projectionHeadTNode)) {
29411
+ appendSerializedNodePath(ngh, projectionHeadTNode, lView);
29412
+ }
29413
+ }
29414
+ else {
29415
+ // If a value is an array, it means that we are processing a projection
29416
+ // where projectable nodes were passed in as DOM nodes (for example, when
29417
+ // calling `ViewContainerRef.createComponent(CmpA, {projectableNodes: [...]})`).
29418
+ //
29419
+ // In this scenario, nodes can come from anywhere (either created manually,
29420
+ // accessed via `document.querySelector`, etc) and may be in any state
29421
+ // (attached or detached from the DOM tree). As a result, we can not reliably
29422
+ // restore the state for such cases during hydration.
29423
+ throw unsupportedProjectionOfDomNodes(unwrapRNode(lView[i]));
29424
+ }
29425
+ }
29426
+ }
28604
29427
  if (isLContainer(lView[i])) {
28605
29428
  // Serialize information about a template.
28606
29429
  const embeddedTView = tNode.tView;
@@ -28630,6 +29453,18 @@ function serializeLView(lView, context) {
28630
29453
  annotateHostElementForHydration(targetNode, lView[i], context);
28631
29454
  }
28632
29455
  }
29456
+ else if (isTI18nNode(tNode)) {
29457
+ // Hydration for i18n nodes is not *yet* supported.
29458
+ // Produce an error message which would also describe possible
29459
+ // solutions (switching back to the "destructive" hydration or
29460
+ // excluding a component from hydration via `ngSkipHydration`).
29461
+ //
29462
+ // TODO(akushnir): we should find a better way to get a hold of the node that has the `i18n`
29463
+ // attribute on it. For now, we either refer to the host element of the component or to the
29464
+ // previous element in the LView.
29465
+ const targetNode = (i === HEADER_OFFSET) ? lView[HOST] : unwrapRNode(lView[i - 1]);
29466
+ throw notYetSupportedI18nBlockError(targetNode);
29467
+ }
28633
29468
  else {
28634
29469
  // <ng-container> case
28635
29470
  if (tNode.type & 8 /* TNodeType.ElementContainer */) {
@@ -28639,6 +29474,20 @@ function serializeLView(lView, context) {
28639
29474
  ngh[ELEMENT_CONTAINERS] ?? (ngh[ELEMENT_CONTAINERS] = {});
28640
29475
  ngh[ELEMENT_CONTAINERS][noOffsetIndex] = calcNumRootNodes(tView, lView, tNode.child);
28641
29476
  }
29477
+ else if (tNode.type & 16 /* TNodeType.Projection */) {
29478
+ // Current TNode represents an `<ng-content>` slot, thus it has no
29479
+ // DOM elements associated with it, so the **next sibling** node would
29480
+ // not be able to find an anchor. In this case, use full path instead.
29481
+ let nextTNode = tNode.next;
29482
+ // Skip over all `<ng-content>` slots in a row.
29483
+ while (nextTNode !== null && (nextTNode.type & 16 /* TNodeType.Projection */)) {
29484
+ nextTNode = nextTNode.next;
29485
+ }
29486
+ if (nextTNode && !isInSkipHydrationBlock(nextTNode)) {
29487
+ // Handle a tNode after the `<ng-content>` slot.
29488
+ appendSerializedNodePath(ngh, nextTNode, lView);
29489
+ }
29490
+ }
28642
29491
  else {
28643
29492
  // Handle cases where text nodes can be lost after DOM serialization:
28644
29493
  // 1. When there is an *empty text node* in DOM: in this case, this
@@ -28675,6 +29524,13 @@ function serializeLView(lView, context) {
28675
29524
  context.corruptedTextNodes.set(rNode, "ngtns" /* TextNodeMarker.Separator */);
28676
29525
  }
28677
29526
  }
29527
+ if (tNode.projectionNext && tNode.projectionNext !== tNode.next &&
29528
+ !isInSkipHydrationBlock(tNode.projectionNext)) {
29529
+ // Check if projection next is not the same as next, in which case
29530
+ // the node would not be found at creation time at runtime and we
29531
+ // need to provide a location for that node.
29532
+ appendSerializedNodePath(ngh, tNode.projectionNext, lView);
29533
+ }
28678
29534
  }
28679
29535
  }
28680
29536
  }
@@ -28813,108 +29669,21 @@ function provideHydrationSupport() {
28813
29669
  // environment. On a server, an application is rendered
28814
29670
  // from scratch, so the host content needs to be empty.
28815
29671
  useFactory: () => isBrowser(),
29672
+ },
29673
+ {
29674
+ provide: APP_BOOTSTRAP_LISTENER,
29675
+ useFactory: () => {
29676
+ if (isBrowser()) {
29677
+ const appRef = inject(ApplicationRef);
29678
+ return () => cleanupDehydratedViews(appRef);
29679
+ }
29680
+ return () => { }; // noop
29681
+ },
29682
+ multi: true,
28816
29683
  }
28817
29684
  ]);
28818
29685
  }
28819
29686
 
28820
- /** Coerces a value (typically a string) to a boolean. */
28821
- function coerceToBoolean(value) {
28822
- return typeof value === 'boolean' ? value : (value != null && value !== 'false');
28823
- }
28824
-
28825
- /**
28826
- * Compiles a partial directive declaration object into a full directive definition object.
28827
- *
28828
- * @codeGenApi
28829
- */
28830
- function ɵɵngDeclareDirective(decl) {
28831
- const compiler = getCompilerFacade({ usage: 1 /* JitCompilerUsage.PartialDeclaration */, kind: 'directive', type: decl.type });
28832
- return compiler.compileDirectiveDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵfac.js`, decl);
28833
- }
28834
- /**
28835
- * Evaluates the class metadata declaration.
28836
- *
28837
- * @codeGenApi
28838
- */
28839
- function ɵɵngDeclareClassMetadata(decl) {
28840
- setClassMetadata(decl.type, decl.decorators, decl.ctorParameters ?? null, decl.propDecorators ?? null);
28841
- }
28842
- /**
28843
- * Compiles a partial component declaration object into a full component definition object.
28844
- *
28845
- * @codeGenApi
28846
- */
28847
- function ɵɵngDeclareComponent(decl) {
28848
- const compiler = getCompilerFacade({ usage: 1 /* JitCompilerUsage.PartialDeclaration */, kind: 'component', type: decl.type });
28849
- return compiler.compileComponentDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵcmp.js`, decl);
28850
- }
28851
- /**
28852
- * Compiles a partial pipe declaration object into a full pipe definition object.
28853
- *
28854
- * @codeGenApi
28855
- */
28856
- function ɵɵngDeclareFactory(decl) {
28857
- const compiler = getCompilerFacade({
28858
- usage: 1 /* JitCompilerUsage.PartialDeclaration */,
28859
- kind: getFactoryKind(decl.target),
28860
- type: decl.type
28861
- });
28862
- return compiler.compileFactoryDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵfac.js`, decl);
28863
- }
28864
- function getFactoryKind(target) {
28865
- switch (target) {
28866
- case FactoryTarget.Directive:
28867
- return 'directive';
28868
- case FactoryTarget.Component:
28869
- return 'component';
28870
- case FactoryTarget.Injectable:
28871
- return 'injectable';
28872
- case FactoryTarget.Pipe:
28873
- return 'pipe';
28874
- case FactoryTarget.NgModule:
28875
- return 'NgModule';
28876
- }
28877
- }
28878
- /**
28879
- * Compiles a partial injectable declaration object into a full injectable definition object.
28880
- *
28881
- * @codeGenApi
28882
- */
28883
- function ɵɵngDeclareInjectable(decl) {
28884
- const compiler = getCompilerFacade({ usage: 1 /* JitCompilerUsage.PartialDeclaration */, kind: 'injectable', type: decl.type });
28885
- return compiler.compileInjectableDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵprov.js`, decl);
28886
- }
28887
- /**
28888
- * Compiles a partial injector declaration object into a full injector definition object.
28889
- *
28890
- * @codeGenApi
28891
- */
28892
- function ɵɵngDeclareInjector(decl) {
28893
- const compiler = getCompilerFacade({ usage: 1 /* JitCompilerUsage.PartialDeclaration */, kind: 'NgModule', type: decl.type });
28894
- return compiler.compileInjectorDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵinj.js`, decl);
28895
- }
28896
- /**
28897
- * Compiles a partial NgModule declaration object into a full NgModule definition object.
28898
- *
28899
- * @codeGenApi
28900
- */
28901
- function ɵɵngDeclareNgModule(decl) {
28902
- const compiler = getCompilerFacade({ usage: 1 /* JitCompilerUsage.PartialDeclaration */, kind: 'NgModule', type: decl.type });
28903
- return compiler.compileNgModuleDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵmod.js`, decl);
28904
- }
28905
- /**
28906
- * Compiles a partial pipe declaration object into a full pipe definition object.
28907
- *
28908
- * @codeGenApi
28909
- */
28910
- function ɵɵngDeclarePipe(decl) {
28911
- const compiler = getCompilerFacade({ usage: 1 /* JitCompilerUsage.PartialDeclaration */, kind: 'pipe', type: decl.type });
28912
- return compiler.compilePipeDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵpipe.js`, decl);
28913
- }
28914
-
28915
- // clang-format off
28916
- // clang-format on
28917
-
28918
29687
  /**
28919
29688
  * Symbol used to tell `Signal`s apart from other functions.
28920
29689
  *
@@ -29061,8 +29830,24 @@ function consumerPollValueStatus(consumer) {
29061
29830
  return false;
29062
29831
  }
29063
29832
 
29833
+ // `WeakRef` is not always defined in every TS environment where Angular is compiled. Instead,
29834
+ // read it off of the global context if available.
29064
29835
  // tslint:disable-next-line: no-toplevel-property-access
29065
- const WeakRef = _global['WeakRef'];
29836
+ let WeakRefImpl = _global['WeakRef'];
29837
+ function newWeakRef(value) {
29838
+ if (typeof ngDevMode !== 'undefined' && ngDevMode && WeakRefImpl === undefined) {
29839
+ throw new Error(`Angular requires a browser which supports the 'WeakRef' API`);
29840
+ }
29841
+ return new WeakRefImpl(value);
29842
+ }
29843
+ /**
29844
+ * Use an alternate implementation of `WeakRef` if a platform implementation isn't available.
29845
+ */
29846
+ function setAlternateWeakRefImpl(impl) {
29847
+ if (!WeakRefImpl) {
29848
+ WeakRefImpl = impl;
29849
+ }
29850
+ }
29066
29851
 
29067
29852
  /**
29068
29853
  * Create a computed `Signal` which derives a reactive value from an expression.
@@ -29119,7 +29904,7 @@ class ComputedImpl {
29119
29904
  */
29120
29905
  this.stale = true;
29121
29906
  this.id = nextReactiveId();
29122
- this.ref = new WeakRef(this);
29907
+ this.ref = newWeakRef(this);
29123
29908
  this.producers = new Map();
29124
29909
  this.consumers = new Map();
29125
29910
  this.trackingVersion = 0;
@@ -29208,7 +29993,7 @@ class Watch {
29208
29993
  this.watch = watch;
29209
29994
  this.schedule = schedule;
29210
29995
  this.id = nextReactiveId();
29211
- this.ref = new WeakRef(this);
29996
+ this.ref = newWeakRef(this);
29212
29997
  this.producers = new Map();
29213
29998
  this.trackingVersion = 0;
29214
29999
  this.dirty = false;
@@ -29252,8 +30037,6 @@ function effect(effectFn) {
29252
30037
  // Effects start dirty.
29253
30038
  watch.notify();
29254
30039
  return {
29255
- consumer: watch,
29256
- schedule: watch.notify.bind(watch),
29257
30040
  destroy: () => {
29258
30041
  queuedWatches.delete(watch);
29259
30042
  globalWatches.delete(watch);
@@ -29310,7 +30093,7 @@ class SettableSignalImpl {
29310
30093
  this.value = value;
29311
30094
  this.equal = equal;
29312
30095
  this.id = nextReactiveId();
29313
- this.ref = new WeakRef(this);
30096
+ this.ref = newWeakRef(this);
29314
30097
  this.consumers = new Map();
29315
30098
  this.valueVersion = 0;
29316
30099
  }
@@ -29388,6 +30171,104 @@ function untracked(nonReactiveReadsFn) {
29388
30171
  }
29389
30172
  }
29390
30173
 
30174
+ /** Coerces a value (typically a string) to a boolean. */
30175
+ function coerceToBoolean(value) {
30176
+ return typeof value === 'boolean' ? value : (value != null && value !== 'false');
30177
+ }
30178
+
30179
+ /**
30180
+ * Compiles a partial directive declaration object into a full directive definition object.
30181
+ *
30182
+ * @codeGenApi
30183
+ */
30184
+ function ɵɵngDeclareDirective(decl) {
30185
+ const compiler = getCompilerFacade({ usage: 1 /* JitCompilerUsage.PartialDeclaration */, kind: 'directive', type: decl.type });
30186
+ return compiler.compileDirectiveDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵfac.js`, decl);
30187
+ }
30188
+ /**
30189
+ * Evaluates the class metadata declaration.
30190
+ *
30191
+ * @codeGenApi
30192
+ */
30193
+ function ɵɵngDeclareClassMetadata(decl) {
30194
+ setClassMetadata(decl.type, decl.decorators, decl.ctorParameters ?? null, decl.propDecorators ?? null);
30195
+ }
30196
+ /**
30197
+ * Compiles a partial component declaration object into a full component definition object.
30198
+ *
30199
+ * @codeGenApi
30200
+ */
30201
+ function ɵɵngDeclareComponent(decl) {
30202
+ const compiler = getCompilerFacade({ usage: 1 /* JitCompilerUsage.PartialDeclaration */, kind: 'component', type: decl.type });
30203
+ return compiler.compileComponentDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵcmp.js`, decl);
30204
+ }
30205
+ /**
30206
+ * Compiles a partial pipe declaration object into a full pipe definition object.
30207
+ *
30208
+ * @codeGenApi
30209
+ */
30210
+ function ɵɵngDeclareFactory(decl) {
30211
+ const compiler = getCompilerFacade({
30212
+ usage: 1 /* JitCompilerUsage.PartialDeclaration */,
30213
+ kind: getFactoryKind(decl.target),
30214
+ type: decl.type
30215
+ });
30216
+ return compiler.compileFactoryDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵfac.js`, decl);
30217
+ }
30218
+ function getFactoryKind(target) {
30219
+ switch (target) {
30220
+ case FactoryTarget.Directive:
30221
+ return 'directive';
30222
+ case FactoryTarget.Component:
30223
+ return 'component';
30224
+ case FactoryTarget.Injectable:
30225
+ return 'injectable';
30226
+ case FactoryTarget.Pipe:
30227
+ return 'pipe';
30228
+ case FactoryTarget.NgModule:
30229
+ return 'NgModule';
30230
+ }
30231
+ }
30232
+ /**
30233
+ * Compiles a partial injectable declaration object into a full injectable definition object.
30234
+ *
30235
+ * @codeGenApi
30236
+ */
30237
+ function ɵɵngDeclareInjectable(decl) {
30238
+ const compiler = getCompilerFacade({ usage: 1 /* JitCompilerUsage.PartialDeclaration */, kind: 'injectable', type: decl.type });
30239
+ return compiler.compileInjectableDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵprov.js`, decl);
30240
+ }
30241
+ /**
30242
+ * Compiles a partial injector declaration object into a full injector definition object.
30243
+ *
30244
+ * @codeGenApi
30245
+ */
30246
+ function ɵɵngDeclareInjector(decl) {
30247
+ const compiler = getCompilerFacade({ usage: 1 /* JitCompilerUsage.PartialDeclaration */, kind: 'NgModule', type: decl.type });
30248
+ return compiler.compileInjectorDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵinj.js`, decl);
30249
+ }
30250
+ /**
30251
+ * Compiles a partial NgModule declaration object into a full NgModule definition object.
30252
+ *
30253
+ * @codeGenApi
30254
+ */
30255
+ function ɵɵngDeclareNgModule(decl) {
30256
+ const compiler = getCompilerFacade({ usage: 1 /* JitCompilerUsage.PartialDeclaration */, kind: 'NgModule', type: decl.type });
30257
+ return compiler.compileNgModuleDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵmod.js`, decl);
30258
+ }
30259
+ /**
30260
+ * Compiles a partial pipe declaration object into a full pipe definition object.
30261
+ *
30262
+ * @codeGenApi
30263
+ */
30264
+ function ɵɵngDeclarePipe(decl) {
30265
+ const compiler = getCompilerFacade({ usage: 1 /* JitCompilerUsage.PartialDeclaration */, kind: 'pipe', type: decl.type });
30266
+ return compiler.compilePipeDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵpipe.js`, decl);
30267
+ }
30268
+
30269
+ // clang-format off
30270
+ // clang-format on
30271
+
29391
30272
  // This file exists to allow the set of reactivity exports to be modified in g3, as these APIs are
29392
30273
 
29393
30274
  /**
@@ -29571,5 +30452,5 @@ if (typeof ngDevMode !== 'undefined' && ngDevMode) {
29571
30452
  * Generated bundle index. Do not edit.
29572
30453
  */
29573
30454
 
29574
- export { ANALYZE_FOR_ENTRY_COMPONENTS, ANIMATION_MODULE_TYPE, APP_BOOTSTRAP_LISTENER, APP_ID, APP_INITIALIZER, ApplicationInitStatus, ApplicationModule, ApplicationRef, Attribute, COMPILER_OPTIONS, 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, ReflectiveInjector, ReflectiveKey, Renderer2, RendererFactory2, RendererStyleFlags2, ResolvedReflectiveFactory, Sanitizer, SecurityContext, Self, SimpleChange, SkipSelf, TRANSLATIONS, TRANSLATIONS_FORMAT, TemplateRef, Testability, TestabilityRegistry, Type, VERSION, Version, ViewChild, ViewChildren, ViewContainerRef, ViewEncapsulation$1 as ViewEncapsulation, ViewRef, asNativeElements, assertPlatform, computed, createComponent, createEnvironmentInjector, createNgModule, createNgModuleRef, createPlatform, createPlatformFactory, defineInjectable, destroyPlatform, effect, enableProdMode, forwardRef, getDebugNode, getModuleFactory, getNgModuleById, getPlatform, importProvidersFrom, inject, isDevMode, isSignal, isStandalone, makeEnvironmentProviders, mergeApplicationConfig, platformCore, reflectComponentType, resolveForwardRef, runInInjectionContext, setTestabilityGetter, signal, untracked, ALLOW_MULTIPLE_PLATFORMS as ɵALLOW_MULTIPLE_PLATFORMS, ComponentFactory$1 as ɵComponentFactory, Console as ɵConsole, DEFAULT_LOCALE_ID as ɵDEFAULT_LOCALE_ID, INJECTOR_SCOPE as ɵINJECTOR_SCOPE, IS_HYDRATION_FEATURE_ENABLED as ɵIS_HYDRATION_FEATURE_ENABLED, 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, TESTABILITY as ɵTESTABILITY, TESTABILITY_GETTER as ɵTESTABILITY_GETTER, TransferState as ɵTransferState, ViewRef$1 as ɵViewRef, XSS_SECURITY_URL as ɵXSS_SECURITY_URL, _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, coerceToBoolean as ɵcoerceToBoolean, 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, detectChanges as ɵdetectChanges, devModeEqual as ɵdevModeEqual, escapeTransferStateContent as ɵescapeTransferStateContent, findLocaleData as ɵfindLocaleData, flushModuleScopingQueueAsMuchAsPossible as ɵflushModuleScopingQueueAsMuchAsPossible, formatRuntimeError as ɵformatRuntimeError, getComponentDef as ɵgetComponentDef, getDebugNode as ɵgetDebugNode, 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, isEnvironmentProviders as ɵisEnvironmentProviders, isInjectable as ɵisInjectable, isNgModule as ɵisNgModule, isPromise as ɵisPromise, isSubscribable as ɵisSubscribable, makeDecorator as ɵmakeDecorator, makeStateKey as ɵmakeStateKey, noSideEffects as ɵnoSideEffects, patchComponentDefWithScope as ɵpatchComponentDefWithScope, provideHydrationSupport as ɵprovideHydrationSupport, provideNgZoneChangeDetection as ɵprovideNgZoneChangeDetection, publishDefaultGlobalUtils$1 as ɵpublishDefaultGlobalUtils, publishGlobalUtil as ɵpublishGlobalUtil, registerLocaleData as ɵregisterLocaleData, resetCompiledComponents as ɵresetCompiledComponents, resetJitOptions as ɵresetJitOptions, resolveComponentResources as ɵresolveComponentResources, setAllowDuplicateNgModuleIdsForTest as ɵsetAllowDuplicateNgModuleIdsForTest, setClassMetadata as ɵsetClassMetadata, setCurrentInjector as ɵsetCurrentInjector, setDocument as ɵsetDocument, setLocaleId as ɵsetLocaleId, ɵsetUnknownElementStrictMode, ɵsetUnknownPropertyStrictMode, store as ɵstore, stringify as ɵstringify, transitiveScopesFor as ɵtransitiveScopesFor, unescapeTransferStateContent as ɵunescapeTransferStateContent, unregisterAllLocaleData as ɵunregisterLocaleData, unwrapSafeValue as ɵunwrapSafeValue, ɵɵCopyDefinitionFeature, FactoryTarget as ɵɵFactoryTarget, ɵɵHostDirectivesFeature, ɵɵInheritDefinitionFeature, ɵɵ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, ɵɵcontentQuery, ɵɵdefineComponent, ɵɵdefineDirective, ɵɵdefineInjectable, ɵɵdefineInjector, ɵɵdefineNgModule, ɵɵdefinePipe, ɵɵdirectiveInject, ɵɵdisableBindings, ɵɵelement, ɵɵelementContainer, ɵɵelementContainerEnd, ɵɵelementContainerStart, ɵɵelementEnd, ɵɵelementStart, ɵɵenableBindings, ɵɵ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, ɵɵ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 };
30455
+ export { ANALYZE_FOR_ENTRY_COMPONENTS, ANIMATION_MODULE_TYPE, APP_BOOTSTRAP_LISTENER, APP_ID, APP_INITIALIZER, 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, ReflectiveInjector, ReflectiveKey, Renderer2, RendererFactory2, RendererStyleFlags2, ResolvedReflectiveFactory, Sanitizer, SecurityContext, Self, SimpleChange, SkipSelf, TRANSLATIONS, TRANSLATIONS_FORMAT, TemplateRef, Testability, TestabilityRegistry, Type, VERSION, Version, ViewChild, ViewChildren, ViewContainerRef, ViewEncapsulation$1 as ViewEncapsulation, ViewRef, asNativeElements, assertPlatform, computed, createComponent, createEnvironmentInjector, createNgModule, createNgModuleRef, createPlatform, createPlatformFactory, defineInjectable, destroyPlatform, effect, enableProdMode, forwardRef, getDebugNode, getModuleFactory, getNgModuleById, getPlatform, importProvidersFrom, inject, isDevMode, isSignal, isStandalone, makeEnvironmentProviders, mergeApplicationConfig, platformCore, reflectComponentType, resolveForwardRef, runInInjectionContext, setTestabilityGetter, signal, untracked, ALLOW_MULTIPLE_PLATFORMS as ɵALLOW_MULTIPLE_PLATFORMS, ComponentFactory$1 as ɵComponentFactory, Console as ɵConsole, DEFAULT_LOCALE_ID as ɵDEFAULT_LOCALE_ID, INJECTOR_SCOPE as ɵINJECTOR_SCOPE, IS_HYDRATION_FEATURE_ENABLED as ɵIS_HYDRATION_FEATURE_ENABLED, 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, TESTABILITY as ɵTESTABILITY, TESTABILITY_GETTER as ɵTESTABILITY_GETTER, TransferState as ɵTransferState, ViewRef$1 as ɵViewRef, XSS_SECURITY_URL as ɵXSS_SECURITY_URL, _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, coerceToBoolean as ɵcoerceToBoolean, 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, detectChanges as ɵdetectChanges, devModeEqual as ɵdevModeEqual, escapeTransferStateContent as ɵescapeTransferStateContent, findLocaleData as ɵfindLocaleData, flushModuleScopingQueueAsMuchAsPossible as ɵflushModuleScopingQueueAsMuchAsPossible, formatRuntimeError as ɵformatRuntimeError, getDebugNode as ɵgetDebugNode, 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, isEnvironmentProviders as ɵisEnvironmentProviders, isInjectable as ɵisInjectable, isNgModule as ɵisNgModule, isPromise as ɵisPromise, isSubscribable as ɵisSubscribable, makeDecorator as ɵmakeDecorator, makeStateKey as ɵmakeStateKey, noSideEffects as ɵnoSideEffects, patchComponentDefWithScope as ɵpatchComponentDefWithScope, provideHydrationSupport as ɵprovideHydrationSupport, provideNgZoneChangeDetection as ɵprovideNgZoneChangeDetection, publishDefaultGlobalUtils$1 as ɵpublishDefaultGlobalUtils, publishGlobalUtil as ɵpublishGlobalUtil, registerLocaleData as ɵregisterLocaleData, resetCompiledComponents as ɵresetCompiledComponents, resetJitOptions as ɵresetJitOptions, resolveComponentResources as ɵresolveComponentResources, setAllowDuplicateNgModuleIdsForTest as ɵsetAllowDuplicateNgModuleIdsForTest, setAlternateWeakRefImpl as ɵsetAlternateWeakRefImpl, setClassMetadata as ɵsetClassMetadata, setCurrentInjector as ɵsetCurrentInjector, setDocument as ɵsetDocument, setLocaleId as ɵsetLocaleId, ɵsetUnknownElementStrictMode, ɵsetUnknownPropertyStrictMode, store as ɵstore, stringify as ɵstringify, transitiveScopesFor as ɵtransitiveScopesFor, unescapeTransferStateContent as ɵunescapeTransferStateContent, unregisterAllLocaleData as ɵunregisterLocaleData, unwrapSafeValue as ɵunwrapSafeValue, ɵɵCopyDefinitionFeature, FactoryTarget as ɵɵFactoryTarget, ɵɵHostDirectivesFeature, ɵɵInheritDefinitionFeature, ɵɵ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, ɵɵcontentQuery, ɵɵdefineComponent, ɵɵdefineDirective, ɵɵdefineInjectable, ɵɵdefineInjector, ɵɵdefineNgModule, ɵɵdefinePipe, ɵɵdirectiveInject, ɵɵdisableBindings, ɵɵelement, ɵɵelementContainer, ɵɵelementContainerEnd, ɵɵelementContainerStart, ɵɵelementEnd, ɵɵelementStart, ɵɵenableBindings, ɵɵ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, ɵɵ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 };
29575
30456
  //# sourceMappingURL=core.mjs.map