@angular/core 20.0.1 → 20.1.0-next.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.
Files changed (69) hide show
  1. package/{api.d-B0vztftH.d.ts → api.d-Dwpmmn5j.d.ts} +2 -2
  2. package/{chrome_dev_tools_performance.d-DvzAxqBc.d.ts → chrome_dev_tools_performance.d-Dk_7kdX9.d.ts} +5 -1
  3. package/{discovery.d-CB2iJta5.d.ts → discovery.d-BAZTj_rM.d.ts} +2 -2
  4. package/event_dispatcher.d-BReQpZfC.d.ts +1 -1
  5. package/fesm2022/attribute-BWp59EjE.mjs +1 -1
  6. package/fesm2022/attribute-BWp59EjE.mjs.map +1 -1
  7. package/fesm2022/core.mjs +12 -11
  8. package/fesm2022/core.mjs.map +1 -1
  9. package/fesm2022/{debug_node-B9JawCEy.mjs → debug_node-CjNGi9N3.mjs} +1463 -1437
  10. package/fesm2022/debug_node-CjNGi9N3.mjs.map +1 -0
  11. package/fesm2022/primitives/di.mjs +1 -1
  12. package/fesm2022/primitives/di.mjs.map +1 -1
  13. package/fesm2022/primitives/event-dispatch.mjs +93 -2
  14. package/fesm2022/primitives/event-dispatch.mjs.map +1 -1
  15. package/fesm2022/primitives/signals.mjs +3 -3
  16. package/fesm2022/primitives/signals.mjs.map +1 -1
  17. package/fesm2022/{resource-W6LObBPP.mjs → resource-1o9xbJml.mjs} +5 -5
  18. package/fesm2022/{resource-W6LObBPP.mjs.map → resource-1o9xbJml.mjs.map} +1 -1
  19. package/fesm2022/{root_effect_scheduler-C4AUixQF.mjs → root_effect_scheduler-Ds-Wmkv_.mjs} +16 -9
  20. package/fesm2022/root_effect_scheduler-Ds-Wmkv_.mjs.map +1 -0
  21. package/fesm2022/rxjs-interop.mjs +4 -4
  22. package/fesm2022/rxjs-interop.mjs.map +1 -1
  23. package/fesm2022/signal-BZ1SD--i.mjs +1 -1
  24. package/fesm2022/signal-BZ1SD--i.mjs.map +1 -1
  25. package/fesm2022/testing.mjs +22 -32
  26. package/fesm2022/testing.mjs.map +1 -1
  27. package/fesm2022/{untracked-RA6XPQ1Z.mjs → untracked-C72kieeB.mjs} +3 -3
  28. package/fesm2022/{untracked-RA6XPQ1Z.mjs.map → untracked-C72kieeB.mjs.map} +1 -1
  29. package/fesm2022/weak_ref-BaIq-pgY.mjs +1 -1
  30. package/fesm2022/weak_ref-BaIq-pgY.mjs.map +1 -1
  31. package/graph.d-BcIOep_B.d.ts +1 -1
  32. package/index.d.ts +10 -7
  33. package/package.json +2 -2
  34. package/primitives/di/index.d.ts +1 -1
  35. package/primitives/event-dispatch/index.d.ts +1 -1
  36. package/primitives/signals/index.d.ts +1 -1
  37. package/rxjs-interop/index.d.ts +3 -3
  38. package/schematics/bundles/{apply_import_manager-DT15wSJs.cjs → apply_import_manager-CSEu0fby.cjs} +3 -3
  39. package/schematics/bundles/{checker-Bu1Wu4f7.cjs → checker-CuQvkMhs.cjs} +680 -528
  40. package/schematics/bundles/cleanup-unused-imports.cjs +5 -5
  41. package/schematics/bundles/{compiler_host-C_4Iw5UD.cjs → compiler_host-Biezhzch.cjs} +2 -2
  42. package/schematics/bundles/control-flow-migration.cjs +3 -3
  43. package/schematics/bundles/document-core.cjs +5 -5
  44. package/schematics/bundles/imports-CIX-JgAN.cjs +1 -1
  45. package/schematics/bundles/{index-CCX_cTPD.cjs → index-C5wL4qaq.cjs} +1001 -585
  46. package/schematics/bundles/{index-CAM7Xiu7.cjs → index-vkqofxID.cjs} +17 -16
  47. package/schematics/bundles/inject-flags.cjs +5 -5
  48. package/schematics/bundles/inject-migration.cjs +3 -3
  49. package/schematics/bundles/leading_space-D9nQ8UQC.cjs +1 -1
  50. package/schematics/bundles/{migrate_ts_type_references-DSqmdRpG.cjs → migrate_ts_type_references-BYgEQg0O.cjs} +26 -77
  51. package/schematics/bundles/ng_decorators-B5HCqr20.cjs +1 -1
  52. package/schematics/bundles/nodes-B16H9JUd.cjs +1 -1
  53. package/schematics/bundles/output-migration.cjs +6 -6
  54. package/schematics/bundles/{project_paths-BjQra9mv.cjs → project_paths-KPCsvRfl.cjs} +3 -3
  55. package/schematics/bundles/project_tsconfig_paths-CDVxT6Ov.cjs +1 -1
  56. package/schematics/bundles/property_name-BBwFuqMe.cjs +1 -1
  57. package/schematics/bundles/route-lazy-loading.cjs +3 -3
  58. package/schematics/bundles/self-closing-tags-migration.cjs +7 -19
  59. package/schematics/bundles/signal-input-migration.cjs +28 -12
  60. package/schematics/bundles/signal-queries-migration.cjs +7 -7
  61. package/schematics/bundles/signals.cjs +7 -7
  62. package/schematics/bundles/standalone-migration.cjs +4 -4
  63. package/schematics/bundles/symbol-VPWguRxr.cjs +1 -1
  64. package/schematics/bundles/test-bed-get.cjs +4 -4
  65. package/signal.d-fOdF0h0o.d.ts +1 -1
  66. package/testing/index.d.ts +3 -3
  67. package/weak_ref.d-eGOEP9S1.d.ts +1 -1
  68. package/fesm2022/debug_node-B9JawCEy.mjs.map +0 -1
  69. package/fesm2022/root_effect_scheduler-C4AUixQF.mjs.map +0 -1
@@ -1,10 +1,10 @@
1
1
  /**
2
- * @license Angular v20.0.1
2
+ * @license Angular v20.1.0-next.0
3
3
  * (c) 2010-2025 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
6
6
 
7
- import { attachInjectFlag, _global, resolveForwardRef, ɵɵinvalidFactoryDep as __invalidFactoryDep, ɵɵinject as __inject, ɵɵdefineInjector as __defineInjector, ɵɵdefineInjectable as __defineInjectable, newArray, assertString, EMPTY_OBJ, assertFirstCreatePass, assertDefined, assertNotEqual, FLAGS, assertEqual, isInCheckNoChangesMode, PREORDER_HOOK_FLAGS, throwError, assertNumber, assertGreaterThan, HEADER_OFFSET, DECLARATION_VIEW, throwCyclicDependencyError, stringifyForError, setInjectorProfilerContext, setInjectImplementation, enterDI, emitInjectorToCreateInstanceEvent, emitInstanceCreatedByInjectorEvent, assertDirectiveDef, leaveDI, isRootView, assertTNodeForLView, runInInjectorProfilerContext, getCurrentTNode, getLView, throwProviderNotFoundError, assertNodeInjector, injectRootLimpMode, assertIndexInRange, TVIEW, EMBEDDED_VIEW_INJECTOR, T_HOST, NG_ELEMENT_ID, INJECTOR$1 as INJECTOR, isComponentDef, isComponentHost, convertToBitFlags, NG_FACTORY_DEF, isForwardRef, getFactoryDef, DECLARATION_COMPONENT_VIEW, RuntimeError, NG_PROV_DEF, getClosureSafeProperty, getNativeByTNode, flatten, arrayEquals, ID, isLView, assertDomNode, getComponentLViewByIndex, CONTEXT, EMPTY_ARRAY, unwrapRNode, assertLView, HOST, getLViewParent, CHILD_HEAD, NEXT, isLContainer, Injector, CLEANUP, getComponentDef, getDirectiveDef, InjectionToken, inject, isContentQueryHost, setCurrentQueryIndex, XSS_SECURITY_URL, renderStringify, ENVIRONMENT, makeEnvironmentProviders, formatRuntimeError, resetPreOrderHookFlags, PARENT, RENDERER, HYDRATION, CHILD_TAIL, assertSame, assertFirstUpdatePass, getSelectedIndex, getTView, assertIndexInDeclRange, setSelectedIndex, INTERNAL_APPLICATION_ERROR_HANDLER, assertNotSame, setCurrentDirectiveIndex, stringify, getCurrentDirectiveIndex, unwrapLView, assertNotReactive, enterView, QUERIES, leaveView, isCreationMode, assertLContainer, DECLARATION_LCONTAINER, isDestroyed, MOVED_VIEWS, NATIVE, assertProjectionSlots, CONTAINER_HEADER_OFFSET, assertParentView, REACTIVE_TEMPLATE_CONSUMER, ON_DESTROY_HOOKS, assertFunction, EFFECTS, AFTER_RENDER_SEQUENCES_TO_ADD, markViewForRefresh, markAncestorsForTraversal, setIsInCheckNoChangesMode, setIsRefreshingViews, isExhaustiveCheckNoChanges, requiresRefreshOrTraversal, setBindingIndex, EFFECTS_TO_SCHEDULE, setBindingRootForHostBindings, viewAttachedToChangeDetector, isRefreshingViews, CheckNoChangesMode, removeFromArray, addToArray, updateAncestorTraversalFlagsOnAttach, storeLViewOnDestroy, VIEW_REFS, assertGreaterThanOrEqual, isInI18nBlock, getCurrentParentTNode, assertTNodeForTView, setCurrentTNode, getCurrentTNodePlaceholderOk, isCurrentTNodeParent, isInSkipHydrationBlock as isInSkipHydrationBlock$1, assertTNode, assertTIcu, assertNumberInRange, DEHYDRATED_VIEWS, getNgModuleDef, getPipeDef as getPipeDef$1, getNgModuleDefOrThrow, isStandalone, concatStringsWithSpace, assertInjectImplementationNotEqual, emitInjectEvent, getConstant, assertLessThan, getOrCreateTViewCleanup, getOrCreateLViewCleanup, isDirectiveHost, assertNotDefined, getSelectedTNode, nextBindingIndex, getTNode, debugStringifyTypeForError, getDirectiveDefOrThrow, ChangeDetectionScheduler, assertComponentType, EnvironmentInjector, SVG_NAMESPACE, MATH_ML_NAMESPACE, viewAttachedToContainer, storeCleanupWithContext, signal, createInjectorWithoutInjectorInstances, R3Injector, getNullInjector, internalImportProvidersFrom, initNgDevMode, fillProperties, wasLastNodeCreated, getBindingsEnabled, lastNodeWasCreated, isInInjectionContext, DestroyRef, PendingTasksInternal, noop, ErrorHandler, assertNotInReactiveContext, assertInInjectionContext, ViewContext, removeLViewOnDestroy, walkUpViews, getNativeByIndex, assertElement, arrayInsert2, arraySplice, setInjectorProfiler, NullInjector, ENVIRONMENT_INITIALIZER, INJECTOR_DEF_TYPES, walkProviderTree, getInjectorDef, deepForEach, isTypeProvider, isSignal, runInInjectionContext, ZONELESS_ENABLED, EffectScheduler, PendingTasks, assertHasParent, getElementDepthCount, getNamespace, enterSkipHydrationBlock, getBindingIndex, increaseElementDepthCount, setCurrentTNodeAsNotParent, isSkipHydrationRootTNode, leaveSkipHydrationBlock, decreaseElementDepthCount, getCurrentDirectiveDef, assertIndexInExpandoRange, assertOneOf, setInI18nBlock, nextContextImpl, getCurrentQueryIndex, getContextLView, load, keyValueArrayIndexOf, incrementBindingIndex, keyValueArrayGet, keyValueArraySet, isWritableSignal, store, providerToFactory, emitProviderConfiguredEvent, isClassProvider, getBindingRoot, NG_COMP_DEF, forwardRef, ɵɵrestoreView as __restoreView, ɵɵdisableBindings as __disableBindings, ɵɵenableBindings as __enableBindings, ɵɵnamespaceSVG as __namespaceSVG, ɵɵnamespaceMathML as __namespaceMathML, ɵɵnamespaceHTML as __namespaceHTML, ɵɵresetView as __resetView, NG_MOD_DEF, NG_INJ_DEF, NG_DIR_DEF, NG_PIPE_DEF, ZONELESS_SCHEDULER_DISABLED, SCHEDULE_IN_ROOT_ZONE, PROVIDED_ZONELESS, getNativeByTNodeOrNull } from './root_effect_scheduler-C4AUixQF.mjs';
7
+ import { attachInjectFlag, _global, ɵɵdefineInjectable as __defineInjectable, ɵɵdefineInjector as __defineInjector, ɵɵinject as __inject, ɵɵinvalidFactoryDep as __invalidFactoryDep, resolveForwardRef, newArray, EMPTY_OBJ, assertString, assertNotEqual, FLAGS, assertEqual, isInCheckNoChangesMode, PREORDER_HOOK_FLAGS, assertFirstCreatePass, assertDefined, throwError, assertNumber, assertGreaterThan, HEADER_OFFSET, DECLARATION_VIEW, NG_FACTORY_DEF, isForwardRef, getFactoryDef, assertIndexInRange, assertTNodeForLView, enterDI, runInInjectorProfilerContext, getCurrentTNode, getLView, emitInjectorToCreateInstanceEvent, emitInstanceCreatedByInjectorEvent, throwProviderNotFoundError, leaveDI, assertNodeInjector, throwCyclicDependencyError, stringifyForError, setInjectorProfilerContext, setInjectImplementation, assertDirectiveDef, NG_ELEMENT_ID, convertToBitFlags, isRootView, T_HOST, TVIEW, injectRootLimpMode, isComponentDef, EMBEDDED_VIEW_INJECTOR, INJECTOR$1 as INJECTOR, DECLARATION_COMPONENT_VIEW, isComponentHost, RuntimeError, NG_PROV_DEF, getClosureSafeProperty, getNativeByTNode, flatten, arrayEquals, ID, isLView, assertDomNode, unwrapRNode, getComponentLViewByIndex, CONTEXT, EMPTY_ARRAY, assertLView, HOST, CHILD_HEAD, NEXT, isLContainer, getLViewParent, Injector, CLEANUP, getComponentDef, getDirectiveDef, InjectionToken, inject, isInSkipHydrationBlock as isInSkipHydrationBlock$1, HYDRATION, isContentQueryHost, setCurrentQueryIndex, XSS_SECURITY_URL, renderStringify, ENVIRONMENT, makeEnvironmentProviders, isDirectiveHost, formatRuntimeError, resetPreOrderHookFlags, PARENT, RENDERER, CHILD_TAIL, assertSame, assertFirstUpdatePass, getSelectedIndex, getTView, assertIndexInDeclRange, setSelectedIndex, assertLContainer, MOVED_VIEWS, isDestroyed, REACTIVE_TEMPLATE_CONSUMER, DECLARATION_LCONTAINER, QUERIES, assertNotReactive, ON_DESTROY_HOOKS, assertFunction, EFFECTS, assertProjectionSlots, NATIVE, assertParentView, CONTAINER_HEADER_OFFSET, assertNotSame, setCurrentDirectiveIndex, setCurrentTNode, getElementDepthCount, increaseElementDepthCount, wasLastNodeCreated, isCurrentTNodeParent, setCurrentTNodeAsNotParent, assertHasParent, INTERNAL_APPLICATION_ERROR_HANDLER, stringify, getCurrentDirectiveIndex, unwrapLView, isCreationMode, enterView, leaveView, AFTER_RENDER_SEQUENCES_TO_ADD, markAncestorsForTraversal, markViewForRefresh, setIsRefreshingViews, isExhaustiveCheckNoChanges, requiresRefreshOrTraversal, setIsInCheckNoChangesMode, CheckNoChangesMode, setBindingIndex, EFFECTS_TO_SCHEDULE, viewAttachedToChangeDetector, setBindingRootForHostBindings, isRefreshingViews, removeFromArray, addToArray, updateAncestorTraversalFlagsOnAttach, storeLViewOnDestroy, VIEW_REFS, assertGreaterThanOrEqual, isInI18nBlock, assertTNodeForTView, getCurrentParentTNode, getCurrentTNodePlaceholderOk, assertTNode, assertTIcu, assertNumberInRange, DEHYDRATED_VIEWS, getNgModuleDef, getPipeDef as getPipeDef$1, getNgModuleDefOrThrow, isStandalone, concatStringsWithSpace, assertInjectImplementationNotEqual, emitInjectEvent, getConstant, assertLessThan, getOrCreateTViewCleanup, getOrCreateLViewCleanup, assertNotDefined, nextBindingIndex, getSelectedTNode, getDirectiveDefOrThrow, getTNode, assertComponentType, debugStringifyTypeForError, ChangeDetectionScheduler, EnvironmentInjector, SVG_NAMESPACE, MATH_ML_NAMESPACE, viewAttachedToContainer, storeCleanupWithContext, signal, createInjectorWithoutInjectorInstances, R3Injector, getNullInjector, internalImportProvidersFrom, initNgDevMode, fillProperties, getBindingsEnabled, lastNodeWasCreated, isInInjectionContext, DestroyRef, PendingTasksInternal, noop, ErrorHandler, assertNotInReactiveContext, assertInInjectionContext, ViewContext, removeLViewOnDestroy, walkUpViews, getNativeByIndex, assertElement, arrayInsert2, arraySplice, setInjectorProfiler, NullInjector, ENVIRONMENT_INITIALIZER, INJECTOR_DEF_TYPES, walkProviderTree, getInjectorDef, deepForEach, isTypeProvider, isSignal, runInInjectionContext, ZONELESS_ENABLED, EffectScheduler, PendingTasks, assertTNodeCreationIndex, isSkipHydrationRootTNode, leaveSkipHydrationBlock, decreaseElementDepthCount, getNamespace, enterSkipHydrationBlock, getCurrentDirectiveDef, assertIndexInExpandoRange, getBindingIndex, assertOneOf, setInI18nBlock, nextContextImpl, getCurrentQueryIndex, getContextLView, load, keyValueArrayIndexOf, keyValueArraySet, keyValueArrayGet, incrementBindingIndex, isWritableSignal, store, providerToFactory, emitProviderConfiguredEvent, isClassProvider, getBindingRoot, NG_COMP_DEF, ɵɵresetView as __resetView, ɵɵnamespaceHTML as __namespaceHTML, ɵɵnamespaceMathML as __namespaceMathML, ɵɵnamespaceSVG as __namespaceSVG, ɵɵenableBindings as __enableBindings, ɵɵdisableBindings as __disableBindings, ɵɵrestoreView as __restoreView, forwardRef, NG_MOD_DEF, NG_INJ_DEF, NG_DIR_DEF, NG_PIPE_DEF, ZONELESS_SCHEDULER_DISABLED, SCHEDULE_IN_ROOT_ZONE, PROVIDED_ZONELESS, getNativeByTNodeOrNull } from './root_effect_scheduler-Ds-Wmkv_.mjs';
8
8
  import { setActiveConsumer, SIGNAL, consumerDestroy, REACTIVE_NODE, consumerPollProducersForChange, consumerBeforeComputation, getActiveConsumer, consumerAfterComputation, createComputed, setThrowInvalidWriteToSignalError } from './signal-BZ1SD--i.mjs';
9
9
  import { Subject, Subscription } from 'rxjs';
10
10
  import { setActiveConsumer as setActiveConsumer$1 } from '@angular/core/primitives/signals';
@@ -1893,7 +1893,7 @@ function searchTokensOnInjector(injectorIndex, lView, token, previousTView, flag
1893
1893
  const isHostSpecialCase = flags & 1 /* InternalInjectFlags.Host */ && hostTElementNode === tNode;
1894
1894
  const injectableIdx = locateDirectiveOrProvider(tNode, currentTView, token, canAccessViewProviders, isHostSpecialCase);
1895
1895
  if (injectableIdx !== null) {
1896
- return getNodeInjectable(lView, currentTView, injectableIdx, tNode);
1896
+ return getNodeInjectable(lView, currentTView, injectableIdx, tNode, flags);
1897
1897
  }
