@angular/core 20.0.0 → 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.
- package/{api.d-B0vztftH.d.ts → api.d-Dwpmmn5j.d.ts} +2 -2
- package/{chrome_dev_tools_performance.d-DvzAxqBc.d.ts → chrome_dev_tools_performance.d-Dk_7kdX9.d.ts} +5 -1
- package/{discovery.d-DZNIp-Fw.d.ts → discovery.d-BAZTj_rM.d.ts} +9 -10
- package/event_dispatcher.d-BReQpZfC.d.ts +1 -1
- package/fesm2022/attribute-BWp59EjE.mjs +1 -1
- package/fesm2022/attribute-BWp59EjE.mjs.map +1 -1
- package/fesm2022/core.mjs +15 -14
- package/fesm2022/core.mjs.map +1 -1
- package/fesm2022/{debug_node-Dn-GvQJo.mjs → debug_node-CjNGi9N3.mjs} +1510 -1474
- package/fesm2022/debug_node-CjNGi9N3.mjs.map +1 -0
- package/fesm2022/primitives/di.mjs +1 -1
- package/fesm2022/primitives/di.mjs.map +1 -1
- package/fesm2022/primitives/event-dispatch.mjs +93 -2
- package/fesm2022/primitives/event-dispatch.mjs.map +1 -1
- package/fesm2022/primitives/signals.mjs +4 -4
- package/fesm2022/primitives/signals.mjs.map +1 -1
- package/fesm2022/{resource-BPCh38bN.mjs → resource-1o9xbJml.mjs} +8 -6
- package/fesm2022/resource-1o9xbJml.mjs.map +1 -0
- package/fesm2022/{root_effect_scheduler-0BxwqIgm.mjs → root_effect_scheduler-Ds-Wmkv_.mjs} +33 -20
- package/fesm2022/root_effect_scheduler-Ds-Wmkv_.mjs.map +1 -0
- package/fesm2022/rxjs-interop.mjs +12 -7
- package/fesm2022/rxjs-interop.mjs.map +1 -1
- package/fesm2022/{signal-ePSl6jXn.mjs → signal-BZ1SD--i.mjs} +8 -9
- package/fesm2022/{signal-ePSl6jXn.mjs.map → signal-BZ1SD--i.mjs.map} +1 -1
- package/fesm2022/testing.mjs +23 -33
- package/fesm2022/testing.mjs.map +1 -1
- package/fesm2022/{untracked-2ouAFbCz.mjs → untracked-C72kieeB.mjs} +3 -3
- package/fesm2022/{untracked-2ouAFbCz.mjs.map → untracked-C72kieeB.mjs.map} +1 -1
- package/fesm2022/weak_ref-BaIq-pgY.mjs +1 -1
- package/fesm2022/weak_ref-BaIq-pgY.mjs.map +1 -1
- package/graph.d-BcIOep_B.d.ts +1 -1
- package/index.d.ts +26 -18
- package/package.json +2 -2
- package/primitives/di/index.d.ts +1 -1
- package/primitives/event-dispatch/index.d.ts +1 -1
- package/primitives/signals/index.d.ts +3 -3
- package/rxjs-interop/index.d.ts +3 -3
- package/schematics/bundles/{apply_import_manager-Bqnvtho4.cjs → apply_import_manager-CSEu0fby.cjs} +3 -3
- package/schematics/bundles/{compiler-Dl11rH6-.cjs → checker-CuQvkMhs.cjs} +18876 -710
- package/schematics/bundles/cleanup-unused-imports.cjs +12 -9
- package/schematics/bundles/{change_tracker-DaCWdziV.cjs → compiler_host-Biezhzch.cjs} +121 -3
- package/schematics/bundles/control-flow-migration.cjs +46 -25
- package/schematics/bundles/document-core.cjs +5 -6
- package/schematics/bundles/imports-CIX-JgAN.cjs +1 -1
- package/schematics/bundles/{index-DPvX-lSh.cjs → index-C5wL4qaq.cjs} +1486 -1071
- package/schematics/bundles/{index-CYxAVSJC.cjs → index-vkqofxID.cjs} +37 -37
- package/schematics/bundles/inject-flags.cjs +5 -6
- package/schematics/bundles/inject-migration.cjs +5 -7
- package/schematics/bundles/leading_space-D9nQ8UQC.cjs +1 -1
- package/schematics/bundles/{migrate_ts_type_references-DWUePVh6.cjs → migrate_ts_type_references-BYgEQg0O.cjs} +26 -78
- package/schematics/bundles/ng_decorators-B5HCqr20.cjs +1 -1
- package/schematics/bundles/nodes-B16H9JUd.cjs +1 -1
- package/schematics/bundles/output-migration.cjs +7 -8
- package/schematics/bundles/{project_paths-BPBAn_A2.cjs → project_paths-KPCsvRfl.cjs} +3 -4
- package/schematics/bundles/project_tsconfig_paths-CDVxT6Ov.cjs +1 -1
- package/schematics/bundles/property_name-BBwFuqMe.cjs +1 -1
- package/schematics/bundles/route-lazy-loading.cjs +5 -7
- package/schematics/bundles/self-closing-tags-migration.cjs +12 -25
- package/schematics/bundles/signal-input-migration.cjs +28 -13
- package/schematics/bundles/signal-queries-migration.cjs +13 -14
- package/schematics/bundles/signals.cjs +7 -8
- package/schematics/bundles/standalone-migration.cjs +9 -11
- package/schematics/bundles/symbol-VPWguRxr.cjs +1 -1
- package/schematics/bundles/test-bed-get.cjs +4 -5
- package/schematics/collection.json +6 -0
- package/schematics/migrations/control-flow-migration/schema.json +20 -0
- package/{signal.d-D6VJ67xi.d.ts → signal.d-fOdF0h0o.d.ts} +4 -3
- package/testing/index.d.ts +4 -4
- package/weak_ref.d-eGOEP9S1.d.ts +1 -1
- package/fesm2022/debug_node-Dn-GvQJo.mjs.map +0 -1
- package/fesm2022/resource-BPCh38bN.mjs.map +0 -1
- package/fesm2022/root_effect_scheduler-0BxwqIgm.mjs.map +0 -1
- package/schematics/bundles/checker-BHgMyU8j.cjs +0 -17996
- package/schematics/bundles/compiler_host-CAfDJO3W.cjs +0 -129
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v20.0.0
|
|
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,
|
|
8
|
-
import { setActiveConsumer, SIGNAL, consumerDestroy, REACTIVE_NODE, consumerPollProducersForChange, consumerBeforeComputation, getActiveConsumer, consumerAfterComputation, createComputed, setThrowInvalidWriteToSignalError } from './signal-
|
|
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
|
+
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';
|
|
11
11
|
import { map } from 'rxjs/operators';
|
|
@@ -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.
|
|
@@ -2435,12 +2435,10 @@ function symbolIterator() {
|
|
|
2435
2435
|
*
|
|
2436
2436
|
* Implements an iterable interface, therefore it can be used in both ES6
|
|
2437
2437
|
* javascript `for (var i of items)` loops as well as in Angular templates with
|
|
2438
|
-
*
|
|
2439
|
-
*
|
|
2440
|
-
* Changes can be observed by subscribing to the changes `Observable`.
|
|
2441
|
-
*
|
|
2442
|
-
* NOTE: In the future this class will implement an `Observable` interface.
|
|
2438
|
+
* `@for(i of myList; track $index)`.
|
|
2443
2439
|
*
|
|
2440
|
+
* Changes can be observed by subscribing to the `changes` `Observable`.
|
|
2441
|
+
* *
|
|
2444
2442
|
* @usageNotes
|
|
2445
2443
|
* ### Example
|
|
2446
2444
|
* ```ts
|
|
@@ -4191,6 +4189,15 @@ class DehydratedBlockRegistry {
|
|
|
4191
4189
|
});
|
|
4192
4190
|
}
|
|
4193
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
|
+
|
|
4194
4201
|
/**
|
|
4195
4202
|
* The name of the key used in the TransferState collection,
|
|
4196
4203
|
* where hydration information is located.
|
|
@@ -4534,6 +4541,18 @@ function isDisconnectedNode$1(hydrationInfo, index) {
|
|
|
4534
4541
|
}
|
|
4535
4542
|
return !!initDisconnectedNodes(hydrationInfo)?.has(index);
|
|
4536
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
|
+
}
|
|
4537
4556
|
/**
|
|
4538
4557
|
* Helper function to prepare text nodes for serialization by ensuring
|
|
4539
4558
|
* that seperate logical text blocks in the DOM remain separate after
|
|
@@ -5898,21 +5917,20 @@ function ɵgetUnknownPropertyStrictMode() {
|
|
|
5898
5917
|
* - the element matches any directive
|
|
5899
5918
|
* - the element is allowed by one of the schemas
|
|
5900
5919
|
*
|
|
5901
|
-
* @param
|
|
5902
|
-
* @param
|
|
5903
|
-
* @param tagName Name of the tag to check
|
|
5904
|
-
* @param schemas Array of schemas
|
|
5905
|
-
* @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
|
|
5906
5922
|
*/
|
|
5907
|
-
function validateElementIsKnown(
|
|
5923
|
+
function validateElementIsKnown(lView, tNode) {
|
|
5924
|
+
const tView = lView[TVIEW];
|
|
5908
5925
|
// If `schemas` is set to `null`, that's an indication that this Component was compiled in AOT
|
|
5909
5926
|
// mode where this check happens at compile time. In JIT mode, `schemas` is always present and
|
|
5910
5927
|
// defined as an array (as an empty array in case `schemas` field is not defined) and we should
|
|
5911
5928
|
// execute the check below.
|
|
5912
|
-
if (schemas === null)
|
|
5929
|
+
if (tView.schemas === null)
|
|
5913
5930
|
return;
|
|
5931
|
+
const tagName = tNode.value;
|
|
5914
5932
|
// If the element matches any directive, it's considered as valid.
|
|
5915
|
-
if (!
|
|
5933
|
+
if (!isDirectiveHost(tNode) && tagName !== null) {
|
|
5916
5934
|
// The element is unknown if it's an instance of HTMLUnknownElement, or it isn't registered
|
|
5917
5935
|
// as a custom element. Note that unknown elements with a dash in their name won't be instances
|
|
5918
5936
|
// of HTMLUnknownElement in browsers that support web components.
|
|
@@ -5921,11 +5939,11 @@ function validateElementIsKnown(element, lView, tagName, schemas, hasDirectives)
|
|
|
5921
5939
|
// Domino doesn't expose HTMLUnknownElement globally.
|
|
5922
5940
|
(typeof HTMLUnknownElement !== 'undefined' &&
|
|
5923
5941
|
HTMLUnknownElement &&
|
|
5924
|
-
|
|
5942
|
+
getNativeByTNode(tNode, lView) instanceof HTMLUnknownElement) ||
|
|
5925
5943
|
(typeof customElements !== 'undefined' &&
|
|
5926
5944
|
tagName.indexOf('-') > -1 &&
|
|
5927
5945
|
!customElements.get(tagName));
|
|
5928
|
-
if (isUnknown && !matchingSchemas(schemas, tagName)) {
|
|
5946
|
+
if (isUnknown && !matchingSchemas(tView.schemas, tagName)) {
|
|
5929
5947
|
const isHostStandalone = isHostComponentStandalone(lView);
|
|
5930
5948
|
const templateLocation = getTemplateLocationDetails(lView);
|
|
5931
5949
|
const schemas = `'${isHostStandalone ? '@Component' : '@NgModule'}.schemas'`;
|
|
@@ -7125,1445 +7143,1478 @@ function writeToDirectiveInput(def, instance, publicName, value) {
|
|
|
7125
7143
|
}
|
|
7126
7144
|
}
|
|
7127
7145
|
|
|
7128
|
-
|
|
7129
|
-
|
|
7130
|
-
|
|
7131
|
-
|
|
7132
|
-
|
|
7133
|
-
|
|
7134
|
-
|
|
7135
|
-
|
|
7136
|
-
|
|
7137
|
-
|
|
7138
|
-
|
|
7139
|
-
|
|
7140
|
-
|
|
7141
|
-
|
|
7142
|
-
|
|
7143
|
-
|
|
7144
|
-
|
|
7145
|
-
|
|
7146
|
-
|
|
7147
|
-
|
|
7148
|
-
|
|
7149
|
-
|
|
7150
|
-
|
|
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);
|
|
7151
7171
|
}
|
|
7152
7172
|
/**
|
|
7153
|
-
*
|
|
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.
|
|
7154
7177
|
*/
|
|
7155
|
-
function
|
|
7156
|
-
|
|
7157
|
-
|
|
7158
|
-
|
|
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();
|
|
7159
7183
|
}
|
|
7160
7184
|
}
|
|
7185
|
+
|
|
7161
7186
|
/**
|
|
7162
|
-
*
|
|
7163
|
-
*
|
|
7187
|
+
* NOTE: for performance reasons, the possible actions are inlined within the function instead of
|
|
7188
|
+
* being passed as an argument.
|
|
7164
7189
|
*/
|
|
7165
|
-
function
|
|
7166
|
-
|
|
7167
|
-
|
|
7168
|
-
|
|
7169
|
-
|
|
7170
|
-
|
|
7171
|
-
|
|
7172
|
-
|
|
7173
|
-
|
|
7174
|
-
|
|
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);
|
|
7175
7229
|
}
|
|
7176
7230
|
}
|
|
7177
7231
|
}
|
|
7178
7232
|
/**
|
|
7179
|
-
*
|
|
7233
|
+
* Removes all DOM elements associated with a view.
|
|
7180
7234
|
*
|
|
7181
|
-
*
|
|
7182
|
-
*
|
|
7183
|
-
*
|
|
7184
|
-
* @param injector Root view injector instance.
|
|
7185
|
-
*/
|
|
7186
|
-
function locateHostElement(renderer, elementOrSelector, encapsulation, injector) {
|
|
7187
|
-
// Note: we use default value for the `PRESERVE_HOST_CONTENT` here even though it's a
|
|
7188
|
-
// tree-shakable one (providedIn:'root'). This code path can be triggered during dynamic
|
|
7189
|
-
// component creation (after calling ViewContainerRef.createComponent) when an injector
|
|
7190
|
-
// instance can be provided. The injector instance might be disconnected from the main DI
|
|
7191
|
-
// tree, thus the `PRESERVE_HOST_CONTENT` would not be able to instantiate. In this case, the
|
|
7192
|
-
// default value will be used.
|
|
7193
|
-
const preserveHostContent = injector.get(PRESERVE_HOST_CONTENT, PRESERVE_HOST_CONTENT_DEFAULT);
|
|
7194
|
-
// When using native Shadow DOM, do not clear host element to allow native slot
|
|
7195
|
-
// projection.
|
|
7196
|
-
const preserveContent = preserveHostContent || encapsulation === ViewEncapsulation.ShadowDom;
|
|
7197
|
-
const rootElement = renderer.selectRootElement(elementOrSelector, preserveContent);
|
|
7198
|
-
applyRootElementTransform(rootElement);
|
|
7199
|
-
return rootElement;
|
|
7200
|
-
}
|
|
7201
|
-
/**
|
|
7202
|
-
* Applies any root element transformations that are needed. If hydration is enabled,
|
|
7203
|
-
* 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.
|
|
7204
7238
|
*
|
|
7205
|
-
* @param
|
|
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
|
|
7206
7241
|
*/
|
|
7207
|
-
function
|
|
7208
|
-
|
|
7242
|
+
function removeViewFromDOM(tView, lView) {
|
|
7243
|
+
detachViewFromDOM(tView, lView);
|
|
7244
|
+
lView[HOST] = null;
|
|
7245
|
+
lView[T_HOST] = null;
|
|
7209
7246
|
}
|
|
7210
7247
|
/**
|
|
7211
|
-
*
|
|
7212
|
-
* of an app. When hydration is enabled, this processes any corrupt text nodes
|
|
7213
|
-
* so they are properly hydratable on the client.
|
|
7248
|
+
* Adds all DOM elements associated with a view.
|
|
7214
7249
|
*
|
|
7215
|
-
*
|
|
7216
|
-
|
|
7217
|
-
|
|
7218
|
-
/**
|
|
7219
|
-
* Processes text node markers before hydration begins. This replaces any special comment
|
|
7220
|
-
* nodes that were added prior to serialization are swapped out to restore proper text
|
|
7221
|
-
* 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.
|
|
7222
7253
|
*
|
|
7223
|
-
* @param
|
|
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
|
|
7224
7260
|
*/
|
|
7225
|
-
function
|
|
7226
|
-
|
|
7227
|
-
|
|
7228
|
-
|
|
7229
|
-
// the contents and render everything from scratch.
|
|
7230
|
-
clearElementContents(rootElement);
|
|
7231
|
-
}
|
|
7232
|
-
else {
|
|
7233
|
-
processTextNodeMarkersBeforeHydration(rootElement);
|
|
7234
|
-
}
|
|
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);
|
|
7235
7265
|
}
|
|
7236
7266
|
/**
|
|
7237
|
-
*
|
|
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.
|
|
7238
7271
|
*/
|
|
7239
|
-
function
|
|
7240
|
-
|
|
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);
|
|
7241
7278
|
}
|
|
7242
7279
|
/**
|
|
7243
|
-
*
|
|
7280
|
+
* Traverses down and up the tree of views and containers to remove listeners and
|
|
7281
|
+
* call onDestroy callbacks.
|
|
7244
7282
|
*
|
|
7245
|
-
*
|
|
7246
|
-
*
|
|
7247
|
-
*
|
|
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)
|
|
7248
7289
|
*
|
|
7249
|
-
*
|
|
7250
|
-
* type-checking machinery of ngtsc.
|
|
7290
|
+
* @param rootView The view to destroy
|
|
7251
7291
|
*/
|
|
7252
|
-
function
|
|
7253
|
-
|
|
7254
|
-
|
|
7255
|
-
if (
|
|
7256
|
-
return
|
|
7257
|
-
if (name === 'formaction')
|
|
7258
|
-
return 'formAction';
|
|
7259
|
-
if (name === 'innerHtml')
|
|
7260
|
-
return 'innerHTML';
|
|
7261
|
-
if (name === 'readonly')
|
|
7262
|
-
return 'readOnly';
|
|
7263
|
-
if (name === 'tabindex')
|
|
7264
|
-
return 'tabIndex';
|
|
7265
|
-
return name;
|
|
7266
|
-
}
|
|
7267
|
-
function setPropertyAndInputs(tNode, lView, propName, value, renderer, sanitizer) {
|
|
7268
|
-
ngDevMode && assertNotSame(value, NO_CHANGE, 'Incoming value should never be NO_CHANGE.');
|
|
7269
|
-
const tView = lView[TVIEW];
|
|
7270
|
-
const hasSetInput = setAllInputsForProperty(tNode, tView, lView, propName, value);
|
|
7271
|
-
if (hasSetInput) {
|
|
7272
|
-
isComponentHost(tNode) && markDirtyIfOnPush(lView, tNode.index);
|
|
7273
|
-
ngDevMode && setNgReflectProperties(lView, tView, tNode, propName, value);
|
|
7274
|
-
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);
|
|
7275
7297
|
}
|
|
7276
|
-
|
|
7277
|
-
|
|
7278
|
-
|
|
7279
|
-
|
|
7280
|
-
|
|
7281
|
-
* @param lView View in which the node is located.
|
|
7282
|
-
* @param propName Name of the property.
|
|
7283
|
-
* @param value Value to set on the property.
|
|
7284
|
-
* @param renderer Renderer to use when setting the property.
|
|
7285
|
-
* @param sanitizer Function used to sanitize the value before setting it.
|
|
7286
|
-
*/
|
|
7287
|
-
function setDomProperty(tNode, lView, propName, value, renderer, sanitizer) {
|
|
7288
|
-
if (tNode.type & 3 /* TNodeType.AnyRNode */) {
|
|
7289
|
-
const element = getNativeByTNode(tNode, lView);
|
|
7290
|
-
propName = mapPropName(propName);
|
|
7291
|
-
if (ngDevMode) {
|
|
7292
|
-
validateAgainstEventProperties(propName);
|
|
7293
|
-
if (!isPropertyValid(element, propName, tNode.value, lView[TVIEW].schemas)) {
|
|
7294
|
-
handleUnknownPropertyError(propName, tNode.value, tNode.type, lView);
|
|
7295
|
-
}
|
|
7298
|
+
while (lViewOrLContainer) {
|
|
7299
|
+
let next = null;
|
|
7300
|
+
if (isLView(lViewOrLContainer)) {
|
|
7301
|
+
// If LView, traverse down to child.
|
|
7302
|
+
next = lViewOrLContainer[CHILD_HEAD];
|
|
7296
7303
|
}
|
|
7297
|
-
|
|
7298
|
-
|
|
7299
|
-
|
|
7300
|
-
|
|
7301
|
-
|
|
7302
|
-
|
|
7303
|
-
|
|
7304
|
-
|
|
7305
|
-
|
|
7306
|
-
|
|
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];
|
|
7307
7326
|
}
|
|
7327
|
+
lViewOrLContainer = next;
|
|
7308
7328
|
}
|
|
7309
7329
|
}
|
|
7310
|
-
|
|
7311
|
-
|
|
7312
|
-
ngDevMode &&
|
|
7313
|
-
|
|
7314
|
-
|
|
7315
|
-
|
|
7316
|
-
|
|
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);
|
|
7317
7337
|
}
|
|
7318
|
-
|
|
7319
|
-
|
|
7320
|
-
|
|
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)) {
|
|
7321
7347
|
return;
|
|
7322
7348
|
}
|
|
7323
|
-
const element = getNativeByTNode(tNode, lView);
|
|
7324
7349
|
const renderer = lView[RENDERER];
|
|
7325
|
-
|
|
7326
|
-
|
|
7327
|
-
if (tNode.type & 3 /* TNodeType.AnyRNode */) {
|
|
7328
|
-
if (value == null) {
|
|
7329
|
-
renderer.removeAttribute(element, attrName);
|
|
7330
|
-
}
|
|
7331
|
-
else {
|
|
7332
|
-
renderer.setAttribute(element, attrName, debugValue);
|
|
7333
|
-
}
|
|
7334
|
-
}
|
|
7335
|
-
else {
|
|
7336
|
-
const textContent = escapeCommentText(`bindings=${JSON.stringify({ [attrName]: debugValue }, null, 2)}`);
|
|
7337
|
-
renderer.setValue(element, textContent);
|
|
7350
|
+
if (renderer.destroyNode) {
|
|
7351
|
+
applyView(tView, lView, renderer, 3 /* WalkTNodeTreeAction.Destroy */, null, null);
|
|
7338
7352
|
}
|
|
7353
|
+
destroyViewTree(lView);
|
|
7339
7354
|
}
|
|
7340
|
-
|
|
7341
|
-
|
|
7342
|
-
|
|
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)) {
|
|
7343
7365
|
return;
|
|
7344
7366
|
}
|
|
7345
|
-
const
|
|
7346
|
-
|
|
7347
|
-
|
|
7348
|
-
|
|
7349
|
-
|
|
7350
|
-
|
|
7351
|
-
|
|
7352
|
-
|
|
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();
|
|
7353
7384
|
}
|
|
7354
|
-
|
|
7355
|
-
|
|
7356
|
-
|
|
7357
|
-
|
|
7358
|
-
|
|
7359
|
-
|
|
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
|
+
}
|
|
7360
7397
|
}
|
|
7398
|
+
// Unregister the view once everything else has been cleaned up.
|
|
7399
|
+
unregisterLView(lView);
|
|
7400
|
+
}
|
|
7401
|
+
finally {
|
|
7402
|
+
setActiveConsumer(prevConsumer);
|
|
7361
7403
|
}
|
|
7362
7404
|
}
|
|
7363
|
-
/**
|
|
7364
|
-
|
|
7365
|
-
|
|
7366
|
-
|
|
7367
|
-
const
|
|
7368
|
-
|
|
7369
|
-
|
|
7370
|
-
|
|
7371
|
-
|
|
7372
|
-
|
|
7373
|
-
|
|
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
|
+
}
|
|
7374
7433
|
}
|
|
7375
|
-
if (
|
|
7376
|
-
|
|
7434
|
+
if (lCleanup !== null) {
|
|
7435
|
+
lView[CLEANUP] = null;
|
|
7377
7436
|
}
|
|
7378
|
-
const
|
|
7379
|
-
|
|
7380
|
-
|
|
7381
|
-
|
|
7382
|
-
|
|
7383
|
-
|
|
7384
|
-
|
|
7385
|
-
|
|
7386
|
-
|
|
7387
|
-
const componentView = getComponentLViewByIndex(tNode.index, lView);
|
|
7388
|
-
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();
|
|
7389
7446
|
}
|
|
7390
7447
|
}
|
|
7391
|
-
|
|
7392
|
-
|
|
7393
|
-
|
|
7394
|
-
|
|
7395
|
-
|
|
7396
|
-
|
|
7397
|
-
try {
|
|
7398
|
-
setSelectedIndex(elementIndex);
|
|
7399
|
-
for (let dirIndex = start; dirIndex < end; dirIndex++) {
|
|
7400
|
-
const def = tView.data[dirIndex];
|
|
7401
|
-
const directive = lView[dirIndex];
|
|
7402
|
-
setCurrentDirectiveIndex(dirIndex);
|
|
7403
|
-
if (def.hostBindings !== null || def.hostVars !== 0 || def.hostAttrs !== null) {
|
|
7404
|
-
invokeHostBindingsInCreationMode(def, directive);
|
|
7405
|
-
}
|
|
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();
|
|
7406
7454
|
}
|
|
7407
7455
|
}
|
|
7408
|
-
finally {
|
|
7409
|
-
setSelectedIndex(-1);
|
|
7410
|
-
setCurrentDirectiveIndex(currentDirectiveIndex);
|
|
7411
|
-
}
|
|
7412
7456
|
}
|
|
7413
|
-
/**
|
|
7414
|
-
|
|
7415
|
-
|
|
7416
|
-
|
|
7417
|
-
|
|
7418
|
-
|
|
7419
|
-
|
|
7420
|
-
|
|
7421
|
-
|
|
7422
|
-
|
|
7423
|
-
|
|
7424
|
-
|
|
7425
|
-
|
|
7426
|
-
|
|
7427
|
-
|
|
7428
|
-
|
|
7429
|
-
|
|
7430
|
-
ngDevMode && assertTNodeType(tNode, 3 /* TNodeType.AnyRNode */ | 12 /* TNodeType.AnyContainer */);
|
|
7431
|
-
const registry = tView.directiveRegistry;
|
|
7432
|
-
let matches = null;
|
|
7433
|
-
if (registry) {
|
|
7434
|
-
for (let i = 0; i < registry.length; i++) {
|
|
7435
|
-
const def = registry[i];
|
|
7436
|
-
if (isNodeMatchingSelectorList(tNode, def.selectors, /* isProjectionMode */ false)) {
|
|
7437
|
-
matches ??= [];
|
|
7438
|
-
if (isComponentDef(def)) {
|
|
7439
|
-
if (ngDevMode) {
|
|
7440
|
-
assertTNodeType(tNode, 2 /* TNodeType.Element */, `"${tNode.value}" tags cannot be used as component hosts. ` +
|
|
7441
|
-
`Please use a different tag to activate the ${stringify(def.type)} component.`);
|
|
7442
|
-
if (matches.length && isComponentDef(matches[0])) {
|
|
7443
|
-
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);
|
|
7444
7474
|
}
|
|
7445
|
-
|
|
7446
|
-
|
|
7447
|
-
|
|
7448
|
-
|
|
7449
|
-
|
|
7450
|
-
|
|
7451
|
-
|
|
7452
|
-
|
|
7453
|
-
|
|
7454
|
-
|
|
7455
|
-
|
|
7456
|
-
|
|
7457
|
-
|
|
7458
|
-
|
|
7459
|
-
|
|
7460
|
-
assertTNodeType(tNode, 2 /* TNodeType.Element */, `Attempted to set attribute \`${name}\` on a container node. ` +
|
|
7461
|
-
`Host bindings are not valid on ng-container or ng-template.`);
|
|
7462
|
-
}
|
|
7463
|
-
const element = getNativeByTNode(tNode, lView);
|
|
7464
|
-
setElementAttribute(lView[RENDERER], element, namespace, tNode.value, name, value, sanitizer);
|
|
7465
|
-
}
|
|
7466
|
-
function setElementAttribute(renderer, element, namespace, tagName, name, value, sanitizer) {
|
|
7467
|
-
if (value == null) {
|
|
7468
|
-
renderer.removeAttribute(element, name, namespace);
|
|
7469
|
-
}
|
|
7470
|
-
else {
|
|
7471
|
-
const strValue = sanitizer == null ? renderStringify(value) : sanitizer(value, tagName || '', name);
|
|
7472
|
-
renderer.setAttribute(element, name, strValue, namespace);
|
|
7473
|
-
}
|
|
7474
|
-
}
|
|
7475
|
-
/**
|
|
7476
|
-
* Sets initial input properties on directive instances from attribute data
|
|
7477
|
-
*
|
|
7478
|
-
* @param lView Current LView that is being processed.
|
|
7479
|
-
* @param directiveIndex Index of the directive in directives array
|
|
7480
|
-
* @param instance Instance of the directive on which to set the initial inputs
|
|
7481
|
-
* @param def The directive def that contains the list of inputs
|
|
7482
|
-
* @param tNode The static data for this node
|
|
7483
|
-
*/
|
|
7484
|
-
function setInputsFromAttrs(lView, directiveIndex, instance, def, tNode, initialInputData) {
|
|
7485
|
-
const initialInputs = initialInputData[directiveIndex];
|
|
7486
|
-
if (initialInputs !== null) {
|
|
7487
|
-
for (let i = 0; i < initialInputs.length; i += 2) {
|
|
7488
|
-
const lookupName = initialInputs[i];
|
|
7489
|
-
const value = initialInputs[i + 1];
|
|
7490
|
-
writeToDirectiveInput(def, instance, lookupName, value);
|
|
7491
|
-
if (ngDevMode) {
|
|
7492
|
-
setNgReflectProperty(lView, tNode, def.inputs[lookupName][0], value);
|
|
7493
|
-
}
|
|
7494
|
-
}
|
|
7495
|
-
}
|
|
7496
|
-
}
|
|
7497
|
-
///////////////////////////////
|
|
7498
|
-
//// Bindings & interpolations
|
|
7499
|
-
///////////////////////////////
|
|
7500
|
-
/**
|
|
7501
|
-
* Stores meta-data for a property binding to be used by TestBed's `DebugElement.properties`.
|
|
7502
|
-
*
|
|
7503
|
-
* In order to support TestBed's `DebugElement.properties` we need to save, for each binding:
|
|
7504
|
-
* - a bound property name;
|
|
7505
|
-
* - a static parts of interpolated strings;
|
|
7506
|
-
*
|
|
7507
|
-
* A given property metadata is saved at the binding's index in the `TView.data` (in other words, a
|
|
7508
|
-
* property binding metadata will be stored in `TView.data` at the same index as a bound value in
|
|
7509
|
-
* `LView`). Metadata are represented as `INTERPOLATION_DELIMITER`-delimited string with the
|
|
7510
|
-
* following format:
|
|
7511
|
-
* - `propertyName` for bound properties;
|
|
7512
|
-
* - `propertyName�prefix�interpolation_static_part1�..interpolation_static_partN�suffix` for
|
|
7513
|
-
* interpolated properties.
|
|
7514
|
-
*
|
|
7515
|
-
* @param tData `TData` where meta-data will be saved;
|
|
7516
|
-
* @param tNode `TNode` that is a target of the binding;
|
|
7517
|
-
* @param propertyName bound property name;
|
|
7518
|
-
* @param bindingIndex binding index in `LView`
|
|
7519
|
-
* @param interpolationParts static interpolation parts (for property interpolations)
|
|
7520
|
-
*/
|
|
7521
|
-
function storePropertyBindingMetadata(tData, tNode, propertyName, bindingIndex, ...interpolationParts) {
|
|
7522
|
-
// Binding meta-data are stored only the first time a given property instruction is processed.
|
|
7523
|
-
// Since we don't have a concept of the "first update pass" we need to check for presence of the
|
|
7524
|
-
// binding meta-data to decide if one should be stored (or if was stored already).
|
|
7525
|
-
if (tData[bindingIndex] === null) {
|
|
7526
|
-
if (!tNode.inputs?.[propertyName] && !tNode.hostDirectiveInputs?.[propertyName]) {
|
|
7527
|
-
const propBindingIdxs = tNode.propertyBindings || (tNode.propertyBindings = []);
|
|
7528
|
-
propBindingIdxs.push(bindingIndex);
|
|
7529
|
-
let bindingMetadata = propertyName;
|
|
7530
|
-
if (interpolationParts.length > 0) {
|
|
7531
|
-
bindingMetadata +=
|
|
7532
|
-
INTERPOLATION_DELIMITER + interpolationParts.join(INTERPOLATION_DELIMITER);
|
|
7533
|
-
}
|
|
7534
|
-
tData[bindingIndex] = bindingMetadata;
|
|
7535
|
-
}
|
|
7536
|
-
}
|
|
7537
|
-
}
|
|
7538
|
-
/**
|
|
7539
|
-
* There are cases where the sub component's renderer needs to be included
|
|
7540
|
-
* instead of the current renderer (see the componentSyntheticHost* instructions).
|
|
7541
|
-
*/
|
|
7542
|
-
function loadComponentRenderer(currentDef, tNode, lView) {
|
|
7543
|
-
// TODO(FW-2043): the `currentDef` is null when host bindings are invoked while creating root
|
|
7544
|
-
// component (see packages/core/src/render3/component.ts). This is not consistent with the process
|
|
7545
|
-
// of creating inner components, when current directive index is available in the state. In order
|
|
7546
|
-
// to avoid relying on current def being `null` (thus special-casing root component creation), the
|
|
7547
|
-
// process of creating root component should be unified with the process of creating inner
|
|
7548
|
-
// components.
|
|
7549
|
-
if (currentDef === null || isComponentDef(currentDef)) {
|
|
7550
|
-
lView = unwrapLView(lView[tNode.index]);
|
|
7551
|
-
}
|
|
7552
|
-
return lView[RENDERER];
|
|
7553
|
-
}
|
|
7554
|
-
/** Handles an error thrown in an LView. */
|
|
7555
|
-
function handleUncaughtError(lView, error) {
|
|
7556
|
-
const injector = lView[INJECTOR];
|
|
7557
|
-
if (!injector) {
|
|
7558
|
-
return;
|
|
7559
|
-
}
|
|
7560
|
-
const errorHandler = injector.get(INTERNAL_APPLICATION_ERROR_HANDLER, null);
|
|
7561
|
-
errorHandler?.(error);
|
|
7562
|
-
}
|
|
7563
|
-
/**
|
|
7564
|
-
* Set all directive inputs with the specific public name on the node.
|
|
7565
|
-
*
|
|
7566
|
-
* @param tNode TNode on which the input is being set.
|
|
7567
|
-
* @param tView Current TView
|
|
7568
|
-
* @param lView `LView` which contains the directives.
|
|
7569
|
-
* @param publicName Public name of the input being set.
|
|
7570
|
-
* @param value Value to set.
|
|
7571
|
-
*/
|
|
7572
|
-
function setAllInputsForProperty(tNode, tView, lView, publicName, value) {
|
|
7573
|
-
const inputs = tNode.inputs?.[publicName];
|
|
7574
|
-
const hostDirectiveInputs = tNode.hostDirectiveInputs?.[publicName];
|
|
7575
|
-
let hasMatch = false;
|
|
7576
|
-
if (hostDirectiveInputs) {
|
|
7577
|
-
for (let i = 0; i < hostDirectiveInputs.length; i += 2) {
|
|
7578
|
-
const index = hostDirectiveInputs[i];
|
|
7579
|
-
ngDevMode && assertIndexInRange(lView, index);
|
|
7580
|
-
const publicName = hostDirectiveInputs[i + 1];
|
|
7581
|
-
const def = tView.data[index];
|
|
7582
|
-
writeToDirectiveInput(def, lView[index], publicName, value);
|
|
7583
|
-
hasMatch = true;
|
|
7584
|
-
}
|
|
7585
|
-
}
|
|
7586
|
-
if (inputs) {
|
|
7587
|
-
for (const index of inputs) {
|
|
7588
|
-
ngDevMode && assertIndexInRange(lView, index);
|
|
7589
|
-
const instance = lView[index];
|
|
7590
|
-
const def = tView.data[index];
|
|
7591
|
-
writeToDirectiveInput(def, instance, publicName, value);
|
|
7592
|
-
hasMatch = true;
|
|
7593
|
-
}
|
|
7594
|
-
}
|
|
7595
|
-
return hasMatch;
|
|
7596
|
-
}
|
|
7597
|
-
/**
|
|
7598
|
-
* Sets an input value only on a specific directive and its host directives.
|
|
7599
|
-
* @param tNode TNode on which the input is being set.
|
|
7600
|
-
* @param tView Current TView
|
|
7601
|
-
* @param lView `LView` which contains the directives.
|
|
7602
|
-
* @param target Directive on which to set the input.
|
|
7603
|
-
* @param publicName Public name of the input being set.
|
|
7604
|
-
* @param value Value to set.
|
|
7605
|
-
*/
|
|
7606
|
-
function setDirectiveInput(tNode, tView, lView, target, publicName, value) {
|
|
7607
|
-
let hostIndex = null;
|
|
7608
|
-
let hostDirectivesStart = null;
|
|
7609
|
-
let hostDirectivesEnd = null;
|
|
7610
|
-
let hasSet = false;
|
|
7611
|
-
if (ngDevMode && !tNode.directiveToIndex?.has(target.type)) {
|
|
7612
|
-
throw new Error(`Node does not have a directive with type ${target.type.name}`);
|
|
7613
|
-
}
|
|
7614
|
-
const data = tNode.directiveToIndex.get(target.type);
|
|
7615
|
-
if (typeof data === 'number') {
|
|
7616
|
-
hostIndex = data;
|
|
7617
|
-
}
|
|
7618
|
-
else {
|
|
7619
|
-
[hostIndex, hostDirectivesStart, hostDirectivesEnd] = data;
|
|
7620
|
-
}
|
|
7621
|
-
if (hostDirectivesStart !== null &&
|
|
7622
|
-
hostDirectivesEnd !== null &&
|
|
7623
|
-
tNode.hostDirectiveInputs?.hasOwnProperty(publicName)) {
|
|
7624
|
-
const hostDirectiveInputs = tNode.hostDirectiveInputs[publicName];
|
|
7625
|
-
for (let i = 0; i < hostDirectiveInputs.length; i += 2) {
|
|
7626
|
-
const index = hostDirectiveInputs[i];
|
|
7627
|
-
if (index >= hostDirectivesStart && index <= hostDirectivesEnd) {
|
|
7628
|
-
ngDevMode && assertIndexInRange(lView, index);
|
|
7629
|
-
const def = tView.data[index];
|
|
7630
|
-
const hostDirectivePublicName = hostDirectiveInputs[i + 1];
|
|
7631
|
-
writeToDirectiveInput(def, lView[index], hostDirectivePublicName, value);
|
|
7632
|
-
hasSet = true;
|
|
7633
|
-
}
|
|
7634
|
-
else if (index > hostDirectivesEnd) {
|
|
7635
|
-
// Directives here are in ascending order so we can stop looking once we're past the range.
|
|
7636
|
-
break;
|
|
7637
|
-
}
|
|
7638
|
-
}
|
|
7639
|
-
}
|
|
7640
|
-
if (hostIndex !== null && target.inputs.hasOwnProperty(publicName)) {
|
|
7641
|
-
ngDevMode && assertIndexInRange(lView, hostIndex);
|
|
7642
|
-
writeToDirectiveInput(target, lView[hostIndex], publicName, value);
|
|
7643
|
-
hasSet = true;
|
|
7644
|
-
}
|
|
7645
|
-
return hasSet;
|
|
7646
|
-
}
|
|
7647
|
-
|
|
7648
|
-
function renderComponent(hostLView, componentHostIdx) {
|
|
7649
|
-
ngDevMode && assertEqual(isCreationMode(hostLView), true, 'Should be run in creation mode');
|
|
7650
|
-
const componentView = getComponentLViewByIndex(componentHostIdx, hostLView);
|
|
7651
|
-
const componentTView = componentView[TVIEW];
|
|
7652
|
-
syncViewWithBlueprint(componentTView, componentView);
|
|
7653
|
-
const hostRNode = componentView[HOST];
|
|
7654
|
-
// Populate an LView with hydration info retrieved from the DOM via TransferState.
|
|
7655
|
-
if (hostRNode !== null && componentView[HYDRATION] === null) {
|
|
7656
|
-
componentView[HYDRATION] = retrieveHydrationInfo(hostRNode, componentView[INJECTOR]);
|
|
7657
|
-
}
|
|
7658
|
-
profiler(18 /* ProfilerEvent.ComponentStart */);
|
|
7659
|
-
renderView(componentTView, componentView, componentView[CONTEXT]);
|
|
7660
|
-
profiler(19 /* ProfilerEvent.ComponentEnd */, componentView[CONTEXT]);
|
|
7661
|
-
}
|
|
7662
|
-
/**
|
|
7663
|
-
* Syncs an LView instance with its blueprint if they have gotten out of sync.
|
|
7664
|
-
*
|
|
7665
|
-
* Typically, blueprints and their view instances should always be in sync, so the loop here
|
|
7666
|
-
* will be skipped. However, consider this case of two components side-by-side:
|
|
7667
|
-
*
|
|
7668
|
-
* App template:
|
|
7669
|
-
* ```html
|
|
7670
|
-
* <comp></comp>
|
|
7671
|
-
* <comp></comp>
|
|
7672
|
-
* ```
|
|
7673
|
-
*
|
|
7674
|
-
* The following will happen:
|
|
7675
|
-
* 1. App template begins processing.
|
|
7676
|
-
* 2. First <comp> is matched as a component and its LView is created.
|
|
7677
|
-
* 3. Second <comp> is matched as a component and its LView is created.
|
|
7678
|
-
* 4. App template completes processing, so it's time to check child templates.
|
|
7679
|
-
* 5. First <comp> template is checked. It has a directive, so its def is pushed to blueprint.
|
|
7680
|
-
* 6. Second <comp> template is checked. Its blueprint has been updated by the first
|
|
7681
|
-
* <comp> template, but its LView was created before this update, so it is out of sync.
|
|
7682
|
-
*
|
|
7683
|
-
* Note that embedded views inside ngFor loops will never be out of sync because these views
|
|
7684
|
-
* are processed as soon as they are created.
|
|
7685
|
-
*
|
|
7686
|
-
* @param tView The `TView` that contains the blueprint for syncing
|
|
7687
|
-
* @param lView The view to sync
|
|
7688
|
-
*/
|
|
7689
|
-
function syncViewWithBlueprint(tView, lView) {
|
|
7690
|
-
for (let i = lView.length; i < tView.blueprint.length; i++) {
|
|
7691
|
-
lView.push(tView.blueprint[i]);
|
|
7692
|
-
}
|
|
7693
|
-
}
|
|
7694
|
-
/**
|
|
7695
|
-
* Processes a view in the creation mode. This includes a number of steps in a specific order:
|
|
7696
|
-
* - creating view query functions (if any);
|
|
7697
|
-
* - executing a template function in the creation mode;
|
|
7698
|
-
* - updating static queries (if any);
|
|
7699
|
-
* - creating child components defined in a given view.
|
|
7700
|
-
*/
|
|
7701
|
-
function renderView(tView, lView, context) {
|
|
7702
|
-
ngDevMode && assertEqual(isCreationMode(lView), true, 'Should be run in creation mode');
|
|
7703
|
-
ngDevMode && assertNotReactive(renderView.name);
|
|
7704
|
-
enterView(lView);
|
|
7705
|
-
try {
|
|
7706
|
-
const viewQuery = tView.viewQuery;
|
|
7707
|
-
if (viewQuery !== null) {
|
|
7708
|
-
executeViewQueryFn(1 /* RenderFlags.Create */, viewQuery, context);
|
|
7709
|
-
}
|
|
7710
|
-
// Execute a template associated with this view, if it exists. A template function might not be
|
|
7711
|
-
// defined for the root component views.
|
|
7712
|
-
const templateFn = tView.template;
|
|
7713
|
-
if (templateFn !== null) {
|
|
7714
|
-
executeTemplate(tView, lView, templateFn, 1 /* RenderFlags.Create */, context);
|
|
7715
|
-
}
|
|
7716
|
-
// This needs to be set before children are processed to support recursive components.
|
|
7717
|
-
// This must be set to false immediately after the first creation run because in an
|
|
7718
|
-
// ngFor loop, all the views will be created together before update mode runs and turns
|
|
7719
|
-
// off firstCreatePass. If we don't set it here, instances will perform directive
|
|
7720
|
-
// matching, etc again and again.
|
|
7721
|
-
if (tView.firstCreatePass) {
|
|
7722
|
-
tView.firstCreatePass = false;
|
|
7723
|
-
}
|
|
7724
|
-
// Mark all queries active in this view as dirty. This is necessary for signal-based queries to
|
|
7725
|
-
// have a clear marking point where we can read query results atomically (for a given view).
|
|
7726
|
-
lView[QUERIES]?.finishViewCreation(tView);
|
|
7727
|
-
// We resolve content queries specifically marked as `static` in creation mode. Dynamic
|
|
7728
|
-
// content queries are resolved during change detection (i.e. update mode), after embedded
|
|
7729
|
-
// views are refreshed (see block above).
|
|
7730
|
-
if (tView.staticContentQueries) {
|
|
7731
|
-
refreshContentQueries(tView, lView);
|
|
7732
|
-
}
|
|
7733
|
-
// We must materialize query results before child components are processed
|
|
7734
|
-
// in case a child component has projected a container. The LContainer needs
|
|
7735
|
-
// to exist so the embedded views are properly attached by the container.
|
|
7736
|
-
if (tView.staticViewQueries) {
|
|
7737
|
-
executeViewQueryFn(2 /* RenderFlags.Update */, tView.viewQuery, context);
|
|
7738
|
-
}
|
|
7739
|
-
// Render child component views.
|
|
7740
|
-
const components = tView.components;
|
|
7741
|
-
if (components !== null) {
|
|
7742
|
-
renderChildComponents(lView, components);
|
|
7743
|
-
}
|
|
7744
|
-
}
|
|
7745
|
-
catch (error) {
|
|
7746
|
-
// If we didn't manage to get past the first template pass due to
|
|
7747
|
-
// an error, mark the view as corrupted so we can try to recover.
|
|
7748
|
-
if (tView.firstCreatePass) {
|
|
7749
|
-
tView.incompleteFirstPass = true;
|
|
7750
|
-
tView.firstCreatePass = false;
|
|
7475
|
+
finally {
|
|
7476
|
+
profiler(5 /* ProfilerEvent.LifecycleHookEnd */, callContext, hook);
|
|
7477
|
+
}
|
|
7478
|
+
}
|
|
7479
|
+
}
|
|
7480
|
+
else {
|
|
7481
|
+
profiler(4 /* ProfilerEvent.LifecycleHookStart */, context, toCall);
|
|
7482
|
+
try {
|
|
7483
|
+
toCall.call(context);
|
|
7484
|
+
}
|
|
7485
|
+
finally {
|
|
7486
|
+
profiler(5 /* ProfilerEvent.LifecycleHookEnd */, context, toCall);
|
|
7487
|
+
}
|
|
7488
|
+
}
|
|
7489
|
+
}
|
|
7751
7490
|
}
|
|
7752
|
-
throw error;
|
|
7753
|
-
}
|
|
7754
|
-
finally {
|
|
7755
|
-
lView[FLAGS] &= -5 /* LViewFlags.CreationMode */;
|
|
7756
|
-
leaveView();
|
|
7757
7491
|
}
|
|
7758
7492
|
}
|
|
7759
|
-
/**
|
|
7760
|
-
|
|
7761
|
-
|
|
7762
|
-
|
|
7763
|
-
|
|
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);
|
|
7764
7511
|
}
|
|
7765
|
-
|
|
7766
|
-
|
|
7767
|
-
|
|
7768
|
-
|
|
7769
|
-
|
|
7770
|
-
|
|
7771
|
-
|
|
7772
|
-
|
|
7773
|
-
|
|
7774
|
-
|
|
7775
|
-
|
|
7776
|
-
|
|
7777
|
-
|
|
7778
|
-
|
|
7779
|
-
|
|
7780
|
-
|
|
7781
|
-
|
|
7782
|
-
|
|
7783
|
-
|
|
7784
|
-
|
|
7785
|
-
|
|
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;
|
|
7786
7536
|
}
|
|
7787
|
-
|
|
7788
|
-
|
|
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];
|
|
7543
|
+
}
|
|
7544
|
+
else {
|
|
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);
|
|
7789
7561
|
}
|
|
7790
7562
|
}
|
|
7791
7563
|
/**
|
|
7792
|
-
*
|
|
7793
|
-
*
|
|
7794
|
-
*
|
|
7795
|
-
*
|
|
7796
|
-
*
|
|
7564
|
+
* Find a node in front of which `currentTNode` should be inserted.
|
|
7565
|
+
*
|
|
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`
|
|
7797
7572
|
*/
|
|
7798
|
-
function
|
|
7799
|
-
return (
|
|
7573
|
+
function getInsertInFrontOfRNode(parentTNode, currentTNode, lView) {
|
|
7574
|
+
return _getInsertInFrontOfRNodeWithI18n(parentTNode, currentTNode, lView);
|
|
7800
7575
|
}
|
|
7801
|
-
|
|
7802
|
-
const USE_EXHAUSTIVE_CHECK_NO_CHANGES_DEFAULT = false;
|
|
7803
|
-
const UseExhaustiveCheckNoChanges = new InjectionToken(ngDevMode ? 'exhaustive checkNoChanges' : '');
|
|
7804
|
-
|
|
7805
|
-
let _icuContainerIterate;
|
|
7806
7576
|
/**
|
|
7807
|
-
*
|
|
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`
|
|
7808
7586
|
*/
|
|
7809
|
-
function
|
|
7810
|
-
|
|
7587
|
+
function getInsertInFrontOfRNodeWithNoI18n(parentTNode, currentTNode, lView) {
|
|
7588
|
+
if (parentTNode.type & (8 /* TNodeType.ElementContainer */ | 32 /* TNodeType.Icu */)) {
|
|
7589
|
+
return getNativeByTNode(parentTNode, lView);
|
|
7590
|
+
}
|
|
7591
|
+
return null;
|
|
7811
7592
|
}
|
|
7812
7593
|
/**
|
|
7813
|
-
*
|
|
7594
|
+
* Tree shakable boundary for `getInsertInFrontOfRNodeWithI18n` function.
|
|
7814
7595
|
*
|
|
7815
|
-
* This function
|
|
7816
|
-
* bundler to tree shake ICU logic and only load it if ICU instruction is executed.
|
|
7596
|
+
* This function will only be set if i18n code runs.
|
|
7817
7597
|
*/
|
|
7818
|
-
|
|
7819
|
-
if (_icuContainerIterate === undefined) {
|
|
7820
|
-
// Do not inline this function. We want to keep `ensureIcuContainerVisitorLoaded` light, so it
|
|
7821
|
-
// can be inlined into call-site.
|
|
7822
|
-
_icuContainerIterate = loader();
|
|
7823
|
-
}
|
|
7824
|
-
}
|
|
7825
|
-
|
|
7598
|
+
let _getInsertInFrontOfRNodeWithI18n = getInsertInFrontOfRNodeWithNoI18n;
|
|
7826
7599
|
/**
|
|
7827
|
-
*
|
|
7828
|
-
*
|
|
7600
|
+
* Tree shakable boundary for `processI18nInsertBefore` function.
|
|
7601
|
+
*
|
|
7602
|
+
* This function will only be set if i18n code runs.
|
|
7829
7603
|
*/
|
|
7830
|
-
|
|
7831
|
-
|
|
7832
|
-
|
|
7833
|
-
|
|
7834
|
-
|
|
7835
|
-
/**
|
|
7836
|
-
* Marks a style as important.
|
|
7837
|
-
*/
|
|
7838
|
-
RendererStyleFlags2[RendererStyleFlags2["Important"] = 1] = "Important";
|
|
7839
|
-
/**
|
|
7840
|
-
* Marks a style as using dash case naming (this-is-dash-case).
|
|
7841
|
-
*/
|
|
7842
|
-
RendererStyleFlags2[RendererStyleFlags2["DashCase"] = 2] = "DashCase";
|
|
7843
|
-
})(RendererStyleFlags2 || (RendererStyleFlags2 = {}));
|
|
7844
|
-
|
|
7604
|
+
let _processI18nInsertBefore;
|
|
7605
|
+
function setI18nHandling(getInsertInFrontOfRNodeWithI18n, processI18nInsertBefore) {
|
|
7606
|
+
_getInsertInFrontOfRNodeWithI18n = getInsertInFrontOfRNodeWithI18n;
|
|
7607
|
+
_processI18nInsertBefore = processI18nInsertBefore;
|
|
7608
|
+
}
|
|
7845
7609
|
/**
|
|
7846
|
-
*
|
|
7847
|
-
*
|
|
7848
|
-
*
|
|
7610
|
+
* Appends the `child` native node (or a collection of nodes) to the `parent`.
|
|
7611
|
+
*
|
|
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
|
|
7849
7616
|
*/
|
|
7850
|
-
function
|
|
7851
|
-
|
|
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);
|
|
7626
|
+
}
|
|
7627
|
+
}
|
|
7628
|
+
else {
|
|
7629
|
+
nativeAppendOrInsertBefore(renderer, parentRNode, childRNode, anchorNode, false);
|
|
7630
|
+
}
|
|
7631
|
+
}
|
|
7632
|
+
_processI18nInsertBefore !== undefined &&
|
|
7633
|
+
_processI18nInsertBefore(renderer, childTNode, lView, childRNode, parentRNode);
|
|
7852
7634
|
}
|
|
7853
|
-
|
|
7854
7635
|
/**
|
|
7855
|
-
*
|
|
7856
|
-
*
|
|
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).
|
|
7857
7639
|
*/
|
|
7858
|
-
function
|
|
7859
|
-
|
|
7860
|
-
|
|
7861
|
-
|
|
7862
|
-
|
|
7863
|
-
|
|
7864
|
-
|
|
7865
|
-
|
|
7866
|
-
|
|
7867
|
-
|
|
7868
|
-
|
|
7869
|
-
if (isLContainer(lNodeToHandle)) {
|
|
7870
|
-
lContainer = lNodeToHandle;
|
|
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);
|
|
7871
7651
|
}
|
|
7872
|
-
else if (
|
|
7873
|
-
|
|
7874
|
-
ngDevMode && assertDefined(lNodeToHandle[HOST], 'HOST must be defined for a component LView');
|
|
7875
|
-
lNodeToHandle = lNodeToHandle[HOST];
|
|
7652
|
+
else if (tNodeType & 4 /* TNodeType.Container */) {
|
|
7653
|
+
return getBeforeNodeForView(-1, lView[tNode.index]);
|
|
7876
7654
|
}
|
|
7877
|
-
|
|
7878
|
-
|
|
7879
|
-
if (
|
|
7880
|
-
|
|
7655
|
+
else if (tNodeType & 8 /* TNodeType.ElementContainer */) {
|
|
7656
|
+
const elIcuContainerChild = tNode.child;
|
|
7657
|
+
if (elIcuContainerChild !== null) {
|
|
7658
|
+
return getFirstNativeNode(lView, elIcuContainerChild);
|
|
7881
7659
|
}
|
|
7882
7660
|
else {
|
|
7883
|
-
|
|
7661
|
+
const rNodeOrLContainer = lView[tNode.index];
|
|
7662
|
+
if (isLContainer(rNodeOrLContainer)) {
|
|
7663
|
+
return getBeforeNodeForView(-1, rNodeOrLContainer);
|
|
7664
|
+
}
|
|
7665
|
+
else {
|
|
7666
|
+
return unwrapRNode(rNodeOrLContainer);
|
|
7667
|
+
}
|
|
7884
7668
|
}
|
|
7885
7669
|
}
|
|
7886
|
-
else if (
|
|
7887
|
-
|
|
7670
|
+
else if (tNodeType & 128 /* TNodeType.LetDeclaration */) {
|
|
7671
|
+
return getFirstNativeNode(lView, tNode.next);
|
|
7888
7672
|
}
|
|
7889
|
-
else if (
|
|
7890
|
-
|
|
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]);
|
|
7891
7678
|
}
|
|
7892
|
-
else
|
|
7893
|
-
|
|
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);
|
|
7691
|
+
}
|
|
7894
7692
|
}
|
|
7895
|
-
|
|
7896
|
-
|
|
7693
|
+
}
|
|
7694
|
+
return null;
|
|
7695
|
+
}
|
|
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];
|
|
7703
|
+
}
|
|
7704
|
+
return null;
|
|
7705
|
+
}
|
|
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);
|
|
7897
7713
|
}
|
|
7898
7714
|
}
|
|
7715
|
+
return lContainer[NATIVE];
|
|
7899
7716
|
}
|
|
7900
7717
|
/**
|
|
7901
|
-
*
|
|
7902
|
-
*
|
|
7903
|
-
* Because some root nodes of the view may be containers, we sometimes need
|
|
7904
|
-
* to propagate deeply into the nested containers to remove all elements in the
|
|
7905
|
-
* views beneath it.
|
|
7906
|
-
*
|
|
7907
|
-
* @param tView The `TView' of the `LView` from which elements should be added or removed
|
|
7908
|
-
* @param lView The view from which elements should be added or removed
|
|
7718
|
+
* Performs the operation of `action` on the node. Typically this involves inserting or removing
|
|
7719
|
+
* nodes on the LView or projection boundary.
|
|
7909
7720
|
*/
|
|
7910
|
-
function
|
|
7911
|
-
|
|
7912
|
-
|
|
7913
|
-
|
|
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;
|
|
7728
|
+
}
|
|
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
|
+
}
|
|
7738
|
+
}
|
|
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
|
+
}
|
|
7759
|
+
}
|
|
7760
|
+
tNode = isProjection ? tNode.projectionNext : tNode.next;
|
|
7761
|
+
}
|
|
7914
7762
|
}
|
|
7915
|
-
|
|
7916
|
-
|
|
7917
|
-
*
|
|
7918
|
-
* Because some root nodes of the view may be containers, we sometimes need
|
|
7919
|
-
* to propagate deeply into the nested containers to add all elements in the
|
|
7920
|
-
* views beneath it.
|
|
7921
|
-
*
|
|
7922
|
-
* @param tView The `TView' of the `LView` from which elements should be added or removed
|
|
7923
|
-
* @param parentTNode The `TNode` where the `LView` should be attached to.
|
|
7924
|
-
* @param renderer Current renderer to use for DOM manipulations.
|
|
7925
|
-
* @param lView The view from which elements should be added or removed
|
|
7926
|
-
* @param parentNativeNode The parent `RElement` where it should be inserted into.
|
|
7927
|
-
* @param beforeNode The node before which elements should be added, if insert mode
|
|
7928
|
-
*/
|
|
7929
|
-
function addViewToDOM(tView, parentTNode, renderer, lView, parentNativeNode, beforeNode) {
|
|
7930
|
-
lView[HOST] = parentNativeNode;
|
|
7931
|
-
lView[T_HOST] = parentTNode;
|
|
7932
|
-
applyView(tView, lView, renderer, 1 /* WalkTNodeTreeAction.Insert */, parentNativeNode, beforeNode);
|
|
7763
|
+
function applyView(tView, lView, renderer, action, parentRElement, beforeNode) {
|
|
7764
|
+
applyNodes(renderer, action, tView.firstChild, lView, parentRElement, beforeNode, false);
|
|
7933
7765
|
}
|
|
7934
7766
|
/**
|
|
7935
|
-
*
|
|
7767
|
+
* `applyProjection` performs operation on the projection.
|
|
7936
7768
|
*
|
|
7937
|
-
*
|
|
7938
|
-
*
|
|
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
|
|
7939
7775
|
*/
|
|
7940
|
-
function
|
|
7941
|
-
|
|
7942
|
-
|
|
7943
|
-
|
|
7944
|
-
|
|
7945
|
-
|
|
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);
|
|
7946
7782
|
}
|
|
7947
7783
|
/**
|
|
7948
|
-
*
|
|
7949
|
-
*
|
|
7784
|
+
* `applyProjectionRecursive` performs operation on the projection specified by `action` (insert,
|
|
7785
|
+
* detach, destroy)
|
|
7950
7786
|
*
|
|
7951
|
-
*
|
|
7952
|
-
*
|
|
7953
|
-
* - Must process containers instead of their views to avoid splicing
|
|
7954
|
-
* when views are destroyed and re-added.
|
|
7955
|
-
* - Using a while loop because it's faster than recursion
|
|
7956
|
-
* - Destroy only called on movement to sibling or movement to parent (laterally or up)
|
|
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.
|
|
7957
7789
|
*
|
|
7958
|
-
*
|
|
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.
|
|
7959
7796
|
*/
|
|
7960
|
-
function
|
|
7961
|
-
|
|
7962
|
-
|
|
7963
|
-
|
|
7964
|
-
|
|
7965
|
-
|
|
7966
|
-
|
|
7967
|
-
|
|
7968
|
-
|
|
7969
|
-
|
|
7970
|
-
|
|
7971
|
-
|
|
7972
|
-
|
|
7973
|
-
|
|
7974
|
-
|
|
7975
|
-
const firstView = lViewOrLContainer[CONTAINER_HEADER_OFFSET];
|
|
7976
|
-
if (firstView)
|
|
7977
|
-
next = firstView;
|
|
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);
|
|
7978
7812
|
}
|
|
7979
|
-
|
|
7980
|
-
|
|
7981
|
-
|
|
7982
|
-
|
|
7983
|
-
|
|
7984
|
-
|
|
7985
|
-
|
|
7986
|
-
|
|
7987
|
-
}
|
|
7988
|
-
if (lViewOrLContainer === null)
|
|
7989
|
-
lViewOrLContainer = rootView;
|
|
7990
|
-
if (isLView(lViewOrLContainer)) {
|
|
7991
|
-
cleanUpView(lViewOrLContainer[TVIEW], lViewOrLContainer);
|
|
7992
|
-
}
|
|
7993
|
-
next = lViewOrLContainer && lViewOrLContainer[NEXT];
|
|
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 */;
|
|
7994
7821
|
}
|
|
7995
|
-
|
|
7822
|
+
applyNodes(renderer, action, nodeToProject, projectedComponentLView, parentRElement, beforeNode, true);
|
|
7996
7823
|
}
|
|
7997
7824
|
}
|
|
7998
|
-
function detachMovedView(declarationContainer, lView) {
|
|
7999
|
-
ngDevMode && assertLContainer(declarationContainer);
|
|
8000
|
-
ngDevMode &&
|
|
8001
|
-
assertDefined(declarationContainer[MOVED_VIEWS], 'A projected view should belong to a non-empty projected views collection');
|
|
8002
|
-
const movedViews = declarationContainer[MOVED_VIEWS];
|
|
8003
|
-
const declarationViewIndex = movedViews.indexOf(lView);
|
|
8004
|
-
movedViews.splice(declarationViewIndex, 1);
|
|
8005
|
-
}
|
|
8006
7825
|
/**
|
|
8007
|
-
*
|
|
8008
|
-
*
|
|
7826
|
+
* `applyContainer` performs an operation on the container and its views as specified by
|
|
7827
|
+
* `action` (insert, detach, destroy)
|
|
8009
7828
|
*
|
|
8010
|
-
*
|
|
8011
|
-
*
|
|
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.
|
|
8012
7837
|
*/
|
|
8013
|
-
function
|
|
8014
|
-
|
|
8015
|
-
|
|
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);
|
|
8016
7854
|
}
|
|
8017
|
-
|
|
8018
|
-
|
|
8019
|
-
applyView(
|
|
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);
|
|
8020
7858
|
}
|
|
8021
|
-
destroyViewTree(lView);
|
|
8022
7859
|
}
|
|
8023
7860
|
/**
|
|
8024
|
-
*
|
|
8025
|
-
* listeners. Listeners are removed as the last step so events delivered in the onDestroys hooks
|
|
8026
|
-
* can be propagated to @Output listeners.
|
|
7861
|
+
* Writes class/style to element.
|
|
8027
7862
|
*
|
|
8028
|
-
* @param
|
|
8029
|
-
* @param
|
|
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).
|
|
8030
7869
|
*/
|
|
8031
|
-
function
|
|
8032
|
-
if (
|
|
8033
|
-
|
|
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);
|
|
7875
|
+
}
|
|
7876
|
+
else {
|
|
7877
|
+
renderer.addClass(rNode, prop);
|
|
7878
|
+
}
|
|
8034
7879
|
}
|
|
8035
|
-
|
|
8036
|
-
|
|
8037
|
-
|
|
8038
|
-
|
|
8039
|
-
lView[FLAGS] &= ~128 /* LViewFlags.Attached */;
|
|
8040
|
-
// Mark the LView as destroyed *before* executing the onDestroy hooks. An onDestroy hook
|
|
8041
|
-
// runs arbitrary user code, which could include its own `viewRef.destroy()` (or similar). If
|
|
8042
|
-
// We don't flag the view as destroyed before the hooks, this could lead to an infinite loop.
|
|
8043
|
-
// This also aligns with the ViewEngine behavior. It also means that the onDestroy hook is
|
|
8044
|
-
// really more of an "afterDestroy" hook if you think about it.
|
|
8045
|
-
lView[FLAGS] |= 256 /* LViewFlags.Destroyed */;
|
|
8046
|
-
lView[REACTIVE_TEMPLATE_CONSUMER] && consumerDestroy(lView[REACTIVE_TEMPLATE_CONSUMER]);
|
|
8047
|
-
executeOnDestroys(tView, lView);
|
|
8048
|
-
processCleanups(tView, lView);
|
|
8049
|
-
// For component views only, the local renderer is destroyed at clean up time.
|
|
8050
|
-
if (lView[TVIEW].type === 1 /* TViewType.Component */) {
|
|
8051
|
-
lView[RENDERER].destroy();
|
|
7880
|
+
else {
|
|
7881
|
+
let flags = prop.indexOf('-') === -1 ? undefined : RendererStyleFlags2.DashCase;
|
|
7882
|
+
if (value == null /** || value === undefined */) {
|
|
7883
|
+
renderer.removeStyle(rNode, prop, flags);
|
|
8052
7884
|
}
|
|
8053
|
-
|
|
8054
|
-
|
|
8055
|
-
|
|
8056
|
-
|
|
8057
|
-
if (
|
|
8058
|
-
|
|
8059
|
-
|
|
8060
|
-
|
|
8061
|
-
const lQueries = lView[QUERIES];
|
|
8062
|
-
if (lQueries !== null) {
|
|
8063
|
-
lQueries.detachView(tView);
|
|
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;
|
|
8064
7893
|
}
|
|
7894
|
+
renderer.setStyle(rNode, prop, value, flags);
|
|
8065
7895
|
}
|
|
8066
|
-
// Unregister the view once everything else has been cleaned up.
|
|
8067
|
-
unregisterLView(lView);
|
|
8068
|
-
}
|
|
8069
|
-
finally {
|
|
8070
|
-
setActiveConsumer(prevConsumer);
|
|
8071
7896
|
}
|
|
8072
7897
|
}
|
|
8073
|
-
|
|
8074
|
-
function
|
|
8075
|
-
|
|
8076
|
-
const
|
|
8077
|
-
|
|
8078
|
-
|
|
8079
|
-
|
|
8080
|
-
|
|
8081
|
-
|
|
8082
|
-
|
|
8083
|
-
const targetIdx = tCleanup[i + 3];
|
|
8084
|
-
ngDevMode && assertNumber(targetIdx, 'cleanup target must be a number');
|
|
8085
|
-
if (targetIdx >= 0) {
|
|
8086
|
-
// Destroy anything whose teardown is a function call (e.g. QueryList, ModelSignal).
|
|
8087
|
-
lCleanup[targetIdx]();
|
|
8088
|
-
}
|
|
8089
|
-
else {
|
|
8090
|
-
// Subscription
|
|
8091
|
-
lCleanup[-targetIdx].unsubscribe();
|
|
8092
|
-
}
|
|
8093
|
-
i += 2;
|
|
8094
|
-
}
|
|
8095
|
-
else {
|
|
8096
|
-
// This is a cleanup function that is grouped with the index of its context
|
|
8097
|
-
const context = lCleanup[tCleanup[i + 1]];
|
|
8098
|
-
tCleanup[i].call(context);
|
|
8099
|
-
}
|
|
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());
|
|
8100
7908
|
}
|
|
7909
|
+
const preHookType = isUpdatePhase
|
|
7910
|
+
? 2 /* ProfilerEvent.TemplateUpdateStart */
|
|
7911
|
+
: 0 /* ProfilerEvent.TemplateCreateStart */;
|
|
7912
|
+
profiler(preHookType, context, templateFn);
|
|
7913
|
+
templateFn(rf, context);
|
|
8101
7914
|
}
|
|
8102
|
-
|
|
8103
|
-
|
|
8104
|
-
|
|
8105
|
-
|
|
8106
|
-
|
|
8107
|
-
|
|
8108
|
-
// themselves from mutating the array during iteration.
|
|
8109
|
-
lView[ON_DESTROY_HOOKS] = null;
|
|
8110
|
-
for (let i = 0; i < destroyHooks.length; i++) {
|
|
8111
|
-
const destroyHooksFn = destroyHooks[i];
|
|
8112
|
-
ngDevMode && assertFunction(destroyHooksFn, 'Expecting destroy hook to be a function.');
|
|
8113
|
-
destroyHooksFn();
|
|
8114
|
-
}
|
|
7915
|
+
finally {
|
|
7916
|
+
setSelectedIndex(prevSelectedIndex);
|
|
7917
|
+
const postHookType = isUpdatePhase
|
|
7918
|
+
? 3 /* ProfilerEvent.TemplateUpdateEnd */
|
|
7919
|
+
: 1 /* ProfilerEvent.TemplateCreateEnd */;
|
|
7920
|
+
profiler(postHookType, context, templateFn);
|
|
8115
7921
|
}
|
|
8116
|
-
|
|
8117
|
-
|
|
8118
|
-
|
|
8119
|
-
|
|
8120
|
-
|
|
8121
|
-
|
|
8122
|
-
|
|
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);
|
|
8123
7930
|
}
|
|
8124
7931
|
}
|
|
8125
|
-
/**
|
|
8126
|
-
|
|
8127
|
-
|
|
8128
|
-
|
|
8129
|
-
|
|
8130
|
-
|
|
8131
|
-
|
|
8132
|
-
|
|
8133
|
-
|
|
8134
|
-
|
|
8135
|
-
|
|
8136
|
-
|
|
8137
|
-
|
|
8138
|
-
|
|
8139
|
-
profiler(4 /* ProfilerEvent.LifecycleHookStart */, callContext, hook);
|
|
8140
|
-
try {
|
|
8141
|
-
hook.call(callContext);
|
|
8142
|
-
}
|
|
8143
|
-
finally {
|
|
8144
|
-
profiler(5 /* ProfilerEvent.LifecycleHookEnd */, callContext, hook);
|
|
8145
|
-
}
|
|
8146
|
-
}
|
|
8147
|
-
}
|
|
8148
|
-
else {
|
|
8149
|
-
profiler(4 /* ProfilerEvent.LifecycleHookStart */, context, toCall);
|
|
8150
|
-
try {
|
|
8151
|
-
toCall.call(context);
|
|
8152
|
-
}
|
|
8153
|
-
finally {
|
|
8154
|
-
profiler(5 /* ProfilerEvent.LifecycleHookEnd */, context, toCall);
|
|
8155
|
-
}
|
|
8156
|
-
}
|
|
8157
|
-
}
|
|
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;
|
|
8158
7946
|
}
|
|
8159
7947
|
}
|
|
8160
7948
|
}
|
|
8161
7949
|
/**
|
|
8162
|
-
*
|
|
8163
|
-
*
|
|
8164
|
-
* There are two reasons why we may not be able to insert a element immediately.
|
|
8165
|
-
* - Projection: When creating a child content element of a component, we have to skip the
|
|
8166
|
-
* insertion because the content of a component will be projected.
|
|
8167
|
-
* `<component><content>delayed due to projection</content></component>`
|
|
8168
|
-
* - Parent container is disconnected: This can happen when we are inserting a view into
|
|
8169
|
-
* parent container, which itself is disconnected. For example the parent container is part
|
|
8170
|
-
* of a View which has not be inserted or is made for projection but has not been inserted
|
|
8171
|
-
* into destination.
|
|
7950
|
+
* Locates the host native element, used for bootstrapping existing nodes into rendering pipeline.
|
|
8172
7951
|
*
|
|
8173
|
-
* @param
|
|
8174
|
-
* @param
|
|
8175
|
-
* @param
|
|
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.
|
|
7956
|
+
*/
|
|
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;
|
|
7971
|
+
}
|
|
7972
|
+
/**
|
|
7973
|
+
* Applies any root element transformations that are needed. If hydration is enabled,
|
|
7974
|
+
* this will process corrupted text nodes.
|
|
7975
|
+
*
|
|
7976
|
+
* @param rootElement the app root HTML Element
|
|
8176
7977
|
*/
|
|
8177
|
-
function
|
|
8178
|
-
|
|
7978
|
+
function applyRootElementTransform(rootElement) {
|
|
7979
|
+
_applyRootElementTransformImpl(rootElement);
|
|
8179
7980
|
}
|
|
8180
7981
|
/**
|
|
8181
|
-
*
|
|
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.
|
|
8182
7985
|
*
|
|
8183
|
-
*
|
|
8184
|
-
|
|
8185
|
-
|
|
8186
|
-
|
|
8187
|
-
*
|
|
7986
|
+
* @param rootElement the app root HTML Element
|
|
7987
|
+
*/
|
|
7988
|
+
let _applyRootElementTransformImpl = () => null;
|
|
7989
|
+
/**
|
|
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.
|
|
8188
7993
|
*
|
|
8189
|
-
* @param
|
|
8190
|
-
* @param tNode: `TNode` for which we wish to retrieve `RElement` (or `null` if host element is
|
|
8191
|
-
* needed).
|
|
8192
|
-
* @param lView: Current `LView`.
|
|
8193
|
-
* @returns `null` if the `RElement` can't be determined at this time (no parent / projection)
|
|
7994
|
+
* @param rootElement the app root HTML Element
|
|
8194
7995
|
*/
|
|
8195
|
-
function
|
|
8196
|
-
|
|
8197
|
-
|
|
8198
|
-
|
|
8199
|
-
|
|
8200
|
-
|
|
8201
|
-
parentTNode.type & (8 /* TNodeType.ElementContainer */ | 32 /* TNodeType.Icu */ | 128 /* TNodeType.LetDeclaration */)) {
|
|
8202
|
-
tNode = parentTNode;
|
|
8203
|
-
parentTNode = tNode.parent;
|
|
8204
|
-
}
|
|
8205
|
-
// If the parent tNode is null, then we are inserting across views: either into an embedded view
|
|
8206
|
-
// or a component view.
|
|
8207
|
-
if (parentTNode === null) {
|
|
8208
|
-
// We are inserting a root element of the component view into the component host element and
|
|
8209
|
-
// it should always be eager.
|
|
8210
|
-
return lView[HOST];
|
|
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);
|
|
8211
8002
|
}
|
|
8212
8003
|
else {
|
|
8213
|
-
|
|
8214
|
-
if (isComponentHost(parentTNode)) {
|
|
8215
|
-
ngDevMode && assertTNodeForLView(parentTNode, lView);
|
|
8216
|
-
const { encapsulation } = tView.data[parentTNode.directiveStart + parentTNode.componentOffset];
|
|
8217
|
-
// We've got a parent which is an element in the current view. We just need to verify if the
|
|
8218
|
-
// parent element is not a component. Component's content nodes are not inserted immediately
|
|
8219
|
-
// because they will be projected, and so doing insert at this point would be wasteful.
|
|
8220
|
-
// Since the projection would then move it to its final destination. Note that we can't
|
|
8221
|
-
// make this assumption when using the Shadow DOM, because the native projection placeholders
|
|
8222
|
-
// (<content> or <slot>) have to be in place as elements are being inserted.
|
|
8223
|
-
if (encapsulation === ViewEncapsulation.None ||
|
|
8224
|
-
encapsulation === ViewEncapsulation.Emulated) {
|
|
8225
|
-
return null;
|
|
8226
|
-
}
|
|
8227
|
-
}
|
|
8228
|
-
return getNativeByTNode(parentTNode, lView);
|
|
8004
|
+
processTextNodeMarkersBeforeHydration(rootElement);
|
|
8229
8005
|
}
|
|
8230
8006
|
}
|
|
8231
8007
|
/**
|
|
8232
|
-
*
|
|
8233
|
-
*
|
|
8234
|
-
* This method determines the `RNode` in front of which we should insert the `currentRNode`. This
|
|
8235
|
-
* takes `TNode.insertBeforeIndex` into account if i18n code has been invoked.
|
|
8236
|
-
*
|
|
8237
|
-
* @param parentTNode parent `TNode`
|
|
8238
|
-
* @param currentTNode current `TNode` (The node which we would like to insert into the DOM)
|
|
8239
|
-
* @param lView current `LView`
|
|
8008
|
+
* Sets the implementation for the `applyRootElementTransform` function.
|
|
8240
8009
|
*/
|
|
8241
|
-
function
|
|
8242
|
-
|
|
8010
|
+
function enableApplyRootElementTransformImpl() {
|
|
8011
|
+
_applyRootElementTransformImpl = applyRootElementTransformImpl;
|
|
8243
8012
|
}
|
|
8244
8013
|
/**
|
|
8245
|
-
*
|
|
8246
|
-
* account)
|
|
8014
|
+
* Mapping between attributes names that don't correspond to their element property names.
|
|
8247
8015
|
*
|
|
8248
|
-
*
|
|
8249
|
-
*
|
|
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.
|
|
8250
8019
|
*
|
|
8251
|
-
*
|
|
8252
|
-
*
|
|
8253
|
-
* @param lView current `LView`
|
|
8020
|
+
* Note: this mapping has to be kept in sync with the equally named mapping in the template
|
|
8021
|
+
* type-checking machinery of ngtsc.
|
|
8254
8022
|
*/
|
|
8255
|
-
function
|
|
8256
|
-
if (
|
|
8257
|
-
return
|
|
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.
|
|
8258
8046
|
}
|
|
8259
|
-
|
|
8047
|
+
setDomProperty(tNode, lView, propName, value, renderer, sanitizer);
|
|
8260
8048
|
}
|
|
8261
8049
|
/**
|
|
8262
|
-
*
|
|
8263
|
-
*
|
|
8264
|
-
*
|
|
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.
|
|
8265
8057
|
*/
|
|
8266
|
-
|
|
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) {
|
|
8092
|
+
return;
|
|
8093
|
+
}
|
|
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);
|
|
8101
|
+
}
|
|
8102
|
+
else {
|
|
8103
|
+
renderer.setAttribute(element, attrName, debugValue);
|
|
8104
|
+
}
|
|
8105
|
+
}
|
|
8106
|
+
else {
|
|
8107
|
+
const textContent = escapeCommentText(`bindings=${JSON.stringify({ [attrName]: debugValue }, null, 2)}`);
|
|
8108
|
+
renderer.setValue(element, textContent);
|
|
8109
|
+
}
|
|
8110
|
+
}
|
|
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;
|
|
8115
|
+
}
|
|
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
|
+
}
|
|
8125
|
+
}
|
|
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);
|
|
8131
|
+
}
|
|
8132
|
+
}
|
|
8133
|
+
}
|
|
8267
8134
|
/**
|
|
8268
|
-
*
|
|
8269
|
-
*
|
|
8270
|
-
* This function will only be set if i18n code runs.
|
|
8135
|
+
* Instantiate all the directives that were previously resolved on the current node.
|
|
8271
8136
|
*/
|
|
8272
|
-
|
|
8273
|
-
|
|
8274
|
-
|
|
8275
|
-
|
|
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);
|
|
8160
|
+
}
|
|
8161
|
+
}
|
|
8162
|
+
}
|
|
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);
|
|
8176
|
+
}
|
|
8177
|
+
}
|
|
8178
|
+
}
|
|
8179
|
+
finally {
|
|
8180
|
+
setSelectedIndex(-1);
|
|
8181
|
+
setCurrentDirectiveIndex(currentDirectiveIndex);
|
|
8182
|
+
}
|
|
8276
8183
|
}
|
|
8277
8184
|
/**
|
|
8278
|
-
*
|
|
8185
|
+
* Invoke the host bindings in creation mode.
|
|
8279
8186
|
*
|
|
8280
|
-
* @param
|
|
8281
|
-
* @param
|
|
8282
|
-
* @param childRNode The native child (or children) that should be appended
|
|
8283
|
-
* @param childTNode The TNode of the child element
|
|
8187
|
+
* @param def `DirectiveDef` which may contain the `hostBindings` function.
|
|
8188
|
+
* @param directive Instance of directive.
|
|
8284
8189
|
*/
|
|
8285
|
-
function
|
|
8286
|
-
|
|
8287
|
-
|
|
8288
|
-
const parentTNode = childTNode.parent || lView[T_HOST];
|
|
8289
|
-
const anchorNode = getInsertInFrontOfRNode(parentTNode, childTNode, lView);
|
|
8290
|
-
if (parentRNode != null) {
|
|
8291
|
-
if (Array.isArray(childRNode)) {
|
|
8292
|
-
for (let i = 0; i < childRNode.length; i++) {
|
|
8293
|
-
nativeAppendOrInsertBefore(renderer, parentRNode, childRNode[i], anchorNode, false);
|
|
8294
|
-
}
|
|
8295
|
-
}
|
|
8296
|
-
else {
|
|
8297
|
-
nativeAppendOrInsertBefore(renderer, parentRNode, childRNode, anchorNode, false);
|
|
8298
|
-
}
|
|
8190
|
+
function invokeHostBindingsInCreationMode(def, directive) {
|
|
8191
|
+
if (def.hostBindings !== null) {
|
|
8192
|
+
def.hostBindings(1 /* RenderFlags.Create */, directive);
|
|
8299
8193
|
}
|
|
8300
|
-
_processI18nInsertBefore !== undefined &&
|
|
8301
|
-
_processI18nInsertBefore(renderer, childTNode, lView, childRNode, parentRNode);
|
|
8302
8194
|
}
|
|
8303
8195
|
/**
|
|
8304
|
-
*
|
|
8305
|
-
*
|
|
8306
|
-
* Native nodes are returned in the order in which those appear in the native tree (DOM).
|
|
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.
|
|
8307
8198
|
*/
|
|
8308
|
-
function
|
|
8309
|
-
|
|
8310
|
-
|
|
8311
|
-
|
|
8312
|
-
|
|
8313
|
-
|
|
8314
|
-
|
|
8315
|
-
|
|
8316
|
-
|
|
8317
|
-
|
|
8318
|
-
|
|
8319
|
-
|
|
8320
|
-
|
|
8321
|
-
|
|
8322
|
-
|
|
8323
|
-
|
|
8324
|
-
|
|
8325
|
-
|
|
8326
|
-
|
|
8327
|
-
}
|
|
8328
|
-
else {
|
|
8329
|
-
const rNodeOrLContainer = lView[tNode.index];
|
|
8330
|
-
if (isLContainer(rNodeOrLContainer)) {
|
|
8331
|
-
return getBeforeNodeForView(-1, rNodeOrLContainer);
|
|
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);
|
|
8332
8218
|
}
|
|
8333
8219
|
else {
|
|
8334
|
-
|
|
8335
|
-
}
|
|
8336
|
-
}
|
|
8337
|
-
}
|
|
8338
|
-
else if (tNodeType & 128 /* TNodeType.LetDeclaration */) {
|
|
8339
|
-
return getFirstNativeNode(lView, tNode.next);
|
|
8340
|
-
}
|
|
8341
|
-
else if (tNodeType & 32 /* TNodeType.Icu */) {
|
|
8342
|
-
let nextRNode = icuContainerIterate(tNode, lView);
|
|
8343
|
-
let rNode = nextRNode();
|
|
8344
|
-
// If the ICU container has no nodes, than we use the ICU anchor as the node.
|
|
8345
|
-
return rNode || unwrapRNode(lView[tNode.index]);
|
|
8346
|
-
}
|
|
8347
|
-
else {
|
|
8348
|
-
const projectionNodes = getProjectionNodes(lView, tNode);
|
|
8349
|
-
if (projectionNodes !== null) {
|
|
8350
|
-
if (Array.isArray(projectionNodes)) {
|
|
8351
|
-
return projectionNodes[0];
|
|
8220
|
+
matches.push(def);
|
|
8352
8221
|
}
|
|
8353
|
-
const parentView = getLViewParent(lView[DECLARATION_COMPONENT_VIEW]);
|
|
8354
|
-
ngDevMode && assertParentView(parentView);
|
|
8355
|
-
return getFirstNativeNode(parentView, projectionNodes);
|
|
8356
|
-
}
|
|
8357
|
-
else {
|
|
8358
|
-
return getFirstNativeNode(lView, tNode.next);
|
|
8359
8222
|
}
|
|
8360
8223
|
}
|
|
8361
8224
|
}
|
|
8362
|
-
return
|
|
8225
|
+
return matches;
|
|
8363
8226
|
}
|
|
8364
|
-
function
|
|
8365
|
-
if (
|
|
8366
|
-
|
|
8367
|
-
|
|
8368
|
-
|
|
8369
|
-
|
|
8370
|
-
return componentHost.projection[slotIdx];
|
|
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.`);
|
|
8371
8233
|
}
|
|
8372
|
-
|
|
8234
|
+
const element = getNativeByTNode(tNode, lView);
|
|
8235
|
+
setElementAttribute(lView[RENDERER], element, namespace, tNode.value, name, value, sanitizer);
|
|
8373
8236
|
}
|
|
8374
|
-
function
|
|
8375
|
-
|
|
8376
|
-
|
|
8377
|
-
|
|
8378
|
-
|
|
8379
|
-
|
|
8380
|
-
|
|
8381
|
-
}
|
|
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);
|
|
8382
8244
|
}
|
|
8383
|
-
return lContainer[NATIVE];
|
|
8384
8245
|
}
|
|
8385
8246
|
/**
|
|
8386
|
-
*
|
|
8387
|
-
*
|
|
8247
|
+
* Sets initial input properties on directive instances from attribute data
|
|
8248
|
+
*
|
|
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
|
|
8388
8254
|
*/
|
|
8389
|
-
function
|
|
8390
|
-
|
|
8391
|
-
|
|
8392
|
-
|
|
8393
|
-
|
|
8394
|
-
|
|
8395
|
-
|
|
8396
|
-
|
|
8397
|
-
|
|
8398
|
-
assertTNodeType(tNode, 3 /* TNodeType.AnyRNode */ | 12 /* TNodeType.AnyContainer */ | 16 /* TNodeType.Projection */ | 32 /* TNodeType.Icu */);
|
|
8399
|
-
const rawSlotValue = lView[tNode.index];
|
|
8400
|
-
const tNodeType = tNode.type;
|
|
8401
|
-
if (isProjection) {
|
|
8402
|
-
if (action === 0 /* WalkTNodeTreeAction.Create */) {
|
|
8403
|
-
rawSlotValue && attachPatchData(unwrapRNode(rawSlotValue), lView);
|
|
8404
|
-
tNode.flags |= 2 /* TNodeFlags.isProjected */;
|
|
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);
|
|
8405
8264
|
}
|
|
8406
8265
|
}
|
|
8407
|
-
|
|
8408
|
-
|
|
8409
|
-
|
|
8410
|
-
|
|
8411
|
-
|
|
8412
|
-
|
|
8413
|
-
|
|
8414
|
-
|
|
8415
|
-
|
|
8416
|
-
|
|
8417
|
-
|
|
8418
|
-
|
|
8419
|
-
|
|
8420
|
-
|
|
8421
|
-
|
|
8422
|
-
|
|
8423
|
-
|
|
8424
|
-
|
|
8425
|
-
|
|
8266
|
+
}
|
|
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
|
+
///////////////////////////////
|
|
8313
|
+
/**
|
|
8314
|
+
* Stores meta-data for a property binding to be used by TestBed's `DebugElement.properties`.
|
|
8315
|
+
*
|
|
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;
|
|
8319
|
+
*
|
|
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.
|
|
8327
|
+
*
|
|
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)
|
|
8333
|
+
*/
|
|
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);
|
|
8426
8346
|
}
|
|
8347
|
+
tData[bindingIndex] = bindingMetadata;
|
|
8427
8348
|
}
|
|
8428
|
-
tNode = isProjection ? tNode.projectionNext : tNode.next;
|
|
8429
8349
|
}
|
|
8430
8350
|
}
|
|
8431
|
-
function applyView(tView, lView, renderer, action, parentRElement, beforeNode) {
|
|
8432
|
-
applyNodes(renderer, action, tView.firstChild, lView, parentRElement, beforeNode, false);
|
|
8433
|
-
}
|
|
8434
8351
|
/**
|
|
8435
|
-
*
|
|
8436
|
-
*
|
|
8437
|
-
* Inserting a projection requires us to locate the projected nodes from the parent component. The
|
|
8438
|
-
* complication is that those nodes themselves could be re-projected from their parent component.
|
|
8439
|
-
*
|
|
8440
|
-
* @param tView The `TView` of `LView` which needs to be inserted, detached, destroyed
|
|
8441
|
-
* @param lView The `LView` which needs to be inserted, detached, destroyed.
|
|
8442
|
-
* @param tProjectionNode node to project
|
|
8352
|
+
* There are cases where the sub component's renderer needs to be included
|
|
8353
|
+
* instead of the current renderer (see the componentSyntheticHost* instructions).
|
|
8443
8354
|
*/
|
|
8444
|
-
function
|
|
8445
|
-
|
|
8446
|
-
|
|
8447
|
-
|
|
8448
|
-
|
|
8449
|
-
|
|
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]);
|
|
8364
|
+
}
|
|
8365
|
+
return lView[RENDERER];
|
|
8366
|
+
}
|
|
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);
|
|
8450
8375
|
}
|
|
8451
8376
|
/**
|
|
8452
|
-
*
|
|
8453
|
-
* detach, destroy)
|
|
8454
|
-
*
|
|
8455
|
-
* Inserting a projection requires us to locate the projected nodes from the parent component. The
|
|
8456
|
-
* complication is that those nodes themselves could be re-projected from their parent component.
|
|
8377
|
+
* Set all directive inputs with the specific public name on the node.
|
|
8457
8378
|
*
|
|
8458
|
-
* @param
|
|
8459
|
-
* @param
|
|
8460
|
-
* @param lView
|
|
8461
|
-
* @param
|
|
8462
|
-
* @param
|
|
8463
|
-
* @param beforeNode Before which node the insertions should happen.
|
|
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.
|
|
8464
8384
|
*/
|
|
8465
|
-
function
|
|
8466
|
-
const
|
|
8467
|
-
const
|
|
8468
|
-
|
|
8469
|
-
|
|
8470
|
-
|
|
8471
|
-
|
|
8472
|
-
|
|
8473
|
-
|
|
8474
|
-
|
|
8475
|
-
|
|
8476
|
-
|
|
8477
|
-
|
|
8478
|
-
|
|
8479
|
-
|
|
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
|
+
}
|
|
8398
|
+
}
|
|
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;
|
|
8480
8406
|
}
|
|
8481
8407
|
}
|
|
8408
|
+
return hasMatch;
|
|
8409
|
+
}
|
|
8410
|
+
/**
|
|
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.
|
|
8418
|
+
*/
|
|
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
|
+
}
|
|
8482
8431
|
else {
|
|
8483
|
-
|
|
8484
|
-
|
|
8485
|
-
|
|
8486
|
-
|
|
8487
|
-
|
|
8488
|
-
|
|
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;
|
|
8446
|
+
}
|
|
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;
|
|
8450
|
+
}
|
|
8489
8451
|
}
|
|
8490
|
-
applyNodes(renderer, action, nodeToProject, projectedComponentLView, parentRElement, beforeNode, true);
|
|
8491
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;
|
|
8459
|
+
}
|
|
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]);
|
|
8492
8474
|
}
|
|
8493
8475
|
/**
|
|
8494
|
-
*
|
|
8495
|
-
* `action` (insert, detach, destroy)
|
|
8476
|
+
* Syncs an LView instance with its blueprint if they have gotten out of sync.
|
|
8496
8477
|
*
|
|
8497
|
-
*
|
|
8498
|
-
*
|
|
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:
|
|
8499
8480
|
*
|
|
8500
|
-
*
|
|
8501
|
-
*
|
|
8502
|
-
*
|
|
8503
|
-
*
|
|
8504
|
-
*
|
|
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
|
|
8505
8501
|
*/
|
|
8506
|
-
function
|
|
8507
|
-
|
|
8508
|
-
|
|
8509
|
-
const native = unwrapRNode(lContainer);
|
|
8510
|
-
// An LContainer can be created dynamically on any node by injecting ViewContainerRef.
|
|
8511
|
-
// Asking for a ViewContainerRef on an element will result in a creation of a separate anchor
|
|
8512
|
-
// node (comment in the DOM) that will be different from the LContainer's host node. In this
|
|
8513
|
-
// particular case we need to execute action on 2 nodes:
|
|
8514
|
-
// - container's host node (this is done in the executeActionOnElementOrContainer)
|
|
8515
|
-
// - container's host node (this is done here)
|
|
8516
|
-
if (anchor !== native) {
|
|
8517
|
-
// This is very strange to me (Misko). I would expect that the native is same as anchor. I
|
|
8518
|
-
// don't see a reason why they should be different, but they are.
|
|
8519
|
-
//
|
|
8520
|
-
// If they are we need to process the second anchor as well.
|
|
8521
|
-
applyToElementOrContainer(action, renderer, parentRElement, anchor, beforeNode);
|
|
8522
|
-
}
|
|
8523
|
-
for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
|
|
8524
|
-
const lView = lContainer[i];
|
|
8525
|
-
applyView(lView[TVIEW], lView, renderer, action, parentRElement, anchor);
|
|
8502
|
+
function syncViewWithBlueprint(tView, lView) {
|
|
8503
|
+
for (let i = lView.length; i < tView.blueprint.length; i++) {
|
|
8504
|
+
lView.push(tView.blueprint[i]);
|
|
8526
8505
|
}
|
|
8527
8506
|
}
|
|
8528
8507
|
/**
|
|
8529
|
-
*
|
|
8530
|
-
*
|
|
8531
|
-
*
|
|
8532
|
-
*
|
|
8533
|
-
*
|
|
8534
|
-
* @param prop Property to write to. This would be the class/style name.
|
|
8535
|
-
* @param value Value to write. If `null`/`undefined`/`false` this is considered a remove (set/add
|
|
8536
|
-
* otherwise).
|
|
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.
|
|
8537
8513
|
*/
|
|
8538
|
-
function
|
|
8539
|
-
|
|
8540
|
-
|
|
8541
|
-
|
|
8542
|
-
|
|
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;
|
|
8543
8536
|
}
|
|
8544
|
-
|
|
8545
|
-
|
|
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);
|
|
8546
8556
|
}
|
|
8547
8557
|
}
|
|
8548
|
-
|
|
8549
|
-
|
|
8550
|
-
|
|
8551
|
-
|
|
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;
|
|
8552
8564
|
}
|
|
8553
|
-
|
|
8554
|
-
|
|
8555
|
-
|
|
8556
|
-
|
|
8557
|
-
|
|
8558
|
-
|
|
8559
|
-
|
|
8560
|
-
|
|
8561
|
-
|
|
8562
|
-
|
|
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]);
|
|
8576
|
+
}
|
|
8577
|
+
}
|
|
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);
|
|
8563
8595
|
}
|
|
8596
|
+
// execute creation mode of a view
|
|
8597
|
+
renderView(embeddedTView, embeddedLView, context);
|
|
8598
|
+
return embeddedLView;
|
|
8564
8599
|
}
|
|
8600
|
+
finally {
|
|
8601
|
+
setActiveConsumer(prevConsumer);
|
|
8602
|
+
}
|
|
8603
|
+
}
|
|
8604
|
+
/**
|
|
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).
|
|
8610
|
+
*/
|
|
8611
|
+
function shouldAddViewToDom(tNode, dehydratedView) {
|
|
8612
|
+
return (!dehydratedView || dehydratedView.firstChild === null || hasInSkipHydrationBlockFlag(tNode));
|
|
8565
8613
|
}
|
|
8566
8614
|
|
|
8615
|
+
const USE_EXHAUSTIVE_CHECK_NO_CHANGES_DEFAULT = false;
|
|
8616
|
+
const UseExhaustiveCheckNoChanges = new InjectionToken(ngDevMode ? 'exhaustive checkNoChanges' : '');
|
|
8617
|
+
|
|
8567
8618
|
function collectNativeNodes(tView, lView, tNode, result, isProjection = false) {
|
|
8568
8619
|
while (tNode !== null) {
|
|
8569
8620
|
// Let declarations don't have corresponding DOM nodes so we skip over them.
|
|
@@ -9102,7 +9153,7 @@ function detectChangesInView(lView, mode) {
|
|
|
9102
9153
|
if (consumer) {
|
|
9103
9154
|
consumer.dirty = false;
|
|
9104
9155
|
}
|
|
9105
|
-
lView[FLAGS] &=
|
|
9156
|
+
lView[FLAGS] &= ~(8192 /* LViewFlags.HasChildViewsToRefresh */ | 1024 /* LViewFlags.RefreshView */);
|
|
9106
9157
|
if (shouldRefreshView) {
|
|
9107
9158
|
refreshView(tView, lView, tView.template, lView[CONTEXT]);
|
|
9108
9159
|
}
|
|
@@ -9298,7 +9349,7 @@ function detachView(lContainer, removeIndex) {
|
|
|
9298
9349
|
viewToDetach[PARENT] = null;
|
|
9299
9350
|
viewToDetach[NEXT] = null;
|
|
9300
9351
|
// Unsets the attached flag
|
|
9301
|
-
viewToDetach[FLAGS] &=
|
|
9352
|
+
viewToDetach[FLAGS] &= ~128 /* LViewFlags.Attached */;
|
|
9302
9353
|
}
|
|
9303
9354
|
return viewToDetach;
|
|
9304
9355
|
}
|
|
@@ -9520,7 +9571,9 @@ class ViewRef {
|
|
|
9520
9571
|
* @Component({
|
|
9521
9572
|
* selector: 'giant-list',
|
|
9522
9573
|
* template: `
|
|
9523
|
-
*
|
|
9574
|
+
* @for(d of dataProvider.data; track $index) {
|
|
9575
|
+
* <li>Data {{d}}</li>
|
|
9576
|
+
* }
|
|
9524
9577
|
* `,
|
|
9525
9578
|
* })
|
|
9526
9579
|
* class GiantList {
|
|
@@ -9544,7 +9597,7 @@ class ViewRef {
|
|
|
9544
9597
|
* ```
|
|
9545
9598
|
*/
|
|
9546
9599
|
detach() {
|
|
9547
|
-
this._lView[FLAGS] &=
|
|
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
|
|
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,
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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.0']
|
|
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,
|
|
14961
|
-
def.pipeDefs = extractDefListOrFactory(dependencies,
|
|
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,
|
|
15226
|
+
function extractDefListOrFactory(dependencies, defExtractor) {
|
|
15176
15227
|
if (!dependencies) {
|
|
15177
15228
|
return null;
|
|
15178
15229
|
}
|
|
15179
|
-
|
|
15180
|
-
|
|
15181
|
-
|
|
15182
|
-
|
|
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
|
|
15714
|
-
|
|
15715
|
-
|
|
15716
|
-
|
|
15717
|
-
|
|
15718
|
-
|
|
15719
|
-
|
|
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
|
-
|
|
15722
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
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
|
|
15813
|
+
function declareDirectiveHostTemplate(declarationLView, declarationTView, index, templateFn, decls, vars, tagName, attrs, flags, localRefsIndex, localRefExtractor) {
|
|
15747
15814
|
const adjustedIndex = index + HEADER_OFFSET;
|
|
15748
|
-
|
|
15749
|
-
|
|
15750
|
-
:
|
|
15751
|
-
|
|
15752
|
-
|
|
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
|
-
|
|
15755
|
-
|
|
15756
|
-
if (wasLastNodeCreated()) {
|
|
15757
|
-
appendChild(declarationTView, declarationLView, comment, tNode);
|
|
15824
|
+
else {
|
|
15825
|
+
tNode = declarationTView.data[adjustedIndex];
|
|
15758
15826
|
}
|
|
15759
|
-
|
|
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
|
-
|
|
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
|
|
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
|
//
|
|
@@ -16177,7 +16261,6 @@ let ngZoneInstanceId = 0;
|
|
|
16177
16261
|
*
|
|
16178
16262
|
* ```ts
|
|
16179
16263
|
* import {Component, NgZone} from '@angular/core';
|
|
16180
|
-
* import {NgIf} from '@angular/common';
|
|
16181
16264
|
*
|
|
16182
16265
|
* @Component({
|
|
16183
16266
|
* selector: 'ng-zone-demo',
|
|
@@ -16185,7 +16268,9 @@ let ngZoneInstanceId = 0;
|
|
|
16185
16268
|
* <h2>Demo: NgZone</h2>
|
|
16186
16269
|
*
|
|
16187
16270
|
* <p>Progress: {{progress}}%</p>
|
|
16188
|
-
*
|
|
16271
|
+
* @if(progress >= 100) {
|
|
16272
|
+
* <p>Done processing {{label}} of Angular zone!</p>
|
|
16273
|
+
* }
|
|
16189
16274
|
*
|
|
16190
16275
|
* <button (click)="processWithinAngularZone()">Process within Angular zone</button>
|
|
16191
16276
|
* <button (click)="processOutsideOfAngularZone()">Process outside of Angular zone</button>
|
|
@@ -18810,9 +18895,6 @@ function isComputedNode(node) {
|
|
|
18810
18895
|
function isTemplateEffectNode(node) {
|
|
18811
18896
|
return node.kind === 'template';
|
|
18812
18897
|
}
|
|
18813
|
-
function isEffectNode(node) {
|
|
18814
|
-
return node.kind === 'effect';
|
|
18815
|
-
}
|
|
18816
18898
|
function isSignalNode(node) {
|
|
18817
18899
|
return node.kind === 'signal';
|
|
18818
18900
|
}
|
|
@@ -18827,39 +18909,59 @@ function getTemplateConsumer(injector) {
|
|
|
18827
18909
|
const lView = getNodeInjectorLView(injector);
|
|
18828
18910
|
assertLView(lView);
|
|
18829
18911
|
const templateLView = lView[tNode.index];
|
|
18830
|
-
|
|
18831
|
-
|
|
18912
|
+
if (isLView(templateLView)) {
|
|
18913
|
+
return templateLView[REACTIVE_TEMPLATE_CONSUMER] ?? null;
|
|
18914
|
+
}
|
|
18915
|
+
return null;
|
|
18832
18916
|
}
|
|
18917
|
+
const signalDebugMap = new WeakMap();
|
|
18918
|
+
let counter$1 = 0;
|
|
18833
18919
|
function getNodesAndEdgesFromSignalMap(signalMap) {
|
|
18834
18920
|
const nodes = Array.from(signalMap.keys());
|
|
18835
18921
|
const debugSignalGraphNodes = [];
|
|
18836
18922
|
const edges = [];
|
|
18837
18923
|
for (const [consumer, producers] of signalMap.entries()) {
|
|
18838
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
|
+
}
|
|
18839
18931
|
// collect node
|
|
18840
|
-
if (isComputedNode(consumer)
|
|
18932
|
+
if (isComputedNode(consumer)) {
|
|
18841
18933
|
debugSignalGraphNodes.push({
|
|
18842
18934
|
label: consumer.debugName,
|
|
18843
18935
|
value: consumer.value,
|
|
18844
18936
|
kind: consumer.kind,
|
|
18937
|
+
epoch: consumer.version,
|
|
18938
|
+
debuggableFn: consumer.computation,
|
|
18939
|
+
id,
|
|
18845
18940
|
});
|
|
18846
18941
|
}
|
|
18847
|
-
else if (
|
|
18942
|
+
else if (isSignalNode(consumer)) {
|
|
18848
18943
|
debugSignalGraphNodes.push({
|
|
18849
|
-
label: consumer.debugName
|
|
18944
|
+
label: consumer.debugName,
|
|
18945
|
+
value: consumer.value,
|
|
18850
18946
|
kind: consumer.kind,
|
|
18947
|
+
epoch: consumer.version,
|
|
18948
|
+
id,
|
|
18851
18949
|
});
|
|
18852
18950
|
}
|
|
18853
|
-
else if (
|
|
18951
|
+
else if (isTemplateEffectNode(consumer)) {
|
|
18854
18952
|
debugSignalGraphNodes.push({
|
|
18855
|
-
label: consumer.debugName,
|
|
18953
|
+
label: consumer.debugName ?? consumer.lView?.[HOST]?.tagName?.toLowerCase?.(),
|
|
18856
18954
|
kind: consumer.kind,
|
|
18955
|
+
epoch: consumer.version,
|
|
18956
|
+
id,
|
|
18857
18957
|
});
|
|
18858
18958
|
}
|
|
18859
18959
|
else {
|
|
18860
18960
|
debugSignalGraphNodes.push({
|
|
18861
18961
|
label: consumer.debugName,
|
|
18862
18962
|
kind: consumer.kind,
|
|
18963
|
+
epoch: consumer.version,
|
|
18964
|
+
id,
|
|
18863
18965
|
});
|
|
18864
18966
|
}
|
|
18865
18967
|
// collect edges for node
|
|
@@ -20076,7 +20178,7 @@ class ApplicationRef {
|
|
|
20076
20178
|
synchronizeOnce() {
|
|
20077
20179
|
// First, process any dirty root effects.
|
|
20078
20180
|
if (this.dirtyFlags & 16 /* ApplicationRefDirtyFlags.RootEffects */) {
|
|
20079
|
-
this.dirtyFlags &=
|
|
20181
|
+
this.dirtyFlags &= ~16 /* ApplicationRefDirtyFlags.RootEffects */;
|
|
20080
20182
|
this.rootEffectScheduler.flush();
|
|
20081
20183
|
}
|
|
20082
20184
|
// First check dirty views, if there are any.
|
|
@@ -20087,7 +20189,7 @@ class ApplicationRef {
|
|
|
20087
20189
|
// `ApplicationRef.tick()` and the `NgZone` integration.
|
|
20088
20190
|
const useGlobalCheck = Boolean(this.dirtyFlags & 1 /* ApplicationRefDirtyFlags.ViewTreeGlobal */);
|
|
20089
20191
|
// Clear the view-related dirty flags.
|
|
20090
|
-
this.dirtyFlags &=
|
|
20192
|
+
this.dirtyFlags &= ~7 /* ApplicationRefDirtyFlags.ViewTreeAny */;
|
|
20091
20193
|
// Set the AfterRender bit, as we're checking views and will need to run afterRender hooks.
|
|
20092
20194
|
this.dirtyFlags |= 8 /* ApplicationRefDirtyFlags.AfterRender */;
|
|
20093
20195
|
// Check all potentially dirty views.
|
|
@@ -20107,7 +20209,7 @@ class ApplicationRef {
|
|
|
20107
20209
|
// If `markForCheck()` was called during view checking, it will have set the `ViewTreeCheck`
|
|
20108
20210
|
// flag. We clear the flag here because, for backwards compatibility, `markForCheck()`
|
|
20109
20211
|
// during view checking doesn't cause the view to be re-checked.
|
|
20110
|
-
this.dirtyFlags &=
|
|
20212
|
+
this.dirtyFlags &= ~4 /* ApplicationRefDirtyFlags.ViewTreeCheck */;
|
|
20111
20213
|
// Check if any views are still dirty after checking and we need to loop back.
|
|
20112
20214
|
this.syncDirtyFlagsWithViews();
|
|
20113
20215
|
if (this.dirtyFlags &
|
|
@@ -20125,7 +20227,7 @@ class ApplicationRef {
|
|
|
20125
20227
|
}
|
|
20126
20228
|
// Even if there were no dirty views, afterRender hooks might still be dirty.
|
|
20127
20229
|
if (this.dirtyFlags & 8 /* ApplicationRefDirtyFlags.AfterRender */) {
|
|
20128
|
-
this.dirtyFlags &=
|
|
20230
|
+
this.dirtyFlags &= ~8 /* ApplicationRefDirtyFlags.AfterRender */;
|
|
20129
20231
|
this.afterRenderManager.execute();
|
|
20130
20232
|
// afterRender hooks might influence dirty flags.
|
|
20131
20233
|
}
|
|
@@ -20154,7 +20256,7 @@ class ApplicationRef {
|
|
|
20154
20256
|
else {
|
|
20155
20257
|
// Even though this flag may be set, none of _our_ views require traversal, and so the
|
|
20156
20258
|
// `ApplicationRef` doesn't require any repeated checking.
|
|
20157
|
-
this.dirtyFlags &=
|
|
20259
|
+
this.dirtyFlags &= ~7 /* ApplicationRefDirtyFlags.ViewTreeAny */;
|
|
20158
20260
|
}
|
|
20159
20261
|
}
|
|
20160
20262
|
/**
|
|
@@ -20675,6 +20777,11 @@ function shouldAttachTrigger(triggerType, lView, tNode) {
|
|
|
20675
20777
|
// TriggerType.Prefetch is active only on the client
|
|
20676
20778
|
return !(typeof ngServerMode !== 'undefined' && ngServerMode);
|
|
20677
20779
|
}
|
|
20780
|
+
/** Whether a given defer block has `hydrate` triggers. */
|
|
20781
|
+
function hasHydrateTriggers(flags) {
|
|
20782
|
+
return (flags != null &&
|
|
20783
|
+
(flags & 1 /* TDeferDetailsFlags.HasHydrateTriggers */) === 1 /* TDeferDetailsFlags.HasHydrateTriggers */);
|
|
20784
|
+
}
|
|
20678
20785
|
/**
|
|
20679
20786
|
* Defines whether a regular trigger logic (e.g. "on viewport") should be attached
|
|
20680
20787
|
* to a defer block. This function defines a condition, which mutually excludes
|
|
@@ -20685,20 +20792,18 @@ function shouldAttachRegularTrigger(lView, tNode) {
|
|
|
20685
20792
|
const injector = lView[INJECTOR];
|
|
20686
20793
|
const tDetails = getTDeferBlockDetails(lView[TVIEW], tNode);
|
|
20687
20794
|
const incrementalHydrationEnabled = isIncrementalHydrationEnabled(injector);
|
|
20688
|
-
const
|
|
20689
|
-
(tDetails.flags & 1 /* TDeferDetailsFlags.HasHydrateTriggers */) ===
|
|
20690
|
-
1 /* TDeferDetailsFlags.HasHydrateTriggers */;
|
|
20795
|
+
const _hasHydrateTriggers = hasHydrateTriggers(tDetails.flags);
|
|
20691
20796
|
// On the server:
|
|
20692
20797
|
if (typeof ngServerMode !== 'undefined' && ngServerMode) {
|
|
20693
20798
|
// Regular triggers are activated on the server when:
|
|
20694
20799
|
// - Either Incremental Hydration is *not* enabled
|
|
20695
20800
|
// - Or Incremental Hydration is enabled, but a given block doesn't have "hydrate" triggers
|
|
20696
|
-
return !incrementalHydrationEnabled || !
|
|
20801
|
+
return !incrementalHydrationEnabled || !_hasHydrateTriggers;
|
|
20697
20802
|
}
|
|
20698
20803
|
// On the client:
|
|
20699
20804
|
const lDetails = getLDeferBlockDetails(lView, tNode);
|
|
20700
20805
|
const wasServerSideRendered = lDetails[SSR_UNIQUE_ID] !== null;
|
|
20701
|
-
if (
|
|
20806
|
+
if (_hasHydrateTriggers && wasServerSideRendered && incrementalHydrationEnabled) {
|
|
20702
20807
|
return false;
|
|
20703
20808
|
}
|
|
20704
20809
|
return true;
|
|
@@ -20830,12 +20935,17 @@ function ɵɵdefer(index, primaryTmplIndex, dependencyResolverFn, loadingTmplInd
|
|
|
20830
20935
|
const lView = getLView();
|
|
20831
20936
|
const tView = getTView();
|
|
20832
20937
|
const adjustedIndex = index + HEADER_OFFSET;
|
|
20833
|
-
const tNode =
|
|
20938
|
+
const tNode = declareNoDirectiveHostTemplate(lView, tView, index, null, 0, 0);
|
|
20834
20939
|
const injector = lView[INJECTOR];
|
|
20835
20940
|
if (tView.firstCreatePass) {
|
|
20836
20941
|
performanceMarkFeature('NgDefer');
|
|
20837
|
-
if (ngDevMode
|
|
20838
|
-
|
|
20942
|
+
if (ngDevMode) {
|
|
20943
|
+
if (typeof ngHmrMode !== 'undefined' && ngHmrMode) {
|
|
20944
|
+
logHmrWarning(injector);
|
|
20945
|
+
}
|
|
20946
|
+
if (hasHydrateTriggers(flags)) {
|
|
20947
|
+
assertIncrementalHydrationIsConfigured(injector);
|
|
20948
|
+
}
|
|
20839
20949
|
}
|
|
20840
20950
|
const tDetails = {
|
|
20841
20951
|
primaryTmplIndex,
|
|
@@ -20883,7 +20993,6 @@ function ɵɵdefer(index, primaryTmplIndex, dependencyResolverFn, loadingTmplInd
|
|
|
20883
20993
|
setLDeferBlockDetails(lView, adjustedIndex, lDetails);
|
|
20884
20994
|
let registry = null;
|
|
20885
20995
|
if (ssrUniqueId !== null) {
|
|
20886
|
-
ngDevMode && assertIncrementalHydrationIsConfigured(injector);
|
|
20887
20996
|
// Store this defer block in the registry, to have an access to
|
|
20888
20997
|
// internal data structures from hydration runtime code.
|
|
20889
20998
|
registry = injector.get(DEHYDRATED_BLOCK_REGISTRY);
|
|
@@ -21791,7 +21900,7 @@ function ɵɵconditionalCreate(index, templateFn, decls, vars, tagName, attrsInd
|
|
|
21791
21900
|
const lView = getLView();
|
|
21792
21901
|
const tView = getTView();
|
|
21793
21902
|
const attrs = getConstant(tView.consts, attrsIndex);
|
|
21794
|
-
|
|
21903
|
+
declareNoDirectiveHostTemplate(lView, tView, index, templateFn, decls, vars, tagName, attrs, 256 /* TNodeFlags.isControlFlowStart */, localRefsIndex, localRefExtractor);
|
|
21795
21904
|
return ɵɵconditionalBranchCreate;
|
|
21796
21905
|
}
|
|
21797
21906
|
/**
|
|
@@ -21817,7 +21926,7 @@ function ɵɵconditionalBranchCreate(index, templateFn, decls, vars, tagName, at
|
|
|
21817
21926
|
const lView = getLView();
|
|
21818
21927
|
const tView = getTView();
|
|
21819
21928
|
const attrs = getConstant(tView.consts, attrsIndex);
|
|
21820
|
-
|
|
21929
|
+
declareNoDirectiveHostTemplate(lView, tView, index, templateFn, decls, vars, tagName, attrs, 512 /* TNodeFlags.isInControlFlow */, localRefsIndex, localRefExtractor);
|
|
21821
21930
|
return ɵɵconditionalBranchCreate;
|
|
21822
21931
|
}
|
|
21823
21932
|
/**
|
|
@@ -21958,13 +22067,13 @@ function ɵɵrepeaterCreate(index, templateFn, decls, vars, tagName, attrsIndex,
|
|
|
21958
22067
|
: trackByFn;
|
|
21959
22068
|
const metadata = new RepeaterMetadata(hasEmptyBlock, boundTrackBy);
|
|
21960
22069
|
hostLView[HEADER_OFFSET + index] = metadata;
|
|
21961
|
-
|
|
22070
|
+
declareNoDirectiveHostTemplate(lView, tView, index + 1, templateFn, decls, vars, tagName, getConstant(tView.consts, attrsIndex), 256 /* TNodeFlags.isControlFlowStart */);
|
|
21962
22071
|
if (hasEmptyBlock) {
|
|
21963
22072
|
ngDevMode &&
|
|
21964
22073
|
assertDefined(emptyDecls, 'Missing number of declarations for the empty repeater block.');
|
|
21965
22074
|
ngDevMode &&
|
|
21966
22075
|
assertDefined(emptyVars, 'Missing number of bindings for the empty repeater block.');
|
|
21967
|
-
|
|
22076
|
+
declareNoDirectiveHostTemplate(lView, tView, index + 2, emptyTemplateFn, emptyDecls, emptyVars, emptyTagName, getConstant(tView.consts, emptyAttrsIndex), 512 /* TNodeFlags.isInControlFlow */);
|
|
21968
22077
|
}
|
|
21969
22078
|
}
|
|
21970
22079
|
function isViewExpensiveToRecreate(lView) {
|
|
@@ -22201,42 +22310,24 @@ function setDirectiveInputsWhichShadowsStyling(tView, tNode, lView, value, isCla
|
|
|
22201
22310
|
*/
|
|
22202
22311
|
function ɵɵelementStart(index, name, attrsIndex, localRefsIndex) {
|
|
22203
22312
|
const lView = getLView();
|
|
22204
|
-
|
|
22205
|
-
const
|
|
22206
|
-
|
|
22207
|
-
assertEqual(getBindingIndex(), tView.bindingStartIndex, 'elements should be created before any bindings');
|
|
22208
|
-
ngDevMode && assertIndexInRange(lView, adjustedIndex);
|
|
22209
|
-
const renderer = lView[RENDERER];
|
|
22313
|
+
ngDevMode && assertTNodeCreationIndex(lView, index);
|
|
22314
|
+
const tView = lView[TVIEW];
|
|
22315
|
+
const adjustedIndex = index + HEADER_OFFSET;
|
|
22210
22316
|
const tNode = tView.firstCreatePass
|
|
22211
|
-
?
|
|
22317
|
+
? directiveHostFirstCreatePass(adjustedIndex, lView, 2 /* TNodeType.Element */, name, findDirectiveDefMatches, getBindingsEnabled(), attrsIndex, localRefsIndex)
|
|
22212
22318
|
: tView.data[adjustedIndex];
|
|
22213
|
-
|
|
22214
|
-
|
|
22215
|
-
|
|
22216
|
-
if (ngDevMode && tView.firstCreatePass) {
|
|
22217
|
-
validateElementIsKnown(native, lView, tNode.value, tView.schemas, hasDirectives);
|
|
22218
|
-
}
|
|
22219
|
-
setCurrentTNode(tNode, true);
|
|
22220
|
-
setupStaticAttributes(renderer, native, tNode);
|
|
22221
|
-
if (!isDetachedByI18n(tNode) && wasLastNodeCreated()) {
|
|
22222
|
-
// In the i18n case, the translation may have removed this element, so only add it if it is not
|
|
22223
|
-
// detached. See `TNodeType.Placeholder` and `LFrame.inI18n` for more context.
|
|
22224
|
-
appendChild(tView, lView, native, tNode);
|
|
22225
|
-
}
|
|
22226
|
-
// any immediate children of a component or template container must be pre-emptively
|
|
22227
|
-
// monkey-patched with the component view data so that the element can be inspected
|
|
22228
|
-
// later on using any element discovery utility methods (see `element_discovery.ts`)
|
|
22229
|
-
if (getElementDepthCount() === 0 || hasDirectives) {
|
|
22230
|
-
attachPatchData(native, lView);
|
|
22231
|
-
}
|
|
22232
|
-
increaseElementDepthCount();
|
|
22233
|
-
if (hasDirectives) {
|
|
22319
|
+
elementLikeStartShared(tNode, lView, index, name, _locateOrCreateElementNode);
|
|
22320
|
+
if (isDirectiveHost(tNode)) {
|
|
22321
|
+
const tView = lView[TVIEW];
|
|
22234
22322
|
createDirectivesInstances(tView, lView, tNode);
|
|
22235
22323
|
executeContentQueries(tView, tNode, lView);
|
|
22236
22324
|
}
|
|
22237
|
-
if (localRefsIndex
|
|
22325
|
+
if (localRefsIndex != null) {
|
|
22238
22326
|
saveResolvedLocalsInData(lView, tNode);
|
|
22239
22327
|
}
|
|
22328
|
+
if (ngDevMode && lView[TVIEW].firstCreatePass) {
|
|
22329
|
+
validateElementIsKnown(lView, tNode);
|
|
22330
|
+
}
|
|
22240
22331
|
return ɵɵelementStart;
|
|
22241
22332
|
}
|
|
22242
22333
|
/**
|
|
@@ -22246,31 +22337,23 @@ function ɵɵelementStart(index, name, attrsIndex, localRefsIndex) {
|
|
|
22246
22337
|
* @codeGenApi
|
|
22247
22338
|
*/
|
|
22248
22339
|
function ɵɵelementEnd() {
|
|
22249
|
-
|
|
22250
|
-
|
|
22251
|
-
|
|
22252
|
-
|
|
22253
|
-
|
|
22254
|
-
|
|
22255
|
-
|
|
22256
|
-
currentTNode = currentTNode.parent;
|
|
22257
|
-
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);
|
|
22258
22347
|
}
|
|
22259
|
-
|
|
22260
|
-
ngDevMode && assertTNodeType(tNode, 3 /* TNodeType.AnyRNode */);
|
|
22261
|
-
if (isSkipHydrationRootTNode(tNode)) {
|
|
22348
|
+
if (isSkipHydrationRootTNode(currentTNode)) {
|
|
22262
22349
|
leaveSkipHydrationBlock();
|
|
22263
22350
|
}
|
|
22264
22351
|
decreaseElementDepthCount();
|
|
22265
|
-
|
|
22266
|
-
|
|
22267
|
-
elementEndFirstCreatePass(tView, tNode);
|
|
22268
|
-
}
|
|
22269
|
-
if (tNode.classesWithoutHost != null && hasClassInput(tNode)) {
|
|
22270
|
-
setDirectiveInputsWhichShadowsStyling(tView, tNode, getLView(), tNode.classesWithoutHost, true);
|
|
22352
|
+
if (currentTNode.classesWithoutHost != null && hasClassInput(currentTNode)) {
|
|
22353
|
+
setDirectiveInputsWhichShadowsStyling(tView, currentTNode, getLView(), currentTNode.classesWithoutHost, true);
|
|
22271
22354
|
}
|
|
22272
|
-
if (
|
|
22273
|
-
setDirectiveInputsWhichShadowsStyling(tView,
|
|
22355
|
+
if (currentTNode.stylesWithoutHost != null && hasStyleInput(currentTNode)) {
|
|
22356
|
+
setDirectiveInputsWhichShadowsStyling(tView, currentTNode, getLView(), currentTNode.stylesWithoutHost, false);
|
|
22274
22357
|
}
|
|
22275
22358
|
return ɵɵelementEnd;
|
|
22276
22359
|
}
|
|
@@ -22290,26 +22373,23 @@ function ɵɵelement(index, name, attrsIndex, localRefsIndex) {
|
|
|
22290
22373
|
ɵɵelementEnd();
|
|
22291
22374
|
return ɵɵelement;
|
|
22292
22375
|
}
|
|
22293
|
-
let _locateOrCreateElementNode = (tView, lView, tNode,
|
|
22376
|
+
let _locateOrCreateElementNode = (tView, lView, tNode, name, index) => {
|
|
22294
22377
|
lastNodeWasCreated(true);
|
|
22295
|
-
return createElementNode(
|
|
22378
|
+
return createElementNode(lView[RENDERER], name, getNamespace());
|
|
22296
22379
|
};
|
|
22297
22380
|
/**
|
|
22298
22381
|
* Enables hydration code path (to lookup existing elements in DOM)
|
|
22299
22382
|
* in addition to the regular creation mode of element nodes.
|
|
22300
22383
|
*/
|
|
22301
|
-
function locateOrCreateElementNodeImpl(tView, lView, tNode,
|
|
22302
|
-
const
|
|
22303
|
-
const isNodeCreationMode = !hydrationInfo ||
|
|
22304
|
-
isInSkipHydrationBlock$1() ||
|
|
22305
|
-
isDetachedByI18n(tNode) ||
|
|
22306
|
-
isDisconnectedNode$1(hydrationInfo, index);
|
|
22384
|
+
function locateOrCreateElementNodeImpl(tView, lView, tNode, name, index) {
|
|
22385
|
+
const isNodeCreationMode = !canHydrateNode(lView, tNode);
|
|
22307
22386
|
lastNodeWasCreated(isNodeCreationMode);
|
|
22308
22387
|
// Regular creation mode.
|
|
22309
22388
|
if (isNodeCreationMode) {
|
|
22310
|
-
return createElementNode(
|
|
22389
|
+
return createElementNode(lView[RENDERER], name, getNamespace());
|
|
22311
22390
|
}
|
|
22312
22391
|
// Hydration mode, looking up an existing element in DOM.
|
|
22392
|
+
const hydrationInfo = lView[HYDRATION];
|
|
22313
22393
|
const native = locateNextRNode(hydrationInfo, tView, lView, tNode);
|
|
22314
22394
|
ngDevMode && validateMatchingNode(native, Node.ELEMENT_NODE, name, lView, tNode);
|
|
22315
22395
|
ngDevMode && markRNodeAsClaimedByHydration(native);
|
|
@@ -22349,26 +22429,6 @@ function enableLocateOrCreateElementNodeImpl() {
|
|
|
22349
22429
|
_locateOrCreateElementNode = locateOrCreateElementNodeImpl;
|
|
22350
22430
|
}
|
|
22351
22431
|
|
|
22352
|
-
function elementContainerStartFirstCreatePass(index, tView, lView, attrsIndex, localRefsIndex) {
|
|
22353
|
-
const tViewConsts = tView.consts;
|
|
22354
|
-
const attrs = getConstant(tViewConsts, attrsIndex);
|
|
22355
|
-
const tNode = getOrCreateTNode(tView, index, 8 /* TNodeType.ElementContainer */, 'ng-container', attrs);
|
|
22356
|
-
// While ng-container doesn't necessarily support styling, we use the style context to identify
|
|
22357
|
-
// and execute directives on the ng-container.
|
|
22358
|
-
if (attrs !== null) {
|
|
22359
|
-
computeStaticStyling(tNode, attrs, true);
|
|
22360
|
-
}
|
|
22361
|
-
const localRefs = getConstant(tViewConsts, localRefsIndex);
|
|
22362
|
-
if (getBindingsEnabled()) {
|
|
22363
|
-
resolveDirectives(tView, lView, tNode, localRefs, findDirectiveDefMatches);
|
|
22364
|
-
}
|
|
22365
|
-
// Merge the template attrs last so that they have the highest priority.
|
|
22366
|
-
tNode.mergedAttrs = mergeHostAttrs(tNode.mergedAttrs, tNode.attrs);
|
|
22367
|
-
if (tView.queries !== null) {
|
|
22368
|
-
tView.queries.elementStart(tView, tNode);
|
|
22369
|
-
}
|
|
22370
|
-
return tNode;
|
|
22371
|
-
}
|
|
22372
22432
|
/**
|
|
22373
22433
|
* Creates a logical container for other nodes (<ng-container>) backed by a comment node in the DOM.
|
|
22374
22434
|
* The instruction must later be followed by `elementContainerEnd()` call.
|
|
@@ -22386,22 +22446,15 @@ function elementContainerStartFirstCreatePass(index, tView, lView, attrsIndex, l
|
|
|
22386
22446
|
*/
|
|
22387
22447
|
function ɵɵelementContainerStart(index, attrsIndex, localRefsIndex) {
|
|
22388
22448
|
const lView = getLView();
|
|
22389
|
-
|
|
22449
|
+
ngDevMode && assertTNodeCreationIndex(lView, index);
|
|
22450
|
+
const tView = lView[TVIEW];
|
|
22390
22451
|
const adjustedIndex = index + HEADER_OFFSET;
|
|
22391
|
-
ngDevMode && assertIndexInRange(lView, adjustedIndex);
|
|
22392
|
-
ngDevMode &&
|
|
22393
|
-
assertEqual(getBindingIndex(), tView.bindingStartIndex, 'element containers should be created before any bindings');
|
|
22394
22452
|
const tNode = tView.firstCreatePass
|
|
22395
|
-
?
|
|
22453
|
+
? directiveHostFirstCreatePass(adjustedIndex, lView, 8 /* TNodeType.ElementContainer */, 'ng-container', findDirectiveDefMatches, getBindingsEnabled(), attrsIndex, localRefsIndex)
|
|
22396
22454
|
: tView.data[adjustedIndex];
|
|
22397
|
-
|
|
22398
|
-
const comment = _locateOrCreateElementContainerNode(tView, lView, tNode, index);
|
|
22399
|
-
lView[adjustedIndex] = comment;
|
|
22400
|
-
if (wasLastNodeCreated()) {
|
|
22401
|
-
appendChild(tView, lView, comment, tNode);
|
|
22402
|
-
}
|
|
22403
|
-
attachPatchData(comment, lView);
|
|
22455
|
+
elementLikeStartShared(tNode, lView, index, 'ng-container', _locateOrCreateElementContainerNode);
|
|
22404
22456
|
if (isDirectiveHost(tNode)) {
|
|
22457
|
+
const tView = lView[TVIEW];
|
|
22405
22458
|
createDirectivesInstances(tView, lView, tNode);
|
|
22406
22459
|
executeContentQueries(tView, tNode, lView);
|
|
22407
22460
|
}
|
|
@@ -22417,23 +22470,14 @@ function ɵɵelementContainerStart(index, attrsIndex, localRefsIndex) {
|
|
|
22417
22470
|
* @codeGenApi
|
|
22418
22471
|
*/
|
|
22419
22472
|
function ɵɵelementContainerEnd() {
|
|
22420
|
-
let currentTNode = getCurrentTNode();
|
|
22421
22473
|
const tView = getTView();
|
|
22422
|
-
|
|
22423
|
-
|
|
22424
|
-
|
|
22425
|
-
else {
|
|
22426
|
-
ngDevMode && assertHasParent(currentTNode);
|
|
22427
|
-
currentTNode = currentTNode.parent;
|
|
22428
|
-
setCurrentTNode(currentTNode, false);
|
|
22429
|
-
}
|
|
22430
|
-
ngDevMode && assertTNodeType(currentTNode, 8 /* TNodeType.ElementContainer */);
|
|
22474
|
+
const initialTNode = getCurrentTNode();
|
|
22475
|
+
ngDevMode && assertDefined(initialTNode, 'No parent node to close.');
|
|
22476
|
+
const currentTNode = elementLikeEndShared(initialTNode);
|
|
22431
22477
|
if (tView.firstCreatePass) {
|
|
22432
|
-
|
|
22433
|
-
if (isContentQueryHost(currentTNode)) {
|
|
22434
|
-
tView.queries.elementEnd(currentTNode);
|
|
22435
|
-
}
|
|
22478
|
+
directiveHostEndFirstCreatePass(tView, currentTNode);
|
|
22436
22479
|
}
|
|
22480
|
+
ngDevMode && assertTNodeType(currentTNode, 8 /* TNodeType.ElementContainer */);
|
|
22437
22481
|
return ɵɵelementContainerEnd;
|
|
22438
22482
|
}
|
|
22439
22483
|
/**
|
|
@@ -22452,28 +22496,25 @@ function ɵɵelementContainer(index, attrsIndex, localRefsIndex) {
|
|
|
22452
22496
|
ɵɵelementContainerEnd();
|
|
22453
22497
|
return ɵɵelementContainer;
|
|
22454
22498
|
}
|
|
22455
|
-
let _locateOrCreateElementContainerNode = (tView, lView, tNode, index) => {
|
|
22499
|
+
let _locateOrCreateElementContainerNode = (tView, lView, tNode, commentText, index) => {
|
|
22456
22500
|
lastNodeWasCreated(true);
|
|
22457
|
-
return createCommentNode(lView[RENDERER], ngDevMode ?
|
|
22501
|
+
return createCommentNode(lView[RENDERER], ngDevMode ? commentText : '');
|
|
22458
22502
|
};
|
|
22459
22503
|
/**
|
|
22460
22504
|
* Enables hydration code path (to lookup existing elements in DOM)
|
|
22461
22505
|
* in addition to the regular creation mode of comment nodes that
|
|
22462
22506
|
* represent <ng-container>'s anchor.
|
|
22463
22507
|
*/
|
|
22464
|
-
function locateOrCreateElementContainerNode(tView, lView, tNode, index) {
|
|
22508
|
+
function locateOrCreateElementContainerNode(tView, lView, tNode, commentText, index) {
|
|
22465
22509
|
let comment;
|
|
22466
|
-
const
|
|
22467
|
-
const isNodeCreationMode = !hydrationInfo ||
|
|
22468
|
-
isInSkipHydrationBlock$1() ||
|
|
22469
|
-
isDisconnectedNode$1(hydrationInfo, index) ||
|
|
22470
|
-
isDetachedByI18n(tNode);
|
|
22510
|
+
const isNodeCreationMode = !canHydrateNode(lView, tNode);
|
|
22471
22511
|
lastNodeWasCreated(isNodeCreationMode);
|
|
22472
22512
|
// Regular creation mode.
|
|
22473
22513
|
if (isNodeCreationMode) {
|
|
22474
|
-
return createCommentNode(lView[RENDERER], ngDevMode ?
|
|
22514
|
+
return createCommentNode(lView[RENDERER], ngDevMode ? commentText : '');
|
|
22475
22515
|
}
|
|
22476
22516
|
// Hydration mode, looking up existing elements in DOM.
|
|
22517
|
+
const hydrationInfo = lView[HYDRATION];
|
|
22477
22518
|
const currentRNode = locateNextRNode(hydrationInfo, tView, lView, tNode);
|
|
22478
22519
|
ngDevMode && validateNodeExists(currentRNode, lView, tNode);
|
|
22479
22520
|
const ngContainerSize = getNgContainerSize(hydrationInfo, index);
|
|
@@ -24551,7 +24592,7 @@ function ɵɵprojection(nodeIndex, selectorIndex = 0, attrs, fallbackTemplateFn,
|
|
|
24551
24592
|
// instances of the component may or may not insert it. Also it needs to be declare *before*
|
|
24552
24593
|
// the projection node in order to work correctly with hydration.
|
|
24553
24594
|
if (fallbackIndex !== null) {
|
|
24554
|
-
|
|
24595
|
+
declareNoDirectiveHostTemplate(lView, tView, fallbackIndex, fallbackTemplateFn, fallbackDecls, fallbackVars, null, attrs);
|
|
24555
24596
|
}
|
|
24556
24597
|
const tProjectionNode = getOrCreateTNode(tView, HEADER_OFFSET + nodeIndex, 16 /* TNodeType.Projection */, null, attrs || null);
|
|
24557
24598
|
// We can't use viewData[HOST_NODE] because projection nodes can be nested in embedded views.
|
|
@@ -24728,7 +24769,7 @@ function getTStylingRangePrevDuplicate(tStylingRange) {
|
|
|
24728
24769
|
function setTStylingRangePrev(tStylingRange, previous) {
|
|
24729
24770
|
ngDevMode && assertNumber(tStylingRange, 'expected number');
|
|
24730
24771
|
ngDevMode && assertNumberInRange(previous, 0, 32767 /* StylingRange.UNSIGNED_MASK */);
|
|
24731
|
-
return ((tStylingRange &
|
|
24772
|
+
return ((tStylingRange & ~4294836224 /* StylingRange.PREV_MASK */) |
|
|
24732
24773
|
(previous << 17 /* StylingRange.PREV_SHIFT */));
|
|
24733
24774
|
}
|
|
24734
24775
|
function setTStylingRangePrevDuplicate(tStylingRange) {
|
|
@@ -24742,7 +24783,7 @@ function getTStylingRangeNext(tStylingRange) {
|
|
|
24742
24783
|
function setTStylingRangeNext(tStylingRange, next) {
|
|
24743
24784
|
ngDevMode && assertNumber(tStylingRange, 'expected number');
|
|
24744
24785
|
ngDevMode && assertNumberInRange(next, 0, 32767 /* StylingRange.UNSIGNED_MASK */);
|
|
24745
|
-
return ((tStylingRange &
|
|
24786
|
+
return ((tStylingRange & ~131068 /* StylingRange.NEXT_MASK */) | //
|
|
24746
24787
|
(next << 2 /* StylingRange.NEXT_SHIFT */));
|
|
24747
24788
|
}
|
|
24748
24789
|
function getTStylingRangeNextDuplicate(tStylingRange) {
|
|
@@ -26070,9 +26111,7 @@ function ɵɵtext(index, value = '') {
|
|
|
26070
26111
|
const lView = getLView();
|
|
26071
26112
|
const tView = getTView();
|
|
26072
26113
|
const adjustedIndex = index + HEADER_OFFSET;
|
|
26073
|
-
ngDevMode &&
|
|
26074
|
-
assertEqual(getBindingIndex(), tView.bindingStartIndex, 'text nodes should be created before any bindings');
|
|
26075
|
-
ngDevMode && assertIndexInRange(lView, adjustedIndex);
|
|
26114
|
+
ngDevMode && assertTNodeCreationIndex(lView, index);
|
|
26076
26115
|
const tNode = tView.firstCreatePass
|
|
26077
26116
|
? getOrCreateTNode(tView, adjustedIndex, 1 /* TNodeType.Text */, value, null)
|
|
26078
26117
|
: tView.data[adjustedIndex];
|
|
@@ -26093,17 +26132,14 @@ let _locateOrCreateTextNode = (tView, lView, tNode, value, index) => {
|
|
|
26093
26132
|
* in addition to the regular creation mode of text nodes.
|
|
26094
26133
|
*/
|
|
26095
26134
|
function locateOrCreateTextNodeImpl(tView, lView, tNode, value, index) {
|
|
26096
|
-
const
|
|
26097
|
-
const isNodeCreationMode = !hydrationInfo ||
|
|
26098
|
-
isInSkipHydrationBlock$1() ||
|
|
26099
|
-
isDetachedByI18n(tNode) ||
|
|
26100
|
-
isDisconnectedNode$1(hydrationInfo, index);
|
|
26135
|
+
const isNodeCreationMode = !canHydrateNode(lView, tNode);
|
|
26101
26136
|
lastNodeWasCreated(isNodeCreationMode);
|
|
26102
26137
|
// Regular creation mode.
|
|
26103
26138
|
if (isNodeCreationMode) {
|
|
26104
26139
|
return createTextNode(lView[RENDERER], value);
|
|
26105
26140
|
}
|
|
26106
26141
|
// Hydration mode, looking up an existing element in DOM.
|
|
26142
|
+
const hydrationInfo = lView[HYDRATION];
|
|
26107
26143
|
const textNative = locateNextRNode(hydrationInfo, tView, lView, tNode);
|
|
26108
26144
|
ngDevMode && validateMatchingNode(textNative, Node.TEXT_NODE, null, lView, tNode);
|
|
26109
26145
|
ngDevMode && markRNodeAsClaimedByHydration(textNative);
|
|
@@ -27118,7 +27154,7 @@ function indexOf(item, arr, begin, end) {
|
|
|
27118
27154
|
/**
|
|
27119
27155
|
* Use this with `multi` `providers`.
|
|
27120
27156
|
*/
|
|
27121
|
-
function multiProvidersFactoryResolver(_, tData, lData, tNode) {
|
|
27157
|
+
function multiProvidersFactoryResolver(_, flags, tData, lData, tNode) {
|
|
27122
27158
|
return multiResolve(this.multi, []);
|
|
27123
27159
|
}
|
|
27124
27160
|
/**
|
|
@@ -27126,7 +27162,7 @@ function multiProvidersFactoryResolver(_, tData, lData, tNode) {
|
|
|
27126
27162
|
*
|
|
27127
27163
|
* This factory knows how to concatenate itself with the existing `multi` `providers`.
|
|
27128
27164
|
*/
|
|
27129
|
-
function multiViewProvidersFactoryResolver(_,
|
|
27165
|
+
function multiViewProvidersFactoryResolver(_, _flags, _tData, lView, tNode) {
|
|
27130
27166
|
const factories = this.multi;
|
|
27131
27167
|
let result;
|
|
27132
27168
|
if (this.providerFactory) {
|
|
@@ -27251,8 +27287,8 @@ function ɵɵExternalStylesFeature(styleUrls) {
|
|
|
27251
27287
|
*/
|
|
27252
27288
|
function ɵɵsetComponentScope(type, directives, pipes) {
|
|
27253
27289
|
const def = type.ɵcmp;
|
|
27254
|
-
def.directiveDefs = extractDefListOrFactory(directives,
|
|
27255
|
-
def.pipeDefs = extractDefListOrFactory(pipes,
|
|
27290
|
+
def.directiveDefs = extractDefListOrFactory(directives, extractDirectiveDef);
|
|
27291
|
+
def.pipeDefs = extractDefListOrFactory(pipes, getPipeDef$1);
|
|
27256
27292
|
}
|
|
27257
27293
|
/**
|
|
27258
27294
|
* Adds the module metadata that is necessary to compute the module's transitive scope to an
|
|
@@ -28160,7 +28196,7 @@ function resetProjectionState(tNode) {
|
|
|
28160
28196
|
if (isTNodeShape(current)) {
|
|
28161
28197
|
// Reset `projectionNext` since it can affect the traversal order during projection.
|
|
28162
28198
|
current.projectionNext = null;
|
|
28163
|
-
current.flags &=
|
|
28199
|
+
current.flags &= ~2 /* TNodeFlags.isProjected */;
|
|
28164
28200
|
}
|
|
28165
28201
|
}
|
|
28166
28202
|
tNode.projection = null;
|
|
@@ -30724,4 +30760,4 @@ function getDebugNode(nativeNode) {
|
|
|
30724
30760
|
}
|
|
30725
30761
|
|
|
30726
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 };
|
|
30727
|
-
//# sourceMappingURL=debug_node-
|
|
30763
|
+
//# sourceMappingURL=debug_node-CjNGi9N3.mjs.map
|