@angular/core 16.2.0-rc.0 → 16.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v16.2.0-rc.0
2
+ * @license Angular v16.2.0
3
3
  * (c) 2010-2022 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -6547,6 +6547,7 @@ const PLATFORM_ID = new InjectionToken('Platform ID', {
6547
6547
  * A [DI token](guide/glossary#di-token "DI token definition") that indicates the root directory of
6548
6548
  * the application
6549
6549
  * @publicApi
6550
+ * @deprecated
6550
6551
  */
6551
6552
  const PACKAGE_ROOT_URL = new InjectionToken('Application Packages Root URL');
6552
6553
  // We keep this token here, rather than the animations package, so that modules that only care
@@ -8559,7 +8560,7 @@ function createElementNode(renderer, name, namespace) {
8559
8560
  * @param tView The `TView' of the `LView` from which elements should be added or removed
8560
8561
  * @param lView The view from which elements should be added or removed
8561
8562
  */
8562
- function removeViewFromContainer(tView, lView) {
8563
+ function removeViewFromDOM(tView, lView) {
8563
8564
  const renderer = lView[RENDERER];
8564
8565
  applyView(tView, lView, renderer, 2 /* WalkTNodeTreeAction.Detach */, null, null);
8565
8566
  lView[HOST] = null;
@@ -8579,7 +8580,7 @@ function removeViewFromContainer(tView, lView) {
8579
8580
  * @param parentNativeNode The parent `RElement` where it should be inserted into.
8580
8581
  * @param beforeNode The node before which elements should be added, if insert mode
8581
8582
  */
8582
- function addViewToContainer(tView, parentTNode, renderer, lView, parentNativeNode, beforeNode) {
8583
+ function addViewToDOM(tView, parentTNode, renderer, lView, parentNativeNode, beforeNode) {
8583
8584
  lView[HOST] = parentNativeNode;
8584
8585
  lView[T_HOST] = parentTNode;
8585
8586
  applyView(tView, lView, renderer, 1 /* WalkTNodeTreeAction.Insert */, parentNativeNode, beforeNode);
@@ -8590,7 +8591,7 @@ function addViewToContainer(tView, parentTNode, renderer, lView, parentNativeNod
8590
8591
  * @param tView The `TView' of the `LView` to be detached
8591
8592
  * @param lView the `LView` to be detached.
8592
8593
  */
8593
- function renderDetachView(tView, lView) {
8594
+ function detachViewFromDOM(tView, lView) {
8594
8595
  applyView(tView, lView, lView[RENDERER], 2 /* WalkTNodeTreeAction.Detach */, null, null);
8595
8596
  }
8596
8597
  /**
@@ -8752,7 +8753,7 @@ function detachView(lContainer, removeIndex) {
8752
8753
  lContainer[indexInContainer - 1][NEXT] = viewToDetach[NEXT];
8753
8754
  }
8754
8755
  const removedLView = removeFromArray(lContainer, CONTAINER_HEADER_OFFSET + removeIndex);
8755
- removeViewFromContainer(viewToDetach[TVIEW], viewToDetach);
8756
+ removeViewFromDOM(viewToDetach[TVIEW], viewToDetach);
8756
8757
  // notify query that a view has been removed
8757
8758
  const lQueries = removedLView[QUERIES];
8758
8759
  if (lQueries !== null) {
@@ -10517,6 +10518,10 @@ const NGH_DATA_KEY = makeStateKey(TRANSFER_STATE_TOKEN_ID);
10517
10518
  * state that contains the necessary hydration info for this component.
10518
10519
  */
10519
10520
  const NGH_ATTR_NAME = 'ngh';
10521
+ /**
10522
+ * Marker used in a comment node to ensure hydration content integrity
10523
+ */
10524
+ const SSR_CONTENT_INTEGRITY_MARKER = 'nghm';
10520
10525
  /**
10521
10526
  * Reference to a function that reads `ngh` attribute value from a given RNode
10522
10527
  * and retrieves hydration information from the TransferState using that value
@@ -10524,12 +10529,30 @@ const NGH_ATTR_NAME = 'ngh';
10524
10529
  *
10525
10530
  * @param rNode Component's host element.
10526
10531
  * @param injector Injector that this component has access to.
10532
+ * @param isRootView Specifies whether we trying to read hydration info for the root view.
10527
10533
  */
10528
- let _retrieveHydrationInfoImpl = (rNode, injector) => null;
10529
- function retrieveHydrationInfoImpl(rNode, injector) {
10530
- const nghAttrValue = rNode.getAttribute(NGH_ATTR_NAME);
10534
+ let _retrieveHydrationInfoImpl = (rNode, injector, isRootView) => null;
10535
+ function retrieveHydrationInfoImpl(rNode, injector, isRootView = false) {
10536
+ let nghAttrValue = rNode.getAttribute(NGH_ATTR_NAME);
10531
10537
  if (nghAttrValue == null)
10532
10538
  return null;
10539
+ // For cases when a root component also acts as an anchor node for a ViewContainerRef
10540
+ // (for example, when ViewContainerRef is injected in a root component), there is a need
10541
+ // to serialize information about the component itself, as well as an LContainer that
10542
+ // represents this ViewContainerRef. Effectively, we need to serialize 2 pieces of info:
10543
+ // (1) hydration info for the root component itself and (2) hydration info for the
10544
+ // ViewContainerRef instance (an LContainer). Each piece of information is included into
10545
+ // the hydration data (in the TransferState object) separately, thus we end up with 2 ids.
10546
+ // Since we only have 1 root element, we encode both bits of info into a single string:
10547
+ // ids are separated by the `|` char (e.g. `10|25`, where `10` is the ngh for a component view
10548
+ // and 25 is the `ngh` for a root view which holds LContainer).
10549
+ const [componentViewNgh, rootViewNgh] = nghAttrValue.split('|');
10550
+ nghAttrValue = isRootView ? rootViewNgh : componentViewNgh;
10551
+ if (!nghAttrValue)
10552
+ return null;
10553
+ // We've read one of the ngh ids, keep the remaining one, so that
10554
+ // we can set it back on the DOM element.
10555
+ const remainingNgh = isRootView ? componentViewNgh : (rootViewNgh ? `|${rootViewNgh}` : '');
10533
10556
  let data = {};
10534
10557
  // An element might have an empty `ngh` attribute value (e.g. `<comp ngh="" />`),
10535
10558
  // which means that no special annotations are required. Do not attempt to read
@@ -10551,9 +10574,29 @@ function retrieveHydrationInfoImpl(rNode, injector) {
10551
10574
  data,
10552
10575
  firstChild: rNode.firstChild ?? null,
10553
10576
  };
10554
- // The `ngh` attribute is cleared from the DOM node now
10555
- // that the data has been retrieved.
10556
- rNode.removeAttribute(NGH_ATTR_NAME);
10577
+ if (isRootView) {
10578
+ // If there is hydration info present for the root view, it means that there was
10579
+ // a ViewContainerRef injected in the root component. The root component host element
10580
+ // acted as an anchor node in this scenario. As a result, the DOM nodes that represent
10581
+ // embedded views in this ViewContainerRef are located as siblings to the host node,
10582
+ // i.e. `<app-root /><#VIEW1><#VIEW2>...<!--container-->`. In this case, the current
10583
+ // node becomes the first child of this root view and the next sibling is the first
10584
+ // element in the DOM segment.
10585
+ dehydratedView.firstChild = rNode;
10586
+ // We use `0` here, since this is the slot (right after the HEADER_OFFSET)
10587
+ // where a component LView or an LContainer is located in a root LView.
10588
+ setSegmentHead(dehydratedView, 0, rNode.nextSibling);
10589
+ }
10590
+ if (remainingNgh) {
10591
+ // If we have only used one of the ngh ids, store the remaining one
10592
+ // back on this RNode.
10593
+ rNode.setAttribute(NGH_ATTR_NAME, remainingNgh);
10594
+ }
10595
+ else {
10596
+ // The `ngh` attribute is cleared from the DOM node now
10597
+ // that the data has been retrieved for all indices.
10598
+ rNode.removeAttribute(NGH_ATTR_NAME);
10599
+ }
10557
10600
  // Note: don't check whether this node was claimed for hydration,
10558
10601
  // because this node might've been previously claimed while processing
10559
10602
  // template instructions.
@@ -10571,14 +10614,16 @@ function enableRetrieveHydrationInfoImpl() {
10571
10614
  * Retrieves hydration info by reading the value from the `ngh` attribute
10572
10615
  * and accessing a corresponding slot in TransferState storage.
10573
10616
  */
10574
- function retrieveHydrationInfo(rNode, injector) {
10575
- return _retrieveHydrationInfoImpl(rNode, injector);
10617
+ function retrieveHydrationInfo(rNode, injector, isRootView = false) {
10618
+ return _retrieveHydrationInfoImpl(rNode, injector, isRootView);
10576
10619
  }
10577
10620
  /**
10578
- * Retrieves an instance of a component LView from a given ViewRef.
10579
- * Returns an instance of a component LView or `null` in case of an embedded view.
10621
+ * Retrieves the necessary object from a given ViewRef to serialize:
10622
+ * - an LView for component views
10623
+ * - an LContainer for cases when component acts as a ViewContainerRef anchor
10624
+ * - `null` in case of an embedded view
10580
10625
  */
10581
- function getComponentLViewForHydration(viewRef) {
10626
+ function getLNodeForHydration(viewRef) {
10582
10627
  // Reading an internal field from `ViewRef` instance.
10583
10628
  let lView = viewRef._lView;
10584
10629
  const tView = lView[TVIEW];
@@ -10592,12 +10637,6 @@ function getComponentLViewForHydration(viewRef) {
10592
10637
  if (isRootView(lView)) {
10593
10638
  lView = lView[HEADER_OFFSET];
10594
10639
  }
10595
- // If a `ViewContainerRef` was injected in a component class, this resulted
10596
- // in an LContainer creation at that location. In this case, the component
10597
- // LView is in the LContainer's `HOST` slot.
10598
- if (isLContainer(lView)) {
10599
- lView = lView[HOST];
10600
- }
10601
10640
  return lView;
10602
10641
  }
10603
10642
  function getTextNodeContent(node) {
@@ -10900,7 +10939,7 @@ class Version {
10900
10939
  /**
10901
10940
  * @publicApi
10902
10941
  */
10903
- const VERSION = new Version('16.2.0-rc.0');
10942
+ const VERSION = new Version('16.2.0');
10904
10943
 
10905
10944
  // This default value is when checking the hierarchy for a token.
10906
10945
  //
@@ -13638,7 +13677,7 @@ class ViewRef {
13638
13677
  }
13639
13678
  detachFromAppRef() {
13640
13679
  this._appRef = null;
13641
- renderDetachView(this._lView[TVIEW], this._lView);
13680
+ detachViewFromDOM(this._lView[TVIEW], this._lView);
13642
13681
  }
13643
13682
  attachToAppRef(appRef) {
13644
13683
  if (this._attachedToViewContainer) {
@@ -13797,9 +13836,13 @@ class ComponentFactory extends ComponentFactory$1 {
13797
13836
  const nonSignalFlags = this.componentDef.onPush ? 64 /* LViewFlags.Dirty */ | 512 /* LViewFlags.IsRoot */ :
13798
13837
  16 /* LViewFlags.CheckAlways */ | 512 /* LViewFlags.IsRoot */;
13799
13838
  const rootFlags = this.componentDef.signals ? signalFlags : nonSignalFlags;
13839
+ let hydrationInfo = null;
13840
+ if (hostRNode !== null) {
13841
+ hydrationInfo = retrieveHydrationInfo(hostRNode, rootViewInjector, true /* isRootView */);
13842
+ }
13800
13843
  // Create the root view. Uses empty TView and ContentTemplate.
13801
13844
  const rootTView = createTView(0 /* TViewType.Root */, null, null, 1, 0, null, null, null, null, null, null);
13802
- const rootLView = createLView(null, rootTView, null, rootFlags, null, null, environment, hostRenderer, rootViewInjector, null, null);
13845
+ const rootLView = createLView(null, rootTView, null, rootFlags, null, null, environment, hostRenderer, rootViewInjector, null, hydrationInfo);
13803
13846
  // rootView is the parent when bootstrapping
13804
13847
  // TODO(misko): it looks like we are entering view here but we don't really need to as
13805
13848
  // `renderView` does that. However as the code is written it is needed because
@@ -13926,7 +13969,7 @@ function createRootComponentTNode(lView, rNode) {
13926
13969
  function createRootComponentView(tNode, hostRNode, rootComponentDef, rootDirectives, rootView, environment, hostRenderer) {
13927
13970
  const tView = rootView[TVIEW];
13928
13971
  applyRootComponentStyling(rootDirectives, tNode, hostRNode, hostRenderer);
13929
- // Hydration info is on the host element and needs to be retreived
13972
+ // Hydration info is on the host element and needs to be retrieved
13930
13973
  // and passed to the component LView.
13931
13974
  let hydrationInfo = null;
13932
13975
  if (hostRNode !== null) {
@@ -23709,6 +23752,57 @@ class QueryList {
23709
23752
  }
23710
23753
  }
23711
23754
 
23755
+ function createAndRenderEmbeddedLView(declarationLView, templateTNode, context, options) {
23756
+ const embeddedTView = templateTNode.tView;
23757
+ ngDevMode && assertDefined(embeddedTView, 'TView must be defined for a template node.');
23758
+ ngDevMode && assertTNodeForLView(templateTNode, declarationLView);
23759
+ // Embedded views follow the change detection strategy of the view they're declared in.
23760
+ const isSignalView = declarationLView[FLAGS] & 4096 /* LViewFlags.SignalView */;
23761
+ const viewFlags = isSignalView ? 4096 /* LViewFlags.SignalView */ : 16 /* LViewFlags.CheckAlways */;
23762
+ const embeddedLView = createLView(declarationLView, embeddedTView, context, viewFlags, null, templateTNode, null, null, null, options?.injector ?? null, options?.hydrationInfo ?? null);
23763
+ const declarationLContainer = declarationLView[templateTNode.index];
23764
+ ngDevMode && assertLContainer(declarationLContainer);
23765
+ embeddedLView[DECLARATION_LCONTAINER] = declarationLContainer;
23766
+ const declarationViewLQueries = declarationLView[QUERIES];
23767
+ if (declarationViewLQueries !== null) {
23768
+ embeddedLView[QUERIES] = declarationViewLQueries.createEmbeddedView(embeddedTView);
23769
+ }
23770
+ // execute creation mode of a view
23771
+ renderView(embeddedTView, embeddedLView, context);
23772
+ return embeddedLView;
23773
+ }
23774
+ function getLViewFromLContainer(lContainer, index) {
23775
+ const adjustedIndex = CONTAINER_HEADER_OFFSET + index;
23776
+ // avoid reading past the array boundaries
23777
+ if (adjustedIndex < lContainer.length) {
23778
+ const lView = lContainer[adjustedIndex];
23779
+ ngDevMode && assertLView(lView);
23780
+ return lView;
23781
+ }
23782
+ return undefined;
23783
+ }
23784
+ function addLViewToLContainer(lContainer, lView, index, addToDOM = true) {
23785
+ const tView = lView[TVIEW];
23786
+ // insert to the view tree so the new view can be change-detected
23787
+ insertView(tView, lView, lContainer, index);
23788
+ // insert to the view to the DOM tree
23789
+ if (addToDOM) {
23790
+ const beforeNode = getBeforeNodeForView(index, lContainer);
23791
+ const renderer = lView[RENDERER];
23792
+ const parentRNode = nativeParentNode(renderer, lContainer[NATIVE]);
23793
+ if (parentRNode !== null) {
23794
+ addViewToDOM(tView, lContainer[T_HOST], renderer, lView, parentRNode, beforeNode);
23795
+ }
23796
+ }
23797
+ }
23798
+ function removeLViewFromLContainer(lContainer, index) {
23799
+ const lView = detachView(lContainer, index);
23800
+ if (lView !== undefined) {
23801
+ destroyLView(lView[TVIEW], lView);
23802
+ }
23803
+ return lView;
23804
+ }
23805
+
23712
23806
  /**
23713
23807
  * Represents an embedded template that can be used to instantiate embedded views.
23714
23808
  * To instantiate embedded views based on a template, use the `ViewContainerRef`
@@ -23754,25 +23848,13 @@ const R3TemplateRef = class TemplateRef extends ViewEngineTemplateRef {
23754
23848
  return this._declarationTContainer.tView?.ssrId || null;
23755
23849
  }
23756
23850
  createEmbeddedView(context, injector) {
23757
- return this.createEmbeddedViewImpl(context, injector, null);
23851
+ return this.createEmbeddedViewImpl(context, injector);
23758
23852
  }
23759
23853
  /**
23760
23854
  * @internal
23761
23855
  */
23762
23856
  createEmbeddedViewImpl(context, injector, hydrationInfo) {
23763
- // Embedded views follow the change detection strategy of the view they're declared in.
23764
- const isSignalView = this._declarationLView[FLAGS] & 4096 /* LViewFlags.SignalView */;
23765
- const viewFlags = isSignalView ? 4096 /* LViewFlags.SignalView */ : 16 /* LViewFlags.CheckAlways */;
23766
- const embeddedTView = this._declarationTContainer.tView;
23767
- const embeddedLView = createLView(this._declarationLView, embeddedTView, context, viewFlags, null, embeddedTView.declTNode, null, null, null, injector || null, hydrationInfo || null);
23768
- const declarationLContainer = this._declarationLView[this._declarationTContainer.index];
23769
- ngDevMode && assertLContainer(declarationLContainer);
23770
- embeddedLView[DECLARATION_LCONTAINER] = declarationLContainer;
23771
- const declarationViewLQueries = this._declarationLView[QUERIES];
23772
- if (declarationViewLQueries !== null) {
23773
- embeddedLView[QUERIES] = declarationViewLQueries.createEmbeddedView(embeddedTView);
23774
- }
23775
- renderView(embeddedTView, embeddedLView, context);
23857
+ const embeddedLView = createAndRenderEmbeddedLView(this._declarationLView, this._declarationTContainer, context, { injector, hydrationInfo });
23776
23858
  return new ViewRef(embeddedLView);
23777
23859
  }
23778
23860
  };
@@ -23869,11 +23951,20 @@ function cleanupLView(lView) {
23869
23951
  function cleanupDehydratedViews(appRef) {
23870
23952
  const viewRefs = appRef._views;
23871
23953
  for (const viewRef of viewRefs) {
23872
- const lView = getComponentLViewForHydration(viewRef);
23954
+ const lNode = getLNodeForHydration(viewRef);
23873
23955
  // An `lView` might be `null` if a `ViewRef` represents
23874
23956
  // an embedded view (not a component view).
23875
- if (lView !== null && lView[HOST] !== null) {
23876
- cleanupLView(lView);
23957
+ if (lNode !== null && lNode[HOST] !== null) {
23958
+ if (isLView(lNode)) {
23959
+ cleanupLView(lNode);
23960
+ }
23961
+ else {
23962
+ // Cleanup in the root component view
23963
+ const componentLView = lNode[HOST];
23964
+ cleanupLView(componentLView);
23965
+ // Cleanup in all views within this view container
23966
+ cleanupLContainer(lNode);
23967
+ }
23877
23968
  ngDevMode && ngDevMode.dehydratedViewsCleanupRuns++;
23878
23969
  }
23879
23970
  }
@@ -24155,16 +24246,7 @@ const R3ViewContainerRef = class ViewContainerRef extends VE_ViewContainerRef {
24155
24246
  // Logical operation of adding `LView` to `LContainer`
24156
24247
  const adjustedIdx = this._adjustIndex(index);
24157
24248
  const lContainer = this._lContainer;
24158
- insertView(tView, lView, lContainer, adjustedIdx);
24159
- // Physical operation of adding the DOM nodes.
24160
- if (!skipDomInsertion) {
24161
- const beforeNode = getBeforeNodeForView(adjustedIdx, lContainer);
24162
- const renderer = lView[RENDERER];
24163
- const parentRNode = nativeParentNode(renderer, lContainer[NATIVE]);
24164
- if (parentRNode !== null) {
24165
- addViewToContainer(tView, lContainer[T_HOST], renderer, lView, parentRNode, beforeNode);
24166
- }
24167
- }
24249
+ addLViewToLContainer(lContainer, lView, adjustedIdx, !skipDomInsertion);
24168
24250
  viewRef.attachToViewContainerRef();
24169
24251
  addToArray(getOrCreateViewRefs(lContainer), adjustedIdx, viewRef);
24170
24252
  return viewRef;