1898
1898
  else {
1899
1899
  return NOT_FOUND;
@@ -1943,7 +1943,7 @@ function locateDirectiveOrProvider(tNode, tView, token, canAccessViewProviders,
1943
1943
  * cached `injectable`. Otherwise if it detects that the value is still a factory it
1944
1944
  * instantiates the `injectable` and caches the value.
1945
1945
  */
1946
- function getNodeInjectable(lView, tView, index, tNode) {
1946
+ function getNodeInjectable(lView, tView, index, tNode, flags) {
1947
1947
  let value = lView[index];
1948
1948
  const tData = tView.data;
1949
1949
  if (value instanceof NodeInjectorFactory) {
@@ -1971,7 +1971,7 @@ function getNodeInjectable(lView, tView, index, tNode) {
1971
1971
  assertEqual(success, true, "Because flags do not contain `SkipSelf' we expect this to always succeed.");
1972
1972
  try {
1973
1973
  ngDevMode && emitInjectorToCreateInstanceEvent(token);
1974
- value = lView[index] = factory.factory(undefined, tData, lView, tNode);
1974
+ value = lView[index] = factory.factory(undefined, flags, tData, lView, tNode);
1975
1975
  ngDevMode && emitInstanceCreatedByInjectorEvent(value);
1976
1976
  // This code path is hit for both directives and providers.
1977
1977
  // For perf reasons, we want to avoid searching for hooks on providers.
@@ -4189,6 +4189,15 @@ class DehydratedBlockRegistry {
4189
4189
  });
4190
4190
  }
4191
4191
 
4192
+ /**
4193
+ * Checks whether a TNode is considered detached, i.e. not present in the
4194
+ * translated i18n template. We should not attempt hydration for such nodes
4195
+ * and instead, use a regular "creation mode".
4196
+ */
4197
+ function isDetachedByI18n(tNode) {
4198
+ return (tNode.flags & 32 /* TNodeFlags.isDetached */) === 32 /* TNodeFlags.isDetached */;
4199
+ }
4200
+
4192
4201
  /**
4193
4202
  * The name of the key used in the TransferState collection,
4194
4203
  * where hydration information is located.
@@ -4532,6 +4541,18 @@ function isDisconnectedNode$1(hydrationInfo, index) {
4532
4541
  }
4533
4542
  return !!initDisconnectedNodes(hydrationInfo)?.has(index);
4534
4543
  }
4544
+ /**
4545
+ * Checks whether a node can be hydrated.
4546
+ * @param lView View in which the node instance is placed.
4547
+ * @param tNode Node to be checked.
4548
+ */
4549
+ function canHydrateNode(lView, tNode) {
4550
+ const hydrationInfo = lView[HYDRATION];
4551
+ return (hydrationInfo !== null &&
4552
+ !isInSkipHydrationBlock$1() &&
4553
+ !isDetachedByI18n(tNode) &&
4554
+ !isDisconnectedNode$1(hydrationInfo, tNode.index - HEADER_OFFSET));
4555
+ }
4535
4556
  /**
4536
4557
  * Helper function to prepare text nodes for serialization by ensuring
4537
4558
  * that seperate logical text blocks in the DOM remain separate after
@@ -5896,21 +5917,20 @@ function ɵgetUnknownPropertyStrictMode() {
5896
5917
  * - the element matches any directive
5897
5918
  * - the element is allowed by one of the schemas
5898
5919
  *
5899
- * @param element Element to validate
5900
- * @param lView An `LView` that represents a current component that is being rendered
5901
- * @param tagName Name of the tag to check
5902
- * @param schemas Array of schemas
5903
- * @param hasDirectives Boolean indicating that the element matches any directive
5920
+ * @param lView An `LView` associated with a template is being rendered
5921
+ * @param tNode TNode representing an element to be validated
5904
5922
  */
5905
- function validateElementIsKnown(element, lView, tagName, schemas, hasDirectives) {
5923
+ function validateElementIsKnown(lView, tNode) {
5924
+ const tView = lView[TVIEW];
5906
5925
  // If `schemas` is set to `null`, that's an indication that this Component was compiled in AOT
5907
5926
  // mode where this check happens at compile time. In JIT mode, `schemas` is always present and
5908
5927
  // defined as an array (as an empty array in case `schemas` field is not defined) and we should
5909
5928
  // execute the check below.
5910
- if (schemas === null)
5929
+ if (tView.schemas === null)
5911
5930
  return;
5931
+ const tagName = tNode.value;
5912
5932
  // If the element matches any directive, it's considered as valid.
5913
- if (!hasDirectives && tagName !== null) {
5933
+ if (!isDirectiveHost(tNode) && tagName !== null) {
5914
5934
  // The element is unknown if it's an instance of HTMLUnknownElement, or it isn't registered
5915
5935
  // as a custom element. Note that unknown elements with a dash in their name won't be instances
5916
5936
  // of HTMLUnknownElement in browsers that support web components.
@@ -5919,11 +5939,11 @@ function validateElementIsKnown(element, lView, tagName, schemas, hasDirectives)
5919
5939
  // Domino doesn't expose HTMLUnknownElement globally.
5920
5940
  (typeof HTMLUnknownElement !== 'undefined' &&
5921
5941
  HTMLUnknownElement &&
5922
- element instanceof HTMLUnknownElement) ||
5942
+ getNativeByTNode(tNode, lView) instanceof HTMLUnknownElement) ||
5923
5943
  (typeof customElements !== 'undefined' &&
5924
5944
  tagName.indexOf('-') > -1 &&
5925
5945
  !customElements.get(tagName));
5926
- if (isUnknown && !matchingSchemas(schemas, tagName)) {
5946
+ if (isUnknown && !matchingSchemas(tView.schemas, tagName)) {
5927
5947
  const isHostStandalone = isHostComponentStandalone(lView);
5928
5948
  const templateLocation = getTemplateLocationDetails(lView);
5929
5949
  const schemas = `'${isHostStandalone ? '@Component' : '@NgModule'}.schemas'`;
@@ -7123,1445 +7143,1478 @@ function writeToDirectiveInput(def, instance, publicName, value) {
7123
7143
  }
7124
7144
  }
7125
7145
 
7126
- function executeTemplate(tView, lView, templateFn, rf, context) {
7127
- const prevSelectedIndex = getSelectedIndex();
7128
- const isUpdatePhase = rf & 2 /* RenderFlags.Update */;
7129
- try {
7130
- setSelectedIndex(-1);
7131
- if (isUpdatePhase && lView.length > HEADER_OFFSET) {
7132
- // When we're updating, inherently select 0 so we don't
7133
- // have to generate that instruction for most update blocks.
7134
- selectIndexInternal(tView, lView, HEADER_OFFSET, !!ngDevMode && isInCheckNoChangesMode());
7135
- }
7136
- const preHookType = isUpdatePhase
7137
- ? 2 /* ProfilerEvent.TemplateUpdateStart */
7138
- : 0 /* ProfilerEvent.TemplateCreateStart */;
7139
- profiler(preHookType, context, templateFn);
7140
- templateFn(rf, context);
7141
- }
7142
- finally {
7143
- setSelectedIndex(prevSelectedIndex);
7144
- const postHookType = isUpdatePhase
7145
- ? 3 /* ProfilerEvent.TemplateUpdateEnd */
7146
- : 1 /* ProfilerEvent.TemplateCreateEnd */;
7147
- profiler(postHookType, context, templateFn);
7148
- }
7146
+ /**
7147
+ * Flags for renderer-specific style modifiers.
7148
+ * @publicApi
7149
+ */
7150
+ var RendererStyleFlags2;
7151
+ (function (RendererStyleFlags2) {
7152
+ // TODO(misko): This needs to be refactored into a separate file so that it can be imported from
7153
+ // `node_manipulation.ts` Currently doing the import cause resolution order to change and fails
7154
+ // the tests. The work around is to have hard coded value in `node_manipulation.ts` for now.
7155
+ /**
7156
+ * Marks a style as important.
7157
+ */
7158
+ RendererStyleFlags2[RendererStyleFlags2["Important"] = 1] = "Important";
7159
+ /**
7160
+ * Marks a style as using dash case naming (this-is-dash-case).
7161
+ */
7162
+ RendererStyleFlags2[RendererStyleFlags2["DashCase"] = 2] = "DashCase";
7163
+ })(RendererStyleFlags2 || (RendererStyleFlags2 = {}));
7164
+
7165
+ let _icuContainerIterate;
7166
+ /**
7167
+ * Iterator which provides ability to visit all of the `TIcuContainerNode` root `RNode`s.
7168
+ */
7169
+ function icuContainerIterate(tIcuContainerNode, lView) {
7170
+ return _icuContainerIterate(tIcuContainerNode, lView);
7149
7171
  }
7150
7172
  /**
7151
- * Creates directive instances.
7173
+ * Ensures that `IcuContainerVisitor`'s implementation is present.
7174
+ *
7175
+ * This function is invoked when i18n instruction comes across an ICU. The purpose is to allow the
7176
+ * bundler to tree shake ICU logic and only load it if ICU instruction is executed.
7152
7177
  */
7153
- function createDirectivesInstances(tView, lView, tNode) {
7154
- instantiateAllDirectives(tView, lView, tNode);
7155
- if ((tNode.flags & 64 /* TNodeFlags.hasHostBindings */) === 64 /* TNodeFlags.hasHostBindings */) {
7156
- invokeDirectivesHostBindings(tView, lView, tNode);
7178
+ function ensureIcuContainerVisitorLoaded(loader) {
7179
+ if (_icuContainerIterate === undefined) {
7180
+ // Do not inline this function. We want to keep `ensureIcuContainerVisitorLoaded` light, so it
7181
+ // can be inlined into call-site.
7182
+ _icuContainerIterate = loader();
7157
7183
  }
7158
7184
  }
7185
+
7159
7186
  /**
7160
- * Takes a list of local names and indices and pushes the resolved local variable values
7161
- * to LView in the same order as they are loaded in the template with load().
7187
+ * NOTE: for performance reasons, the possible actions are inlined within the function instead of
7188
+ * being passed as an argument.
7162
7189
  */
7163
- function saveResolvedLocalsInData(viewData, tNode, localRefExtractor = getNativeByTNode) {
7164
- const localNames = tNode.localNames;
7165
- if (localNames !== null) {
7166
- let localIndex = tNode.index + 1;
7167
- for (let i = 0; i < localNames.length; i += 2) {
7168
- const index = localNames[i + 1];
7169
- const value = index === -1
7170
- ? localRefExtractor(tNode, viewData)
7171
- : viewData[index];
7172
- viewData[localIndex++] = value;
7190
+ function applyToElementOrContainer(action, renderer, parent, lNodeToHandle, beforeNode) {
7191
+ // If this slot was allocated for a text node dynamically created by i18n, the text node itself
7192
+ // won't be created until i18nApply() in the update block, so this node should be skipped.
7193
+ // For more info, see "ICU expressions should work inside an ngTemplateOutlet inside an ngFor"
7194
+ // in `i18n_spec.ts`.
7195
+ if (lNodeToHandle != null) {
7196
+ let lContainer;
7197
+ let isComponent = false;
7198
+ // We are expecting an RNode, but in the case of a component or LContainer the `RNode` is
7199
+ // wrapped in an array which needs to be unwrapped. We need to know if it is a component and if
7200
+ // it has LContainer so that we can process all of those cases appropriately.
7201
+ if (isLContainer(lNodeToHandle)) {
7202
+ lContainer = lNodeToHandle;
7203
+ }
7204
+ else if (isLView(lNodeToHandle)) {
7205
+ isComponent = true;
7206
+ ngDevMode && assertDefined(lNodeToHandle[HOST], 'HOST must be defined for a component LView');
7207
+ lNodeToHandle = lNodeToHandle[HOST];
7208
+ }
7209
+ const rNode = unwrapRNode(lNodeToHandle);
7210
+ if (action === 0 /* WalkTNodeTreeAction.Create */ && parent !== null) {
7211
+ if (beforeNode == null) {
7212
+ nativeAppendChild(renderer, parent, rNode);
7213
+ }
7214
+ else {
7215
+ nativeInsertBefore(renderer, parent, rNode, beforeNode || null, true);
7216
+ }
7217
+ }
7218
+ else if (action === 1 /* WalkTNodeTreeAction.Insert */ && parent !== null) {
7219
+ nativeInsertBefore(renderer, parent, rNode, beforeNode || null, true);
7220
+ }
7221
+ else if (action === 2 /* WalkTNodeTreeAction.Detach */) {
7222
+ nativeRemoveNode(renderer, rNode, isComponent);
7223
+ }
7224
+ else if (action === 3 /* WalkTNodeTreeAction.Destroy */) {
7225
+ renderer.destroyNode(rNode);
7226
+ }
7227
+ if (lContainer != null) {
7228
+ applyContainer(renderer, action, lContainer, parent, beforeNode);
7173
7229
  }
7174
7230
  }
7175
7231
  }
7176
7232
  /**
7177
- * Locates the host native element, used for bootstrapping existing nodes into rendering pipeline.
7233
+ * Removes all DOM elements associated with a view.
7178
7234
  *
7179
- * @param renderer the renderer used to locate the element.
7180
- * @param elementOrSelector Render element or CSS selector to locate the element.
7181
- * @param encapsulation View Encapsulation defined for component that requests host element.
7182
- * @param injector Root view injector instance.
7183
- */
7184
- function locateHostElement(renderer, elementOrSelector, encapsulation, injector) {
7185
- // Note: we use default value for the `PRESERVE_HOST_CONTENT` here even though it's a
7186
- // tree-shakable one (providedIn:'root'). This code path can be triggered during dynamic
7187
- // component creation (after calling ViewContainerRef.createComponent) when an injector
7188
- // instance can be provided. The injector instance might be disconnected from the main DI
7189
- // tree, thus the `PRESERVE_HOST_CONTENT` would not be able to instantiate. In this case, the
7190
- // default value will be used.
7191
- const preserveHostContent = injector.get(PRESERVE_HOST_CONTENT, PRESERVE_HOST_CONTENT_DEFAULT);
7192
- // When using native Shadow DOM, do not clear host element to allow native slot
7193
- // projection.
7194
- const preserveContent = preserveHostContent || encapsulation === ViewEncapsulation.ShadowDom;
7195
- const rootElement = renderer.selectRootElement(elementOrSelector, preserveContent);
7196
- applyRootElementTransform(rootElement);
7197
- return rootElement;
7198
- }
7199
- /**
7200
- * Applies any root element transformations that are needed. If hydration is enabled,
7201
- * this will process corrupted text nodes.
7235
+ * Because some root nodes of the view may be containers, we sometimes need
7236
+ * to propagate deeply into the nested containers to remove all elements in the
7237
+ * views beneath it.
7202
7238
  *
7203
- * @param rootElement the app root HTML Element
7239
+ * @param tView The `TView' of the `LView` from which elements should be added or removed
7240
+ * @param lView The view from which elements should be added or removed
7204
7241
  */
7205
- function applyRootElementTransform(rootElement) {
7206
- _applyRootElementTransformImpl(rootElement);
7242
+ function removeViewFromDOM(tView, lView) {
7243
+ detachViewFromDOM(tView, lView);
7244
+ lView[HOST] = null;
7245
+ lView[T_HOST] = null;
7207
7246
  }
7208
7247
  /**
7209
- * Reference to a function that applies transformations to the root HTML element
7210
- * of an app. When hydration is enabled, this processes any corrupt text nodes
7211
- * so they are properly hydratable on the client.
7248
+ * Adds all DOM elements associated with a view.
7212
7249
  *
7213
- * @param rootElement the app root HTML Element
7214
- */
7215
- let _applyRootElementTransformImpl = () => null;
7216
- /**
7217
- * Processes text node markers before hydration begins. This replaces any special comment
7218
- * nodes that were added prior to serialization are swapped out to restore proper text
7219
- * nodes before hydration.
7250
+ * Because some root nodes of the view may be containers, we sometimes need
7251
+ * to propagate deeply into the nested containers to add all elements in the
7252
+ * views beneath it.
7220
7253
  *
7221
- * @param rootElement the app root HTML Element
7254
+ * @param tView The `TView' of the `LView` from which elements should be added or removed
7255
+ * @param parentTNode The `TNode` where the `LView` should be attached to.
7256
+ * @param renderer Current renderer to use for DOM manipulations.
7257
+ * @param lView The view from which elements should be added or removed
7258
+ * @param parentNativeNode The parent `RElement` where it should be inserted into.
7259
+ * @param beforeNode The node before which elements should be added, if insert mode
7222
7260
  */
7223
- function applyRootElementTransformImpl(rootElement) {
7224
- if (hasSkipHydrationAttrOnRElement(rootElement)) {
7225
- // Handle a situation when the `ngSkipHydration` attribute is applied
7226
- // to the root node of an application. In this case, we should clear
7227
- // the contents and render everything from scratch.
7228
- clearElementContents(rootElement);
7229
- }
7230
- else {
7231
- processTextNodeMarkersBeforeHydration(rootElement);
7232
- }
7261
+ function addViewToDOM(tView, parentTNode, renderer, lView, parentNativeNode, beforeNode) {
7262
+ lView[HOST] = parentNativeNode;
7263
+ lView[T_HOST] = parentTNode;
7264
+ applyView(tView, lView, renderer, 1 /* WalkTNodeTreeAction.Insert */, parentNativeNode, beforeNode);
7233
7265
  }
7234
7266
  /**
7235
- * Sets the implementation for the `applyRootElementTransform` function.
7267
+ * Detach a `LView` from the DOM by detaching its nodes.
7268
+ *
7269
+ * @param tView The `TView' of the `LView` to be detached
7270
+ * @param lView the `LView` to be detached.
7236
7271
  */
7237
- function enableApplyRootElementTransformImpl() {
7238
- _applyRootElementTransformImpl = applyRootElementTransformImpl;
7272
+ function detachViewFromDOM(tView, lView) {
7273
+ // When we remove a view from the DOM, we need to rerun afterRender hooks
7274
+ // We don't necessarily needs to run change detection. DOM removal only requires
7275
+ // change detection if animations are enabled (this notification is handled by animations).
7276
+ lView[ENVIRONMENT].changeDetectionScheduler?.notify(9 /* NotificationSource.ViewDetachedFromDOM */);
7277
+ applyView(tView, lView, lView[RENDERER], 2 /* WalkTNodeTreeAction.Detach */, null, null);
7239
7278
  }
7240
7279
  /**
7241
- * Mapping between attributes names that don't correspond to their element property names.
7280
+ * Traverses down and up the tree of views and containers to remove listeners and
7281
+ * call onDestroy callbacks.
7242
7282
  *
7243
- * Performance note: this function is written as a series of if checks (instead of, say, a property
7244
- * object lookup) for performance reasons - the series of `if` checks seems to be the fastest way of
7245
- * mapping property names. Do NOT change without benchmarking.
7283
+ * Notes:
7284
+ * - Because it's used for onDestroy calls, it needs to be bottom-up.
7285
+ * - Must process containers instead of their views to avoid splicing
7286
+ * when views are destroyed and re-added.
7287
+ * - Using a while loop because it's faster than recursion
7288
+ * - Destroy only called on movement to sibling or movement to parent (laterally or up)
7246
7289
  *
7247
- * Note: this mapping has to be kept in sync with the equally named mapping in the template
7248
- * type-checking machinery of ngtsc.
7290
+ * @param rootView The view to destroy
7249
7291
  */
7250
- function mapPropName(name) {
7251
- if (name === 'class')
7252
- return 'className';
7253
- if (name === 'for')
7254
- return 'htmlFor';
7255
- if (name === 'formaction')
7256
- return 'formAction';
7257
- if (name === 'innerHtml')
7258
- return 'innerHTML';
7259
- if (name === 'readonly')
7260
- return 'readOnly';
7261
- if (name === 'tabindex')
7262
- return 'tabIndex';
7263
- return name;
7264
- }
7265
- function setPropertyAndInputs(tNode, lView, propName, value, renderer, sanitizer) {
7266
- ngDevMode && assertNotSame(value, NO_CHANGE, 'Incoming value should never be NO_CHANGE.');
7267
- const tView = lView[TVIEW];
7268
- const hasSetInput = setAllInputsForProperty(tNode, tView, lView, propName, value);
7269
- if (hasSetInput) {
7270
- isComponentHost(tNode) && markDirtyIfOnPush(lView, tNode.index);
7271
- ngDevMode && setNgReflectProperties(lView, tView, tNode, propName, value);
7272
- return; // Stop propcessing if we've matched at least one input.
7292
+ function destroyViewTree(rootView) {
7293
+ // If the view has no children, we can clean it up and return early.
7294
+ let lViewOrLContainer = rootView[CHILD_HEAD];
7295
+ if (!lViewOrLContainer) {
7296
+ return cleanUpView(rootView[TVIEW], rootView);
7273
7297
  }
7274
- setDomProperty(tNode, lView, propName, value, renderer, sanitizer);
7275
- }
7276
- /**
7277
- * Sets a DOM property on a specific node.
7278
- * @param tNode TNode on which to set the value.
7279
- * @param lView View in which the node is located.
7280
- * @param propName Name of the property.
7281
- * @param value Value to set on the property.
7282
- * @param renderer Renderer to use when setting the property.
7283
- * @param sanitizer Function used to sanitize the value before setting it.
7284
- */
7285
- function setDomProperty(tNode, lView, propName, value, renderer, sanitizer) {
7286
- if (tNode.type & 3 /* TNodeType.AnyRNode */) {
7287
- const element = getNativeByTNode(tNode, lView);
7288
- propName = mapPropName(propName);
7289
- if (ngDevMode) {
7290
- validateAgainstEventProperties(propName);
7291
- if (!isPropertyValid(element, propName, tNode.value, lView[TVIEW].schemas)) {
7292
- handleUnknownPropertyError(propName, tNode.value, tNode.type, lView);
7293
- }
7298
+ while (lViewOrLContainer) {
7299
+ let next = null;
7300
+ if (isLView(lViewOrLContainer)) {
7301
+ // If LView, traverse down to child.
7302
+ next = lViewOrLContainer[CHILD_HEAD];
7294
7303
  }
7295
- // It is assumed that the sanitizer is only added when the compiler determines that the
7296
- // property is risky, so sanitization can be done without further checks.
7297
- value = sanitizer != null ? sanitizer(value, tNode.value || '', propName) : value;
7298
- renderer.setProperty(element, propName, value);
7299
- }
7300
- else if (tNode.type & 12 /* TNodeType.AnyContainer */) {
7301
- // If the node is a container and the property didn't
7302
- // match any of the inputs or schemas we should throw.
7303
- if (ngDevMode && !matchingSchemas(lView[TVIEW].schemas, tNode.value)) {
7304
- handleUnknownPropertyError(propName, tNode.value, tNode.type, lView);
7304
+ else {
7305
+ ngDevMode && assertLContainer(lViewOrLContainer);
7306
+ // If container, traverse down to its first LView.
7307
+ const firstView = lViewOrLContainer[CONTAINER_HEADER_OFFSET];
7308
+ if (firstView)
7309
+ next = firstView;
7310
+ }
7311
+ if (!next) {
7312
+ // Only clean up view when moving to the side or up, as destroy hooks
7313
+ // should be called in order from the bottom up.
7314
+ while (lViewOrLContainer && !lViewOrLContainer[NEXT] && lViewOrLContainer !== rootView) {
7315
+ if (isLView(lViewOrLContainer)) {
7316
+ cleanUpView(lViewOrLContainer[TVIEW], lViewOrLContainer);
7317
+ }
7318
+ lViewOrLContainer = lViewOrLContainer[PARENT];
7319
+ }
7320
+ if (lViewOrLContainer === null)
7321
+ lViewOrLContainer = rootView;
7322
+ if (isLView(lViewOrLContainer)) {
7323
+ cleanUpView(lViewOrLContainer[TVIEW], lViewOrLContainer);
7324
+ }
7325
+ next = lViewOrLContainer && lViewOrLContainer[NEXT];
7305
7326
  }
7327
+ lViewOrLContainer = next;
7306
7328
  }
7307
7329
  }
7308
- /** If node is an OnPush component, marks its LView dirty. */
7309
- function markDirtyIfOnPush(lView, viewIndex) {
7310
- ngDevMode && assertLView(lView);
7311
- const childComponentLView = getComponentLViewByIndex(viewIndex, lView);
7312
- if (!(childComponentLView[FLAGS] & 16 /* LViewFlags.CheckAlways */)) {
7313
- childComponentLView[FLAGS] |= 64 /* LViewFlags.Dirty */;
7314
- }
7330
+ function detachMovedView(declarationContainer, lView) {
7331
+ ngDevMode && assertLContainer(declarationContainer);
7332
+ ngDevMode &&
7333
+ assertDefined(declarationContainer[MOVED_VIEWS], 'A projected view should belong to a non-empty projected views collection');
7334
+ const movedViews = declarationContainer[MOVED_VIEWS];
7335
+ const declarationViewIndex = movedViews.indexOf(lView);
7336
+ movedViews.splice(declarationViewIndex, 1);
7315
7337
  }
7316
- function setNgReflectProperty(lView, tNode, attrName, value) {
7317
- const environment = lView[ENVIRONMENT];
7318
- if (!environment.ngReflect) {
7338
+ /**
7339
+ * A standalone function which destroys an LView,
7340
+ * conducting clean up (e.g. removing listeners, calling onDestroys).
7341
+ *
7342
+ * @param tView The `TView' of the `LView` to be destroyed
7343
+ * @param lView The view to be destroyed.
7344
+ */
7345
+ function destroyLView(tView, lView) {
7346
+ if (isDestroyed(lView)) {
7319
7347
  return;
7320
7348
  }
7321
- const element = getNativeByTNode(tNode, lView);
7322
7349
  const renderer = lView[RENDERER];
7323
- attrName = normalizeDebugBindingName(attrName);
7324
- const debugValue = normalizeDebugBindingValue(value);
7325
- if (tNode.type & 3 /* TNodeType.AnyRNode */) {
7326
- if (value == null) {
7327
- renderer.removeAttribute(element, attrName);
7328
- }
7329
- else {
7330
- renderer.setAttribute(element, attrName, debugValue);
7331
- }
7332
- }
7333
- else {
7334
- const textContent = escapeCommentText(`bindings=${JSON.stringify({ [attrName]: debugValue }, null, 2)}`);
7335
- renderer.setValue(element, textContent);
7350
+ if (renderer.destroyNode) {
7351
+ applyView(tView, lView, renderer, 3 /* WalkTNodeTreeAction.Destroy */, null, null);
7336
7352
  }
7353
+ destroyViewTree(lView);
7337
7354
  }
7338
- function setNgReflectProperties(lView, tView, tNode, publicName, value) {
7339
- const environment = lView[ENVIRONMENT];
7340
- if (!environment.ngReflect || !(tNode.type & (3 /* TNodeType.AnyRNode */ | 4 /* TNodeType.Container */))) {
7355
+ /**
7356
+ * Calls onDestroys hooks for all directives and pipes in a given view and then removes all
7357
+ * listeners. Listeners are removed as the last step so events delivered in the onDestroys hooks
7358
+ * can be propagated to @Output listeners.
7359
+ *
7360
+ * @param tView `TView` for the `LView` to clean up.
7361
+ * @param lView The LView to clean up
7362
+ */
7363
+ function cleanUpView(tView, lView) {
7364
+ if (isDestroyed(lView)) {
7341
7365
  return;
7342
7366
  }
7343
- const inputConfig = tNode.inputs?.[publicName];
7344
- const hostInputConfig = tNode.hostDirectiveInputs?.[publicName];
7345
- if (hostInputConfig) {
7346
- for (let i = 0; i < hostInputConfig.length; i += 2) {
7347
- const index = hostInputConfig[i];
7348
- const publicName = hostInputConfig[i + 1];
7349
- const def = tView.data[index];
7350
- setNgReflectProperty(lView, tNode, def.inputs[publicName][0], value);
7367
+ const prevConsumer = setActiveConsumer(null);
7368
+ try {
7369
+ // Usually the Attached flag is removed when the view is detached from its parent, however
7370
+ // if it's a root view, the flag won't be unset hence why we're also removing on destroy.
7371
+ lView[FLAGS] &= ~128 /* LViewFlags.Attached */;
7372
+ // Mark the LView as destroyed *before* executing the onDestroy hooks. An onDestroy hook
7373
+ // runs arbitrary user code, which could include its own `viewRef.destroy()` (or similar). If
7374
+ // We don't flag the view as destroyed before the hooks, this could lead to an infinite loop.
7375
+ // This also aligns with the ViewEngine behavior. It also means that the onDestroy hook is
7376
+ // really more of an "afterDestroy" hook if you think about it.
7377
+ lView[FLAGS] |= 256 /* LViewFlags.Destroyed */;
7378
+ lView[REACTIVE_TEMPLATE_CONSUMER] && consumerDestroy(lView[REACTIVE_TEMPLATE_CONSUMER]);
7379
+ executeOnDestroys(tView, lView);
7380
+ processCleanups(tView, lView);
7381
+ // For component views only, the local renderer is destroyed at clean up time.
7382
+ if (lView[TVIEW].type === 1 /* TViewType.Component */) {
7383
+ lView[RENDERER].destroy();
7351
7384
  }
7352
- }
7353
- // Note: we set the private name of the input as the reflected property, not the public one.
7354
- if (inputConfig) {
7355
- for (const index of inputConfig) {
7356
- const def = tView.data[index];
7357
- setNgReflectProperty(lView, tNode, def.inputs[publicName][0], value);
7385
+ const declarationContainer = lView[DECLARATION_LCONTAINER];
7386
+ // we are dealing with an embedded view that is still inserted into a container
7387
+ if (declarationContainer !== null && isLContainer(lView[PARENT])) {
7388
+ // and this is a projected view
7389
+ if (declarationContainer !== lView[PARENT]) {
7390
+ detachMovedView(declarationContainer, lView);
7391
+ }
7392
+ // For embedded views still attached to a container: remove query result from this view.
7393
+ const lQueries = lView[QUERIES];
7394
+ if (lQueries !== null) {
7395
+ lQueries.detachView(tView);
7396
+ }
7358
7397
  }
7398
+ // Unregister the view once everything else has been cleaned up.
7399
+ unregisterLView(lView);
7400
+ }
7401
+ finally {
7402
+ setActiveConsumer(prevConsumer);
7359
7403
  }
7360
7404
  }
7361
- /**
7362
- * Instantiate all the directives that were previously resolved on the current node.
7363
- */
7364
- function instantiateAllDirectives(tView, lView, tNode) {
7365
- const start = tNode.directiveStart;
7366
- const end = tNode.directiveEnd;
7367
- // The component view needs to be created before creating the node injector
7368
- // since it is used to inject some special symbols like `ChangeDetectorRef`.
7369
- if (isComponentHost(tNode)) {
7370
- ngDevMode && assertTNodeType(tNode, 3 /* TNodeType.AnyRNode */);
7371
- createComponentLView(lView, tNode, tView.data[start + tNode.componentOffset]);
7405
+ /** Removes listeners and unsubscribes from output subscriptions */
7406
+ function processCleanups(tView, lView) {
7407
+ ngDevMode && assertNotReactive(processCleanups.name);
7408
+ const tCleanup = tView.cleanup;
7409
+ const lCleanup = lView[CLEANUP];
7410
+ if (tCleanup !== null) {
7411
+ for (let i = 0; i < tCleanup.length - 1; i += 2) {
7412
+ if (typeof tCleanup[i] === 'string') {
7413
+ // This is a native DOM listener. It will occupy 4 entries in the TCleanup array (hence i +=
7414
+ // 2 at the end of this block).
7415
+ const targetIdx = tCleanup[i + 3];
7416
+ ngDevMode && assertNumber(targetIdx, 'cleanup target must be a number');
7417
+ if (targetIdx >= 0) {
7418
+ // Destroy anything whose teardown is a function call (e.g. QueryList, ModelSignal).
7419
+ lCleanup[targetIdx]();
7420
+ }
7421
+ else {
7422
+ // Subscription
7423
+ lCleanup[-targetIdx].unsubscribe();
7424
+ }
7425
+ i += 2;
7426
+ }
7427
+ else {
7428
+ // This is a cleanup function that is grouped with the index of its context
7429
+ const context = lCleanup[tCleanup[i + 1]];
7430
+ tCleanup[i].call(context);
7431
+ }
7432
+ }
7372
7433
  }
7373
- if (!tView.firstCreatePass) {
7374
- getOrCreateNodeInjectorForNode(tNode, lView);
7434
+ if (lCleanup !== null) {
7435
+ lView[CLEANUP] = null;
7375
7436
  }
7376
- const initialInputs = tNode.initialInputs;
7377
- for (let i = start; i < end; i++) {
7378
- const def = tView.data[i];
7379
- const directive = getNodeInjectable(lView, tView, i, tNode);
7380
- attachPatchData(directive, lView);
7381
- if (initialInputs !== null) {
7382
- setInputsFromAttrs(lView, i - start, directive, def, tNode, initialInputs);
7383
- }
7384
- if (isComponentDef(def)) {
7385
- const componentView = getComponentLViewByIndex(tNode.index, lView);
7386
- componentView[CONTEXT] = getNodeInjectable(lView, tView, i, tNode);
7437
+ const destroyHooks = lView[ON_DESTROY_HOOKS];
7438
+ if (destroyHooks !== null) {
7439
+ // Reset the ON_DESTROY_HOOKS array before iterating over it to prevent hooks that unregister
7440
+ // themselves from mutating the array during iteration.
7441
+ lView[ON_DESTROY_HOOKS] = null;
7442
+ for (let i = 0; i < destroyHooks.length; i++) {
7443
+ const destroyHooksFn = destroyHooks[i];
7444
+ ngDevMode && assertFunction(destroyHooksFn, 'Expecting destroy hook to be a function.');
7445
+ destroyHooksFn();
7387
7446
  }
7388
7447
  }
7389
- }
7390
- function invokeDirectivesHostBindings(tView, lView, tNode) {
7391
- const start = tNode.directiveStart;
7392
- const end = tNode.directiveEnd;
7393
- const elementIndex = tNode.index;
7394
- const currentDirectiveIndex = getCurrentDirectiveIndex();
7395
- try {
7396
- setSelectedIndex(elementIndex);
7397
- for (let dirIndex = start; dirIndex < end; dirIndex++) {
7398
- const def = tView.data[dirIndex];
7399
- const directive = lView[dirIndex];
7400
- setCurrentDirectiveIndex(dirIndex);
7401
- if (def.hostBindings !== null || def.hostVars !== 0 || def.hostAttrs !== null) {
7402
- invokeHostBindingsInCreationMode(def, directive);
7403
- }
7448
+ // Destroy effects registered to the view. Many of these will have been processed above.
7449
+ const effects = lView[EFFECTS];
7450
+ if (effects !== null) {
7451
+ lView[EFFECTS] = null;
7452
+ for (const effect of effects) {
7453
+ effect.destroy();
7404
7454
  }
7405
7455
  }
7406
- finally {
7407
- setSelectedIndex(-1);
7408
- setCurrentDirectiveIndex(currentDirectiveIndex);
7409
- }
7410
7456
  }
7411
- /**
7412
- * Invoke the host bindings in creation mode.
7413
- *
7414
- * @param def `DirectiveDef` which may contain the `hostBindings` function.
7415
- * @param directive Instance of directive.
7416
- */
7417
- function invokeHostBindingsInCreationMode(def, directive) {
7418
- if (def.hostBindings !== null) {
7419
- def.hostBindings(1 /* RenderFlags.Create */, directive);
7420
- }
7421
- }
7422
- /**
7423
- * Matches the current node against all available selectors.
7424
- * If a component is matched (at most one), it is returned in first position in the array.
7425
- */
7426
- function findDirectiveDefMatches(tView, tNode) {
7427
- ngDevMode && assertFirstCreatePass(tView);
7428
- ngDevMode && assertTNodeType(tNode, 3 /* TNodeType.AnyRNode */ | 12 /* TNodeType.AnyContainer */);
7429
- const registry = tView.directiveRegistry;
7430
- let matches = null;
7431
- if (registry) {
7432
- for (let i = 0; i < registry.length; i++) {
7433
- const def = registry[i];
7434
- if (isNodeMatchingSelectorList(tNode, def.selectors, /* isProjectionMode */ false)) {
7435
- matches ??= [];
7436
- if (isComponentDef(def)) {
7437
- if (ngDevMode) {
7438
- assertTNodeType(tNode, 2 /* TNodeType.Element */, `"${tNode.value}" tags cannot be used as component hosts. ` +
7439
- `Please use a different tag to activate the ${stringify(def.type)} component.`);
7440
- if (matches.length && isComponentDef(matches[0])) {
7441
- throwMultipleComponentError(tNode, matches.find(isComponentDef).type, def.type);
7457
+ /** Calls onDestroy hooks for this view */
7458
+ function executeOnDestroys(tView, lView) {
7459
+ ngDevMode && assertNotReactive(executeOnDestroys.name);
7460
+ let destroyHooks;
7461
+ if (tView != null && (destroyHooks = tView.destroyHooks) != null) {
7462
+ for (let i = 0; i < destroyHooks.length; i += 2) {
7463
+ const context = lView[destroyHooks[i]];
7464
+ // Only call the destroy hook if the context has been requested.
7465
+ if (!(context instanceof NodeInjectorFactory)) {
7466
+ const toCall = destroyHooks[i + 1];
7467
+ if (Array.isArray(toCall)) {
7468
+ for (let j = 0; j < toCall.length; j += 2) {
7469
+ const callContext = context[toCall[j]];
7470
+ const hook = toCall[j + 1];
7471
+ profiler(4 /* ProfilerEvent.LifecycleHookStart */, callContext, hook);
7472
+ try {
7473
+ hook.call(callContext);
7474
+ }
7475
+ finally {
7476
+ profiler(5 /* ProfilerEvent.LifecycleHookEnd */, callContext, hook);
7442
7477
  }
7443
7478
  }
7444
- matches.unshift(def);
7445
7479
  }
7446
7480
  else {
7447
- matches.push(def);
7481
+ profiler(4 /* ProfilerEvent.LifecycleHookStart */, context, toCall);
7482
+ try {
7483
+ toCall.call(context);
7484
+ }
7485
+ finally {
7486
+ profiler(5 /* ProfilerEvent.LifecycleHookEnd */, context, toCall);
7487
+ }
7448
7488
  }
7449
7489
  }
7450
7490
  }
7451
7491
  }
7452
- return matches;
7453
7492
  }
7454
- function elementAttributeInternal(tNode, lView, name, value, sanitizer, namespace) {
7455
- if (ngDevMode) {
7456
- assertNotSame(value, NO_CHANGE, 'Incoming value should never be NO_CHANGE.');
7457
- validateAgainstEventAttributes(name);
7458
- assertTNodeType(tNode, 2 /* TNodeType.Element */, `Attempted to set attribute \`${name}\` on a container node. ` +
7459
- `Host bindings are not valid on ng-container or ng-template.`);
7460
- }
7461
- const element = getNativeByTNode(tNode, lView);
7462
- setElementAttribute(lView[RENDERER], element, namespace, tNode.value, name, value, sanitizer);
7493
+ /**
7494
+ * Returns a native element if a node can be inserted into the given parent.
7495
+ *
7496
+ * There are two reasons why we may not be able to insert a element immediately.
7497
+ * - Projection: When creating a child content element of a component, we have to skip the
7498
+ * insertion because the content of a component will be projected.
7499
+ * `<component><content>delayed due to projection</content></component>`
7500
+ * - Parent container is disconnected: This can happen when we are inserting a view into
7501
+ * parent container, which itself is disconnected. For example the parent container is part
7502
+ * of a View which has not be inserted or is made for projection but has not been inserted
7503
+ * into destination.
7504
+ *
7505
+ * @param tView: Current `TView`.
7506
+ * @param tNode: `TNode` for which we wish to retrieve render parent.
7507
+ * @param lView: Current `LView`.
7508
+ */
7509
+ function getParentRElement(tView, tNode, lView) {
7510
+ return getClosestRElement(tView, tNode.parent, lView);
7463
7511
  }
7464
- function setElementAttribute(renderer, element, namespace, tagName, name, value, sanitizer) {
7465
- if (value == null) {
7466
- renderer.removeAttribute(element, name, namespace);
7512
+ /**
7513
+ * Get closest `RElement` or `null` if it can't be found.
7514
+ *
7515
+ * If `TNode` is `TNodeType.Element` => return `RElement` at `LView[tNode.index]` location.
7516
+ * If `TNode` is `TNodeType.ElementContainer|IcuContain` => return the parent (recursively).
7517
+ * If `TNode` is `null` then return host `RElement`:
7518
+ * - return `null` if projection
7519
+ * - return `null` if parent container is disconnected (we have no parent.)
7520
+ *
7521
+ * @param tView: Current `TView`.
7522
+ * @param tNode: `TNode` for which we wish to retrieve `RElement` (or `null` if host element is
7523
+ * needed).
7524
+ * @param lView: Current `LView`.
7525
+ * @returns `null` if the `RElement` can't be determined at this time (no parent / projection)
7526
+ */
7527
+ function getClosestRElement(tView, tNode, lView) {
7528
+ let parentTNode = tNode;
7529
+ // Skip over element and ICU containers as those are represented by a comment node and
7530
+ // can't be used as a render parent. Also skip let declarations since they don't have a
7531
+ // corresponding DOM node at all.
7532
+ while (parentTNode !== null &&
7533
+ parentTNode.type & (8 /* TNodeType.ElementContainer */ | 32 /* TNodeType.Icu */ | 128 /* TNodeType.LetDeclaration */)) {
7534
+ tNode = parentTNode;
7535
+ parentTNode = tNode.parent;
7536
+ }
7537
+ // If the parent tNode is null, then we are inserting across views: either into an embedded view
7538
+ // or a component view.
7539
+ if (parentTNode === null) {
7540
+ // We are inserting a root element of the component view into the component host element and
7541
+ // it should always be eager.
7542
+ return lView[HOST];
7467
7543
  }
7468
7544
  else {
7469
- const strValue = sanitizer == null ? renderStringify(value) : sanitizer(value, tagName || '', name);
7470
- renderer.setAttribute(element, name, strValue, namespace);
7545
+ ngDevMode && assertTNodeType(parentTNode, 3 /* TNodeType.AnyRNode */ | 4 /* TNodeType.Container */);
7546
+ if (isComponentHost(parentTNode)) {
7547
+ ngDevMode && assertTNodeForLView(parentTNode, lView);
7548
+ const { encapsulation } = tView.data[parentTNode.directiveStart + parentTNode.componentOffset];
7549
+ // We've got a parent which is an element in the current view. We just need to verify if the
7550
+ // parent element is not a component. Component's content nodes are not inserted immediately
7551
+ // because they will be projected, and so doing insert at this point would be wasteful.
7552
+ // Since the projection would then move it to its final destination. Note that we can't
7553
+ // make this assumption when using the Shadow DOM, because the native projection placeholders
7554
+ // (<content> or <slot>) have to be in place as elements are being inserted.
7555
+ if (encapsulation === ViewEncapsulation.None ||
7556
+ encapsulation === ViewEncapsulation.Emulated) {
7557
+ return null;
7558
+ }
7559
+ }
7560
+ return getNativeByTNode(parentTNode, lView);
7471
7561
  }
7472
7562
  }
7473
7563
  /**
7474
- * Sets initial input properties on directive instances from attribute data
7564
+ * Find a node in front of which `currentTNode` should be inserted.
7475
7565
  *
7476
- * @param lView Current LView that is being processed.
7477
- * @param directiveIndex Index of the directive in directives array
7478
- * @param instance Instance of the directive on which to set the initial inputs
7479
- * @param def The directive def that contains the list of inputs
7480
- * @param tNode The static data for this node
7566
+ * This method determines the `RNode` in front of which we should insert the `currentRNode`. This
7567
+ * takes `TNode.insertBeforeIndex` into account if i18n code has been invoked.
7568
+ *
7569
+ * @param parentTNode parent `TNode`
7570
+ * @param currentTNode current `TNode` (The node which we would like to insert into the DOM)
7571
+ * @param lView current `LView`
7481
7572
  */
7482
- function setInputsFromAttrs(lView, directiveIndex, instance, def, tNode, initialInputData) {
7483
- const initialInputs = initialInputData[directiveIndex];
7484
- if (initialInputs !== null) {
7485
- for (let i = 0; i < initialInputs.length; i += 2) {
7486
- const lookupName = initialInputs[i];
7487
- const value = initialInputs[i + 1];
7488
- writeToDirectiveInput(def, instance, lookupName, value);
7489
- if (ngDevMode) {
7490
- setNgReflectProperty(lView, tNode, def.inputs[lookupName][0], value);
7491
- }
7492
- }
7573
+ function getInsertInFrontOfRNode(parentTNode, currentTNode, lView) {
7574
+ return _getInsertInFrontOfRNodeWithI18n(parentTNode, currentTNode, lView);
7575
+ }
7576
+ /**
7577
+ * Find a node in front of which `currentTNode` should be inserted. (Does not take i18n into
7578
+ * account)
7579
+ *
7580
+ * This method determines the `RNode` in front of which we should insert the `currentRNode`. This
7581
+ * does not take `TNode.insertBeforeIndex` into account.
7582
+ *
7583
+ * @param parentTNode parent `TNode`
7584
+ * @param currentTNode current `TNode` (The node which we would like to insert into the DOM)
7585
+ * @param lView current `LView`
7586
+ */
7587
+ function getInsertInFrontOfRNodeWithNoI18n(parentTNode, currentTNode, lView) {
7588
+ if (parentTNode.type & (8 /* TNodeType.ElementContainer */ | 32 /* TNodeType.Icu */)) {
7589
+ return getNativeByTNode(parentTNode, lView);
7493
7590
  }
7591
+ return null;
7494
7592
  }
7495
- ///////////////////////////////
7496
- //// Bindings & interpolations
7497
- ///////////////////////////////
7498
7593
  /**
7499
- * Stores meta-data for a property binding to be used by TestBed's `DebugElement.properties`.
7594
+ * Tree shakable boundary for `getInsertInFrontOfRNodeWithI18n` function.
7500
7595
  *
7501
- * In order to support TestBed's `DebugElement.properties` we need to save, for each binding:
7502
- * - a bound property name;
7503
- * - a static parts of interpolated strings;
7596
+ * This function will only be set if i18n code runs.
7597
+ */
7598
+ let _getInsertInFrontOfRNodeWithI18n = getInsertInFrontOfRNodeWithNoI18n;
7599
+ /**
7600
+ * Tree shakable boundary for `processI18nInsertBefore` function.
7504
7601
  *
7505
- * A given property metadata is saved at the binding's index in the `TView.data` (in other words, a
7506
- * property binding metadata will be stored in `TView.data` at the same index as a bound value in
7507
- * `LView`). Metadata are represented as `INTERPOLATION_DELIMITER`-delimited string with the
7508
- * following format:
7509
- * - `propertyName` for bound properties;
7510
- * - `propertyName�prefix�interpolation_static_part1�..interpolation_static_partN�suffix` for
7511
- * interpolated properties.
7602
+ * This function will only be set if i18n code runs.
7603
+ */
7604
+ let _processI18nInsertBefore;
7605
+ function setI18nHandling(getInsertInFrontOfRNodeWithI18n, processI18nInsertBefore) {
7606
+ _getInsertInFrontOfRNodeWithI18n = getInsertInFrontOfRNodeWithI18n;
7607
+ _processI18nInsertBefore = processI18nInsertBefore;
7608
+ }
7609
+ /**
7610
+ * Appends the `child` native node (or a collection of nodes) to the `parent`.
7512
7611
  *
7513
- * @param tData `TData` where meta-data will be saved;
7514
- * @param tNode `TNode` that is a target of the binding;
7515
- * @param propertyName bound property name;
7516
- * @param bindingIndex binding index in `LView`
7517
- * @param interpolationParts static interpolation parts (for property interpolations)
7612
+ * @param tView The `TView' to be appended
7613
+ * @param lView The current LView
7614
+ * @param childRNode The native child (or children) that should be appended
7615
+ * @param childTNode The TNode of the child element
7518
7616
  */
7519
- function storePropertyBindingMetadata(tData, tNode, propertyName, bindingIndex, ...interpolationParts) {
7520
- // Binding meta-data are stored only the first time a given property instruction is processed.
7521
- // Since we don't have a concept of the "first update pass" we need to check for presence of the
7522
- // binding meta-data to decide if one should be stored (or if was stored already).
7523
- if (tData[bindingIndex] === null) {
7524
- if (!tNode.inputs?.[propertyName] && !tNode.hostDirectiveInputs?.[propertyName]) {
7525
- const propBindingIdxs = tNode.propertyBindings || (tNode.propertyBindings = []);
7526
- propBindingIdxs.push(bindingIndex);
7527
- let bindingMetadata = propertyName;
7528
- if (interpolationParts.length > 0) {
7529
- bindingMetadata +=
7530
- INTERPOLATION_DELIMITER + interpolationParts.join(INTERPOLATION_DELIMITER);
7617
+ function appendChild(tView, lView, childRNode, childTNode) {
7618
+ const parentRNode = getParentRElement(tView, childTNode, lView);
7619
+ const renderer = lView[RENDERER];
7620
+ const parentTNode = childTNode.parent || lView[T_HOST];
7621
+ const anchorNode = getInsertInFrontOfRNode(parentTNode, childTNode, lView);
7622
+ if (parentRNode != null) {
7623
+ if (Array.isArray(childRNode)) {
7624
+ for (let i = 0; i < childRNode.length; i++) {
7625
+ nativeAppendOrInsertBefore(renderer, parentRNode, childRNode[i], anchorNode, false);
7531
7626
  }
7532
- tData[bindingIndex] = bindingMetadata;
7627
+ }
7628
+ else {
7629
+ nativeAppendOrInsertBefore(renderer, parentRNode, childRNode, anchorNode, false);
7533
7630
  }
7534
7631
  }
7632
+ _processI18nInsertBefore !== undefined &&
7633
+ _processI18nInsertBefore(renderer, childTNode, lView, childRNode, parentRNode);
7535
7634
  }
7536
7635
  /**
7537
- * There are cases where the sub component's renderer needs to be included
7538
- * instead of the current renderer (see the componentSyntheticHost* instructions).
7636
+ * Returns the first native node for a given LView, starting from the provided TNode.
7637
+ *
7638
+ * Native nodes are returned in the order in which those appear in the native tree (DOM).
7539
7639
  */
7540
- function loadComponentRenderer(currentDef, tNode, lView) {
7541
- // TODO(FW-2043): the `currentDef` is null when host bindings are invoked while creating root
7542
- // component (see packages/core/src/render3/component.ts). This is not consistent with the process
7543
- // of creating inner components, when current directive index is available in the state. In order
7544
- // to avoid relying on current def being `null` (thus special-casing root component creation), the
7545
- // process of creating root component should be unified with the process of creating inner
7546
- // components.
7547
- if (currentDef === null || isComponentDef(currentDef)) {
7548
- lView = unwrapLView(lView[tNode.index]);
7549
- }
7550
- return lView[RENDERER];
7551
- }
7552
- /** Handles an error thrown in an LView. */
7553
- function handleUncaughtError(lView, error) {
7554
- const injector = lView[INJECTOR];
7555
- if (!injector) {
7556
- return;
7557
- }
7558
- const errorHandler = injector.get(INTERNAL_APPLICATION_ERROR_HANDLER, null);
7559
- errorHandler?.(error);
7560
- }
7561
- /**
7562
- * Set all directive inputs with the specific public name on the node.
7563
- *
7564
- * @param tNode TNode on which the input is being set.
7565
- * @param tView Current TView
7566
- * @param lView `LView` which contains the directives.
7567
- * @param publicName Public name of the input being set.
7568
- * @param value Value to set.
7569
- */
7570
- function setAllInputsForProperty(tNode, tView, lView, publicName, value) {
7571
- const inputs = tNode.inputs?.[publicName];
7572
- const hostDirectiveInputs = tNode.hostDirectiveInputs?.[publicName];
7573
- let hasMatch = false;
7574
- if (hostDirectiveInputs) {
7575
- for (let i = 0; i < hostDirectiveInputs.length; i += 2) {
7576
- const index = hostDirectiveInputs[i];
7577
- ngDevMode && assertIndexInRange(lView, index);
7578
- const publicName = hostDirectiveInputs[i + 1];
7579
- const def = tView.data[index];
7580
- writeToDirectiveInput(def, lView[index], publicName, value);
7581
- hasMatch = true;
7640
+ function getFirstNativeNode(lView, tNode) {
7641
+ if (tNode !== null) {
7642
+ ngDevMode &&
7643
+ assertTNodeType(tNode, 3 /* TNodeType.AnyRNode */ |
7644
+ 12 /* TNodeType.AnyContainer */ |
7645
+ 32 /* TNodeType.Icu */ |
7646
+ 16 /* TNodeType.Projection */ |
7647
+ 128 /* TNodeType.LetDeclaration */);
7648
+ const tNodeType = tNode.type;
7649
+ if (tNodeType & 3 /* TNodeType.AnyRNode */) {
7650
+ return getNativeByTNode(tNode, lView);
7582
7651
  }
7583
- }
7584
- if (inputs) {
7585
- for (const index of inputs) {
7586
- ngDevMode && assertIndexInRange(lView, index);
7587
- const instance = lView[index];
7588
- const def = tView.data[index];
7589
- writeToDirectiveInput(def, instance, publicName, value);
7590
- hasMatch = true;
7652
+ else if (tNodeType & 4 /* TNodeType.Container */) {
7653
+ return getBeforeNodeForView(-1, lView[tNode.index]);
7591
7654
  }
7592
- }
7593
- return hasMatch;
7594
- }
7595
- /**
7596
- * Sets an input value only on a specific directive and its host directives.
7597
- * @param tNode TNode on which the input is being set.
7598
- * @param tView Current TView
7599
- * @param lView `LView` which contains the directives.
7600
- * @param target Directive on which to set the input.
7601
- * @param publicName Public name of the input being set.
7602
- * @param value Value to set.
7603
- */
7604
- function setDirectiveInput(tNode, tView, lView, target, publicName, value) {
7605
- let hostIndex = null;
7606
- let hostDirectivesStart = null;
7607
- let hostDirectivesEnd = null;
7608
- let hasSet = false;
7609
- if (ngDevMode && !tNode.directiveToIndex?.has(target.type)) {
7610
- throw new Error(`Node does not have a directive with type ${target.type.name}`);
7611
- }
7612
- const data = tNode.directiveToIndex.get(target.type);
7613
- if (typeof data === 'number') {
7614
- hostIndex = data;
7615
- }
7616
- else {
7617
- [hostIndex, hostDirectivesStart, hostDirectivesEnd] = data;
7618
- }
7619
- if (hostDirectivesStart !== null &&
7620
- hostDirectivesEnd !== null &&
7621
- tNode.hostDirectiveInputs?.hasOwnProperty(publicName)) {
7622
- const hostDirectiveInputs = tNode.hostDirectiveInputs[publicName];
7623
- for (let i = 0; i < hostDirectiveInputs.length; i += 2) {
7624
- const index = hostDirectiveInputs[i];
7625
- if (index >= hostDirectivesStart && index <= hostDirectivesEnd) {
7626
- ngDevMode && assertIndexInRange(lView, index);
7627
- const def = tView.data[index];
7628
- const hostDirectivePublicName = hostDirectiveInputs[i + 1];
7629
- writeToDirectiveInput(def, lView[index], hostDirectivePublicName, value);
7630
- hasSet = true;
7655
+ else if (tNodeType & 8 /* TNodeType.ElementContainer */) {
7656
+ const elIcuContainerChild = tNode.child;
7657
+ if (elIcuContainerChild !== null) {
7658
+ return getFirstNativeNode(lView, elIcuContainerChild);
7631
7659
  }
7632
- else if (index > hostDirectivesEnd) {
7633
- // Directives here are in ascending order so we can stop looking once we're past the range.
7634
- break;
7660
+ else {
7661
+ const rNodeOrLContainer = lView[tNode.index];
7662
+ if (isLContainer(rNodeOrLContainer)) {
7663
+ return getBeforeNodeForView(-1, rNodeOrLContainer);
7664
+ }
7665
+ else {
7666
+ return unwrapRNode(rNodeOrLContainer);
7667
+ }
7668
+ }
7669
+ }
7670
+ else if (tNodeType & 128 /* TNodeType.LetDeclaration */) {
7671
+ return getFirstNativeNode(lView, tNode.next);
7672
+ }
7673
+ else if (tNodeType & 32 /* TNodeType.Icu */) {
7674
+ let nextRNode = icuContainerIterate(tNode, lView);
7675
+ let rNode = nextRNode();
7676
+ // If the ICU container has no nodes, than we use the ICU anchor as the node.
7677
+ return rNode || unwrapRNode(lView[tNode.index]);
7678
+ }
7679
+ else {
7680
+ const projectionNodes = getProjectionNodes(lView, tNode);
7681
+ if (projectionNodes !== null) {
7682
+ if (Array.isArray(projectionNodes)) {
7683
+ return projectionNodes[0];
7684
+ }
7685
+ const parentView = getLViewParent(lView[DECLARATION_COMPONENT_VIEW]);
7686
+ ngDevMode && assertParentView(parentView);
7687
+ return getFirstNativeNode(parentView, projectionNodes);
7688
+ }
7689
+ else {
7690
+ return getFirstNativeNode(lView, tNode.next);
7635
7691
  }
7636
7692
  }
7637
7693
  }
7638
- if (hostIndex !== null && target.inputs.hasOwnProperty(publicName)) {
7639
- ngDevMode && assertIndexInRange(lView, hostIndex);
7640
- writeToDirectiveInput(target, lView[hostIndex], publicName, value);
7641
- hasSet = true;
7642
- }
7643
- return hasSet;
7694
+ return null;
7644
7695
  }
7645
-
7646
- function renderComponent(hostLView, componentHostIdx) {
7647
- ngDevMode && assertEqual(isCreationMode(hostLView), true, 'Should be run in creation mode');
7648
- const componentView = getComponentLViewByIndex(componentHostIdx, hostLView);
7649
- const componentTView = componentView[TVIEW];
7650
- syncViewWithBlueprint(componentTView, componentView);
7651
- const hostRNode = componentView[HOST];
7652
- // Populate an LView with hydration info retrieved from the DOM via TransferState.
7653
- if (hostRNode !== null && componentView[HYDRATION] === null) {
7654
- componentView[HYDRATION] = retrieveHydrationInfo(hostRNode, componentView[INJECTOR]);
7696
+ function getProjectionNodes(lView, tNode) {
7697
+ if (tNode !== null) {
7698
+ const componentView = lView[DECLARATION_COMPONENT_VIEW];
7699
+ const componentHost = componentView[T_HOST];
7700
+ const slotIdx = tNode.projection;
7701
+ ngDevMode && assertProjectionSlots(lView);
7702
+ return componentHost.projection[slotIdx];
7655
7703
  }
7656
- profiler(18 /* ProfilerEvent.ComponentStart */);
7657
- renderView(componentTView, componentView, componentView[CONTEXT]);
7658
- profiler(19 /* ProfilerEvent.ComponentEnd */, componentView[CONTEXT]);
7704
+ return null;
7659
7705
  }
7660
- /**
7661
- * Syncs an LView instance with its blueprint if they have gotten out of sync.
7662
- *
7663
- * Typically, blueprints and their view instances should always be in sync, so the loop here
7664
- * will be skipped. However, consider this case of two components side-by-side:
7665
- *
7666
- * App template:
7667
- * ```html
7668
- * <comp></comp>
7669
- * <comp></comp>
7670
- * ```
7671
- *
7672
- * The following will happen:
7673
- * 1. App template begins processing.
7674
- * 2. First <comp> is matched as a component and its LView is created.
7675
- * 3. Second <comp> is matched as a component and its LView is created.
7676
- * 4. App template completes processing, so it's time to check child templates.
7677
- * 5. First <comp> template is checked. It has a directive, so its def is pushed to blueprint.
7678
- * 6. Second <comp> template is checked. Its blueprint has been updated by the first
7679
- * <comp> template, but its LView was created before this update, so it is out of sync.
7680
- *
7681
- * Note that embedded views inside ngFor loops will never be out of sync because these views
7682
- * are processed as soon as they are created.
7683
- *
7684
- * @param tView The `TView` that contains the blueprint for syncing
7685
- * @param lView The view to sync
7686
- */
7687
- function syncViewWithBlueprint(tView, lView) {
7688
- for (let i = lView.length; i < tView.blueprint.length; i++) {
7689
- lView.push(tView.blueprint[i]);
7706
+ function getBeforeNodeForView(viewIndexInContainer, lContainer) {
7707
+ const nextViewIndex = CONTAINER_HEADER_OFFSET + viewIndexInContainer + 1;
7708
+ if (nextViewIndex < lContainer.length) {
7709
+ const lView = lContainer[nextViewIndex];
7710
+ const firstTNodeOfView = lView[TVIEW].firstChild;
7711
+ if (firstTNodeOfView !== null) {
7712
+ return getFirstNativeNode(lView, firstTNodeOfView);
7713
+ }
7690
7714
  }
7715
+ return lContainer[NATIVE];
7691
7716
  }
7692
7717
  /**
7693
- * Processes a view in the creation mode. This includes a number of steps in a specific order:
7694
- * - creating view query functions (if any);
7695
- * - executing a template function in the creation mode;
7696
- * - updating static queries (if any);
7697
- * - creating child components defined in a given view.
7718
+ * Performs the operation of `action` on the node. Typically this involves inserting or removing
7719
+ * nodes on the LView or projection boundary.
7698
7720
  */
7699
- function renderView(tView, lView, context) {
7700
- ngDevMode && assertEqual(isCreationMode(lView), true, 'Should be run in creation mode');
7701
- ngDevMode && assertNotReactive(renderView.name);
7702
- enterView(lView);
7703
- try {
7704
- const viewQuery = tView.viewQuery;
7705
- if (viewQuery !== null) {
7706
- executeViewQueryFn(1 /* RenderFlags.Create */, viewQuery, context);
7707
- }
7708
- // Execute a template associated with this view, if it exists. A template function might not be
7709
- // defined for the root component views.
7710
- const templateFn = tView.template;
7711
- if (templateFn !== null) {
7712
- executeTemplate(tView, lView, templateFn, 1 /* RenderFlags.Create */, context);
7713
- }
7714
- // This needs to be set before children are processed to support recursive components.
7715
- // This must be set to false immediately after the first creation run because in an
7716
- // ngFor loop, all the views will be created together before update mode runs and turns
7717
- // off firstCreatePass. If we don't set it here, instances will perform directive
7718
- // matching, etc again and again.
7719
- if (tView.firstCreatePass) {
7720
- tView.firstCreatePass = false;
7721
- }
7722
- // Mark all queries active in this view as dirty. This is necessary for signal-based queries to
7723
- // have a clear marking point where we can read query results atomically (for a given view).
7724
- lView[QUERIES]?.finishViewCreation(tView);
7725
- // We resolve content queries specifically marked as `static` in creation mode. Dynamic
7726
- // content queries are resolved during change detection (i.e. update mode), after embedded
7727
- // views are refreshed (see block above).
7728
- if (tView.staticContentQueries) {
7729
- refreshContentQueries(tView, lView);
7730
- }
7731
- // We must materialize query results before child components are processed
7732
- // in case a child component has projected a container. The LContainer needs
7733
- // to exist so the embedded views are properly attached by the container.
7734
- if (tView.staticViewQueries) {
7735
- executeViewQueryFn(2 /* RenderFlags.Update */, tView.viewQuery, context);
7736
- }
7737
- // Render child component views.
7738
- const components = tView.components;
7739
- if (components !== null) {
7740
- renderChildComponents(lView, components);
7721
+ function applyNodes(renderer, action, tNode, lView, parentRElement, beforeNode, isProjection) {
7722
+ while (tNode != null) {
7723
+ ngDevMode && assertTNodeForLView(tNode, lView);
7724
+ // Let declarations don't have corresponding DOM nodes so we skip over them.
7725
+ if (tNode.type === 128 /* TNodeType.LetDeclaration */) {
7726
+ tNode = tNode.next;
7727
+ continue;
7741
7728
  }
7742
- }
7743
- catch (error) {
7744
- // If we didn't manage to get past the first template pass due to
7745
- // an error, mark the view as corrupted so we can try to recover.
7746
- if (tView.firstCreatePass) {
7747
- tView.incompleteFirstPass = true;
7748
- tView.firstCreatePass = false;
7729
+ ngDevMode &&
7730
+ assertTNodeType(tNode, 3 /* TNodeType.AnyRNode */ | 12 /* TNodeType.AnyContainer */ | 16 /* TNodeType.Projection */ | 32 /* TNodeType.Icu */);
7731
+ const rawSlotValue = lView[tNode.index];
7732
+ const tNodeType = tNode.type;
7733
+ if (isProjection) {
7734
+ if (action === 0 /* WalkTNodeTreeAction.Create */) {
7735
+ rawSlotValue && attachPatchData(unwrapRNode(rawSlotValue), lView);
7736
+ tNode.flags |= 2 /* TNodeFlags.isProjected */;
7737
+ }
7749
7738
  }
7750
- throw error;
7751
- }
7752
- finally {
7753
- lView[FLAGS] &= -5 /* LViewFlags.CreationMode */;
7754
- leaveView();
7755
- }
7756
- }
7757
- /** Renders child components in the current view (creation mode). */
7758
- function renderChildComponents(hostLView, components) {
7759
- for (let i = 0; i < components.length; i++) {
7760
- renderComponent(hostLView, components[i]);
7761
- }
7762
- }
7763
-
7764
- function createAndRenderEmbeddedLView(declarationLView, templateTNode, context, options) {
7765
- const prevConsumer = setActiveConsumer(null);
7766
- try {
7767
- const embeddedTView = templateTNode.tView;
7768
- ngDevMode && assertDefined(embeddedTView, 'TView must be defined for a template node.');
7769
- ngDevMode && assertTNodeForLView(templateTNode, declarationLView);
7770
- // Embedded views follow the change detection strategy of the view they're declared in.
7771
- const isSignalView = declarationLView[FLAGS] & 4096 /* LViewFlags.SignalView */;
7772
- const viewFlags = isSignalView ? 4096 /* LViewFlags.SignalView */ : 16 /* LViewFlags.CheckAlways */;
7773
- const embeddedLView = createLView(declarationLView, embeddedTView, context, viewFlags, null, templateTNode, null, null, options?.injector ?? null, options?.embeddedViewInjector ?? null, options?.dehydratedView ?? null);
7774
- const declarationLContainer = declarationLView[templateTNode.index];
7775
- ngDevMode && assertLContainer(declarationLContainer);
7776
- embeddedLView[DECLARATION_LCONTAINER] = declarationLContainer;
7777
- const declarationViewLQueries = declarationLView[QUERIES];
7778
- if (declarationViewLQueries !== null) {
7779
- embeddedLView[QUERIES] = declarationViewLQueries.createEmbeddedView(embeddedTView);
7739
+ if (!isDetachedByI18n(tNode)) {
7740
+ if (tNodeType & 8 /* TNodeType.ElementContainer */) {
7741
+ applyNodes(renderer, action, tNode.child, lView, parentRElement, beforeNode, false);
7742
+ applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode);
7743
+ }
7744
+ else if (tNodeType & 32 /* TNodeType.Icu */) {
7745
+ const nextRNode = icuContainerIterate(tNode, lView);
7746
+ let rNode;
7747
+ while ((rNode = nextRNode())) {
7748
+ applyToElementOrContainer(action, renderer, parentRElement, rNode, beforeNode);
7749
+ }
7750
+ applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode);
7751
+ }
7752
+ else if (tNodeType & 16 /* TNodeType.Projection */) {
7753
+ applyProjectionRecursive(renderer, action, lView, tNode, parentRElement, beforeNode);
7754
+ }
7755
+ else {
7756
+ ngDevMode && assertTNodeType(tNode, 3 /* TNodeType.AnyRNode */ | 4 /* TNodeType.Container */);
7757
+ applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode);
7758
+ }
7780
7759
  }
7781
- // execute creation mode of a view
7782
- renderView(embeddedTView, embeddedLView, context);
7783
- return embeddedLView;
7784
- }
7785
- finally {
7786
- setActiveConsumer(prevConsumer);
7760
+ tNode = isProjection ? tNode.projectionNext : tNode.next;
7787
7761
  }
7788
7762
  }
7789
- /**
7790
- * Returns whether an elements that belong to a view should be
7791
- * inserted into the DOM. For client-only cases, DOM elements are
7792
- * always inserted. For hydration cases, we check whether serialized
7793
- * info is available for a view and the view is not in a "skip hydration"
7794
- * block (in which case view contents was re-created, thus needing insertion).
7795
- */
7796
- function shouldAddViewToDom(tNode, dehydratedView) {
7797
- return (!dehydratedView || dehydratedView.firstChild === null || hasInSkipHydrationBlockFlag(tNode));
7763
+ function applyView(tView, lView, renderer, action, parentRElement, beforeNode) {
7764
+ applyNodes(renderer, action, tView.firstChild, lView, parentRElement, beforeNode, false);
7798
7765
  }
7799
-
7800
- const USE_EXHAUSTIVE_CHECK_NO_CHANGES_DEFAULT = false;
7801
- const UseExhaustiveCheckNoChanges = new InjectionToken(ngDevMode ? 'exhaustive checkNoChanges' : '');
7802
-
7803
- let _icuContainerIterate;
7804
7766
  /**
7805
- * Iterator which provides ability to visit all of the `TIcuContainerNode` root `RNode`s.
7767
+ * `applyProjection` performs operation on the projection.
7768
+ *
7769
+ * Inserting a projection requires us to locate the projected nodes from the parent component. The
7770
+ * complication is that those nodes themselves could be re-projected from their parent component.
7771
+ *
7772
+ * @param tView The `TView` of `LView` which needs to be inserted, detached, destroyed
7773
+ * @param lView The `LView` which needs to be inserted, detached, destroyed.
7774
+ * @param tProjectionNode node to project
7806
7775
  */
7807
- function icuContainerIterate(tIcuContainerNode, lView) {
7808
- return _icuContainerIterate(tIcuContainerNode, lView);
7776
+ function applyProjection(tView, lView, tProjectionNode) {
7777
+ const renderer = lView[RENDERER];
7778
+ const parentRNode = getParentRElement(tView, tProjectionNode, lView);
7779
+ const parentTNode = tProjectionNode.parent || lView[T_HOST];
7780
+ let beforeNode = getInsertInFrontOfRNode(parentTNode, tProjectionNode, lView);
7781
+ applyProjectionRecursive(renderer, 0 /* WalkTNodeTreeAction.Create */, lView, tProjectionNode, parentRNode, beforeNode);
7809
7782
  }
7810
7783
  /**
7811
- * Ensures that `IcuContainerVisitor`'s implementation is present.
7784
+ * `applyProjectionRecursive` performs operation on the projection specified by `action` (insert,
7785
+ * detach, destroy)
7812
7786
  *
7813
- * This function is invoked when i18n instruction comes across an ICU. The purpose is to allow the
7814
- * bundler to tree shake ICU logic and only load it if ICU instruction is executed.
7787
+ * Inserting a projection requires us to locate the projected nodes from the parent component. The
7788
+ * complication is that those nodes themselves could be re-projected from their parent component.
7789
+ *
7790
+ * @param renderer Render to use
7791
+ * @param action action to perform (insert, detach, destroy)
7792
+ * @param lView The LView which needs to be inserted, detached, destroyed.
7793
+ * @param tProjectionNode node to project
7794
+ * @param parentRElement parent DOM element for insertion/removal.
7795
+ * @param beforeNode Before which node the insertions should happen.
7815
7796
  */
7816
- function ensureIcuContainerVisitorLoaded(loader) {
7817
- if (_icuContainerIterate === undefined) {
7818
- // Do not inline this function. We want to keep `ensureIcuContainerVisitorLoaded` light, so it
7819
- // can be inlined into call-site.
7820
- _icuContainerIterate = loader();
7797
+ function applyProjectionRecursive(renderer, action, lView, tProjectionNode, parentRElement, beforeNode) {
7798
+ const componentLView = lView[DECLARATION_COMPONENT_VIEW];
7799
+ const componentNode = componentLView[T_HOST];
7800
+ ngDevMode &&
7801
+ assertEqual(typeof tProjectionNode.projection, 'number', 'expecting projection index');
7802
+ const nodeToProjectOrRNodes = componentNode.projection[tProjectionNode.projection];
7803
+ if (Array.isArray(nodeToProjectOrRNodes)) {
7804
+ // This should not exist, it is a bit of a hack. When we bootstrap a top level node and we
7805
+ // need to support passing projectable nodes, so we cheat and put them in the TNode
7806
+ // of the Host TView. (Yes we put instance info at the T Level). We can get away with it
7807
+ // because we know that TView is not shared and therefore it will not be a problem.
7808
+ // This should be refactored and cleaned up.
7809
+ for (let i = 0; i < nodeToProjectOrRNodes.length; i++) {
7810
+ const rNode = nodeToProjectOrRNodes[i];
7811
+ applyToElementOrContainer(action, renderer, parentRElement, rNode, beforeNode);
7812
+ }
7813
+ }
7814
+ else {
7815
+ let nodeToProject = nodeToProjectOrRNodes;
7816
+ const projectedComponentLView = componentLView[PARENT];
7817
+ // If a parent <ng-content> is located within a skip hydration block,
7818
+ // annotate an actual node that is being projected with the same flag too.
7819
+ if (hasInSkipHydrationBlockFlag(tProjectionNode)) {
7820
+ nodeToProject.flags |= 128 /* TNodeFlags.inSkipHydrationBlock */;
7821
+ }
7822
+ applyNodes(renderer, action, nodeToProject, projectedComponentLView, parentRElement, beforeNode, true);
7821
7823
  }
7822
7824
  }
7823
-
7824
- /**
7825
- * Flags for renderer-specific style modifiers.
7826
- * @publicApi
7827
- */
7828
- var RendererStyleFlags2;
7829
- (function (RendererStyleFlags2) {
7830
- // TODO(misko): This needs to be refactored into a separate file so that it can be imported from
7831
- // `node_manipulation.ts` Currently doing the import cause resolution order to change and fails
7832
- // the tests. The work around is to have hard coded value in `node_manipulation.ts` for now.
7833
- /**
7834
- * Marks a style as important.
7835
- */
7836
- RendererStyleFlags2[RendererStyleFlags2["Important"] = 1] = "Important";
7837
- /**
7838
- * Marks a style as using dash case naming (this-is-dash-case).
7839
- */
7840
- RendererStyleFlags2[RendererStyleFlags2["DashCase"] = 2] = "DashCase";
7841
- })(RendererStyleFlags2 || (RendererStyleFlags2 = {}));
7842
-
7843
7825
  /**
7844
- * Checks whether a TNode is considered detached, i.e. not present in the
7845
- * translated i18n template. We should not attempt hydration for such nodes
7846
- * and instead, use a regular "creation mode".
7826
+ * `applyContainer` performs an operation on the container and its views as specified by
7827
+ * `action` (insert, detach, destroy)
7828
+ *
7829
+ * Inserting a Container is complicated by the fact that the container may have Views which
7830
+ * themselves have containers or projections.
7831
+ *
7832
+ * @param renderer Renderer to use
7833
+ * @param action action to perform (insert, detach, destroy)
7834
+ * @param lContainer The LContainer which needs to be inserted, detached, destroyed.
7835
+ * @param parentRElement parent DOM element for insertion/removal.
7836
+ * @param beforeNode Before which node the insertions should happen.
7847
7837
  */
7848
- function isDetachedByI18n(tNode) {
7849
- return (tNode.flags & 32 /* TNodeFlags.isDetached */) === 32 /* TNodeFlags.isDetached */;
7838
+ function applyContainer(renderer, action, lContainer, parentRElement, beforeNode) {
7839
+ ngDevMode && assertLContainer(lContainer);
7840
+ const anchor = lContainer[NATIVE]; // LContainer has its own before node.
7841
+ const native = unwrapRNode(lContainer);
7842
+ // An LContainer can be created dynamically on any node by injecting ViewContainerRef.
7843
+ // Asking for a ViewContainerRef on an element will result in a creation of a separate anchor
7844
+ // node (comment in the DOM) that will be different from the LContainer's host node. In this
7845
+ // particular case we need to execute action on 2 nodes:
7846
+ // - container's host node (this is done in the executeActionOnElementOrContainer)
7847
+ // - container's host node (this is done here)
7848
+ if (anchor !== native) {
7849
+ // This is very strange to me (Misko). I would expect that the native is same as anchor. I
7850
+ // don't see a reason why they should be different, but they are.
7851
+ //
7852
+ // If they are we need to process the second anchor as well.
7853
+ applyToElementOrContainer(action, renderer, parentRElement, anchor, beforeNode);
7854
+ }
7855
+ for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
7856
+ const lView = lContainer[i];
7857
+ applyView(lView[TVIEW], lView, renderer, action, parentRElement, anchor);
7858
+ }
7850
7859
  }
7851
-
7852
7860
  /**
7853
- * NOTE: for performance reasons, the possible actions are inlined within the function instead of
7854
- * being passed as an argument.
7861
+ * Writes class/style to element.
7862
+ *
7863
+ * @param renderer Renderer to use.
7864
+ * @param isClassBased `true` if it should be written to `class` (`false` to write to `style`)
7865
+ * @param rNode The Node to write to.
7866
+ * @param prop Property to write to. This would be the class/style name.
7867
+ * @param value Value to write. If `null`/`undefined`/`false` this is considered a remove (set/add
7868
+ * otherwise).
7855
7869
  */
7856
- function applyToElementOrContainer(action, renderer, parent, lNodeToHandle, beforeNode) {
7857
- // If this slot was allocated for a text node dynamically created by i18n, the text node itself
7858
- // won't be created until i18nApply() in the update block, so this node should be skipped.
7859
- // For more info, see "ICU expressions should work inside an ngTemplateOutlet inside an ngFor"
7860
- // in `i18n_spec.ts`.
7861
- if (lNodeToHandle != null) {
7862
- let lContainer;
7863
- let isComponent = false;
7864
- // We are expecting an RNode, but in the case of a component or LContainer the `RNode` is
7865
- // wrapped in an array which needs to be unwrapped. We need to know if it is a component and if
7866
- // it has LContainer so that we can process all of those cases appropriately.
7867
- if (isLContainer(lNodeToHandle)) {
7868
- lContainer = lNodeToHandle;
7869
- }
7870
- else if (isLView(lNodeToHandle)) {
7871
- isComponent = true;
7872
- ngDevMode && assertDefined(lNodeToHandle[HOST], 'HOST must be defined for a component LView');
7873
- lNodeToHandle = lNodeToHandle[HOST];
7870
+ function applyStyling(renderer, isClassBased, rNode, prop, value) {
7871
+ if (isClassBased) {
7872
+ // We actually want JS true/false here because any truthy value should add the class
7873
+ if (!value) {
7874
+ renderer.removeClass(rNode, prop);
7874
7875
  }
7875
- const rNode = unwrapRNode(lNodeToHandle);
7876
- if (action === 0 /* WalkTNodeTreeAction.Create */ && parent !== null) {
7877
- if (beforeNode == null) {
7878
- nativeAppendChild(renderer, parent, rNode);
7879
- }
7880
- else {
7881
- nativeInsertBefore(renderer, parent, rNode, beforeNode || null, true);
7882
- }
7876
+ else {
7877
+ renderer.addClass(rNode, prop);
7883
7878
  }
7884
- else if (action === 1 /* WalkTNodeTreeAction.Insert */ && parent !== null) {
7885
- nativeInsertBefore(renderer, parent, rNode, beforeNode || null, true);
7879
+ }
7880
+ else {
7881
+ let flags = prop.indexOf('-') === -1 ? undefined : RendererStyleFlags2.DashCase;
7882
+ if (value == null /** || value === undefined */) {
7883
+ renderer.removeStyle(rNode, prop, flags);
7886
7884
  }
7887
- else if (action === 2 /* WalkTNodeTreeAction.Detach */) {
7888
- nativeRemoveNode(renderer, rNode, isComponent);
7885
+ else {
7886
+ // A value is important if it ends with `!important`. The style
7887
+ // parser strips any semicolons at the end of the value.
7888
+ const isImportant = typeof value === 'string' ? value.endsWith('!important') : false;
7889
+ if (isImportant) {
7890
+ // !important has to be stripped from the value for it to be valid.
7891
+ value = value.slice(0, -10);
7892
+ flags |= RendererStyleFlags2.Important;
7893
+ }
7894
+ renderer.setStyle(rNode, prop, value, flags);
7889
7895
  }
7890
- else if (action === 3 /* WalkTNodeTreeAction.Destroy */) {
7891
- renderer.destroyNode(rNode);
7896
+ }
7897
+ }
7898
+
7899
+ function executeTemplate(tView, lView, templateFn, rf, context) {
7900
+ const prevSelectedIndex = getSelectedIndex();
7901
+ const isUpdatePhase = rf & 2 /* RenderFlags.Update */;
7902
+ try {
7903
+ setSelectedIndex(-1);
7904
+ if (isUpdatePhase && lView.length > HEADER_OFFSET) {
7905
+ // When we're updating, inherently select 0 so we don't
7906
+ // have to generate that instruction for most update blocks.
7907
+ selectIndexInternal(tView, lView, HEADER_OFFSET, !!ngDevMode && isInCheckNoChangesMode());
7892
7908
  }
7893
- if (lContainer != null) {
7894
- applyContainer(renderer, action, lContainer, parent, beforeNode);
7909
+ const preHookType = isUpdatePhase
7910
+ ? 2 /* ProfilerEvent.TemplateUpdateStart */
7911
+ : 0 /* ProfilerEvent.TemplateCreateStart */;
7912
+ profiler(preHookType, context, templateFn);
7913
+ templateFn(rf, context);
7914
+ }
7915
+ finally {
7916
+ setSelectedIndex(prevSelectedIndex);
7917
+ const postHookType = isUpdatePhase
7918
+ ? 3 /* ProfilerEvent.TemplateUpdateEnd */
7919
+ : 1 /* ProfilerEvent.TemplateCreateEnd */;
7920
+ profiler(postHookType, context, templateFn);
7921
+ }
7922
+ }
7923
+ /**
7924
+ * Creates directive instances.
7925
+ */
7926
+ function createDirectivesInstances(tView, lView, tNode) {
7927
+ instantiateAllDirectives(tView, lView, tNode);
7928
+ if ((tNode.flags & 64 /* TNodeFlags.hasHostBindings */) === 64 /* TNodeFlags.hasHostBindings */) {
7929
+ invokeDirectivesHostBindings(tView, lView, tNode);
7930
+ }
7931
+ }
7932
+ /**
7933
+ * Takes a list of local names and indices and pushes the resolved local variable values
7934
+ * to LView in the same order as they are loaded in the template with load().
7935
+ */
7936
+ function saveResolvedLocalsInData(viewData, tNode, localRefExtractor = getNativeByTNode) {
7937
+ const localNames = tNode.localNames;
7938
+ if (localNames !== null) {
7939
+ let localIndex = tNode.index + 1;
7940
+ for (let i = 0; i < localNames.length; i += 2) {
7941
+ const index = localNames[i + 1];
7942
+ const value = index === -1
7943
+ ? localRefExtractor(tNode, viewData)
7944
+ : viewData[index];
7945
+ viewData[localIndex++] = value;
7895
7946
  }
7896
7947
  }
7897
7948
  }
7898
7949
  /**
7899
- * Removes all DOM elements associated with a view.
7900
- *
7901
- * Because some root nodes of the view may be containers, we sometimes need
7902
- * to propagate deeply into the nested containers to remove all elements in the
7903
- * views beneath it.
7950
+ * Locates the host native element, used for bootstrapping existing nodes into rendering pipeline.
7904
7951
  *
7905
- * @param tView The `TView' of the `LView` from which elements should be added or removed
7906
- * @param lView The view from which elements should be added or removed
7952
+ * @param renderer the renderer used to locate the element.
7953
+ * @param elementOrSelector Render element or CSS selector to locate the element.
7954
+ * @param encapsulation View Encapsulation defined for component that requests host element.
7955
+ * @param injector Root view injector instance.
7907
7956
  */
7908
- function removeViewFromDOM(tView, lView) {
7909
- detachViewFromDOM(tView, lView);
7910
- lView[HOST] = null;
7911
- lView[T_HOST] = null;
7957
+ function locateHostElement(renderer, elementOrSelector, encapsulation, injector) {
7958
+ // Note: we use default value for the `PRESERVE_HOST_CONTENT` here even though it's a
7959
+ // tree-shakable one (providedIn:'root'). This code path can be triggered during dynamic
7960
+ // component creation (after calling ViewContainerRef.createComponent) when an injector
7961
+ // instance can be provided. The injector instance might be disconnected from the main DI
7962
+ // tree, thus the `PRESERVE_HOST_CONTENT` would not be able to instantiate. In this case, the
7963
+ // default value will be used.
7964
+ const preserveHostContent = injector.get(PRESERVE_HOST_CONTENT, PRESERVE_HOST_CONTENT_DEFAULT);
7965
+ // When using native Shadow DOM, do not clear host element to allow native slot
7966
+ // projection.
7967
+ const preserveContent = preserveHostContent || encapsulation === ViewEncapsulation.ShadowDom;
7968
+ const rootElement = renderer.selectRootElement(elementOrSelector, preserveContent);
7969
+ applyRootElementTransform(rootElement);
7970
+ return rootElement;
7912
7971
  }
7913
7972
  /**
7914
- * Adds all DOM elements associated with a view.
7915
- *
7916
- * Because some root nodes of the view may be containers, we sometimes need
7917
- * to propagate deeply into the nested containers to add all elements in the
7918
- * views beneath it.
7973
+ * Applies any root element transformations that are needed. If hydration is enabled,
7974
+ * this will process corrupted text nodes.
7919
7975
  *
7920
- * @param tView The `TView' of the `LView` from which elements should be added or removed
7921
- * @param parentTNode The `TNode` where the `LView` should be attached to.
7922
- * @param renderer Current renderer to use for DOM manipulations.
7923
- * @param lView The view from which elements should be added or removed
7924
- * @param parentNativeNode The parent `RElement` where it should be inserted into.
7925
- * @param beforeNode The node before which elements should be added, if insert mode
7976
+ * @param rootElement the app root HTML Element
7926
7977
  */
7927
- function addViewToDOM(tView, parentTNode, renderer, lView, parentNativeNode, beforeNode) {
7928
- lView[HOST] = parentNativeNode;
7929
- lView[T_HOST] = parentTNode;
7930
- applyView(tView, lView, renderer, 1 /* WalkTNodeTreeAction.Insert */, parentNativeNode, beforeNode);
7978
+ function applyRootElementTransform(rootElement) {
7979
+ _applyRootElementTransformImpl(rootElement);
7931
7980
  }
7932
7981
  /**
7933
- * Detach a `LView` from the DOM by detaching its nodes.
7982
+ * Reference to a function that applies transformations to the root HTML element
7983
+ * of an app. When hydration is enabled, this processes any corrupt text nodes
7984
+ * so they are properly hydratable on the client.
7934
7985
  *
7935
- * @param tView The `TView' of the `LView` to be detached
7936
- * @param lView the `LView` to be detached.
7986
+ * @param rootElement the app root HTML Element
7937
7987
  */
7938
- function detachViewFromDOM(tView, lView) {
7939
- // When we remove a view from the DOM, we need to rerun afterRender hooks
7940
- // We don't necessarily needs to run change detection. DOM removal only requires
7941
- // change detection if animations are enabled (this notification is handled by animations).
7942
- lView[ENVIRONMENT].changeDetectionScheduler?.notify(9 /* NotificationSource.ViewDetachedFromDOM */);
7943
- applyView(tView, lView, lView[RENDERER], 2 /* WalkTNodeTreeAction.Detach */, null, null);
7944
- }
7988
+ let _applyRootElementTransformImpl = () => null;
7945
7989
  /**
7946
- * Traverses down and up the tree of views and containers to remove listeners and
7947
- * call onDestroy callbacks.
7948
- *
7949
- * Notes:
7950
- * - Because it's used for onDestroy calls, it needs to be bottom-up.
7951
- * - Must process containers instead of their views to avoid splicing
7952
- * when views are destroyed and re-added.
7953
- * - Using a while loop because it's faster than recursion
7954
- * - Destroy only called on movement to sibling or movement to parent (laterally or up)
7990
+ * Processes text node markers before hydration begins. This replaces any special comment
7991
+ * nodes that were added prior to serialization are swapped out to restore proper text
7992
+ * nodes before hydration.
7955
7993
  *
7956
- * @param rootView The view to destroy
7994
+ * @param rootElement the app root HTML Element
7957
7995
  */
7958
- function destroyViewTree(rootView) {
7959
- // If the view has no children, we can clean it up and return early.
7960
- let lViewOrLContainer = rootView[CHILD_HEAD];
7961
- if (!lViewOrLContainer) {
7962
- return cleanUpView(rootView[TVIEW], rootView);
7996
+ function applyRootElementTransformImpl(rootElement) {
7997
+ if (hasSkipHydrationAttrOnRElement(rootElement)) {
7998
+ // Handle a situation when the `ngSkipHydration` attribute is applied
7999
+ // to the root node of an application. In this case, we should clear
8000
+ // the contents and render everything from scratch.
8001
+ clearElementContents(rootElement);
7963
8002
  }
7964
- while (lViewOrLContainer) {
7965
- let next = null;
7966
- if (isLView(lViewOrLContainer)) {
7967
- // If LView, traverse down to child.
7968
- next = lViewOrLContainer[CHILD_HEAD];
7969
- }
7970
- else {
7971
- ngDevMode && assertLContainer(lViewOrLContainer);
7972
- // If container, traverse down to its first LView.
7973
- const firstView = lViewOrLContainer[CONTAINER_HEADER_OFFSET];
7974
- if (firstView)
7975
- next = firstView;
7976
- }
7977
- if (!next) {
7978
- // Only clean up view when moving to the side or up, as destroy hooks
7979
- // should be called in order from the bottom up.
7980
- while (lViewOrLContainer && !lViewOrLContainer[NEXT] && lViewOrLContainer !== rootView) {
7981
- if (isLView(lViewOrLContainer)) {
7982
- cleanUpView(lViewOrLContainer[TVIEW], lViewOrLContainer);
7983
- }
7984
- lViewOrLContainer = lViewOrLContainer[PARENT];
7985
- }
7986
- if (lViewOrLContainer === null)
7987
- lViewOrLContainer = rootView;
7988
- if (isLView(lViewOrLContainer)) {
7989
- cleanUpView(lViewOrLContainer[TVIEW], lViewOrLContainer);
7990
- }
7991
- next = lViewOrLContainer && lViewOrLContainer[NEXT];
7992
- }
7993
- lViewOrLContainer = next;
8003
+ else {
8004
+ processTextNodeMarkersBeforeHydration(rootElement);
7994
8005
  }
7995
8006
  }
7996
- function detachMovedView(declarationContainer, lView) {
7997
- ngDevMode && assertLContainer(declarationContainer);
7998
- ngDevMode &&
7999
- assertDefined(declarationContainer[MOVED_VIEWS], 'A projected view should belong to a non-empty projected views collection');
8000
- const movedViews = declarationContainer[MOVED_VIEWS];
8001
- const declarationViewIndex = movedViews.indexOf(lView);
8002
- movedViews.splice(declarationViewIndex, 1);
8007
+ /**
8008
+ * Sets the implementation for the `applyRootElementTransform` function.
8009
+ */
8010
+ function enableApplyRootElementTransformImpl() {
8011
+ _applyRootElementTransformImpl = applyRootElementTransformImpl;
8003
8012
  }
8004
8013
  /**
8005
- * A standalone function which destroys an LView,
8006
- * conducting clean up (e.g. removing listeners, calling onDestroys).
8014
+ * Mapping between attributes names that don't correspond to their element property names.
8007
8015
  *
8008
- * @param tView The `TView' of the `LView` to be destroyed
8009
- * @param lView The view to be destroyed.
8016
+ * Performance note: this function is written as a series of if checks (instead of, say, a property
8017
+ * object lookup) for performance reasons - the series of `if` checks seems to be the fastest way of
8018
+ * mapping property names. Do NOT change without benchmarking.
8019
+ *
8020
+ * Note: this mapping has to be kept in sync with the equally named mapping in the template
8021
+ * type-checking machinery of ngtsc.
8010
8022
  */
8011
- function destroyLView(tView, lView) {
8012
- if (isDestroyed(lView)) {
8013
- return;
8014
- }
8015
- const renderer = lView[RENDERER];
8016
- if (renderer.destroyNode) {
8017
- applyView(tView, lView, renderer, 3 /* WalkTNodeTreeAction.Destroy */, null, null);
8023
+ function mapPropName(name) {
8024
+ if (name === 'class')
8025
+ return 'className';
8026
+ if (name === 'for')
8027
+ return 'htmlFor';
8028
+ if (name === 'formaction')
8029
+ return 'formAction';
8030
+ if (name === 'innerHtml')
8031
+ return 'innerHTML';
8032
+ if (name === 'readonly')
8033
+ return 'readOnly';
8034
+ if (name === 'tabindex')
8035
+ return 'tabIndex';
8036
+ return name;
8037
+ }
8038
+ function setPropertyAndInputs(tNode, lView, propName, value, renderer, sanitizer) {
8039
+ ngDevMode && assertNotSame(value, NO_CHANGE, 'Incoming value should never be NO_CHANGE.');
8040
+ const tView = lView[TVIEW];
8041
+ const hasSetInput = setAllInputsForProperty(tNode, tView, lView, propName, value);
8042
+ if (hasSetInput) {
8043
+ isComponentHost(tNode) && markDirtyIfOnPush(lView, tNode.index);
8044
+ ngDevMode && setNgReflectProperties(lView, tView, tNode, propName, value);
8045
+ return; // Stop propcessing if we've matched at least one input.
8018
8046
  }
8019
- destroyViewTree(lView);
8047
+ setDomProperty(tNode, lView, propName, value, renderer, sanitizer);
8020
8048
  }
8021
8049
  /**
8022
- * Calls onDestroys hooks for all directives and pipes in a given view and then removes all
8023
- * listeners. Listeners are removed as the last step so events delivered in the onDestroys hooks
8024
- * can be propagated to @Output listeners.
8025
- *
8026
- * @param tView `TView` for the `LView` to clean up.
8027
- * @param lView The LView to clean up
8050
+ * Sets a DOM property on a specific node.
8051
+ * @param tNode TNode on which to set the value.
8052
+ * @param lView View in which the node is located.
8053
+ * @param propName Name of the property.
8054
+ * @param value Value to set on the property.
8055
+ * @param renderer Renderer to use when setting the property.
8056
+ * @param sanitizer Function used to sanitize the value before setting it.
8028
8057
  */
8029
- function cleanUpView(tView, lView) {
8030
- if (isDestroyed(lView)) {
8058
+ function setDomProperty(tNode, lView, propName, value, renderer, sanitizer) {
8059
+ if (tNode.type & 3 /* TNodeType.AnyRNode */) {
8060
+ const element = getNativeByTNode(tNode, lView);
8061
+ propName = mapPropName(propName);
8062
+ if (ngDevMode) {
8063
+ validateAgainstEventProperties(propName);
8064
+ if (!isPropertyValid(element, propName, tNode.value, lView[TVIEW].schemas)) {
8065
+ handleUnknownPropertyError(propName, tNode.value, tNode.type, lView);
8066
+ }
8067
+ }
8068
+ // It is assumed that the sanitizer is only added when the compiler determines that the
8069
+ // property is risky, so sanitization can be done without further checks.
8070
+ value = sanitizer != null ? sanitizer(value, tNode.value || '', propName) : value;
8071
+ renderer.setProperty(element, propName, value);
8072
+ }
8073
+ else if (tNode.type & 12 /* TNodeType.AnyContainer */) {
8074
+ // If the node is a container and the property didn't
8075
+ // match any of the inputs or schemas we should throw.
8076
+ if (ngDevMode && !matchingSchemas(lView[TVIEW].schemas, tNode.value)) {
8077
+ handleUnknownPropertyError(propName, tNode.value, tNode.type, lView);
8078
+ }
8079
+ }
8080
+ }
8081
+ /** If node is an OnPush component, marks its LView dirty. */
8082
+ function markDirtyIfOnPush(lView, viewIndex) {
8083
+ ngDevMode && assertLView(lView);
8084
+ const childComponentLView = getComponentLViewByIndex(viewIndex, lView);
8085
+ if (!(childComponentLView[FLAGS] & 16 /* LViewFlags.CheckAlways */)) {
8086
+ childComponentLView[FLAGS] |= 64 /* LViewFlags.Dirty */;
8087
+ }
8088
+ }
8089
+ function setNgReflectProperty(lView, tNode, attrName, value) {
8090
+ const environment = lView[ENVIRONMENT];
8091
+ if (!environment.ngReflect) {
8031
8092
  return;
8032
8093
  }
8033
- const prevConsumer = setActiveConsumer(null);
8034
- try {
8035
- // Usually the Attached flag is removed when the view is detached from its parent, however
8036
- // if it's a root view, the flag won't be unset hence why we're also removing on destroy.
8037
- lView[FLAGS] &= ~128 /* LViewFlags.Attached */;
8038
- // Mark the LView as destroyed *before* executing the onDestroy hooks. An onDestroy hook
8039
- // runs arbitrary user code, which could include its own `viewRef.destroy()` (or similar). If
8040
- // We don't flag the view as destroyed before the hooks, this could lead to an infinite loop.
8041
- // This also aligns with the ViewEngine behavior. It also means that the onDestroy hook is
8042
- // really more of an "afterDestroy" hook if you think about it.
8043
- lView[FLAGS] |= 256 /* LViewFlags.Destroyed */;
8044
- lView[REACTIVE_TEMPLATE_CONSUMER] && consumerDestroy(lView[REACTIVE_TEMPLATE_CONSUMER]);
8045
- executeOnDestroys(tView, lView);
8046
- processCleanups(tView, lView);
8047
- // For component views only, the local renderer is destroyed at clean up time.
8048
- if (lView[TVIEW].type === 1 /* TViewType.Component */) {
8049
- lView[RENDERER].destroy();
8094
+ const element = getNativeByTNode(tNode, lView);
8095
+ const renderer = lView[RENDERER];
8096
+ attrName = normalizeDebugBindingName(attrName);
8097
+ const debugValue = normalizeDebugBindingValue(value);
8098
+ if (tNode.type & 3 /* TNodeType.AnyRNode */) {
8099
+ if (value == null) {
8100
+ renderer.removeAttribute(element, attrName);
8050
8101
  }
8051
- const declarationContainer = lView[DECLARATION_LCONTAINER];
8052
- // we are dealing with an embedded view that is still inserted into a container
8053
- if (declarationContainer !== null && isLContainer(lView[PARENT])) {
8054
- // and this is a projected view
8055
- if (declarationContainer !== lView[PARENT]) {
8056
- detachMovedView(declarationContainer, lView);
8057
- }
8058
- // For embedded views still attached to a container: remove query result from this view.
8059
- const lQueries = lView[QUERIES];
8060
- if (lQueries !== null) {
8061
- lQueries.detachView(tView);
8062
- }
8102
+ else {
8103
+ renderer.setAttribute(element, attrName, debugValue);
8063
8104
  }
8064
- // Unregister the view once everything else has been cleaned up.
8065
- unregisterLView(lView);
8066
8105
  }
8067
- finally {
8068
- setActiveConsumer(prevConsumer);
8106
+ else {
8107
+ const textContent = escapeCommentText(`bindings=${JSON.stringify({ [attrName]: debugValue }, null, 2)}`);
8108
+ renderer.setValue(element, textContent);
8069
8109
  }
8070
8110
  }
8071
- /** Removes listeners and unsubscribes from output subscriptions */
8072
- function processCleanups(tView, lView) {
8073
- ngDevMode && assertNotReactive(processCleanups.name);
8074
- const tCleanup = tView.cleanup;
8075
- const lCleanup = lView[CLEANUP];
8076
- if (tCleanup !== null) {
8077
- for (let i = 0; i < tCleanup.length - 1; i += 2) {
8078
- if (typeof tCleanup[i] === 'string') {
8079
- // This is a native DOM listener. It will occupy 4 entries in the TCleanup array (hence i +=
8080
- // 2 at the end of this block).
8081
- const targetIdx = tCleanup[i + 3];
8082
- ngDevMode && assertNumber(targetIdx, 'cleanup target must be a number');
8083
- if (targetIdx >= 0) {
8084
- // Destroy anything whose teardown is a function call (e.g. QueryList, ModelSignal).
8085
- lCleanup[targetIdx]();
8086
- }
8087
- else {
8088
- // Subscription
8089
- lCleanup[-targetIdx].unsubscribe();
8090
- }
8091
- i += 2;
8092
- }
8093
- else {
8094
- // This is a cleanup function that is grouped with the index of its context
8095
- const context = lCleanup[tCleanup[i + 1]];
8096
- tCleanup[i].call(context);
8097
- }
8098
- }
8111
+ function setNgReflectProperties(lView, tView, tNode, publicName, value) {
8112
+ const environment = lView[ENVIRONMENT];
8113
+ if (!environment.ngReflect || !(tNode.type & (3 /* TNodeType.AnyRNode */ | 4 /* TNodeType.Container */))) {
8114
+ return;
8099
8115
  }
8100
- if (lCleanup !== null) {
8101
- lView[CLEANUP] = null;
8116
+ const inputConfig = tNode.inputs?.[publicName];
8117
+ const hostInputConfig = tNode.hostDirectiveInputs?.[publicName];
8118
+ if (hostInputConfig) {
8119
+ for (let i = 0; i < hostInputConfig.length; i += 2) {
8120
+ const index = hostInputConfig[i];
8121
+ const publicName = hostInputConfig[i + 1];
8122
+ const def = tView.data[index];
8123
+ setNgReflectProperty(lView, tNode, def.inputs[publicName][0], value);
8124
+ }
8102
8125
  }
8103
- const destroyHooks = lView[ON_DESTROY_HOOKS];
8104
- if (destroyHooks !== null) {
8105
- // Reset the ON_DESTROY_HOOKS array before iterating over it to prevent hooks that unregister
8106
- // themselves from mutating the array during iteration.
8107
- lView[ON_DESTROY_HOOKS] = null;
8108
- for (let i = 0; i < destroyHooks.length; i++) {
8109
- const destroyHooksFn = destroyHooks[i];
8110
- ngDevMode && assertFunction(destroyHooksFn, 'Expecting destroy hook to be a function.');
8111
- destroyHooksFn();
8126
+ // Note: we set the private name of the input as the reflected property, not the public one.
8127
+ if (inputConfig) {
8128
+ for (const index of inputConfig) {
8129
+ const def = tView.data[index];
8130
+ setNgReflectProperty(lView, tNode, def.inputs[publicName][0], value);
8112
8131
  }
8113
8132
  }
8114
- // Destroy effects registered to the view. Many of these will have been processed above.
8115
- const effects = lView[EFFECTS];
8116
- if (effects !== null) {
8117
- lView[EFFECTS] = null;
8118
- for (const effect of effects) {
8119
- effect.destroy();
8133
+ }
8134
+ /**
8135
+ * Instantiate all the directives that were previously resolved on the current node.
8136
+ */
8137
+ function instantiateAllDirectives(tView, lView, tNode) {
8138
+ const start = tNode.directiveStart;
8139
+ const end = tNode.directiveEnd;
8140
+ // The component view needs to be created before creating the node injector
8141
+ // since it is used to inject some special symbols like `ChangeDetectorRef`.
8142
+ if (isComponentHost(tNode)) {
8143
+ ngDevMode && assertTNodeType(tNode, 3 /* TNodeType.AnyRNode */);
8144
+ createComponentLView(lView, tNode, tView.data[start + tNode.componentOffset]);
8145
+ }
8146
+ if (!tView.firstCreatePass) {
8147
+ getOrCreateNodeInjectorForNode(tNode, lView);
8148
+ }
8149
+ const initialInputs = tNode.initialInputs;
8150
+ for (let i = start; i < end; i++) {
8151
+ const def = tView.data[i];
8152
+ const directive = getNodeInjectable(lView, tView, i, tNode);
8153
+ attachPatchData(directive, lView);
8154
+ if (initialInputs !== null) {
8155
+ setInputsFromAttrs(lView, i - start, directive, def, tNode, initialInputs);
8156
+ }
8157
+ if (isComponentDef(def)) {
8158
+ const componentView = getComponentLViewByIndex(tNode.index, lView);
8159
+ componentView[CONTEXT] = getNodeInjectable(lView, tView, i, tNode);
8120
8160
  }
8121
8161
  }
8122
8162
  }
8123
- /** Calls onDestroy hooks for this view */
8124
- function executeOnDestroys(tView, lView) {
8125
- ngDevMode && assertNotReactive(executeOnDestroys.name);
8126
- let destroyHooks;
8127
- if (tView != null && (destroyHooks = tView.destroyHooks) != null) {
8128
- for (let i = 0; i < destroyHooks.length; i += 2) {
8129
- const context = lView[destroyHooks[i]];
8130
- // Only call the destroy hook if the context has been requested.
8131
- if (!(context instanceof NodeInjectorFactory)) {
8132
- const toCall = destroyHooks[i + 1];
8133
- if (Array.isArray(toCall)) {
8134
- for (let j = 0; j < toCall.length; j += 2) {
8135
- const callContext = context[toCall[j]];
8136
- const hook = toCall[j + 1];
8137
- profiler(4 /* ProfilerEvent.LifecycleHookStart */, callContext, hook);
8138
- try {
8139
- hook.call(callContext);
8140
- }
8141
- finally {
8142
- profiler(5 /* ProfilerEvent.LifecycleHookEnd */, callContext, hook);
8143
- }
8144
- }
8145
- }
8146
- else {
8147
- profiler(4 /* ProfilerEvent.LifecycleHookStart */, context, toCall);
8148
- try {
8149
- toCall.call(context);
8150
- }
8151
- finally {
8152
- profiler(5 /* ProfilerEvent.LifecycleHookEnd */, context, toCall);
8153
- }
8154
- }
8163
+ function invokeDirectivesHostBindings(tView, lView, tNode) {
8164
+ const start = tNode.directiveStart;
8165
+ const end = tNode.directiveEnd;
8166
+ const elementIndex = tNode.index;
8167
+ const currentDirectiveIndex = getCurrentDirectiveIndex();
8168
+ try {
8169
+ setSelectedIndex(elementIndex);
8170
+ for (let dirIndex = start; dirIndex < end; dirIndex++) {
8171
+ const def = tView.data[dirIndex];
8172
+ const directive = lView[dirIndex];
8173
+ setCurrentDirectiveIndex(dirIndex);
8174
+ if (def.hostBindings !== null || def.hostVars !== 0 || def.hostAttrs !== null) {
8175
+ invokeHostBindingsInCreationMode(def, directive);
8155
8176
  }
8156
8177
  }
8157
8178
  }
8179
+ finally {
8180
+ setSelectedIndex(-1);
8181
+ setCurrentDirectiveIndex(currentDirectiveIndex);
8182
+ }
8158
8183
  }
8159
8184
  /**
8160
- * Returns a native element if a node can be inserted into the given parent.
8161
- *
8162
- * There are two reasons why we may not be able to insert a element immediately.
8163
- * - Projection: When creating a child content element of a component, we have to skip the
8164
- * insertion because the content of a component will be projected.
8165
- * `<component><content>delayed due to projection</content></component>`
8166
- * - Parent container is disconnected: This can happen when we are inserting a view into
8167
- * parent container, which itself is disconnected. For example the parent container is part
8168
- * of a View which has not be inserted or is made for projection but has not been inserted
8169
- * into destination.
8185
+ * Invoke the host bindings in creation mode.
8170
8186
  *
8171
- * @param tView: Current `TView`.
8172
- * @param tNode: `TNode` for which we wish to retrieve render parent.
8173
- * @param lView: Current `LView`.
8187
+ * @param def `DirectiveDef` which may contain the `hostBindings` function.
8188
+ * @param directive Instance of directive.
8174
8189
  */
8175
- function getParentRElement(tView, tNode, lView) {
8176
- return getClosestRElement(tView, tNode.parent, lView);
8190
+ function invokeHostBindingsInCreationMode(def, directive) {
8191
+ if (def.hostBindings !== null) {
8192
+ def.hostBindings(1 /* RenderFlags.Create */, directive);
8193
+ }
8177
8194
  }
8178
8195
  /**
8179
- * Get closest `RElement` or `null` if it can't be found.
8180
- *
8181
- * If `TNode` is `TNodeType.Element` => return `RElement` at `LView[tNode.index]` location.
8182
- * If `TNode` is `TNodeType.ElementContainer|IcuContain` => return the parent (recursively).
8183
- * If `TNode` is `null` then return host `RElement`:
8184
- * - return `null` if projection
8185
- * - return `null` if parent container is disconnected (we have no parent.)
8186
- *
8187
- * @param tView: Current `TView`.
8188
- * @param tNode: `TNode` for which we wish to retrieve `RElement` (or `null` if host element is
8189
- * needed).
8190
- * @param lView: Current `LView`.
8191
- * @returns `null` if the `RElement` can't be determined at this time (no parent / projection)
8196
+ * Matches the current node against all available selectors.
8197
+ * If a component is matched (at most one), it is returned in first position in the array.
8192
8198
  */
8193
- function getClosestRElement(tView, tNode, lView) {
8194
- let parentTNode = tNode;
8195
- // Skip over element and ICU containers as those are represented by a comment node and
8196
- // can't be used as a render parent. Also skip let declarations since they don't have a
8197
- // corresponding DOM node at all.
8198
- while (parentTNode !== null &&
8199
- parentTNode.type & (8 /* TNodeType.ElementContainer */ | 32 /* TNodeType.Icu */ | 128 /* TNodeType.LetDeclaration */)) {
8200
- tNode = parentTNode;
8201
- parentTNode = tNode.parent;
8202
- }
8203
- // If the parent tNode is null, then we are inserting across views: either into an embedded view
8204
- // or a component view.
8205
- if (parentTNode === null) {
8206
- // We are inserting a root element of the component view into the component host element and
8207
- // it should always be eager.
8208
- return lView[HOST];
8209
- }
8210
- else {
8211
- ngDevMode && assertTNodeType(parentTNode, 3 /* TNodeType.AnyRNode */ | 4 /* TNodeType.Container */);
8212
- if (isComponentHost(parentTNode)) {
8213
- ngDevMode && assertTNodeForLView(parentTNode, lView);
8214
- const { encapsulation } = tView.data[parentTNode.directiveStart + parentTNode.componentOffset];
8215
- // We've got a parent which is an element in the current view. We just need to verify if the
8216
- // parent element is not a component. Component's content nodes are not inserted immediately
8217
- // because they will be projected, and so doing insert at this point would be wasteful.
8218
- // Since the projection would then move it to its final destination. Note that we can't
8219
- // make this assumption when using the Shadow DOM, because the native projection placeholders
8220
- // (<content> or <slot>) have to be in place as elements are being inserted.
8221
- if (encapsulation === ViewEncapsulation.None ||
8222
- encapsulation === ViewEncapsulation.Emulated) {
8223
- return null;
8199
+ function findDirectiveDefMatches(tView, tNode) {
8200
+ ngDevMode && assertFirstCreatePass(tView);
8201
+ ngDevMode && assertTNodeType(tNode, 3 /* TNodeType.AnyRNode */ | 12 /* TNodeType.AnyContainer */);
8202
+ const registry = tView.directiveRegistry;
8203
+ let matches = null;
8204
+ if (registry) {
8205
+ for (let i = 0; i < registry.length; i++) {
8206
+ const def = registry[i];
8207
+ if (isNodeMatchingSelectorList(tNode, def.selectors, /* isProjectionMode */ false)) {
8208
+ matches ??= [];
8209
+ if (isComponentDef(def)) {
8210
+ if (ngDevMode) {
8211
+ assertTNodeType(tNode, 2 /* TNodeType.Element */, `"${tNode.value}" tags cannot be used as component hosts. ` +
8212
+ `Please use a different tag to activate the ${stringify(def.type)} component.`);
8213
+ if (matches.length && isComponentDef(matches[0])) {
8214
+ throwMultipleComponentError(tNode, matches.find(isComponentDef).type, def.type);
8215
+ }
8216
+ }
8217
+ matches.unshift(def);
8218
+ }
8219
+ else {
8220
+ matches.push(def);
8221
+ }
8224
8222
  }
8225
8223
  }
8226
- return getNativeByTNode(parentTNode, lView);
8227
8224
  }
8225
+ return matches;
8228
8226
  }
8229
- /**
8230
- * Find a node in front of which `currentTNode` should be inserted.
8231
- *
8232
- * This method determines the `RNode` in front of which we should insert the `currentRNode`. This
8233
- * takes `TNode.insertBeforeIndex` into account if i18n code has been invoked.
8234
- *
8235
- * @param parentTNode parent `TNode`
8236
- * @param currentTNode current `TNode` (The node which we would like to insert into the DOM)
8237
- * @param lView current `LView`
8238
- */
8239
- function getInsertInFrontOfRNode(parentTNode, currentTNode, lView) {
8240
- return _getInsertInFrontOfRNodeWithI18n(parentTNode, currentTNode, lView);
8227
+ function elementAttributeInternal(tNode, lView, name, value, sanitizer, namespace) {
8228
+ if (ngDevMode) {
8229
+ assertNotSame(value, NO_CHANGE, 'Incoming value should never be NO_CHANGE.');
8230
+ validateAgainstEventAttributes(name);
8231
+ assertTNodeType(tNode, 2 /* TNodeType.Element */, `Attempted to set attribute \`${name}\` on a container node. ` +
8232
+ `Host bindings are not valid on ng-container or ng-template.`);
8233
+ }
8234
+ const element = getNativeByTNode(tNode, lView);
8235
+ setElementAttribute(lView[RENDERER], element, namespace, tNode.value, name, value, sanitizer);
8236
+ }
8237
+ function setElementAttribute(renderer, element, namespace, tagName, name, value, sanitizer) {
8238
+ if (value == null) {
8239
+ renderer.removeAttribute(element, name, namespace);
8240
+ }
8241
+ else {
8242
+ const strValue = sanitizer == null ? renderStringify(value) : sanitizer(value, tagName || '', name);
8243
+ renderer.setAttribute(element, name, strValue, namespace);
8244
+ }
8241
8245
  }
8242
8246
  /**
8243
- * Find a node in front of which `currentTNode` should be inserted. (Does not take i18n into
8244
- * account)
8245
- *
8246
- * This method determines the `RNode` in front of which we should insert the `currentRNode`. This
8247
- * does not take `TNode.insertBeforeIndex` into account.
8247
+ * Sets initial input properties on directive instances from attribute data
8248
8248
  *
8249
- * @param parentTNode parent `TNode`
8250
- * @param currentTNode current `TNode` (The node which we would like to insert into the DOM)
8251
- * @param lView current `LView`
8249
+ * @param lView Current LView that is being processed.
8250
+ * @param directiveIndex Index of the directive in directives array
8251
+ * @param instance Instance of the directive on which to set the initial inputs
8252
+ * @param def The directive def that contains the list of inputs
8253
+ * @param tNode The static data for this node
8252
8254
  */
8253
- function getInsertInFrontOfRNodeWithNoI18n(parentTNode, currentTNode, lView) {
8254
- if (parentTNode.type & (8 /* TNodeType.ElementContainer */ | 32 /* TNodeType.Icu */)) {
8255
- return getNativeByTNode(parentTNode, lView);
8255
+ function setInputsFromAttrs(lView, directiveIndex, instance, def, tNode, initialInputData) {
8256
+ const initialInputs = initialInputData[directiveIndex];
8257
+ if (initialInputs !== null) {
8258
+ for (let i = 0; i < initialInputs.length; i += 2) {
8259
+ const lookupName = initialInputs[i];
8260
+ const value = initialInputs[i + 1];
8261
+ writeToDirectiveInput(def, instance, lookupName, value);
8262
+ if (ngDevMode) {
8263
+ setNgReflectProperty(lView, tNode, def.inputs[lookupName][0], value);
8264
+ }
8265
+ }
8256
8266
  }
8257
- return null;
8258
8267
  }
8268
+ /** Shared code between instructions that indicate the start of an element. */
8269
+ function elementLikeStartShared(tNode, lView, index, name, locateOrCreateNativeNode) {
8270
+ const adjustedIndex = HEADER_OFFSET + index;
8271
+ const tView = lView[TVIEW];
8272
+ const native = locateOrCreateNativeNode(tView, lView, tNode, name, index);
8273
+ lView[adjustedIndex] = native;
8274
+ setCurrentTNode(tNode, true);
8275
+ // It's important that this runs before we've instantiated the directives.
8276
+ const isElement = tNode.type === 2 /* TNodeType.Element */;
8277
+ if (isElement) {
8278
+ setupStaticAttributes(lView[RENDERER], native, tNode);
8279
+ // any immediate children of a component or template container must be pre-emptively
8280
+ // monkey-patched with the component view data so that the element can be inspected
8281
+ // later on using any element discovery utility methods (see `element_discovery.ts`)
8282
+ if (getElementDepthCount() === 0 || isDirectiveHost(tNode)) {
8283
+ attachPatchData(native, lView);
8284
+ }
8285
+ increaseElementDepthCount();
8286
+ }
8287
+ else {
8288
+ attachPatchData(native, lView);
8289
+ }
8290
+ if (wasLastNodeCreated() && (!isElement || !isDetachedByI18n(tNode))) {
8291
+ // In the i18n case, the translation may have removed this element, so only add it if it is not
8292
+ // detached. See `TNodeType.Placeholder` and `LFrame.inI18n` for more context.
8293
+ appendChild(tView, lView, native, tNode);
8294
+ }
8295
+ return tNode;
8296
+ }
8297
+ /** Shared code between instructions that indicate the end of an element. */
8298
+ function elementLikeEndShared(tNode) {
8299
+ let currentTNode = tNode;
8300
+ if (isCurrentTNodeParent()) {
8301
+ setCurrentTNodeAsNotParent();
8302
+ }
8303
+ else {
8304
+ ngDevMode && assertHasParent(getCurrentTNode());
8305
+ currentTNode = currentTNode.parent;
8306
+ setCurrentTNode(currentTNode, false);
8307
+ }
8308
+ return currentTNode;
8309
+ }
8310
+ ///////////////////////////////
8311
+ //// Bindings & interpolations
8312
+ ///////////////////////////////
8259
8313
  /**
8260
- * Tree shakable boundary for `getInsertInFrontOfRNodeWithI18n` function.
8314
+ * Stores meta-data for a property binding to be used by TestBed's `DebugElement.properties`.
8261
8315
  *
8262
- * This function will only be set if i18n code runs.
8263
- */
8264
- let _getInsertInFrontOfRNodeWithI18n = getInsertInFrontOfRNodeWithNoI18n;
8265
- /**
8266
- * Tree shakable boundary for `processI18nInsertBefore` function.
8316
+ * In order to support TestBed's `DebugElement.properties` we need to save, for each binding:
8317
+ * - a bound property name;
8318
+ * - a static parts of interpolated strings;
8267
8319
  *
8268
- * This function will only be set if i18n code runs.
8269
- */
8270
- let _processI18nInsertBefore;
8271
- function setI18nHandling(getInsertInFrontOfRNodeWithI18n, processI18nInsertBefore) {
8272
- _getInsertInFrontOfRNodeWithI18n = getInsertInFrontOfRNodeWithI18n;
8273
- _processI18nInsertBefore = processI18nInsertBefore;
8274
- }
8275
- /**
8276
- * Appends the `child` native node (or a collection of nodes) to the `parent`.
8320
+ * A given property metadata is saved at the binding's index in the `TView.data` (in other words, a
8321
+ * property binding metadata will be stored in `TView.data` at the same index as a bound value in
8322
+ * `LView`). Metadata are represented as `INTERPOLATION_DELIMITER`-delimited string with the
8323
+ * following format:
8324
+ * - `propertyName` for bound properties;
8325
+ * - `propertyName�prefix�interpolation_static_part1�..interpolation_static_partN�suffix` for
8326
+ * interpolated properties.
8277
8327
  *
8278
- * @param tView The `TView' to be appended
8279
- * @param lView The current LView
8280
- * @param childRNode The native child (or children) that should be appended
8281
- * @param childTNode The TNode of the child element
8328
+ * @param tData `TData` where meta-data will be saved;
8329
+ * @param tNode `TNode` that is a target of the binding;
8330
+ * @param propertyName bound property name;
8331
+ * @param bindingIndex binding index in `LView`
8332
+ * @param interpolationParts static interpolation parts (for property interpolations)
8282
8333
  */
8283
- function appendChild(tView, lView, childRNode, childTNode) {
8284
- const parentRNode = getParentRElement(tView, childTNode, lView);
8285
- const renderer = lView[RENDERER];
8286
- const parentTNode = childTNode.parent || lView[T_HOST];
8287
- const anchorNode = getInsertInFrontOfRNode(parentTNode, childTNode, lView);
8288
- if (parentRNode != null) {
8289
- if (Array.isArray(childRNode)) {
8290
- for (let i = 0; i < childRNode.length; i++) {
8291
- nativeAppendOrInsertBefore(renderer, parentRNode, childRNode[i], anchorNode, false);
8334
+ function storePropertyBindingMetadata(tData, tNode, propertyName, bindingIndex, ...interpolationParts) {
8335
+ // Binding meta-data are stored only the first time a given property instruction is processed.
8336
+ // Since we don't have a concept of the "first update pass" we need to check for presence of the
8337
+ // binding meta-data to decide if one should be stored (or if was stored already).
8338
+ if (tData[bindingIndex] === null) {
8339
+ if (!tNode.inputs?.[propertyName] && !tNode.hostDirectiveInputs?.[propertyName]) {
8340
+ const propBindingIdxs = tNode.propertyBindings || (tNode.propertyBindings = []);
8341
+ propBindingIdxs.push(bindingIndex);
8342
+ let bindingMetadata = propertyName;
8343
+ if (interpolationParts.length > 0) {
8344
+ bindingMetadata +=
8345
+ INTERPOLATION_DELIMITER + interpolationParts.join(INTERPOLATION_DELIMITER);
8292
8346
  }
8293
- }
8294
- else {
8295
- nativeAppendOrInsertBefore(renderer, parentRNode, childRNode, anchorNode, false);
8347
+ tData[bindingIndex] = bindingMetadata;
8296
8348
  }
8297
8349
  }
8298
- _processI18nInsertBefore !== undefined &&
8299
- _processI18nInsertBefore(renderer, childTNode, lView, childRNode, parentRNode);
8300
8350
  }
8301
8351
  /**
8302
- * Returns the first native node for a given LView, starting from the provided TNode.
8303
- *
8304
- * Native nodes are returned in the order in which those appear in the native tree (DOM).
8352
+ * There are cases where the sub component's renderer needs to be included
8353
+ * instead of the current renderer (see the componentSyntheticHost* instructions).
8305
8354
  */
8306
- function getFirstNativeNode(lView, tNode) {
8307
- if (tNode !== null) {
8308
- ngDevMode &&
8309
- assertTNodeType(tNode, 3 /* TNodeType.AnyRNode */ |
8310
- 12 /* TNodeType.AnyContainer */ |
8311
- 32 /* TNodeType.Icu */ |
8312
- 16 /* TNodeType.Projection */ |
8313
- 128 /* TNodeType.LetDeclaration */);
8314
- const tNodeType = tNode.type;
8315
- if (tNodeType & 3 /* TNodeType.AnyRNode */) {
8316
- return getNativeByTNode(tNode, lView);
8317
- }
8318
- else if (tNodeType & 4 /* TNodeType.Container */) {
8319
- return getBeforeNodeForView(-1, lView[tNode.index]);
8320
- }
8321
- else if (tNodeType & 8 /* TNodeType.ElementContainer */) {
8322
- const elIcuContainerChild = tNode.child;
8323
- if (elIcuContainerChild !== null) {
8324
- return getFirstNativeNode(lView, elIcuContainerChild);
8325
- }
8326
- else {
8327
- const rNodeOrLContainer = lView[tNode.index];
8328
- if (isLContainer(rNodeOrLContainer)) {
8329
- return getBeforeNodeForView(-1, rNodeOrLContainer);
8330
- }
8331
- else {
8332
- return unwrapRNode(rNodeOrLContainer);
8333
- }
8334
- }
8335
- }
8336
- else if (tNodeType & 128 /* TNodeType.LetDeclaration */) {
8337
- return getFirstNativeNode(lView, tNode.next);
8338
- }
8339
- else if (tNodeType & 32 /* TNodeType.Icu */) {
8340
- let nextRNode = icuContainerIterate(tNode, lView);
8341
- let rNode = nextRNode();
8342
- // If the ICU container has no nodes, than we use the ICU anchor as the node.
8343
- return rNode || unwrapRNode(lView[tNode.index]);
8344
- }
8345
- else {
8346
- const projectionNodes = getProjectionNodes(lView, tNode);
8347
- if (projectionNodes !== null) {
8348
- if (Array.isArray(projectionNodes)) {
8349
- return projectionNodes[0];
8350
- }
8351
- const parentView = getLViewParent(lView[DECLARATION_COMPONENT_VIEW]);
8352
- ngDevMode && assertParentView(parentView);
8353
- return getFirstNativeNode(parentView, projectionNodes);
8354
- }
8355
- else {
8356
- return getFirstNativeNode(lView, tNode.next);
8357
- }
8358
- }
8355
+ function loadComponentRenderer(currentDef, tNode, lView) {
8356
+ // TODO(FW-2043): the `currentDef` is null when host bindings are invoked while creating root
8357
+ // component (see packages/core/src/render3/component.ts). This is not consistent with the process
8358
+ // of creating inner components, when current directive index is available in the state. In order
8359
+ // to avoid relying on current def being `null` (thus special-casing root component creation), the
8360
+ // process of creating root component should be unified with the process of creating inner
8361
+ // components.
8362
+ if (currentDef === null || isComponentDef(currentDef)) {
8363
+ lView = unwrapLView(lView[tNode.index]);
8359
8364
  }
8360
- return null;
8365
+ return lView[RENDERER];
8361
8366
  }
8362
- function getProjectionNodes(lView, tNode) {
8363
- if (tNode !== null) {
8364
- const componentView = lView[DECLARATION_COMPONENT_VIEW];
8365
- const componentHost = componentView[T_HOST];
8366
- const slotIdx = tNode.projection;
8367
- ngDevMode && assertProjectionSlots(lView);
8368
- return componentHost.projection[slotIdx];
8367
+ /** Handles an error thrown in an LView. */
8368
+ function handleUncaughtError(lView, error) {
8369
+ const injector = lView[INJECTOR];
8370
+ if (!injector) {
8371
+ return;
8372
+ }
8373
+ const errorHandler = injector.get(INTERNAL_APPLICATION_ERROR_HANDLER, null);
8374
+ errorHandler?.(error);
8375
+ }
8376
+ /**
8377
+ * Set all directive inputs with the specific public name on the node.
8378
+ *
8379
+ * @param tNode TNode on which the input is being set.
8380
+ * @param tView Current TView
8381
+ * @param lView `LView` which contains the directives.
8382
+ * @param publicName Public name of the input being set.
8383
+ * @param value Value to set.
8384
+ */
8385
+ function setAllInputsForProperty(tNode, tView, lView, publicName, value) {
8386
+ const inputs = tNode.inputs?.[publicName];
8387
+ const hostDirectiveInputs = tNode.hostDirectiveInputs?.[publicName];
8388
+ let hasMatch = false;
8389
+ if (hostDirectiveInputs) {
8390
+ for (let i = 0; i < hostDirectiveInputs.length; i += 2) {
8391
+ const index = hostDirectiveInputs[i];
8392
+ ngDevMode && assertIndexInRange(lView, index);
8393
+ const publicName = hostDirectiveInputs[i + 1];
8394
+ const def = tView.data[index];
8395
+ writeToDirectiveInput(def, lView[index], publicName, value);
8396
+ hasMatch = true;
8397
+ }
8369
8398
  }
8370
- return null;
8371
- }
8372
- function getBeforeNodeForView(viewIndexInContainer, lContainer) {
8373
- const nextViewIndex = CONTAINER_HEADER_OFFSET + viewIndexInContainer + 1;
8374
- if (nextViewIndex < lContainer.length) {
8375
- const lView = lContainer[nextViewIndex];
8376
- const firstTNodeOfView = lView[TVIEW].firstChild;
8377
- if (firstTNodeOfView !== null) {
8378
- return getFirstNativeNode(lView, firstTNodeOfView);
8399
+ if (inputs) {
8400
+ for (const index of inputs) {
8401
+ ngDevMode && assertIndexInRange(lView, index);
8402
+ const instance = lView[index];
8403
+ const def = tView.data[index];
8404
+ writeToDirectiveInput(def, instance, publicName, value);
8405
+ hasMatch = true;
8379
8406
  }
8380
8407
  }
8381
- return lContainer[NATIVE];
8408
+ return hasMatch;
8382
8409
  }
8383
8410
  /**
8384
- * Performs the operation of `action` on the node. Typically this involves inserting or removing
8385
- * nodes on the LView or projection boundary.
8411
+ * Sets an input value only on a specific directive and its host directives.
8412
+ * @param tNode TNode on which the input is being set.
8413
+ * @param tView Current TView
8414
+ * @param lView `LView` which contains the directives.
8415
+ * @param target Directive on which to set the input.
8416
+ * @param publicName Public name of the input being set.
8417
+ * @param value Value to set.
8386
8418
  */
8387
- function applyNodes(renderer, action, tNode, lView, parentRElement, beforeNode, isProjection) {
8388
- while (tNode != null) {
8389
- ngDevMode && assertTNodeForLView(tNode, lView);
8390
- // Let declarations don't have corresponding DOM nodes so we skip over them.
8391
- if (tNode.type === 128 /* TNodeType.LetDeclaration */) {
8392
- tNode = tNode.next;
8393
- continue;
8394
- }
8395
- ngDevMode &&
8396
- assertTNodeType(tNode, 3 /* TNodeType.AnyRNode */ | 12 /* TNodeType.AnyContainer */ | 16 /* TNodeType.Projection */ | 32 /* TNodeType.Icu */);
8397
- const rawSlotValue = lView[tNode.index];
8398
- const tNodeType = tNode.type;
8399
- if (isProjection) {
8400
- if (action === 0 /* WalkTNodeTreeAction.Create */) {
8401
- rawSlotValue && attachPatchData(unwrapRNode(rawSlotValue), lView);
8402
- tNode.flags |= 2 /* TNodeFlags.isProjected */;
8403
- }
8404
- }
8405
- if (!isDetachedByI18n(tNode)) {
8406
- if (tNodeType & 8 /* TNodeType.ElementContainer */) {
8407
- applyNodes(renderer, action, tNode.child, lView, parentRElement, beforeNode, false);
8408
- applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode);
8409
- }
8410
- else if (tNodeType & 32 /* TNodeType.Icu */) {
8411
- const nextRNode = icuContainerIterate(tNode, lView);
8412
- let rNode;
8413
- while ((rNode = nextRNode())) {
8414
- applyToElementOrContainer(action, renderer, parentRElement, rNode, beforeNode);
8415
- }
8416
- applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode);
8417
- }
8418
- else if (tNodeType & 16 /* TNodeType.Projection */) {
8419
- applyProjectionRecursive(renderer, action, lView, tNode, parentRElement, beforeNode);
8419
+ function setDirectiveInput(tNode, tView, lView, target, publicName, value) {
8420
+ let hostIndex = null;
8421
+ let hostDirectivesStart = null;
8422
+ let hostDirectivesEnd = null;
8423
+ let hasSet = false;
8424
+ if (ngDevMode && !tNode.directiveToIndex?.has(target.type)) {
8425
+ throw new Error(`Node does not have a directive with type ${target.type.name}`);
8426
+ }
8427
+ const data = tNode.directiveToIndex.get(target.type);
8428
+ if (typeof data === 'number') {
8429
+ hostIndex = data;
8430
+ }
8431
+ else {
8432
+ [hostIndex, hostDirectivesStart, hostDirectivesEnd] = data;
8433
+ }
8434
+ if (hostDirectivesStart !== null &&
8435
+ hostDirectivesEnd !== null &&
8436
+ tNode.hostDirectiveInputs?.hasOwnProperty(publicName)) {
8437
+ const hostDirectiveInputs = tNode.hostDirectiveInputs[publicName];
8438
+ for (let i = 0; i < hostDirectiveInputs.length; i += 2) {
8439
+ const index = hostDirectiveInputs[i];
8440
+ if (index >= hostDirectivesStart && index <= hostDirectivesEnd) {
8441
+ ngDevMode && assertIndexInRange(lView, index);
8442
+ const def = tView.data[index];
8443
+ const hostDirectivePublicName = hostDirectiveInputs[i + 1];
8444
+ writeToDirectiveInput(def, lView[index], hostDirectivePublicName, value);
8445
+ hasSet = true;
8420
8446
  }
8421
- else {
8422
- ngDevMode && assertTNodeType(tNode, 3 /* TNodeType.AnyRNode */ | 4 /* TNodeType.Container */);
8423
- applyToElementOrContainer(action, renderer, parentRElement, rawSlotValue, beforeNode);
8447
+ else if (index > hostDirectivesEnd) {
8448
+ // Directives here are in ascending order so we can stop looking once we're past the range.
8449
+ break;
8424
8450
  }
8425
8451
  }
8426
- tNode = isProjection ? tNode.projectionNext : tNode.next;
8427
8452
  }
8453
+ if (hostIndex !== null && target.inputs.hasOwnProperty(publicName)) {
8454
+ ngDevMode && assertIndexInRange(lView, hostIndex);
8455
+ writeToDirectiveInput(target, lView[hostIndex], publicName, value);
8456
+ hasSet = true;
8457
+ }
8458
+ return hasSet;
8428
8459
  }
8429
- function applyView(tView, lView, renderer, action, parentRElement, beforeNode) {
8430
- applyNodes(renderer, action, tView.firstChild, lView, parentRElement, beforeNode, false);
8460
+
8461
+ function renderComponent(hostLView, componentHostIdx) {
8462
+ ngDevMode && assertEqual(isCreationMode(hostLView), true, 'Should be run in creation mode');
8463
+ const componentView = getComponentLViewByIndex(componentHostIdx, hostLView);
8464
+ const componentTView = componentView[TVIEW];
8465
+ syncViewWithBlueprint(componentTView, componentView);
8466
+ const hostRNode = componentView[HOST];
8467
+ // Populate an LView with hydration info retrieved from the DOM via TransferState.
8468
+ if (hostRNode !== null && componentView[HYDRATION] === null) {
8469
+ componentView[HYDRATION] = retrieveHydrationInfo(hostRNode, componentView[INJECTOR]);
8470
+ }
8471
+ profiler(18 /* ProfilerEvent.ComponentStart */);
8472
+ renderView(componentTView, componentView, componentView[CONTEXT]);
8473
+ profiler(19 /* ProfilerEvent.ComponentEnd */, componentView[CONTEXT]);
8431
8474
  }
8432
8475
  /**
8433
- * `applyProjection` performs operation on the projection.
8476
+ * Syncs an LView instance with its blueprint if they have gotten out of sync.
8434
8477
  *
8435
- * Inserting a projection requires us to locate the projected nodes from the parent component. The
8436
- * complication is that those nodes themselves could be re-projected from their parent component.
8478
+ * Typically, blueprints and their view instances should always be in sync, so the loop here
8479
+ * will be skipped. However, consider this case of two components side-by-side:
8437
8480
  *
8438
- * @param tView The `TView` of `LView` which needs to be inserted, detached, destroyed
8439
- * @param lView The `LView` which needs to be inserted, detached, destroyed.
8440
- * @param tProjectionNode node to project
8481
+ * App template:
8482
+ * ```html
8483
+ * <comp></comp>
8484
+ * <comp></comp>
8485
+ * ```
8486
+ *
8487
+ * The following will happen:
8488
+ * 1. App template begins processing.
8489
+ * 2. First <comp> is matched as a component and its LView is created.
8490
+ * 3. Second <comp> is matched as a component and its LView is created.
8491
+ * 4. App template completes processing, so it's time to check child templates.
8492
+ * 5. First <comp> template is checked. It has a directive, so its def is pushed to blueprint.
8493
+ * 6. Second <comp> template is checked. Its blueprint has been updated by the first
8494
+ * <comp> template, but its LView was created before this update, so it is out of sync.
8495
+ *
8496
+ * Note that embedded views inside ngFor loops will never be out of sync because these views
8497
+ * are processed as soon as they are created.
8498
+ *
8499
+ * @param tView The `TView` that contains the blueprint for syncing
8500
+ * @param lView The view to sync
8441
8501
  */
8442
- function applyProjection(tView, lView, tProjectionNode) {
8443
- const renderer = lView[RENDERER];
8444
- const parentRNode = getParentRElement(tView, tProjectionNode, lView);
8445
- const parentTNode = tProjectionNode.parent || lView[T_HOST];
8446
- let beforeNode = getInsertInFrontOfRNode(parentTNode, tProjectionNode, lView);
8447
- applyProjectionRecursive(renderer, 0 /* WalkTNodeTreeAction.Create */, lView, tProjectionNode, parentRNode, beforeNode);
8502
+ function syncViewWithBlueprint(tView, lView) {
8503
+ for (let i = lView.length; i < tView.blueprint.length; i++) {
8504
+ lView.push(tView.blueprint[i]);
8505
+ }
8448
8506
  }
8449
8507
  /**
8450
- * `applyProjectionRecursive` performs operation on the projection specified by `action` (insert,
8451
- * detach, destroy)
8452
- *
8453
- * Inserting a projection requires us to locate the projected nodes from the parent component. The
8454
- * complication is that those nodes themselves could be re-projected from their parent component.
8455
- *
8456
- * @param renderer Render to use
8457
- * @param action action to perform (insert, detach, destroy)
8458
- * @param lView The LView which needs to be inserted, detached, destroyed.
8459
- * @param tProjectionNode node to project
8460
- * @param parentRElement parent DOM element for insertion/removal.
8461
- * @param beforeNode Before which node the insertions should happen.
8508
+ * Processes a view in the creation mode. This includes a number of steps in a specific order:
8509
+ * - creating view query functions (if any);
8510
+ * - executing a template function in the creation mode;
8511
+ * - updating static queries (if any);
8512
+ * - creating child components defined in a given view.
8462
8513
  */
8463
- function applyProjectionRecursive(renderer, action, lView, tProjectionNode, parentRElement, beforeNode) {
8464
- const componentLView = lView[DECLARATION_COMPONENT_VIEW];
8465
- const componentNode = componentLView[T_HOST];
8466
- ngDevMode &&
8467
- assertEqual(typeof tProjectionNode.projection, 'number', 'expecting projection index');
8468
- const nodeToProjectOrRNodes = componentNode.projection[tProjectionNode.projection];
8469
- if (Array.isArray(nodeToProjectOrRNodes)) {
8470
- // This should not exist, it is a bit of a hack. When we bootstrap a top level node and we
8471
- // need to support passing projectable nodes, so we cheat and put them in the TNode
8472
- // of the Host TView. (Yes we put instance info at the T Level). We can get away with it
8473
- // because we know that TView is not shared and therefore it will not be a problem.
8474
- // This should be refactored and cleaned up.
8475
- for (let i = 0; i < nodeToProjectOrRNodes.length; i++) {
8476
- const rNode = nodeToProjectOrRNodes[i];
8477
- applyToElementOrContainer(action, renderer, parentRElement, rNode, beforeNode);
8514
+ function renderView(tView, lView, context) {
8515
+ ngDevMode && assertEqual(isCreationMode(lView), true, 'Should be run in creation mode');
8516
+ ngDevMode && assertNotReactive(renderView.name);
8517
+ enterView(lView);
8518
+ try {
8519
+ const viewQuery = tView.viewQuery;
8520
+ if (viewQuery !== null) {
8521
+ executeViewQueryFn(1 /* RenderFlags.Create */, viewQuery, context);
8522
+ }
8523
+ // Execute a template associated with this view, if it exists. A template function might not be
8524
+ // defined for the root component views.
8525
+ const templateFn = tView.template;
8526
+ if (templateFn !== null) {
8527
+ executeTemplate(tView, lView, templateFn, 1 /* RenderFlags.Create */, context);
8528
+ }
8529
+ // This needs to be set before children are processed to support recursive components.
8530
+ // This must be set to false immediately after the first creation run because in an
8531
+ // ngFor loop, all the views will be created together before update mode runs and turns
8532
+ // off firstCreatePass. If we don't set it here, instances will perform directive
8533
+ // matching, etc again and again.
8534
+ if (tView.firstCreatePass) {
8535
+ tView.firstCreatePass = false;
8536
+ }
8537
+ // Mark all queries active in this view as dirty. This is necessary for signal-based queries to
8538
+ // have a clear marking point where we can read query results atomically (for a given view).
8539
+ lView[QUERIES]?.finishViewCreation(tView);
8540
+ // We resolve content queries specifically marked as `static` in creation mode. Dynamic
8541
+ // content queries are resolved during change detection (i.e. update mode), after embedded
8542
+ // views are refreshed (see block above).
8543
+ if (tView.staticContentQueries) {
8544
+ refreshContentQueries(tView, lView);
8545
+ }
8546
+ // We must materialize query results before child components are processed
8547
+ // in case a child component has projected a container. The LContainer needs
8548
+ // to exist so the embedded views are properly attached by the container.
8549
+ if (tView.staticViewQueries) {
8550
+ executeViewQueryFn(2 /* RenderFlags.Update */, tView.viewQuery, context);
8551
+ }
8552
+ // Render child component views.
8553
+ const components = tView.components;
8554
+ if (components !== null) {
8555
+ renderChildComponents(lView, components);
8478
8556
  }
8479
8557
  }
8480
- else {
8481
- let nodeToProject = nodeToProjectOrRNodes;
8482
- const projectedComponentLView = componentLView[PARENT];
8483
- // If a parent <ng-content> is located within a skip hydration block,
8484
- // annotate an actual node that is being projected with the same flag too.
8485
- if (hasInSkipHydrationBlockFlag(tProjectionNode)) {
8486
- nodeToProject.flags |= 128 /* TNodeFlags.inSkipHydrationBlock */;
8558
+ catch (error) {
8559
+ // If we didn't manage to get past the first template pass due to
8560
+ // an error, mark the view as corrupted so we can try to recover.
8561
+ if (tView.firstCreatePass) {
8562
+ tView.incompleteFirstPass = true;
8563
+ tView.firstCreatePass = false;
8487
8564
  }
8488
- applyNodes(renderer, action, nodeToProject, projectedComponentLView, parentRElement, beforeNode, true);
8565
+ throw error;
8566
+ }
8567
+ finally {
8568
+ lView[FLAGS] &= ~4 /* LViewFlags.CreationMode */;
8569
+ leaveView();
8570
+ }
8571
+ }
8572
+ /** Renders child components in the current view (creation mode). */
8573
+ function renderChildComponents(hostLView, components) {
8574
+ for (let i = 0; i < components.length; i++) {
8575
+ renderComponent(hostLView, components[i]);
8489
8576
  }
8490
8577
  }
8491
- /**
8492
- * `applyContainer` performs an operation on the container and its views as specified by
8493
- * `action` (insert, detach, destroy)
8494
- *
8495
- * Inserting a Container is complicated by the fact that the container may have Views which
8496
- * themselves have containers or projections.
8497
- *
8498
- * @param renderer Renderer to use
8499
- * @param action action to perform (insert, detach, destroy)
8500
- * @param lContainer The LContainer which needs to be inserted, detached, destroyed.
8501
- * @param parentRElement parent DOM element for insertion/removal.
8502
- * @param beforeNode Before which node the insertions should happen.
8503
- */
8504
- function applyContainer(renderer, action, lContainer, parentRElement, beforeNode) {
8505
- ngDevMode && assertLContainer(lContainer);
8506
- const anchor = lContainer[NATIVE]; // LContainer has its own before node.
8507
- const native = unwrapRNode(lContainer);
8508
- // An LContainer can be created dynamically on any node by injecting ViewContainerRef.
8509
- // Asking for a ViewContainerRef on an element will result in a creation of a separate anchor
8510
- // node (comment in the DOM) that will be different from the LContainer's host node. In this
8511
- // particular case we need to execute action on 2 nodes:
8512
- // - container's host node (this is done in the executeActionOnElementOrContainer)
8513
- // - container's host node (this is done here)
8514
- if (anchor !== native) {
8515
- // This is very strange to me (Misko). I would expect that the native is same as anchor. I
8516
- // don't see a reason why they should be different, but they are.
8517
- //
8518
- // If they are we need to process the second anchor as well.
8519
- applyToElementOrContainer(action, renderer, parentRElement, anchor, beforeNode);
8578
+
8579
+ function createAndRenderEmbeddedLView(declarationLView, templateTNode, context, options) {
8580
+ const prevConsumer = setActiveConsumer(null);
8581
+ try {
8582
+ const embeddedTView = templateTNode.tView;
8583
+ ngDevMode && assertDefined(embeddedTView, 'TView must be defined for a template node.');
8584
+ ngDevMode && assertTNodeForLView(templateTNode, declarationLView);
8585
+ // Embedded views follow the change detection strategy of the view they're declared in.
8586
+ const isSignalView = declarationLView[FLAGS] & 4096 /* LViewFlags.SignalView */;
8587
+ const viewFlags = isSignalView ? 4096 /* LViewFlags.SignalView */ : 16 /* LViewFlags.CheckAlways */;
8588
+ const embeddedLView = createLView(declarationLView, embeddedTView, context, viewFlags, null, templateTNode, null, null, options?.injector ?? null, options?.embeddedViewInjector ?? null, options?.dehydratedView ?? null);
8589
+ const declarationLContainer = declarationLView[templateTNode.index];
8590
+ ngDevMode && assertLContainer(declarationLContainer);
8591
+ embeddedLView[DECLARATION_LCONTAINER] = declarationLContainer;
8592
+ const declarationViewLQueries = declarationLView[QUERIES];
8593
+ if (declarationViewLQueries !== null) {
8594
+ embeddedLView[QUERIES] = declarationViewLQueries.createEmbeddedView(embeddedTView);
8595
+ }
8596
+ // execute creation mode of a view
8597
+ renderView(embeddedTView, embeddedLView, context);
8598
+ return embeddedLView;
8520
8599
  }
8521
- for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
8522
- const lView = lContainer[i];
8523
- applyView(lView[TVIEW], lView, renderer, action, parentRElement, anchor);
8600
+ finally {
8601
+ setActiveConsumer(prevConsumer);
8524
8602
  }
8525
8603
  }
8526
8604
  /**
8527
- * Writes class/style to element.
8528
- *
8529
- * @param renderer Renderer to use.
8530
- * @param isClassBased `true` if it should be written to `class` (`false` to write to `style`)
8531
- * @param rNode The Node to write to.
8532
- * @param prop Property to write to. This would be the class/style name.
8533
- * @param value Value to write. If `null`/`undefined`/`false` this is considered a remove (set/add
8534
- * otherwise).
8605
+ * Returns whether an elements that belong to a view should be
8606
+ * inserted into the DOM. For client-only cases, DOM elements are
8607
+ * always inserted. For hydration cases, we check whether serialized
8608
+ * info is available for a view and the view is not in a "skip hydration"
8609
+ * block (in which case view contents was re-created, thus needing insertion).
8535
8610
  */
8536
- function applyStyling(renderer, isClassBased, rNode, prop, value) {
8537
- if (isClassBased) {
8538
- // We actually want JS true/false here because any truthy value should add the class
8539
- if (!value) {
8540
- renderer.removeClass(rNode, prop);
8541
- }
8542
- else {
8543
- renderer.addClass(rNode, prop);
8544
- }
8545
- }
8546
- else {
8547
- let flags = prop.indexOf('-') === -1 ? undefined : RendererStyleFlags2.DashCase;
8548
- if (value == null /** || value === undefined */) {
8549
- renderer.removeStyle(rNode, prop, flags);
8550
- }
8551
- else {
8552
- // A value is important if it ends with `!important`. The style
8553
- // parser strips any semicolons at the end of the value.
8554
- const isImportant = typeof value === 'string' ? value.endsWith('!important') : false;
8555
- if (isImportant) {
8556
- // !important has to be stripped from the value for it to be valid.
8557
- value = value.slice(0, -10);
8558
- flags |= RendererStyleFlags2.Important;
8559
- }
8560
- renderer.setStyle(rNode, prop, value, flags);
8561
- }
8562
- }
8611
+ function shouldAddViewToDom(tNode, dehydratedView) {
8612
+ return (!dehydratedView || dehydratedView.firstChild === null || hasInSkipHydrationBlockFlag(tNode));
8563
8613
  }
8564
8614
 
8615
+ const USE_EXHAUSTIVE_CHECK_NO_CHANGES_DEFAULT = false;
8616
+ const UseExhaustiveCheckNoChanges = new InjectionToken(ngDevMode ? 'exhaustive checkNoChanges' : '');
8617
+
8565
8618
  function collectNativeNodes(tView, lView, tNode, result, isProjection = false) {
8566
8619
  while (tNode !== null) {
8567
8620
  // Let declarations don't have corresponding DOM nodes so we skip over them.
@@ -9100,7 +9153,7 @@ function detectChangesInView(lView, mode) {
9100
9153
  if (consumer) {
9101
9154
  consumer.dirty = false;
9102
9155
  }
9103
- lView[FLAGS] &= -9217;
9156
+ lView[FLAGS] &= ~(8192 /* LViewFlags.HasChildViewsToRefresh */ | 1024 /* LViewFlags.RefreshView */);
9104
9157
  if (shouldRefreshView) {
9105
9158
  refreshView(tView, lView, tView.template, lView[CONTEXT]);
9106
9159
  }
@@ -9296,7 +9349,7 @@ function detachView(lContainer, removeIndex) {
9296
9349
  viewToDetach[PARENT] = null;
9297
9350
  viewToDetach[NEXT] = null;
9298
9351
  // Unsets the attached flag
9299
- viewToDetach[FLAGS] &= -129 /* LViewFlags.Attached */;
9352
+ viewToDetach[FLAGS] &= ~128 /* LViewFlags.Attached */;
9300
9353
  }
9301
9354
  return viewToDetach;
9302
9355
  }
@@ -9544,7 +9597,7 @@ class ViewRef {
9544
9597
  * ```
9545
9598
  */
9546
9599
  detach() {
9547
- this._lView[FLAGS] &= -129 /* LViewFlags.Attached */;
9600
+ this._lView[FLAGS] &= ~128 /* LViewFlags.Attached */;
9548
9601
  }
9549
9602
  /**
9550
9603
  * Re-attaches a view to the change detection tree.
@@ -12669,11 +12722,12 @@ function assertNoDuplicateDirectives(directives) {
12669
12722
  }
12670
12723
  }
12671
12724
 
12672
- function elementStartFirstCreatePass(index, tView, lView, name, directiveMatcher, bindingsEnabled, attrsIndex, localRefsIndex) {
12725
+ function directiveHostFirstCreatePass(index, lView, type, name, directiveMatcher, bindingsEnabled, attrsIndex, localRefsIndex) {
12726
+ const tView = lView[TVIEW];
12673
12727
  ngDevMode && assertFirstCreatePass(tView);
12674
12728
  const tViewConsts = tView.consts;
12675
12729
  const attrs = getConstant(tViewConsts, attrsIndex);
12676
- const tNode = getOrCreateTNode(tView, index, 2 /* TNodeType.Element */, name, attrs);
12730
+ const tNode = getOrCreateTNode(tView, index, type, name, attrs);
12677
12731
  if (bindingsEnabled) {
12678
12732
  resolveDirectives(tView, lView, tNode, getConstant(tViewConsts, localRefsIndex), directiveMatcher);
12679
12733
  }
@@ -12690,7 +12744,7 @@ function elementStartFirstCreatePass(index, tView, lView, name, directiveMatcher
12690
12744
  }
12691
12745
  return tNode;
12692
12746
  }
12693
- function elementEndFirstCreatePass(tView, tNode) {
12747
+ function directiveHostEndFirstCreatePass(tView, tNode) {
12694
12748
  ngDevMode && assertFirstCreatePass(tView);
12695
12749
  registerPostOrderHooks(tView, tNode);
12696
12750
  if (isContentQueryHost(tNode)) {
@@ -13343,7 +13397,7 @@ class ComponentFactory extends ComponentFactory$1 {
13343
13397
  enterView(rootLView);
13344
13398
  let componentView = null;
13345
13399
  try {
13346
- const hostTNode = elementStartFirstCreatePass(HEADER_OFFSET, rootTView, rootLView, '#host', () => rootTView.directiveRegistry, true, 0);
13400
+ const hostTNode = directiveHostFirstCreatePass(HEADER_OFFSET, rootLView, 2 /* TNodeType.Element */, '#host', () => rootTView.directiveRegistry, true, 0);
13347
13401
  // ---- element instruction
13348
13402
  // TODO(crisbeto): in practice `hostElement` should always be defined, but there are some
13349
13403
  // tests where the renderer is mocked out and `undefined` is returned. We should update the
@@ -13355,7 +13409,7 @@ class ComponentFactory extends ComponentFactory$1 {
13355
13409
  // TODO(pk): this logic is similar to the instruction code where a node can have directives
13356
13410
  createDirectivesInstances(rootTView, rootLView, hostTNode);
13357
13411
  executeContentQueries(rootTView, hostTNode, rootLView);
13358
- elementEndFirstCreatePass(rootTView, hostTNode);
13412
+ directiveHostEndFirstCreatePass(rootTView, hostTNode);
13359
13413
  if (projectableNodes !== undefined) {
13360
13414
  projectNodes(hostTNode, this.ngContentSelectors, projectableNodes);
13361
13415
  }
@@ -13386,7 +13440,7 @@ class ComponentFactory extends ComponentFactory$1 {
13386
13440
  }
13387
13441
  function createRootTView(rootSelectorOrNode, componentDef, componentBindings, directives) {
13388
13442
  const tAttributes = rootSelectorOrNode
13389
- ? ['ng-version', '20.0.1']
13443
+ ? ['ng-version', '20.1.0-next.0']
13390
13444
  : // Extract attributes and classes from the first selector only to match VE behavior.
13391
13445
  extractAttrsAndClassesFromSelector(componentDef.selectors[0]);
13392
13446
  let creationBindings = null;
@@ -14957,8 +15011,8 @@ function ɵɵdefineComponent(componentDefinition) {
14957
15011
  }
14958
15012
  initFeatures(def);
14959
15013
  const dependencies = componentDefinition.dependencies;
14960
- def.directiveDefs = extractDefListOrFactory(dependencies, /* pipeDef */ false);
14961
- def.pipeDefs = extractDefListOrFactory(dependencies, /* pipeDef */ true);
15014
+ def.directiveDefs = extractDefListOrFactory(dependencies, extractDirectiveDef);
15015
+ def.pipeDefs = extractDefListOrFactory(dependencies, getPipeDef$1);
14962
15016
  def.id = getComponentId(def);
14963
15017
  return def;
14964
15018
  });
@@ -14966,9 +15020,6 @@ function ɵɵdefineComponent(componentDefinition) {
14966
15020
  function extractDirectiveDef(type) {
14967
15021
  return getComponentDef(type) || getDirectiveDef(type);
14968
15022
  }
14969
- function nonNull(value) {
14970
- return value !== null;
14971
- }
14972
15023
  /**
14973
15024
  * @codeGenApi
14974
15025
  */
@@ -15172,14 +15223,21 @@ function getNgDirectiveDef(directiveDefinition) {
15172
15223
  function initFeatures(definition) {
15173
15224
  definition.features?.forEach((fn) => fn(definition));
15174
15225
  }
15175
- function extractDefListOrFactory(dependencies, pipeDef) {
15226
+ function extractDefListOrFactory(dependencies, defExtractor) {
15176
15227
  if (!dependencies) {
15177
15228
  return null;
15178
15229
  }
15179
- const defExtractor = pipeDef ? getPipeDef$1 : extractDirectiveDef;
15180
- return () => (typeof dependencies === 'function' ? dependencies() : dependencies)
15181
- .map((dep) => defExtractor(dep))
15182
- .filter(nonNull);
15230
+ return () => {
15231
+ const resolvedDependencies = typeof dependencies === 'function' ? dependencies() : dependencies;
15232
+ const result = [];
15233
+ for (const dep of resolvedDependencies) {
15234
+ const definition = defExtractor(dep);
15235
+ if (definition !== null) {
15236
+ result.push(definition);
15237
+ }
15238
+ }
15239
+ return result;
15240
+ };
15183
15241
  }
15184
15242
  /**
15185
15243
  * A map that contains the generated component IDs and type.
@@ -15710,26 +15768,35 @@ function validateMappings(bindingType, def, hostDirectiveBindings) {
15710
15768
  }
15711
15769
  }
15712
15770
 
15713
- function templateFirstCreatePass(index, tView, lView, templateFn, decls, vars, tagName, attrs, localRefsIndex) {
15714
- ngDevMode && assertFirstCreatePass(tView);
15715
- const tViewConsts = tView.consts;
15716
- // TODO(pk): refactor getOrCreateTNode to have the "create" only version
15717
- const tNode = getOrCreateTNode(tView, index, 4 /* TNodeType.Container */, tagName || null, attrs || null);
15718
- if (getBindingsEnabled()) {
15719
- resolveDirectives(tView, lView, tNode, getConstant(tViewConsts, localRefsIndex), findDirectiveDefMatches);
15771
+ function templateCreate(tNode, declarationLView, declarationTView, index, templateFn, decls, vars, flags) {
15772
+ if (declarationTView.firstCreatePass) {
15773
+ // Merge the template attrs last so that they have the highest priority.
15774
+ tNode.mergedAttrs = mergeHostAttrs(tNode.mergedAttrs, tNode.attrs);
15775
+ const embeddedTView = (tNode.tView = createTView(2 /* TViewType.Embedded */, tNode, templateFn, decls, vars, declarationTView.directiveRegistry, declarationTView.pipeRegistry, null, declarationTView.schemas, declarationTView.consts, null /* ssrId */));
15776
+ if (declarationTView.queries !== null) {
15777
+ declarationTView.queries.template(declarationTView, tNode);
15778
+ embeddedTView.queries = declarationTView.queries.embeddedTView(tNode);
15779
+ }
15720
15780
  }
15721
- // Merge the template attrs last so that they have the highest priority.
15722
- tNode.mergedAttrs = mergeHostAttrs(tNode.mergedAttrs, tNode.attrs);
15723
- registerPostOrderHooks(tView, tNode);
15724
- const embeddedTView = (tNode.tView = createTView(2 /* TViewType.Embedded */, tNode, templateFn, decls, vars, tView.directiveRegistry, tView.pipeRegistry, null, tView.schemas, tViewConsts, null /* ssrId */));
15725
- if (tView.queries !== null) {
15726
- tView.queries.template(tView, tNode);
15727
- embeddedTView.queries = tView.queries.embeddedTView(tNode);
15781
+ if (flags) {
15782
+ tNode.flags |= flags;
15728
15783
  }
15729
- return tNode;
15784
+ setCurrentTNode(tNode, false);
15785
+ const comment = _locateOrCreateContainerAnchor(declarationTView, declarationLView, tNode, index);
15786
+ if (wasLastNodeCreated()) {
15787
+ appendChild(declarationTView, declarationLView, comment, tNode);
15788
+ }
15789
+ attachPatchData(comment, declarationLView);
15790
+ const lContainer = createLContainer(comment, declarationLView, comment, tNode);
15791
+ declarationLView[index + HEADER_OFFSET] = lContainer;
15792
+ addToEndOfViewTree(declarationLView, lContainer);
15793
+ // If hydration is enabled, looks up dehydrated views in the DOM
15794
+ // using hydration annotation info and stores those views on LContainer.
15795
+ // In client-only mode, this function is a noop.
15796
+ populateDehydratedViewsInLContainer(lContainer, tNode, declarationLView);
15730
15797
  }
15731
15798
  /**
15732
- * Creates an LContainer for an embedded view.
15799
+ * Declares a new template that can have directives on its host node.
15733
15800
  *
15734
15801
  * @param declarationLView LView in which the template was declared.
15735
15802
  * @param declarationTView TView in which the template wa declared.
@@ -15743,27 +15810,21 @@ function templateFirstCreatePass(index, tView, lView, templateFn, decls, vars, t
15743
15810
  * @param localRefExtractor A function which extracts local-refs values from the template.
15744
15811
  * Defaults to the current element associated with the local-ref.
15745
15812
  */
15746
- function declareTemplate(declarationLView, declarationTView, index, templateFn, decls, vars, tagName, attrs, flags, localRefsIndex, localRefExtractor) {
15813
+ function declareDirectiveHostTemplate(declarationLView, declarationTView, index, templateFn, decls, vars, tagName, attrs, flags, localRefsIndex, localRefExtractor) {
15747
15814
  const adjustedIndex = index + HEADER_OFFSET;
15748
- const tNode = declarationTView.firstCreatePass
15749
- ? templateFirstCreatePass(adjustedIndex, declarationTView, declarationLView, templateFn, decls, vars, tagName, attrs, localRefsIndex)
15750
- : declarationTView.data[adjustedIndex];
15751
- if (flags) {
15752
- tNode.flags |= flags;
15815
+ let tNode;
15816
+ if (declarationTView.firstCreatePass) {
15817
+ // TODO(pk): refactor getOrCreateTNode to have the "create" only version
15818
+ tNode = getOrCreateTNode(declarationTView, adjustedIndex, 4 /* TNodeType.Container */, tagName || null, attrs || null);
15819
+ if (getBindingsEnabled()) {
15820
+ resolveDirectives(declarationTView, declarationLView, tNode, getConstant(declarationTView.consts, localRefsIndex), findDirectiveDefMatches);
15821
+ }
15822
+ registerPostOrderHooks(declarationTView, tNode);
15753
15823
  }
15754
- setCurrentTNode(tNode, false);
15755
- const comment = _locateOrCreateContainerAnchor(declarationTView, declarationLView, tNode, index);
15756
- if (wasLastNodeCreated()) {
15757
- appendChild(declarationTView, declarationLView, comment, tNode);
15824
+ else {
15825
+ tNode = declarationTView.data[adjustedIndex];
15758
15826
  }
15759
- attachPatchData(comment, declarationLView);
15760
- const lContainer = createLContainer(comment, declarationLView, comment, tNode);
15761
- declarationLView[adjustedIndex] = lContainer;
15762
- addToEndOfViewTree(declarationLView, lContainer);
15763
- // If hydration is enabled, looks up dehydrated views in the DOM
15764
- // using hydration annotation info and stores those views on LContainer.
15765
- // In client-only mode, this function is a noop.
15766
- populateDehydratedViewsInLContainer(lContainer, tNode, declarationLView);
15827
+ templateCreate(tNode, declarationLView, declarationTView, index, templateFn, decls, vars, flags);
15767
15828
  if (isDirectiveHost(tNode)) {
15768
15829
  createDirectivesInstances(declarationTView, declarationLView, tNode);
15769
15830
  }
@@ -15772,6 +15833,32 @@ function declareTemplate(declarationLView, declarationTView, index, templateFn,
15772
15833
  }
15773
15834
  return tNode;
15774
15835
  }
15836
+ /**
15837
+ * Declares a new template that *cannot& have directives on its host node.
15838
+ *
15839
+ * @param declarationLView LView in which the template was declared.
15840
+ * @param declarationTView TView in which the template wa declared.
15841
+ * @param index The index of the container in the data array
15842
+ * @param templateFn Inline template
15843
+ * @param decls The number of nodes, local refs, and pipes for this template
15844
+ * @param vars The number of bindings for this template
15845
+ * @param tagName The name of the container element, if applicable
15846
+ * @param attrsIndex Index of template attributes in the `consts` array.
15847
+ * @param localRefs Index of the local references in the `consts` array.
15848
+ * @param localRefExtractor A function which extracts local-refs values from the template.
15849
+ * Defaults to the current element associated with the local-ref.
15850
+ */
15851
+ function declareNoDirectiveHostTemplate(declarationLView, declarationTView, index, templateFn, decls, vars, tagName, attrs, flags, localRefsIndex, localRefExtractor) {
15852
+ const adjustedIndex = index + HEADER_OFFSET;
15853
+ const tNode = declarationTView.firstCreatePass
15854
+ ? getOrCreateTNode(declarationTView, adjustedIndex, 4 /* TNodeType.Container */, tagName || null, attrs || null)
15855
+ : declarationTView.data[adjustedIndex];
15856
+ templateCreate(tNode, declarationLView, declarationTView, index, templateFn, decls, vars, flags);
15857
+ if (localRefsIndex != null) {
15858
+ saveResolvedLocalsInData(declarationLView, tNode, localRefExtractor);
15859
+ }
15860
+ return tNode;
15861
+ }
15775
15862
  /**
15776
15863
  * Creates an LContainer for an ng-template (dynamically-inserted view), e.g.
15777
15864
  *
@@ -15795,7 +15882,7 @@ function ɵɵtemplate(index, templateFn, decls, vars, tagName, attrsIndex, local
15795
15882
  const lView = getLView();
15796
15883
  const tView = getTView();
15797
15884
  const attrs = getConstant(tView.consts, attrsIndex);
15798
- declareTemplate(lView, tView, index, templateFn, decls, vars, tagName, attrs, undefined, localRefsIndex, localRefExtractor);
15885
+ declareDirectiveHostTemplate(lView, tView, index, templateFn, decls, vars, tagName, attrs, undefined, localRefsIndex, localRefExtractor);
15799
15886
  return ɵɵtemplate;
15800
15887
  }
15801
15888
  let _locateOrCreateContainerAnchor = createContainerAnchorImpl;
@@ -15812,16 +15899,13 @@ function createContainerAnchorImpl(tView, lView, tNode, index) {
15812
15899
  * anchor (comment) nodes.
15813
15900
  */
15814
15901
  function locateOrCreateContainerAnchorImpl(tView, lView, tNode, index) {
15815
- const hydrationInfo = lView[HYDRATION];
15816
- const isNodeCreationMode = !hydrationInfo ||
15817
- isInSkipHydrationBlock$1() ||
15818
- isDetachedByI18n(tNode) ||
15819
- isDisconnectedNode$1(hydrationInfo, index);
15902
+ const isNodeCreationMode = !canHydrateNode(lView, tNode);
15820
15903
  lastNodeWasCreated(isNodeCreationMode);
15821
15904
  // Regular creation mode.
15822
15905
  if (isNodeCreationMode) {
15823
15906
  return createContainerAnchorImpl(tView, lView);
15824
15907
  }
15908
+ const hydrationInfo = lView[HYDRATION];
15825
15909
  const ssrId = hydrationInfo.data[TEMPLATES]?.[index] ?? null;
15826
15910
  // Apply `ssrId` value to the underlying TView if it was not previously set.
15827
15911
  //
@@ -18811,9 +18895,6 @@ function isComputedNode(node) {
18811
18895
  function isTemplateEffectNode(node) {
18812
18896
  return node.kind === 'template';
18813
18897
  }
18814
- function isEffectNode(node) {
18815
- return node.kind === 'effect';
18816
- }
18817
18898
  function isSignalNode(node) {
18818
18899
  return node.kind === 'signal';
18819
18900
  }
@@ -18833,36 +18914,54 @@ function getTemplateConsumer(injector) {
18833
18914
  }
18834
18915
  return null;
18835
18916
  }
18917
+ const signalDebugMap = new WeakMap();
18918
+ let counter$1 = 0;
18836
18919
  function getNodesAndEdgesFromSignalMap(signalMap) {
18837
18920
  const nodes = Array.from(signalMap.keys());
18838
18921
  const debugSignalGraphNodes = [];
18839
18922
  const edges = [];
18840
18923
  for (const [consumer, producers] of signalMap.entries()) {
18841
18924
  const consumerIndex = nodes.indexOf(consumer);
18925
+ let id = signalDebugMap.get(consumer);
18926
+ if (!id) {
18927
+ counter$1++;
18928
+ id = counter$1.toString();
18929
+ signalDebugMap.set(consumer, id);
18930
+ }
18842
18931
  // collect node
18843
- if (isComputedNode(consumer) || isSignalNode(consumer)) {
18932
+ if (isComputedNode(consumer)) {
18844
18933
  debugSignalGraphNodes.push({
18845
18934
  label: consumer.debugName,
18846
18935
  value: consumer.value,
18847
18936
  kind: consumer.kind,
18937
+ epoch: consumer.version,
18938
+ debuggableFn: consumer.computation,
18939
+ id,
18848
18940
  });
18849
18941
  }
18850
- else if (isTemplateEffectNode(consumer)) {
18942
+ else if (isSignalNode(consumer)) {
18851
18943
  debugSignalGraphNodes.push({
18852
- label: consumer.debugName ?? consumer.lView?.[HOST]?.tagName?.toLowerCase?.(),
18944
+ label: consumer.debugName,
18945
+ value: consumer.value,
18853
18946
  kind: consumer.kind,
18947
+ epoch: consumer.version,
18948
+ id,
18854
18949
  });
18855
18950
  }
18856
- else if (isEffectNode(consumer)) {
18951
+ else if (isTemplateEffectNode(consumer)) {
18857
18952
  debugSignalGraphNodes.push({
18858
- label: consumer.debugName,
18953
+ label: consumer.debugName ?? consumer.lView?.[HOST]?.tagName?.toLowerCase?.(),
18859
18954
  kind: consumer.kind,
18955
+ epoch: consumer.version,
18956
+ id,
18860
18957
  });
18861
18958
  }
18862
18959
  else {
18863
18960
  debugSignalGraphNodes.push({
18864
18961
  label: consumer.debugName,
18865
18962
  kind: consumer.kind,
18963
+ epoch: consumer.version,
18964
+ id,
18866
18965
  });
18867
18966
  }
18868
18967
  // collect edges for node
@@ -20079,7 +20178,7 @@ class ApplicationRef {
20079
20178
  synchronizeOnce() {
20080
20179
  // First, process any dirty root effects.
20081
20180
  if (this.dirtyFlags & 16 /* ApplicationRefDirtyFlags.RootEffects */) {
20082
- this.dirtyFlags &= -17 /* ApplicationRefDirtyFlags.RootEffects */;
20181
+ this.dirtyFlags &= ~16 /* ApplicationRefDirtyFlags.RootEffects */;
20083
20182
  this.rootEffectScheduler.flush();
20084
20183
  }
20085
20184
  // First check dirty views, if there are any.
@@ -20090,7 +20189,7 @@ class ApplicationRef {
20090
20189
  // `ApplicationRef.tick()` and the `NgZone` integration.
20091
20190
  const useGlobalCheck = Boolean(this.dirtyFlags & 1 /* ApplicationRefDirtyFlags.ViewTreeGlobal */);
20092
20191
  // Clear the view-related dirty flags.
20093
- this.dirtyFlags &= -8 /* ApplicationRefDirtyFlags.ViewTreeAny */;
20192
+ this.dirtyFlags &= ~7 /* ApplicationRefDirtyFlags.ViewTreeAny */;
20094
20193
  // Set the AfterRender bit, as we're checking views and will need to run afterRender hooks.
20095
20194
  this.dirtyFlags |= 8 /* ApplicationRefDirtyFlags.AfterRender */;
20096
20195
  // Check all potentially dirty views.
@@ -20110,7 +20209,7 @@ class ApplicationRef {
20110
20209
  // If `markForCheck()` was called during view checking, it will have set the `ViewTreeCheck`
20111
20210
  // flag. We clear the flag here because, for backwards compatibility, `markForCheck()`
20112
20211
  // during view checking doesn't cause the view to be re-checked.
20113
- this.dirtyFlags &= -5 /* ApplicationRefDirtyFlags.ViewTreeCheck */;
20212
+ this.dirtyFlags &= ~4 /* ApplicationRefDirtyFlags.ViewTreeCheck */;
20114
20213
  // Check if any views are still dirty after checking and we need to loop back.
20115
20214
  this.syncDirtyFlagsWithViews();
20116
20215
  if (this.dirtyFlags &
@@ -20128,7 +20227,7 @@ class ApplicationRef {
20128
20227
  }
20129
20228
  // Even if there were no dirty views, afterRender hooks might still be dirty.
20130
20229
  if (this.dirtyFlags & 8 /* ApplicationRefDirtyFlags.AfterRender */) {
20131
- this.dirtyFlags &= -9 /* ApplicationRefDirtyFlags.AfterRender */;
20230
+ this.dirtyFlags &= ~8 /* ApplicationRefDirtyFlags.AfterRender */;
20132
20231
  this.afterRenderManager.execute();
20133
20232
  // afterRender hooks might influence dirty flags.
20134
20233
  }
@@ -20157,7 +20256,7 @@ class ApplicationRef {
20157
20256
  else {
20158
20257
  // Even though this flag may be set, none of _our_ views require traversal, and so the
20159
20258
  // `ApplicationRef` doesn't require any repeated checking.
20160
- this.dirtyFlags &= -8 /* ApplicationRefDirtyFlags.ViewTreeAny */;
20259
+ this.dirtyFlags &= ~7 /* ApplicationRefDirtyFlags.ViewTreeAny */;
20161
20260
  }
20162
20261
  }
20163
20262
  /**
@@ -20836,7 +20935,7 @@ function ɵɵdefer(index, primaryTmplIndex, dependencyResolverFn, loadingTmplInd
20836
20935
  const lView = getLView();
20837
20936
  const tView = getTView();
20838
20937
  const adjustedIndex = index + HEADER_OFFSET;
20839
- const tNode = declareTemplate(lView, tView, index, null, 0, 0);
20938
+ const tNode = declareNoDirectiveHostTemplate(lView, tView, index, null, 0, 0);
20840
20939
  const injector = lView[INJECTOR];
20841
20940
  if (tView.firstCreatePass) {
20842
20941
  performanceMarkFeature('NgDefer');
@@ -21801,7 +21900,7 @@ function ɵɵconditionalCreate(index, templateFn, decls, vars, tagName, attrsInd
21801
21900
  const lView = getLView();
21802
21901
  const tView = getTView();
21803
21902
  const attrs = getConstant(tView.consts, attrsIndex);
21804
- declareTemplate(lView, tView, index, templateFn, decls, vars, tagName, attrs, 256 /* TNodeFlags.isControlFlowStart */, localRefsIndex, localRefExtractor);
21903
+ declareNoDirectiveHostTemplate(lView, tView, index, templateFn, decls, vars, tagName, attrs, 256 /* TNodeFlags.isControlFlowStart */, localRefsIndex, localRefExtractor);
21805
21904
  return ɵɵconditionalBranchCreate;
21806
21905
  }
21807
21906
  /**
@@ -21827,7 +21926,7 @@ function ɵɵconditionalBranchCreate(index, templateFn, decls, vars, tagName, at
21827
21926
  const lView = getLView();
21828
21927
  const tView = getTView();
21829
21928
  const attrs = getConstant(tView.consts, attrsIndex);
21830
- declareTemplate(lView, tView, index, templateFn, decls, vars, tagName, attrs, 512 /* TNodeFlags.isInControlFlow */, localRefsIndex, localRefExtractor);
21929
+ declareNoDirectiveHostTemplate(lView, tView, index, templateFn, decls, vars, tagName, attrs, 512 /* TNodeFlags.isInControlFlow */, localRefsIndex, localRefExtractor);
21831
21930
  return ɵɵconditionalBranchCreate;
21832
21931
  }
21833
21932
  /**
@@ -21968,13 +22067,13 @@ function ɵɵrepeaterCreate(index, templateFn, decls, vars, tagName, attrsIndex,
21968
22067
  : trackByFn;
21969
22068
  const metadata = new RepeaterMetadata(hasEmptyBlock, boundTrackBy);
21970
22069
  hostLView[HEADER_OFFSET + index] = metadata;
21971
- declareTemplate(lView, tView, index + 1, templateFn, decls, vars, tagName, getConstant(tView.consts, attrsIndex), 256 /* TNodeFlags.isControlFlowStart */);
22070
+ declareNoDirectiveHostTemplate(lView, tView, index + 1, templateFn, decls, vars, tagName, getConstant(tView.consts, attrsIndex), 256 /* TNodeFlags.isControlFlowStart */);
21972
22071
  if (hasEmptyBlock) {
21973
22072
  ngDevMode &&
21974
22073
  assertDefined(emptyDecls, 'Missing number of declarations for the empty repeater block.');
21975
22074
  ngDevMode &&
21976
22075
  assertDefined(emptyVars, 'Missing number of bindings for the empty repeater block.');
21977
- declareTemplate(lView, tView, index + 2, emptyTemplateFn, emptyDecls, emptyVars, emptyTagName, getConstant(tView.consts, emptyAttrsIndex), 512 /* TNodeFlags.isInControlFlow */);
22076
+ declareNoDirectiveHostTemplate(lView, tView, index + 2, emptyTemplateFn, emptyDecls, emptyVars, emptyTagName, getConstant(tView.consts, emptyAttrsIndex), 512 /* TNodeFlags.isInControlFlow */);
21978
22077
  }
21979
22078
  }
21980
22079
  function isViewExpensiveToRecreate(lView) {
@@ -22211,42 +22310,24 @@ function setDirectiveInputsWhichShadowsStyling(tView, tNode, lView, value, isCla
22211
22310
  */
22212
22311
  function ɵɵelementStart(index, name, attrsIndex, localRefsIndex) {
22213
22312
  const lView = getLView();
22214
- const tView = getTView();
22215
- const adjustedIndex = HEADER_OFFSET + index;
22216
- ngDevMode &&
22217
- assertEqual(getBindingIndex(), tView.bindingStartIndex, 'elements should be created before any bindings');
22218
- ngDevMode && assertIndexInRange(lView, adjustedIndex);
22219
- const renderer = lView[RENDERER];
22313
+ ngDevMode && assertTNodeCreationIndex(lView, index);
22314
+ const tView = lView[TVIEW];
22315
+ const adjustedIndex = index + HEADER_OFFSET;
22220
22316
  const tNode = tView.firstCreatePass
22221
- ? elementStartFirstCreatePass(adjustedIndex, tView, lView, name, findDirectiveDefMatches, getBindingsEnabled(), attrsIndex, localRefsIndex)
22317
+ ? directiveHostFirstCreatePass(adjustedIndex, lView, 2 /* TNodeType.Element */, name, findDirectiveDefMatches, getBindingsEnabled(), attrsIndex, localRefsIndex)
22222
22318
  : tView.data[adjustedIndex];
22223
- const native = _locateOrCreateElementNode(tView, lView, tNode, renderer, name, index);
22224
- lView[adjustedIndex] = native;
22225
- const hasDirectives = isDirectiveHost(tNode);
22226
- if (ngDevMode && tView.firstCreatePass) {
22227
- validateElementIsKnown(native, lView, tNode.value, tView.schemas, hasDirectives);
22228
- }
22229
- setCurrentTNode(tNode, true);
22230
- setupStaticAttributes(renderer, native, tNode);
22231
- if (!isDetachedByI18n(tNode) && wasLastNodeCreated()) {
22232
- // In the i18n case, the translation may have removed this element, so only add it if it is not
22233
- // detached. See `TNodeType.Placeholder` and `LFrame.inI18n` for more context.
22234
- appendChild(tView, lView, native, tNode);
22235
- }
22236
- // any immediate children of a component or template container must be pre-emptively
22237
- // monkey-patched with the component view data so that the element can be inspected
22238
- // later on using any element discovery utility methods (see `element_discovery.ts`)
22239
- if (getElementDepthCount() === 0 || hasDirectives) {
22240
- attachPatchData(native, lView);
22241
- }
22242
- increaseElementDepthCount();
22243
- if (hasDirectives) {
22319
+ elementLikeStartShared(tNode, lView, index, name, _locateOrCreateElementNode);
22320
+ if (isDirectiveHost(tNode)) {
22321
+ const tView = lView[TVIEW];
22244
22322
  createDirectivesInstances(tView, lView, tNode);
22245
22323
  executeContentQueries(tView, tNode, lView);
22246
22324
  }
22247
- if (localRefsIndex !== null) {
22325
+ if (localRefsIndex != null) {
22248
22326
  saveResolvedLocalsInData(lView, tNode);
22249
22327
  }
22328
+ if (ngDevMode && lView[TVIEW].firstCreatePass) {
22329
+ validateElementIsKnown(lView, tNode);
22330
+ }
22250
22331
  return ɵɵelementStart;
22251
22332
  }
22252
22333
  /**
@@ -22256,31 +22337,23 @@ function ɵɵelementStart(index, name, attrsIndex, localRefsIndex) {
22256
22337
  * @codeGenApi
22257
22338
  */
22258
22339
  function ɵɵelementEnd() {
22259
- let currentTNode = getCurrentTNode();
22260
- ngDevMode && assertDefined(currentTNode, 'No parent node to close.');
22261
- if (isCurrentTNodeParent()) {
22262
- setCurrentTNodeAsNotParent();
22263
- }
22264
- else {
22265
- ngDevMode && assertHasParent(getCurrentTNode());
22266
- currentTNode = currentTNode.parent;
22267
- setCurrentTNode(currentTNode, false);
22340
+ const tView = getTView();
22341
+ const initialTNode = getCurrentTNode();
22342
+ ngDevMode && assertDefined(initialTNode, 'No parent node to close.');
22343
+ const currentTNode = elementLikeEndShared(initialTNode);
22344
+ ngDevMode && assertTNodeType(currentTNode, 3 /* TNodeType.AnyRNode */);
22345
+ if (tView.firstCreatePass) {
22346
+ directiveHostEndFirstCreatePass(tView, currentTNode);
22268
22347
  }
22269
- const tNode = currentTNode;
22270
- ngDevMode && assertTNodeType(tNode, 3 /* TNodeType.AnyRNode */);
22271
- if (isSkipHydrationRootTNode(tNode)) {
22348
+ if (isSkipHydrationRootTNode(currentTNode)) {
22272
22349
  leaveSkipHydrationBlock();
22273
22350
  }
22274
22351
  decreaseElementDepthCount();
22275
- const tView = getTView();
22276
- if (tView.firstCreatePass) {
22277
- elementEndFirstCreatePass(tView, tNode);
22278
- }
22279
- if (tNode.classesWithoutHost != null && hasClassInput(tNode)) {
22280
- setDirectiveInputsWhichShadowsStyling(tView, tNode, getLView(), tNode.classesWithoutHost, true);
22352
+ if (currentTNode.classesWithoutHost != null && hasClassInput(currentTNode)) {
22353
+ setDirectiveInputsWhichShadowsStyling(tView, currentTNode, getLView(), currentTNode.classesWithoutHost, true);
22281
22354
  }
22282
- if (tNode.stylesWithoutHost != null && hasStyleInput(tNode)) {
22283
- setDirectiveInputsWhichShadowsStyling(tView, tNode, getLView(), tNode.stylesWithoutHost, false);
22355
+ if (currentTNode.stylesWithoutHost != null && hasStyleInput(currentTNode)) {
22356
+ setDirectiveInputsWhichShadowsStyling(tView, currentTNode, getLView(), currentTNode.stylesWithoutHost, false);
22284
22357
  }
22285
22358
  return ɵɵelementEnd;
22286
22359
  }
@@ -22300,26 +22373,23 @@ function ɵɵelement(index, name, attrsIndex, localRefsIndex) {
22300
22373
  ɵɵelementEnd();
22301
22374
  return ɵɵelement;
22302
22375
  }
22303
- let _locateOrCreateElementNode = (tView, lView, tNode, renderer, name, index) => {
22376
+ let _locateOrCreateElementNode = (tView, lView, tNode, name, index) => {
22304
22377
  lastNodeWasCreated(true);
22305
- return createElementNode(renderer, name, getNamespace());
22378
+ return createElementNode(lView[RENDERER], name, getNamespace());
22306
22379
  };
22307
22380
  /**
22308
22381
  * Enables hydration code path (to lookup existing elements in DOM)
22309
22382
  * in addition to the regular creation mode of element nodes.
22310
22383
  */
22311
- function locateOrCreateElementNodeImpl(tView, lView, tNode, renderer, name, index) {
22312
- const hydrationInfo = lView[HYDRATION];
22313
- const isNodeCreationMode = !hydrationInfo ||
22314
- isInSkipHydrationBlock$1() ||
22315
- isDetachedByI18n(tNode) ||
22316
- isDisconnectedNode$1(hydrationInfo, index);
22384
+ function locateOrCreateElementNodeImpl(tView, lView, tNode, name, index) {
22385
+ const isNodeCreationMode = !canHydrateNode(lView, tNode);
22317
22386
  lastNodeWasCreated(isNodeCreationMode);
22318
22387
  // Regular creation mode.
22319
22388
  if (isNodeCreationMode) {
22320
- return createElementNode(renderer, name, getNamespace());
22389
+ return createElementNode(lView[RENDERER], name, getNamespace());
22321
22390
  }
22322
22391
  // Hydration mode, looking up an existing element in DOM.
22392
+ const hydrationInfo = lView[HYDRATION];
22323
22393
  const native = locateNextRNode(hydrationInfo, tView, lView, tNode);
22324
22394
  ngDevMode && validateMatchingNode(native, Node.ELEMENT_NODE, name, lView, tNode);
22325
22395
  ngDevMode && markRNodeAsClaimedByHydration(native);
@@ -22359,26 +22429,6 @@ function enableLocateOrCreateElementNodeImpl() {
22359
22429
  _locateOrCreateElementNode = locateOrCreateElementNodeImpl;
22360
22430
  }
22361
22431
 
22362
- function elementContainerStartFirstCreatePass(index, tView, lView, attrsIndex, localRefsIndex) {
22363
- const tViewConsts = tView.consts;
22364
- const attrs = getConstant(tViewConsts, attrsIndex);
22365
- const tNode = getOrCreateTNode(tView, index, 8 /* TNodeType.ElementContainer */, 'ng-container', attrs);
22366
- // While ng-container doesn't necessarily support styling, we use the style context to identify
22367
- // and execute directives on the ng-container.
22368
- if (attrs !== null) {
22369
- computeStaticStyling(tNode, attrs, true);
22370
- }
22371
- const localRefs = getConstant(tViewConsts, localRefsIndex);
22372
- if (getBindingsEnabled()) {
22373
- resolveDirectives(tView, lView, tNode, localRefs, findDirectiveDefMatches);
22374
- }
22375
- // Merge the template attrs last so that they have the highest priority.
22376
- tNode.mergedAttrs = mergeHostAttrs(tNode.mergedAttrs, tNode.attrs);
22377
- if (tView.queries !== null) {
22378
- tView.queries.elementStart(tView, tNode);
22379
- }
22380
- return tNode;
22381
- }
22382
22432
  /**
22383
22433
  * Creates a logical container for other nodes (<ng-container>) backed by a comment node in the DOM.
22384
22434
  * The instruction must later be followed by `elementContainerEnd()` call.
@@ -22396,22 +22446,15 @@ function elementContainerStartFirstCreatePass(index, tView, lView, attrsIndex, l
22396
22446
  */
22397
22447
  function ɵɵelementContainerStart(index, attrsIndex, localRefsIndex) {
22398
22448
  const lView = getLView();
22399
- const tView = getTView();
22449
+ ngDevMode && assertTNodeCreationIndex(lView, index);
22450
+ const tView = lView[TVIEW];
22400
22451
  const adjustedIndex = index + HEADER_OFFSET;
22401
- ngDevMode && assertIndexInRange(lView, adjustedIndex);
22402
- ngDevMode &&
22403
- assertEqual(getBindingIndex(), tView.bindingStartIndex, 'element containers should be created before any bindings');
22404
22452
  const tNode = tView.firstCreatePass
22405
- ? elementContainerStartFirstCreatePass(adjustedIndex, tView, lView, attrsIndex, localRefsIndex)
22453
+ ? directiveHostFirstCreatePass(adjustedIndex, lView, 8 /* TNodeType.ElementContainer */, 'ng-container', findDirectiveDefMatches, getBindingsEnabled(), attrsIndex, localRefsIndex)
22406
22454
  : tView.data[adjustedIndex];
22407
- setCurrentTNode(tNode, true);
22408
- const comment = _locateOrCreateElementContainerNode(tView, lView, tNode, index);
22409
- lView[adjustedIndex] = comment;
22410
- if (wasLastNodeCreated()) {
22411
- appendChild(tView, lView, comment, tNode);
22412
- }
22413
- attachPatchData(comment, lView);
22455
+ elementLikeStartShared(tNode, lView, index, 'ng-container', _locateOrCreateElementContainerNode);
22414
22456
  if (isDirectiveHost(tNode)) {
22457
+ const tView = lView[TVIEW];
22415
22458
  createDirectivesInstances(tView, lView, tNode);
22416
22459
  executeContentQueries(tView, tNode, lView);
22417
22460
  }
@@ -22427,23 +22470,14 @@ function ɵɵelementContainerStart(index, attrsIndex, localRefsIndex) {
22427
22470
  * @codeGenApi
22428
22471
  */
22429
22472
  function ɵɵelementContainerEnd() {
22430
- let currentTNode = getCurrentTNode();
22431
22473
  const tView = getTView();
22432
- if (isCurrentTNodeParent()) {
22433
- setCurrentTNodeAsNotParent();
22434
- }
22435
- else {
22436
- ngDevMode && assertHasParent(currentTNode);
22437
- currentTNode = currentTNode.parent;
22438
- setCurrentTNode(currentTNode, false);
22439
- }
22440
- ngDevMode && assertTNodeType(currentTNode, 8 /* TNodeType.ElementContainer */);
22474
+ const initialTNode = getCurrentTNode();
22475
+ ngDevMode && assertDefined(initialTNode, 'No parent node to close.');
22476
+ const currentTNode = elementLikeEndShared(initialTNode);
22441
22477
  if (tView.firstCreatePass) {
22442
- registerPostOrderHooks(tView, currentTNode);
22443
- if (isContentQueryHost(currentTNode)) {
22444
- tView.queries.elementEnd(currentTNode);
22445
- }
22478
+ directiveHostEndFirstCreatePass(tView, currentTNode);
22446
22479
  }
22480
+ ngDevMode && assertTNodeType(currentTNode, 8 /* TNodeType.ElementContainer */);
22447
22481
  return ɵɵelementContainerEnd;
22448
22482
  }
22449
22483
  /**
@@ -22462,28 +22496,25 @@ function ɵɵelementContainer(index, attrsIndex, localRefsIndex) {
22462
22496
  ɵɵelementContainerEnd();
22463
22497
  return ɵɵelementContainer;
22464
22498
  }
22465
- let _locateOrCreateElementContainerNode = (tView, lView, tNode, index) => {
22499
+ let _locateOrCreateElementContainerNode = (tView, lView, tNode, commentText, index) => {
22466
22500
  lastNodeWasCreated(true);
22467
- return createCommentNode(lView[RENDERER], ngDevMode ? 'ng-container' : '');
22501
+ return createCommentNode(lView[RENDERER], ngDevMode ? commentText : '');
22468
22502
  };
22469
22503
  /**
22470
22504
  * Enables hydration code path (to lookup existing elements in DOM)
22471
22505
  * in addition to the regular creation mode of comment nodes that
22472
22506
  * represent <ng-container>'s anchor.
22473
22507
  */
22474
- function locateOrCreateElementContainerNode(tView, lView, tNode, index) {
22508
+ function locateOrCreateElementContainerNode(tView, lView, tNode, commentText, index) {
22475
22509
  let comment;
22476
- const hydrationInfo = lView[HYDRATION];
22477
- const isNodeCreationMode = !hydrationInfo ||
22478
- isInSkipHydrationBlock$1() ||
22479
- isDisconnectedNode$1(hydrationInfo, index) ||
22480
- isDetachedByI18n(tNode);
22510
+ const isNodeCreationMode = !canHydrateNode(lView, tNode);
22481
22511
  lastNodeWasCreated(isNodeCreationMode);
22482
22512
  // Regular creation mode.
22483
22513
  if (isNodeCreationMode) {
22484
- return createCommentNode(lView[RENDERER], ngDevMode ? 'ng-container' : '');
22514
+ return createCommentNode(lView[RENDERER], ngDevMode ? commentText : '');
22485
22515
  }
22486
22516
  // Hydration mode, looking up existing elements in DOM.
22517
+ const hydrationInfo = lView[HYDRATION];
22487
22518
  const currentRNode = locateNextRNode(hydrationInfo, tView, lView, tNode);
22488
22519
  ngDevMode && validateNodeExists(currentRNode, lView, tNode);
22489
22520
  const ngContainerSize = getNgContainerSize(hydrationInfo, index);
@@ -24561,7 +24592,7 @@ function ɵɵprojection(nodeIndex, selectorIndex = 0, attrs, fallbackTemplateFn,
24561
24592
  // instances of the component may or may not insert it. Also it needs to be declare *before*
24562
24593
  // the projection node in order to work correctly with hydration.
24563
24594
  if (fallbackIndex !== null) {
24564
- declareTemplate(lView, tView, fallbackIndex, fallbackTemplateFn, fallbackDecls, fallbackVars, null, attrs);
24595
+ declareNoDirectiveHostTemplate(lView, tView, fallbackIndex, fallbackTemplateFn, fallbackDecls, fallbackVars, null, attrs);
24565
24596
  }
24566
24597
  const tProjectionNode = getOrCreateTNode(tView, HEADER_OFFSET + nodeIndex, 16 /* TNodeType.Projection */, null, attrs || null);
24567
24598
  // We can't use viewData[HOST_NODE] because projection nodes can be nested in embedded views.
@@ -24738,7 +24769,7 @@ function getTStylingRangePrevDuplicate(tStylingRange) {
24738
24769
  function setTStylingRangePrev(tStylingRange, previous) {
24739
24770
  ngDevMode && assertNumber(tStylingRange, 'expected number');
24740
24771
  ngDevMode && assertNumberInRange(previous, 0, 32767 /* StylingRange.UNSIGNED_MASK */);
24741
- return ((tStylingRange & 131071 /* StylingRange.PREV_MASK */) |
24772
+ return ((tStylingRange & ~4294836224 /* StylingRange.PREV_MASK */) |
24742
24773
  (previous << 17 /* StylingRange.PREV_SHIFT */));
24743
24774
  }
24744
24775
  function setTStylingRangePrevDuplicate(tStylingRange) {
@@ -24752,7 +24783,7 @@ function getTStylingRangeNext(tStylingRange) {
24752
24783
  function setTStylingRangeNext(tStylingRange, next) {
24753
24784
  ngDevMode && assertNumber(tStylingRange, 'expected number');
24754
24785
  ngDevMode && assertNumberInRange(next, 0, 32767 /* StylingRange.UNSIGNED_MASK */);
24755
- return ((tStylingRange & -131069 /* StylingRange.NEXT_MASK */) | //
24786
+ return ((tStylingRange & ~131068 /* StylingRange.NEXT_MASK */) | //
24756
24787
  (next << 2 /* StylingRange.NEXT_SHIFT */));
24757
24788
  }
24758
24789
  function getTStylingRangeNextDuplicate(tStylingRange) {
@@ -26080,9 +26111,7 @@ function ɵɵtext(index, value = '') {
26080
26111
  const lView = getLView();
26081
26112
  const tView = getTView();
26082
26113
  const adjustedIndex = index + HEADER_OFFSET;
26083
- ngDevMode &&
26084
- assertEqual(getBindingIndex(), tView.bindingStartIndex, 'text nodes should be created before any bindings');
26085
- ngDevMode && assertIndexInRange(lView, adjustedIndex);
26114
+ ngDevMode && assertTNodeCreationIndex(lView, index);
26086
26115
  const tNode = tView.firstCreatePass
26087
26116
  ? getOrCreateTNode(tView, adjustedIndex, 1 /* TNodeType.Text */, value, null)
26088
26117
  : tView.data[adjustedIndex];
@@ -26103,17 +26132,14 @@ let _locateOrCreateTextNode = (tView, lView, tNode, value, index) => {
26103
26132
  * in addition to the regular creation mode of text nodes.
26104
26133
  */
26105
26134
  function locateOrCreateTextNodeImpl(tView, lView, tNode, value, index) {
26106
- const hydrationInfo = lView[HYDRATION];
26107
- const isNodeCreationMode = !hydrationInfo ||
26108
- isInSkipHydrationBlock$1() ||
26109
- isDetachedByI18n(tNode) ||
26110
- isDisconnectedNode$1(hydrationInfo, index);
26135
+ const isNodeCreationMode = !canHydrateNode(lView, tNode);
26111
26136
  lastNodeWasCreated(isNodeCreationMode);
26112
26137
  // Regular creation mode.
26113
26138
  if (isNodeCreationMode) {
26114
26139
  return createTextNode(lView[RENDERER], value);
26115
26140
  }
26116
26141
  // Hydration mode, looking up an existing element in DOM.
26142
+ const hydrationInfo = lView[HYDRATION];
26117
26143
  const textNative = locateNextRNode(hydrationInfo, tView, lView, tNode);
26118
26144
  ngDevMode && validateMatchingNode(textNative, Node.TEXT_NODE, null, lView, tNode);
26119
26145
  ngDevMode && markRNodeAsClaimedByHydration(textNative);
@@ -27128,7 +27154,7 @@ function indexOf(item, arr, begin, end) {
27128
27154
  /**
27129
27155
  * Use this with `multi` `providers`.
27130
27156
  */
27131
- function multiProvidersFactoryResolver(_, tData, lData, tNode) {
27157
+ function multiProvidersFactoryResolver(_, flags, tData, lData, tNode) {
27132
27158
  return multiResolve(this.multi, []);
27133
27159
  }
27134
27160
  /**
@@ -27136,7 +27162,7 @@ function multiProvidersFactoryResolver(_, tData, lData, tNode) {
27136
27162
  *
27137
27163
  * This factory knows how to concatenate itself with the existing `multi` `providers`.
27138
27164
  */
27139
- function multiViewProvidersFactoryResolver(_, tData, lView, tNode) {
27165
+ function multiViewProvidersFactoryResolver(_, _flags, _tData, lView, tNode) {
27140
27166
  const factories = this.multi;
27141
27167
  let result;
27142
27168
  if (this.providerFactory) {
@@ -27261,8 +27287,8 @@ function ɵɵExternalStylesFeature(styleUrls) {
27261
27287
  */
27262
27288
  function ɵɵsetComponentScope(type, directives, pipes) {
27263
27289
  const def = type.ɵcmp;
27264
- def.directiveDefs = extractDefListOrFactory(directives, /* pipeDef */ false);
27265
- def.pipeDefs = extractDefListOrFactory(pipes, /* pipeDef */ true);
27290
+ def.directiveDefs = extractDefListOrFactory(directives, extractDirectiveDef);
27291
+ def.pipeDefs = extractDefListOrFactory(pipes, getPipeDef$1);
27266
27292
  }
27267
27293
  /**
27268
27294
  * Adds the module metadata that is necessary to compute the module's transitive scope to an
@@ -28170,7 +28196,7 @@ function resetProjectionState(tNode) {
28170
28196
  if (isTNodeShape(current)) {
28171
28197
  // Reset `projectionNext` since it can affect the traversal order during projection.
28172
28198
  current.projectionNext = null;
28173
- current.flags &= -3 /* TNodeFlags.isProjected */;
28199
+ current.flags &= ~2 /* TNodeFlags.isProjected */;
28174
28200
  }
28175
28201
  }
28176
28202
  tNode.projection = null;
@@ -30734,4 +30760,4 @@ function getDebugNode(nativeNode) {
30734
30760
  }
30735
30761
 
30736
30762
  export { AFTER_RENDER_PHASES, ANIMATION_MODULE_TYPE, APP_BOOTSTRAP_LISTENER, APP_ID, APP_INITIALIZER, AcxChangeDetectionStrategy, AcxViewEncapsulation, AfterRenderImpl, AfterRenderManager, AfterRenderSequence, ApplicationInitStatus, ApplicationRef, Attribute, COMPILER_OPTIONS, CONTAINERS, CSP_NONCE, CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionSchedulerImpl, ChangeDetectionStrategy, Compiler, CompilerFactory, Component, ComponentFactory, ComponentFactory$1, ComponentFactoryResolver$1 as ComponentFactoryResolver, ComponentRef$1 as ComponentRef, ComponentRef as ComponentRef$1, Console, DEFAULT_CURRENCY_CODE, DEFAULT_LOCALE_ID, DEFER_BLOCK_CONFIG, DEFER_BLOCK_DEPENDENCY_INTERCEPTOR, DEFER_BLOCK_ID, DEFER_BLOCK_SSR_ID_ATTRIBUTE, DEFER_BLOCK_STATE$1 as DEFER_BLOCK_STATE, DEFER_BLOCK_STATE as DEFER_BLOCK_STATE$1, DEFER_HYDRATE_TRIGGERS, DEFER_PARENT_BLOCK_ID, DEHYDRATED_BLOCK_REGISTRY, DISCONNECTED_NODES, DebugElement, DebugEventListener, DebugNode, DeferBlockBehavior, DeferBlockState, DehydratedBlockRegistry, Directive, ELEMENT_CONTAINERS, EVENT_REPLAY_ENABLED_DEFAULT, ElementRef, EnvironmentNgModuleRefAdapter, EventEmitter, Framework, Host, HostBinding, HostListener, HydrationStatus, I18N_DATA, IMAGE_CONFIG, IMAGE_CONFIG_DEFAULTS, IS_EVENT_REPLAY_ENABLED, IS_HYDRATION_DOM_REUSE_ENABLED, IS_I18N_HYDRATION_ENABLED, IS_INCREMENTAL_HYDRATION_ENABLED, Inject, Injectable, Input, JSACTION_BLOCK_ELEMENT_MAP, JSACTION_EVENT_CONTRACT, LContext, LOCALE_ID, LocaleDataIndex, MULTIPLIER, MissingTranslationStrategy, ModuleWithComponentFactories, NGH_ATTR_NAME, NGH_DATA_KEY, NGH_DEFER_BLOCKS_KEY, NODES, NOOP_AFTER_RENDER_REF, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR, NO_CHANGE, NO_ERRORS_SCHEMA, NUM_ROOT_NODES, NgModule, NgModuleFactory, NgModuleFactory$1, NgModuleRef, NgModuleRef$1, NgProbeToken, NgZone, NoopNgZone, Optional, Output, PACKAGE_ROOT_URL, PLATFORM_ID, PLATFORM_INITIALIZER, PRESERVE_HOST_CONTENT, PROVIDED_NG_ZONE, Pipe, QueryList, ReflectionCapabilities, Renderer2, RendererFactory2, RendererStyleFlags2, SKIP_HYDRATION_ATTR_NAME, SSR_CONTENT_INTEGRITY_MARKER, Sanitizer, SecurityContext, Self, SimpleChange, SkipSelf, TEMPLATES, TEMPLATE_ID, TESTABILITY, TESTABILITY_GETTER, TRANSLATIONS, TRANSLATIONS_FORMAT, TemplateRef, Testability, TestabilityRegistry, TimerScheduler, TracingAction, TracingService, TransferState, Type, UseExhaustiveCheckNoChanges, ViewContainerRef, ViewEncapsulation, ViewRef, _sanitizeHtml, _sanitizeUrl, afterEveryRender, afterNextRender, allowSanitizationBypassAndThrow, angularCoreEnv, appendDeferBlocksToJSActionMap, asNativeElements, assertComponentDef, assertStandaloneComponentType, bypassSanitizationTrustHtml, bypassSanitizationTrustResourceUrl, bypassSanitizationTrustScript, bypassSanitizationTrustStyle, bypassSanitizationTrustUrl, calcPathForNode, checkNoChangesInternal, cleanupDehydratedViews, clearResolutionOfComponentResourcesQueue, collectNativeNodes, collectNativeNodesInLContainer, compileComponent, compileDirective, compileNgModule, compileNgModuleDefs, compilePipe, convertHydrateTriggersToJsAction, countBlocksSkippedByHydration, createEnvironmentInjector, createMultiResultQuerySignalFn, createNgModule, createNgModuleRef, createNgModuleRefWithProviders, createSingleResultOptionalQuerySignalFn, createSingleResultRequiredQuerySignalFn, depsTracker, devModeEqual, enableApplyRootElementTransformImpl, enableClaimDehydratedIcuCaseImpl, enableFindMatchingDehydratedViewImpl, enableLocateOrCreateContainerAnchorImpl, enableLocateOrCreateContainerRefImpl, enableLocateOrCreateElementContainerNodeImpl, enableLocateOrCreateElementNodeImpl, enableLocateOrCreateI18nNodeImpl, enableLocateOrCreateTextNodeImpl, enablePrepareI18nBlockForHydrationImpl, enableProfiling, enableRetrieveDeferBlockDataImpl, enableRetrieveHydrationInfoImpl, enableStashEventListenerImpl, findLocaleData, flushModuleScopingQueueAsMuchAsPossible, gatherDeferBlocksCommentNodes, generateStandaloneInDeclarationsError, getAsyncClassMetadataFn, getCompilerFacade, getDebugNode, getDeferBlocks$1 as getDeferBlocks, getDirectives, getDocument, getHostElement, getLContext, getLDeferBlockDetails, getLNodeForHydration, getLocaleCurrencyCode, getLocalePluralCase, getNgZone, getNgZoneOptions, getOrComputeI18nChildren, getRegisteredNgModuleType, getSanitizationBypassType, getTDeferBlockDetails, inputBinding, internalProvideZoneChangeDetection, invokeListeners, isBoundToModule, isComponentDefPendingResolution, isComponentResourceResolutionQueueEmpty, isDeferBlock, isDetachedByI18n, isDisconnectedNode, isI18nHydrationEnabled, isI18nHydrationSupportEnabled, isInSkipHydrationBlock, isIncrementalHydrationEnabled, isJsObject, isLetDeclaration, isListLikeIterable, isNgModule, isPromise, isSubscribable, isTNodeShape, isViewDirty, iterateListLike, makePropDecorator, makeStateKey, markForRefresh, noSideEffects, optionsReducer, outputBinding, patchComponentDefWithScope, performanceMarkFeature, processAndInitTriggers, processBlockData, processTextNodeBeforeSerialization, profiler, provideAppInitializer, provideNgReflectAttributes, provideZoneChangeDetection, provideZonelessChangeDetection, publishDefaultGlobalUtils, publishExternalGlobalUtil, publishSignalConfiguration, readHydrationInfo, readPatchedLView, registerLocaleData, registerNgModuleType, remove, removeListeners, renderDeferBlockState, resetCompiledComponents, resetJitOptions, resolveComponentResources, restoreComponentResolutionQueue, setAllowDuplicateNgModuleIdsForTest, setClassMetadata, setClassMetadataAsync, setDocument, setIsI18nHydrationSupportEnabled, setJSActionAttributes, setJitOptions, setLocaleId, setStashFn, setTestabilityGetter, sharedMapFunction, sharedStashFunction, transitiveScopesFor, triggerHydrationFromBlockName, triggerResourceLoading, trySerializeI18nBlock, twoWayBinding, unregisterAllLocaleData, unsupportedProjectionOfDomNodes, unwrapSafeValue, validateMatchingNode, validateNodeExists, verifySsrContentsIntegrity, ɵgetUnknownElementStrictMode, ɵgetUnknownPropertyStrictMode, ɵsetClassDebugInfo, ɵsetUnknownElementStrictMode, ɵsetUnknownPropertyStrictMode, ɵɵCopyDefinitionFeature, ɵɵExternalStylesFeature, ɵɵHostDirectivesFeature, ɵɵInheritDefinitionFeature, ɵɵNgOnChangesFeature, ɵɵProvidersFeature, ɵɵadvance, ɵɵattachSourceLocations, ɵɵattribute, ɵɵclassMap, ɵɵclassProp, ɵɵcomponentInstance, ɵɵconditional, ɵɵconditionalBranchCreate, ɵɵconditionalCreate, ɵɵcontentQuery, ɵɵcontentQuerySignal, ɵɵdeclareLet, ɵɵdefer, ɵɵdeferEnableTimerScheduling, ɵɵdeferHydrateNever, ɵɵdeferHydrateOnHover, ɵɵdeferHydrateOnIdle, ɵɵdeferHydrateOnImmediate, ɵɵdeferHydrateOnInteraction, ɵɵdeferHydrateOnTimer, ɵɵdeferHydrateOnViewport, ɵɵdeferHydrateWhen, ɵɵdeferOnHover, ɵɵdeferOnIdle, ɵɵdeferOnImmediate, ɵɵdeferOnInteraction, ɵɵdeferOnTimer, ɵɵdeferOnViewport, ɵɵdeferPrefetchOnHover, ɵɵdeferPrefetchOnIdle, ɵɵdeferPrefetchOnImmediate, ɵɵdeferPrefetchOnInteraction, ɵɵdeferPrefetchOnTimer, ɵɵdeferPrefetchOnViewport, ɵɵdeferPrefetchWhen, ɵɵdeferWhen, ɵɵdefineComponent, ɵɵdefineDirective, ɵɵdefineNgModule, ɵɵdefinePipe, ɵɵdirectiveInject, ɵɵdomProperty, ɵɵelement, ɵɵelementContainer, ɵɵelementContainerEnd, ɵɵelementContainerStart, ɵɵelementEnd, ɵɵelementStart, ɵɵgetComponentDepsFactory, ɵɵgetCurrentView, ɵɵgetInheritedFactory, ɵɵgetReplaceMetadataURL, ɵɵi18n, ɵɵi18nApply, ɵɵi18nAttributes, ɵɵi18nEnd, ɵɵi18nExp, ɵɵi18nPostprocess, ɵɵi18nStart, ɵɵinjectAttribute, ɵɵinterpolate, ɵɵinterpolate1, ɵɵinterpolate2, ɵɵinterpolate3, ɵɵinterpolate4, ɵɵinterpolate5, ɵɵinterpolate6, ɵɵinterpolate7, ɵɵinterpolate8, ɵɵinterpolateV, ɵɵinvalidFactory, ɵɵlistener, ɵɵloadQuery, ɵɵnextContext, ɵɵpipe, ɵɵpipeBind1, ɵɵpipeBind2, ɵɵpipeBind3, ɵɵpipeBind4, ɵɵpipeBindV, ɵɵprojection, ɵɵprojectionDef, ɵɵproperty, ɵɵpureFunction0, ɵɵpureFunction1, ɵɵpureFunction2, ɵɵpureFunction3, ɵɵpureFunction4, ɵɵpureFunction5, ɵɵpureFunction6, ɵɵpureFunction7, ɵɵpureFunction8, ɵɵpureFunctionV, ɵɵqueryAdvance, ɵɵqueryRefresh, ɵɵreadContextLet, ɵɵreference, ɵɵrepeater, ɵɵrepeaterCreate, ɵɵrepeaterTrackByIdentity, ɵɵrepeaterTrackByIndex, ɵɵreplaceMetadata, ɵɵresolveBody, ɵɵresolveDocument, ɵɵresolveWindow, ɵɵsanitizeHtml, ɵɵsanitizeResourceUrl, ɵɵsanitizeScript, ɵɵsanitizeStyle, ɵɵsanitizeUrl, ɵɵsanitizeUrlOrResourceUrl, ɵɵsetComponentScope, ɵɵsetNgModuleScope, ɵɵstoreLet, ɵɵstyleMap, ɵɵstyleProp, ɵɵsyntheticHostListener, ɵɵsyntheticHostProperty, ɵɵtemplate, ɵɵtemplateRefExtractor, ɵɵtext, ɵɵtextInterpolate, ɵɵtextInterpolate1, ɵɵtextInterpolate2, ɵɵtextInterpolate3, ɵɵtextInterpolate4, ɵɵtextInterpolate5, ɵɵtextInterpolate6, ɵɵtextInterpolate7, ɵɵtextInterpolate8, ɵɵtextInterpolateV, ɵɵtrustConstantHtml, ɵɵtrustConstantResourceUrl, ɵɵtwoWayBindingSet, ɵɵtwoWayListener, ɵɵtwoWayProperty, ɵɵvalidateIframeAttribute, ɵɵviewQuery, ɵɵviewQuerySignal };
30737
- //# sourceMappingURL=debug_node-B9JawCEy.mjs.map
30763
+ //# sourceMappingURL=debug_node-CjNGi9N3.mjs.map