@angular/core 16.0.0-next.0 → 16.0.0-next.2
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/esm2020/src/application_config.mjs +21 -0
- package/esm2020/src/application_init.mjs +23 -31
- package/esm2020/src/application_module.mjs +3 -2
- package/esm2020/src/application_ref.mjs +35 -33
- package/esm2020/src/application_tokens.mjs +2 -13
- package/esm2020/src/change_detection/change_detection.mjs +2 -2
- package/esm2020/src/change_detection/change_detector_ref.mjs +3 -2
- package/esm2020/src/change_detection/constants.mjs +1 -49
- package/esm2020/src/change_detection/differs/iterable_differs.mjs +3 -2
- package/esm2020/src/change_detection/differs/keyvalue_differs.mjs +3 -2
- package/esm2020/src/console.mjs +3 -2
- package/esm2020/src/core.mjs +4 -3
- package/esm2020/src/core_private_export.mjs +6 -7
- package/esm2020/src/core_render3_private_export.mjs +3 -1
- package/esm2020/src/debug/debug_node.mjs +1 -5
- package/esm2020/src/di/injector.mjs +3 -2
- package/esm2020/src/di/r3_injector.mjs +5 -1
- package/esm2020/src/di/reflective_injector.mjs +3 -2
- package/esm2020/src/hydration/annotate.mjs +140 -0
- package/esm2020/src/hydration/api.mjs +120 -0
- package/esm2020/src/hydration/error_handling.mjs +29 -0
- package/esm2020/src/hydration/interfaces.mjs +10 -0
- package/esm2020/src/hydration/node_lookup_utils.mjs +75 -0
- package/esm2020/src/hydration/skip_hydration.mjs +34 -0
- package/esm2020/src/hydration/tokens.mjs +25 -0
- package/esm2020/src/hydration/utils.mjs +131 -0
- package/esm2020/src/linker/compiler.mjs +3 -2
- package/esm2020/src/linker/component_factory_resolver.mjs +3 -2
- package/esm2020/src/linker/destroy_ref.mjs +41 -0
- package/esm2020/src/linker/element_ref.mjs +3 -2
- package/esm2020/src/linker/query_list.mjs +6 -7
- package/esm2020/src/linker/template_ref.mjs +6 -5
- package/esm2020/src/linker/view_container_ref.mjs +3 -2
- package/esm2020/src/linker.mjs +2 -1
- package/esm2020/src/render/api.mjs +3 -2
- package/esm2020/src/render3/component_ref.mjs +16 -9
- package/esm2020/src/render3/features/standalone_feature.mjs +1 -1
- package/esm2020/src/render3/fields.mjs +10 -1
- package/esm2020/src/render3/hooks.mjs +3 -2
- package/esm2020/src/render3/i18n/i18n_util.mjs +3 -3
- package/esm2020/src/render3/instructions/element.mjs +56 -13
- package/esm2020/src/render3/instructions/element_container.mjs +54 -9
- package/esm2020/src/render3/instructions/listener.mjs +3 -3
- package/esm2020/src/render3/instructions/shared.mjs +40 -24
- package/esm2020/src/render3/instructions/template.mjs +2 -2
- package/esm2020/src/render3/instructions/text.mjs +36 -5
- package/esm2020/src/render3/interfaces/definition.mjs +1 -1
- package/esm2020/src/render3/interfaces/node.mjs +1 -1
- package/esm2020/src/render3/interfaces/renderer_dom.mjs +1 -1
- package/esm2020/src/render3/interfaces/view.mjs +4 -2
- package/esm2020/src/render3/jit/directive.mjs +1 -2
- package/esm2020/src/render3/node_manipulation.mjs +25 -14
- package/esm2020/src/render3/state.mjs +45 -1
- package/esm2020/src/render3/util/view_utils.mjs +11 -2
- package/esm2020/src/render3/view_ref.mjs +4 -3
- package/esm2020/src/sanitization/sanitizer.mjs +3 -2
- package/esm2020/src/testability/testability.mjs +5 -3
- package/esm2020/src/transfer_state.mjs +153 -0
- package/esm2020/src/util/iterable.mjs +6 -7
- package/esm2020/src/util/lang.mjs +1 -11
- package/esm2020/src/util/ng_dev_mode.mjs +3 -1
- package/esm2020/src/version.mjs +1 -1
- package/esm2020/testing/src/logger.mjs +6 -5
- package/esm2020/testing/src/ng_zone_mock.mjs +6 -5
- package/esm2020/testing/src/test_bed.mjs +3 -2
- package/fesm2015/core.mjs +1076 -297
- package/fesm2015/core.mjs.map +1 -1
- package/fesm2015/testing.mjs +747 -159
- package/fesm2015/testing.mjs.map +1 -1
- package/fesm2020/core.mjs +1066 -295
- package/fesm2020/core.mjs.map +1 -1
- package/fesm2020/testing.mjs +741 -159
- package/fesm2020/testing.mjs.map +1 -1
- package/index.d.ts +290 -87
- package/package.json +3 -3
- package/schematics/migrations/router-link-with-href/bundle.js.map +2 -2
- package/schematics/ng-generate/standalone-migration/bundle.js +1044 -1024
- package/schematics/ng-generate/standalone-migration/bundle.js.map +4 -4
- package/testing/index.d.ts +1 -1
- package/esm2020/src/util/symbol.mjs +0 -30
package/fesm2020/testing.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v16.0.0-next.
|
|
2
|
+
* @license Angular v16.0.0-next.2
|
|
3
3
|
* (c) 2010-2022 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -1635,6 +1635,8 @@ function ngDevModeResetPerfCounters() {
|
|
|
1635
1635
|
rendererAppendChild: 0,
|
|
1636
1636
|
rendererInsertBefore: 0,
|
|
1637
1637
|
rendererCreateComment: 0,
|
|
1638
|
+
hydratedNodes: 0,
|
|
1639
|
+
hydratedComponents: 0,
|
|
1638
1640
|
};
|
|
1639
1641
|
// Make sure to refer to ngDevMode as ['ngDevMode'] for closure.
|
|
1640
1642
|
const allowNgDevModeTrue = locationString.indexOf('ngDevMode=false') === -1;
|
|
@@ -2114,54 +2116,6 @@ var ChangeDetectionStrategy;
|
|
|
2114
2116
|
*/
|
|
2115
2117
|
ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 1] = "Default";
|
|
2116
2118
|
})(ChangeDetectionStrategy || (ChangeDetectionStrategy = {}));
|
|
2117
|
-
/**
|
|
2118
|
-
* Defines the possible states of the default change detector.
|
|
2119
|
-
* @see `ChangeDetectorRef`
|
|
2120
|
-
*/
|
|
2121
|
-
var ChangeDetectorStatus;
|
|
2122
|
-
(function (ChangeDetectorStatus) {
|
|
2123
|
-
/**
|
|
2124
|
-
* A state in which, after calling `detectChanges()`, the change detector
|
|
2125
|
-
* state becomes `Checked`, and must be explicitly invoked or reactivated.
|
|
2126
|
-
*/
|
|
2127
|
-
ChangeDetectorStatus[ChangeDetectorStatus["CheckOnce"] = 0] = "CheckOnce";
|
|
2128
|
-
/**
|
|
2129
|
-
* A state in which change detection is skipped until the change detector mode
|
|
2130
|
-
* becomes `CheckOnce`.
|
|
2131
|
-
*/
|
|
2132
|
-
ChangeDetectorStatus[ChangeDetectorStatus["Checked"] = 1] = "Checked";
|
|
2133
|
-
/**
|
|
2134
|
-
* A state in which change detection continues automatically until explicitly
|
|
2135
|
-
* deactivated.
|
|
2136
|
-
*/
|
|
2137
|
-
ChangeDetectorStatus[ChangeDetectorStatus["CheckAlways"] = 2] = "CheckAlways";
|
|
2138
|
-
/**
|
|
2139
|
-
* A state in which a change detector sub tree is not a part of the main tree and
|
|
2140
|
-
* should be skipped.
|
|
2141
|
-
*/
|
|
2142
|
-
ChangeDetectorStatus[ChangeDetectorStatus["Detached"] = 3] = "Detached";
|
|
2143
|
-
/**
|
|
2144
|
-
* Indicates that the change detector encountered an error checking a binding
|
|
2145
|
-
* or calling a directive lifecycle method and is now in an inconsistent state. Change
|
|
2146
|
-
* detectors in this state do not detect changes.
|
|
2147
|
-
*/
|
|
2148
|
-
ChangeDetectorStatus[ChangeDetectorStatus["Errored"] = 4] = "Errored";
|
|
2149
|
-
/**
|
|
2150
|
-
* Indicates that the change detector has been destroyed.
|
|
2151
|
-
*/
|
|
2152
|
-
ChangeDetectorStatus[ChangeDetectorStatus["Destroyed"] = 5] = "Destroyed";
|
|
2153
|
-
})(ChangeDetectorStatus || (ChangeDetectorStatus = {}));
|
|
2154
|
-
/**
|
|
2155
|
-
* Reports whether a given strategy is currently the default for change detection.
|
|
2156
|
-
* @param changeDetectionStrategy The strategy to check.
|
|
2157
|
-
* @returns True if the given strategy is the current default, false otherwise.
|
|
2158
|
-
* @see `ChangeDetectorStatus`
|
|
2159
|
-
* @see `ChangeDetectorRef`
|
|
2160
|
-
*/
|
|
2161
|
-
function isDefaultChangeDetectionStrategy(changeDetectionStrategy) {
|
|
2162
|
-
return changeDetectionStrategy == null ||
|
|
2163
|
-
changeDetectionStrategy === ChangeDetectionStrategy.Default;
|
|
2164
|
-
}
|
|
2165
2119
|
|
|
2166
2120
|
/**
|
|
2167
2121
|
* Defines the CSS styles encapsulation policies for the {@link Component} decorator's
|
|
@@ -2233,6 +2187,15 @@ const NG_FACTORY_DEF = getClosureSafeProperty({ ɵfac: getClosureSafeProperty })
|
|
|
2233
2187
|
*/
|
|
2234
2188
|
// TODO(misko): This is wrong. The NG_ELEMENT_ID should never be minified.
|
|
2235
2189
|
const NG_ELEMENT_ID = getClosureSafeProperty({ __NG_ELEMENT_ID__: getClosureSafeProperty });
|
|
2190
|
+
/**
|
|
2191
|
+
* The `NG_ENV_ID` field on a DI token indicates special processing in the `EnvironmentInjector`:
|
|
2192
|
+
* getting such tokens from the `EnvironmentInjector` will bypass the standard DI resolution
|
|
2193
|
+
* strategy and instead will return implementation produced by the `NG_ENV_ID` factory function.
|
|
2194
|
+
*
|
|
2195
|
+
* This particular retrieval of DI tokens is mostly done to eliminate circular dependencies and
|
|
2196
|
+
* improve tree-shaking.
|
|
2197
|
+
*/
|
|
2198
|
+
const NG_ENV_ID = getClosureSafeProperty({ __NG_ENV_ID__: getClosureSafeProperty });
|
|
2236
2199
|
|
|
2237
2200
|
/** Counter used to generate unique IDs for component definitions. */
|
|
2238
2201
|
let componentDefCount = 0;
|
|
@@ -2549,6 +2512,8 @@ const PREORDER_HOOK_FLAGS = 18;
|
|
|
2549
2512
|
const QUERIES = 19;
|
|
2550
2513
|
const ID = 20;
|
|
2551
2514
|
const EMBEDDED_VIEW_INJECTOR = 21;
|
|
2515
|
+
const ON_DESTROY_HOOKS = 22;
|
|
2516
|
+
const HYDRATION = 23;
|
|
2552
2517
|
/**
|
|
2553
2518
|
* Size of LView's header. Necessary to adjust for it when setting slots.
|
|
2554
2519
|
*
|
|
@@ -2556,7 +2521,7 @@ const EMBEDDED_VIEW_INJECTOR = 21;
|
|
|
2556
2521
|
* instruction index into `LView` index. All other indexes should be in the `LView` index space and
|
|
2557
2522
|
* there should be no need to refer to `HEADER_OFFSET` anywhere else.
|
|
2558
2523
|
*/
|
|
2559
|
-
const HEADER_OFFSET =
|
|
2524
|
+
const HEADER_OFFSET = 24;
|
|
2560
2525
|
// Note: This hack is necessary so we don't erroneously get a circular dependency
|
|
2561
2526
|
// failure based on types.
|
|
2562
2527
|
const unusedValueExportToPlacateAjd$4 = 1;
|
|
@@ -3032,10 +2997,20 @@ function updateTransplantedViewCount(lContainer, amount) {
|
|
|
3032
2997
|
parent = parent[PARENT];
|
|
3033
2998
|
}
|
|
3034
2999
|
}
|
|
3000
|
+
/**
|
|
3001
|
+
* Stores a LView-specific destroy callback.
|
|
3002
|
+
*/
|
|
3003
|
+
function storeLViewOnDestroy(lView, onDestroyCallback) {
|
|
3004
|
+
if (lView[ON_DESTROY_HOOKS] === null) {
|
|
3005
|
+
lView[ON_DESTROY_HOOKS] = [];
|
|
3006
|
+
}
|
|
3007
|
+
lView[ON_DESTROY_HOOKS].push(onDestroyCallback);
|
|
3008
|
+
}
|
|
3035
3009
|
|
|
3036
3010
|
const instructionState = {
|
|
3037
3011
|
lFrame: createLFrame(null),
|
|
3038
3012
|
bindingsEnabled: true,
|
|
3013
|
+
skipHydrationRootTNode: null,
|
|
3039
3014
|
};
|
|
3040
3015
|
/**
|
|
3041
3016
|
* In this mode, any changes in bindings will throw an ExpressionChangedAfterChecked error.
|
|
@@ -3066,6 +3041,21 @@ function decreaseElementDepthCount() {
|
|
|
3066
3041
|
function getBindingsEnabled() {
|
|
3067
3042
|
return instructionState.bindingsEnabled;
|
|
3068
3043
|
}
|
|
3044
|
+
/**
|
|
3045
|
+
* Returns true if currently inside a skip hydration block.
|
|
3046
|
+
* @returns boolean
|
|
3047
|
+
*/
|
|
3048
|
+
function isInSkipHydrationBlock() {
|
|
3049
|
+
return instructionState.skipHydrationRootTNode !== null;
|
|
3050
|
+
}
|
|
3051
|
+
/**
|
|
3052
|
+
* Returns true if this is the root TNode of the skip hydration block.
|
|
3053
|
+
* @param tNode the current TNode
|
|
3054
|
+
* @returns boolean
|
|
3055
|
+
*/
|
|
3056
|
+
function isSkipHydrationRootTNode(tNode) {
|
|
3057
|
+
return instructionState.skipHydrationRootTNode === tNode;
|
|
3058
|
+
}
|
|
3069
3059
|
/**
|
|
3070
3060
|
* Enables directive matching on elements.
|
|
3071
3061
|
*
|
|
@@ -3088,6 +3078,13 @@ function getBindingsEnabled() {
|
|
|
3088
3078
|
function ɵɵenableBindings() {
|
|
3089
3079
|
instructionState.bindingsEnabled = true;
|
|
3090
3080
|
}
|
|
3081
|
+
/**
|
|
3082
|
+
* Sets a flag to specify that the TNode is in a skip hydration block.
|
|
3083
|
+
* @param tNode the current TNode
|
|
3084
|
+
*/
|
|
3085
|
+
function enterSkipHydrationBlock(tNode) {
|
|
3086
|
+
instructionState.skipHydrationRootTNode = tNode;
|
|
3087
|
+
}
|
|
3091
3088
|
/**
|
|
3092
3089
|
* Disables directive matching on element.
|
|
3093
3090
|
*
|
|
@@ -3110,6 +3107,12 @@ function ɵɵenableBindings() {
|
|
|
3110
3107
|
function ɵɵdisableBindings() {
|
|
3111
3108
|
instructionState.bindingsEnabled = false;
|
|
3112
3109
|
}
|
|
3110
|
+
/**
|
|
3111
|
+
* Clears the root skip hydration node when leaving a skip hydration block.
|
|
3112
|
+
*/
|
|
3113
|
+
function leaveSkipHydrationBlock() {
|
|
3114
|
+
instructionState.skipHydrationRootTNode = null;
|
|
3115
|
+
}
|
|
3113
3116
|
/**
|
|
3114
3117
|
* Return the current `LView`.
|
|
3115
3118
|
*/
|
|
@@ -3534,6 +3537,21 @@ function namespaceHTMLInternal() {
|
|
|
3534
3537
|
function getNamespace$1() {
|
|
3535
3538
|
return instructionState.lFrame.currentNamespace;
|
|
3536
3539
|
}
|
|
3540
|
+
let _wasLastNodeCreated = true;
|
|
3541
|
+
/**
|
|
3542
|
+
* Retrieves a global flag that indicates whether the most recent DOM node
|
|
3543
|
+
* was created or hydrated.
|
|
3544
|
+
*/
|
|
3545
|
+
function wasLastNodeCreated() {
|
|
3546
|
+
return _wasLastNodeCreated;
|
|
3547
|
+
}
|
|
3548
|
+
/**
|
|
3549
|
+
* Sets a global flag to indicate whether the most recent DOM node
|
|
3550
|
+
* was created or hydrated.
|
|
3551
|
+
*/
|
|
3552
|
+
function lastNodeWasCreated(flag) {
|
|
3553
|
+
_wasLastNodeCreated = flag;
|
|
3554
|
+
}
|
|
3537
3555
|
|
|
3538
3556
|
/**
|
|
3539
3557
|
* Adds all directive lifecycle hooks from the given `DirectiveDef` to the given `TView`.
|
|
@@ -3709,8 +3727,9 @@ function callHooks(currentView, arr, initPhase, currentNodeIndex) {
|
|
|
3709
3727
|
}
|
|
3710
3728
|
else {
|
|
3711
3729
|
const isInitHook = arr[i] < 0;
|
|
3712
|
-
if (isInitHook)
|
|
3730
|
+
if (isInitHook) {
|
|
3713
3731
|
currentView[PREORDER_HOOK_FLAGS] += 65536 /* PreOrderHookFlags.NumberOfInitHooksCalledIncrementer */;
|
|
3732
|
+
}
|
|
3714
3733
|
if (lastNodeIndexFound < nodeIndexLimit || nodeIndexLimit == -1) {
|
|
3715
3734
|
callHook(currentView, initPhase, arr, i);
|
|
3716
3735
|
currentView[PREORDER_HOOK_FLAGS] =
|
|
@@ -6241,10 +6260,6 @@ function cleanUpView(tView, lView) {
|
|
|
6241
6260
|
function processCleanups(tView, lView) {
|
|
6242
6261
|
const tCleanup = tView.cleanup;
|
|
6243
6262
|
const lCleanup = lView[CLEANUP];
|
|
6244
|
-
// `LCleanup` contains both share information with `TCleanup` as well as instance specific
|
|
6245
|
-
// information appended at the end. We need to know where the end of the `TCleanup` information
|
|
6246
|
-
// is, and we track this with `lastLCleanupIndex`.
|
|
6247
|
-
let lastLCleanupIndex = -1;
|
|
6248
6263
|
if (tCleanup !== null) {
|
|
6249
6264
|
for (let i = 0; i < tCleanup.length - 1; i += 2) {
|
|
6250
6265
|
if (typeof tCleanup[i] === 'string') {
|
|
@@ -6254,29 +6269,33 @@ function processCleanups(tView, lView) {
|
|
|
6254
6269
|
ngDevMode && assertNumber(targetIdx, 'cleanup target must be a number');
|
|
6255
6270
|
if (targetIdx >= 0) {
|
|
6256
6271
|
// unregister
|
|
6257
|
-
lCleanup[
|
|
6272
|
+
lCleanup[targetIdx]();
|
|
6258
6273
|
}
|
|
6259
6274
|
else {
|
|
6260
6275
|
// Subscription
|
|
6261
|
-
lCleanup[
|
|
6276
|
+
lCleanup[-targetIdx].unsubscribe();
|
|
6262
6277
|
}
|
|
6263
6278
|
i += 2;
|
|
6264
6279
|
}
|
|
6265
6280
|
else {
|
|
6266
6281
|
// This is a cleanup function that is grouped with the index of its context
|
|
6267
|
-
const context = lCleanup[
|
|
6282
|
+
const context = lCleanup[tCleanup[i + 1]];
|
|
6268
6283
|
tCleanup[i].call(context);
|
|
6269
6284
|
}
|
|
6270
6285
|
}
|
|
6271
6286
|
}
|
|
6272
6287
|
if (lCleanup !== null) {
|
|
6273
|
-
for (let i = lastLCleanupIndex + 1; i < lCleanup.length; i++) {
|
|
6274
|
-
const instanceCleanupFn = lCleanup[i];
|
|
6275
|
-
ngDevMode && assertFunction(instanceCleanupFn, 'Expecting instance cleanup function.');
|
|
6276
|
-
instanceCleanupFn();
|
|
6277
|
-
}
|
|
6278
6288
|
lView[CLEANUP] = null;
|
|
6279
6289
|
}
|
|
6290
|
+
const destroyHooks = lView[ON_DESTROY_HOOKS];
|
|
6291
|
+
if (destroyHooks !== null) {
|
|
6292
|
+
for (let i = 0; i < destroyHooks.length; i++) {
|
|
6293
|
+
const destroyHooksFn = destroyHooks[i];
|
|
6294
|
+
ngDevMode && assertFunction(destroyHooksFn, 'Expecting destroy hook to be a function.');
|
|
6295
|
+
destroyHooksFn();
|
|
6296
|
+
}
|
|
6297
|
+
lView[ON_DESTROY_HOOKS] = null;
|
|
6298
|
+
}
|
|
6280
6299
|
}
|
|
6281
6300
|
/** Calls onDestroy hooks for this view */
|
|
6282
6301
|
function executeOnDestroys(tView, lView) {
|
|
@@ -6587,6 +6606,17 @@ function nativeRemoveNode(renderer, rNode, isHostElement) {
|
|
|
6587
6606
|
nativeRemoveChild(renderer, nativeParent, rNode, isHostElement);
|
|
6588
6607
|
}
|
|
6589
6608
|
}
|
|
6609
|
+
/**
|
|
6610
|
+
* Removes the contents of a given RElement using a given renderer.
|
|
6611
|
+
*
|
|
6612
|
+
* @param renderer A renderer to be used
|
|
6613
|
+
* @param rElement the native RElement to be cleared
|
|
6614
|
+
*/
|
|
6615
|
+
function clearElementContents(renderer, rElement) {
|
|
6616
|
+
while (rElement.firstChild) {
|
|
6617
|
+
nativeRemoveChild(renderer, rElement, rElement.firstChild, false);
|
|
6618
|
+
}
|
|
6619
|
+
}
|
|
6590
6620
|
/**
|
|
6591
6621
|
* Performs the operation of `action` on the node. Typically this involves inserting or removing
|
|
6592
6622
|
* nodes on the LView or projection boundary.
|
|
@@ -8286,6 +8316,9 @@ class R3Injector extends EnvironmentInjector {
|
|
|
8286
8316
|
}
|
|
8287
8317
|
get(token, notFoundValue = THROW_IF_NOT_FOUND, flags = InjectFlags.Default) {
|
|
8288
8318
|
this.assertNotDestroyed();
|
|
8319
|
+
if (token.hasOwnProperty(NG_ENV_ID)) {
|
|
8320
|
+
return token[NG_ENV_ID](this);
|
|
8321
|
+
}
|
|
8289
8322
|
flags = convertToBitFlags(flags);
|
|
8290
8323
|
// Set the injection context.
|
|
8291
8324
|
const previousInjector = setCurrentInjector(this);
|
|
@@ -8563,6 +8596,328 @@ function forEachSingleProvider(providers, fn) {
|
|
|
8563
8596
|
}
|
|
8564
8597
|
}
|
|
8565
8598
|
|
|
8599
|
+
/**
|
|
8600
|
+
* A [DI token](guide/glossary#di-token "DI token definition") representing a unique string ID, used
|
|
8601
|
+
* primarily for prefixing application attributes and CSS styles when
|
|
8602
|
+
* {@link ViewEncapsulation#Emulated ViewEncapsulation.Emulated} is being used.
|
|
8603
|
+
*
|
|
8604
|
+
* BY default, the value is randomly generated and assigned to the application by Angular.
|
|
8605
|
+
* To provide a custom ID value, use a DI provider <!-- TODO: provider --> to configure
|
|
8606
|
+
* the root {@link Injector} that uses this token.
|
|
8607
|
+
*
|
|
8608
|
+
* @publicApi
|
|
8609
|
+
*/
|
|
8610
|
+
const APP_ID = new InjectionToken('AppId', {
|
|
8611
|
+
providedIn: 'root',
|
|
8612
|
+
factory: _appIdRandomProviderFactory,
|
|
8613
|
+
});
|
|
8614
|
+
function _appIdRandomProviderFactory() {
|
|
8615
|
+
return `${_randomChar()}${_randomChar()}${_randomChar()}`;
|
|
8616
|
+
}
|
|
8617
|
+
/**
|
|
8618
|
+
* Providers that generate a random `APP_ID_TOKEN`.
|
|
8619
|
+
* @publicApi
|
|
8620
|
+
*/
|
|
8621
|
+
const APP_ID_RANDOM_PROVIDER = {
|
|
8622
|
+
provide: APP_ID,
|
|
8623
|
+
useFactory: _appIdRandomProviderFactory,
|
|
8624
|
+
deps: [],
|
|
8625
|
+
};
|
|
8626
|
+
function _randomChar() {
|
|
8627
|
+
return String.fromCharCode(97 + Math.floor(Math.random() * 25));
|
|
8628
|
+
}
|
|
8629
|
+
/**
|
|
8630
|
+
* A function that is executed when a platform is initialized.
|
|
8631
|
+
* @publicApi
|
|
8632
|
+
*/
|
|
8633
|
+
const PLATFORM_INITIALIZER = new InjectionToken('Platform Initializer');
|
|
8634
|
+
/**
|
|
8635
|
+
* A token that indicates an opaque platform ID.
|
|
8636
|
+
* @publicApi
|
|
8637
|
+
*/
|
|
8638
|
+
const PLATFORM_ID = new InjectionToken('Platform ID', {
|
|
8639
|
+
providedIn: 'platform',
|
|
8640
|
+
factory: () => 'unknown', // set a default platform name, when none set explicitly
|
|
8641
|
+
});
|
|
8642
|
+
/**
|
|
8643
|
+
* A [DI token](guide/glossary#di-token "DI token definition") that indicates the root directory of
|
|
8644
|
+
* the application
|
|
8645
|
+
* @publicApi
|
|
8646
|
+
*/
|
|
8647
|
+
const PACKAGE_ROOT_URL = new InjectionToken('Application Packages Root URL');
|
|
8648
|
+
// We keep this token here, rather than the animations package, so that modules that only care
|
|
8649
|
+
// about which animations module is loaded (e.g. the CDK) can retrieve it without having to
|
|
8650
|
+
// include extra dependencies. See #44970 for more context.
|
|
8651
|
+
/**
|
|
8652
|
+
* A [DI token](guide/glossary#di-token "DI token definition") that indicates which animations
|
|
8653
|
+
* module has been loaded.
|
|
8654
|
+
* @publicApi
|
|
8655
|
+
*/
|
|
8656
|
+
const ANIMATION_MODULE_TYPE = new InjectionToken('AnimationModuleType');
|
|
8657
|
+
|
|
8658
|
+
function escapeTransferStateContent(text) {
|
|
8659
|
+
const escapedText = {
|
|
8660
|
+
'&': '&a;',
|
|
8661
|
+
'"': '&q;',
|
|
8662
|
+
'\'': '&s;',
|
|
8663
|
+
'<': '&l;',
|
|
8664
|
+
'>': '&g;',
|
|
8665
|
+
};
|
|
8666
|
+
return text.replace(/[&"'<>]/g, s => escapedText[s]);
|
|
8667
|
+
}
|
|
8668
|
+
function unescapeTransferStateContent(text) {
|
|
8669
|
+
const unescapedText = {
|
|
8670
|
+
'&a;': '&',
|
|
8671
|
+
'&q;': '"',
|
|
8672
|
+
'&s;': '\'',
|
|
8673
|
+
'&l;': '<',
|
|
8674
|
+
'&g;': '>',
|
|
8675
|
+
};
|
|
8676
|
+
return text.replace(/&[^;]+;/g, s => unescapedText[s]);
|
|
8677
|
+
}
|
|
8678
|
+
/**
|
|
8679
|
+
* Create a `StateKey<T>` that can be used to store value of type T with `TransferState`.
|
|
8680
|
+
*
|
|
8681
|
+
* Example:
|
|
8682
|
+
*
|
|
8683
|
+
* ```
|
|
8684
|
+
* const COUNTER_KEY = makeStateKey<number>('counter');
|
|
8685
|
+
* let value = 10;
|
|
8686
|
+
*
|
|
8687
|
+
* transferState.set(COUNTER_KEY, value);
|
|
8688
|
+
* ```
|
|
8689
|
+
*
|
|
8690
|
+
* @publicApi
|
|
8691
|
+
*/
|
|
8692
|
+
function makeStateKey(key) {
|
|
8693
|
+
return key;
|
|
8694
|
+
}
|
|
8695
|
+
function initTransferState() {
|
|
8696
|
+
const transferState = new TransferState();
|
|
8697
|
+
transferState.store = retrieveTransferredState(getDocument(), inject$1(APP_ID));
|
|
8698
|
+
return transferState;
|
|
8699
|
+
}
|
|
8700
|
+
/**
|
|
8701
|
+
* A key value store that is transferred from the application on the server side to the application
|
|
8702
|
+
* on the client side.
|
|
8703
|
+
*
|
|
8704
|
+
* The `TransferState` is available as an injectable token.
|
|
8705
|
+
* On the client, just inject this token using DI and use it, it will be lazily initialized.
|
|
8706
|
+
* On the server it's already included if `renderApplication` function is used. Otherwise, import
|
|
8707
|
+
* the `ServerTransferStateModule` module to make the `TransferState` available.
|
|
8708
|
+
*
|
|
8709
|
+
* The values in the store are serialized/deserialized using JSON.stringify/JSON.parse. So only
|
|
8710
|
+
* boolean, number, string, null and non-class objects will be serialized and deserialized in a
|
|
8711
|
+
* non-lossy manner.
|
|
8712
|
+
*
|
|
8713
|
+
* @publicApi
|
|
8714
|
+
*/
|
|
8715
|
+
class TransferState {
|
|
8716
|
+
constructor() {
|
|
8717
|
+
/** @internal */
|
|
8718
|
+
this.store = {};
|
|
8719
|
+
this.onSerializeCallbacks = {};
|
|
8720
|
+
}
|
|
8721
|
+
/**
|
|
8722
|
+
* Get the value corresponding to a key. Return `defaultValue` if key is not found.
|
|
8723
|
+
*/
|
|
8724
|
+
get(key, defaultValue) {
|
|
8725
|
+
return this.store[key] !== undefined ? this.store[key] : defaultValue;
|
|
8726
|
+
}
|
|
8727
|
+
/**
|
|
8728
|
+
* Set the value corresponding to a key.
|
|
8729
|
+
*/
|
|
8730
|
+
set(key, value) {
|
|
8731
|
+
this.store[key] = value;
|
|
8732
|
+
}
|
|
8733
|
+
/**
|
|
8734
|
+
* Remove a key from the store.
|
|
8735
|
+
*/
|
|
8736
|
+
remove(key) {
|
|
8737
|
+
delete this.store[key];
|
|
8738
|
+
}
|
|
8739
|
+
/**
|
|
8740
|
+
* Test whether a key exists in the store.
|
|
8741
|
+
*/
|
|
8742
|
+
hasKey(key) {
|
|
8743
|
+
return this.store.hasOwnProperty(key);
|
|
8744
|
+
}
|
|
8745
|
+
/**
|
|
8746
|
+
* Indicates whether the state is empty.
|
|
8747
|
+
*/
|
|
8748
|
+
get isEmpty() {
|
|
8749
|
+
return Object.keys(this.store).length === 0;
|
|
8750
|
+
}
|
|
8751
|
+
/**
|
|
8752
|
+
* Register a callback to provide the value for a key when `toJson` is called.
|
|
8753
|
+
*/
|
|
8754
|
+
onSerialize(key, callback) {
|
|
8755
|
+
this.onSerializeCallbacks[key] = callback;
|
|
8756
|
+
}
|
|
8757
|
+
/**
|
|
8758
|
+
* Serialize the current state of the store to JSON.
|
|
8759
|
+
*/
|
|
8760
|
+
toJson() {
|
|
8761
|
+
// Call the onSerialize callbacks and put those values into the store.
|
|
8762
|
+
for (const key in this.onSerializeCallbacks) {
|
|
8763
|
+
if (this.onSerializeCallbacks.hasOwnProperty(key)) {
|
|
8764
|
+
try {
|
|
8765
|
+
this.store[key] = this.onSerializeCallbacks[key]();
|
|
8766
|
+
}
|
|
8767
|
+
catch (e) {
|
|
8768
|
+
console.warn('Exception in onSerialize callback: ', e);
|
|
8769
|
+
}
|
|
8770
|
+
}
|
|
8771
|
+
}
|
|
8772
|
+
return JSON.stringify(this.store);
|
|
8773
|
+
}
|
|
8774
|
+
}
|
|
8775
|
+
/** @nocollapse */
|
|
8776
|
+
TransferState.ɵprov =
|
|
8777
|
+
/** @pureOrBreakMyCode */ ɵɵdefineInjectable({
|
|
8778
|
+
token: TransferState,
|
|
8779
|
+
providedIn: 'root',
|
|
8780
|
+
factory: initTransferState,
|
|
8781
|
+
});
|
|
8782
|
+
function retrieveTransferredState(doc, appId) {
|
|
8783
|
+
// Locate the script tag with the JSON data transferred from the server.
|
|
8784
|
+
// The id of the script tag is set to the Angular appId + 'state'.
|
|
8785
|
+
const script = doc.getElementById(appId + '-state');
|
|
8786
|
+
let initialState = {};
|
|
8787
|
+
if (script && script.textContent) {
|
|
8788
|
+
try {
|
|
8789
|
+
// Avoid using any here as it triggers lint errors in google3 (any is not allowed).
|
|
8790
|
+
initialState = JSON.parse(unescapeTransferStateContent(script.textContent));
|
|
8791
|
+
}
|
|
8792
|
+
catch (e) {
|
|
8793
|
+
console.warn('Exception while restoring TransferState for app ' + appId, e);
|
|
8794
|
+
}
|
|
8795
|
+
}
|
|
8796
|
+
return initialState;
|
|
8797
|
+
}
|
|
8798
|
+
|
|
8799
|
+
/* Represents a key in NghDom that holds information about <ng-container>s. */
|
|
8800
|
+
const ELEMENT_CONTAINERS = 'e';
|
|
8801
|
+
|
|
8802
|
+
/**
|
|
8803
|
+
* The name of the key used in the TransferState collection,
|
|
8804
|
+
* where hydration information is located.
|
|
8805
|
+
*/
|
|
8806
|
+
const TRANSFER_STATE_TOKEN_ID = '__ɵnghData__';
|
|
8807
|
+
/**
|
|
8808
|
+
* Lookup key used to reference DOM hydration data (ngh) in `TransferState`.
|
|
8809
|
+
*/
|
|
8810
|
+
const NGH_DATA_KEY = makeStateKey(TRANSFER_STATE_TOKEN_ID);
|
|
8811
|
+
/**
|
|
8812
|
+
* The name of the attribute that would be added to host component
|
|
8813
|
+
* nodes and contain a reference to a particular slot in transferred
|
|
8814
|
+
* state that contains the necessary hydration info for this component.
|
|
8815
|
+
*/
|
|
8816
|
+
const NGH_ATTR_NAME = 'ngh';
|
|
8817
|
+
/**
|
|
8818
|
+
* Reference to a function that reads `ngh` attribute value from a given RNode
|
|
8819
|
+
* and retrieves hydration information from the TransferState using that value
|
|
8820
|
+
* as an index. Returns `null` by default, when hydration is not enabled.
|
|
8821
|
+
*
|
|
8822
|
+
* @param rNode Component's host element.
|
|
8823
|
+
* @param injector Injector that this component has access to.
|
|
8824
|
+
*/
|
|
8825
|
+
let _retrieveHydrationInfoImpl = (rNode, injector) => null;
|
|
8826
|
+
function retrieveHydrationInfoImpl(rNode, injector) {
|
|
8827
|
+
const nghAttrValue = rNode.getAttribute(NGH_ATTR_NAME);
|
|
8828
|
+
if (nghAttrValue == null)
|
|
8829
|
+
return null;
|
|
8830
|
+
let data = {};
|
|
8831
|
+
// An element might have an empty `ngh` attribute value (e.g. `<comp ngh="" />`),
|
|
8832
|
+
// which means that no special annotations are required. Do not attempt to read
|
|
8833
|
+
// from the TransferState in this case.
|
|
8834
|
+
if (nghAttrValue !== '') {
|
|
8835
|
+
const transferState = injector.get(TransferState, null, { optional: true });
|
|
8836
|
+
if (transferState !== null) {
|
|
8837
|
+
const nghData = transferState.get(NGH_DATA_KEY, []);
|
|
8838
|
+
// The nghAttrValue is always a number referencing an index
|
|
8839
|
+
// in the hydration TransferState data.
|
|
8840
|
+
data = nghData[Number(nghAttrValue)];
|
|
8841
|
+
// If the `ngh` attribute exists and has a non-empty value,
|
|
8842
|
+
// the hydration info *must* be present in the TransferState.
|
|
8843
|
+
// If there is no data for some reasons, this is an error.
|
|
8844
|
+
ngDevMode && assertDefined(data, 'Unable to retrieve hydration info from the TransferState.');
|
|
8845
|
+
}
|
|
8846
|
+
}
|
|
8847
|
+
const dehydratedView = {
|
|
8848
|
+
data,
|
|
8849
|
+
firstChild: rNode.firstChild ?? null,
|
|
8850
|
+
};
|
|
8851
|
+
// The `ngh` attribute is cleared from the DOM node now
|
|
8852
|
+
// that the data has been retrieved.
|
|
8853
|
+
rNode.removeAttribute(NGH_ATTR_NAME);
|
|
8854
|
+
// Note: don't check whether this node was claimed for hydration,
|
|
8855
|
+
// because this node might've been previously claimed while processing
|
|
8856
|
+
// template instructions.
|
|
8857
|
+
ngDevMode && markRNodeAsClaimedByHydration(rNode, /* checkIfAlreadyClaimed */ false);
|
|
8858
|
+
ngDevMode && ngDevMode.hydratedComponents++;
|
|
8859
|
+
return dehydratedView;
|
|
8860
|
+
}
|
|
8861
|
+
/**
|
|
8862
|
+
* Sets the implementation for the `retrieveNghInfo` function.
|
|
8863
|
+
*/
|
|
8864
|
+
function enableRetrieveHydrationInfoImpl() {
|
|
8865
|
+
_retrieveHydrationInfoImpl = retrieveHydrationInfoImpl;
|
|
8866
|
+
}
|
|
8867
|
+
/**
|
|
8868
|
+
* Retrieves hydration info by reading the value from the `ngh` attribute
|
|
8869
|
+
* and accessing a corresponding slot in TransferState storage.
|
|
8870
|
+
*/
|
|
8871
|
+
function retrieveHydrationInfo(rNode, injector) {
|
|
8872
|
+
return _retrieveHydrationInfoImpl(rNode, injector);
|
|
8873
|
+
}
|
|
8874
|
+
/**
|
|
8875
|
+
* Retrieves an instance of a component LView from a given ViewRef.
|
|
8876
|
+
* Returns an instance of a component LView or `null` in case of an embedded view.
|
|
8877
|
+
*/
|
|
8878
|
+
function getComponentLViewForHydration(viewRef) {
|
|
8879
|
+
// Reading an internal field from `ViewRef` instance.
|
|
8880
|
+
let lView = viewRef._lView;
|
|
8881
|
+
const tView = lView[TVIEW];
|
|
8882
|
+
// A registered ViewRef might represent an instance of an
|
|
8883
|
+
// embedded view, in which case we do not need to annotate it.
|
|
8884
|
+
if (tView.type === 2 /* TViewType.Embedded */) {
|
|
8885
|
+
return null;
|
|
8886
|
+
}
|
|
8887
|
+
// Check if it's a root view and if so, retrieve component's
|
|
8888
|
+
// LView from the first slot after the header.
|
|
8889
|
+
if (isRootView(lView)) {
|
|
8890
|
+
lView = lView[HEADER_OFFSET];
|
|
8891
|
+
}
|
|
8892
|
+
return lView;
|
|
8893
|
+
}
|
|
8894
|
+
/**
|
|
8895
|
+
* Marks a node as "claimed" by hydration process.
|
|
8896
|
+
* This is needed to make assessments in tests whether
|
|
8897
|
+
* the hydration process handled all nodes.
|
|
8898
|
+
*/
|
|
8899
|
+
function markRNodeAsClaimedByHydration(node, checkIfAlreadyClaimed = true) {
|
|
8900
|
+
if (!ngDevMode) {
|
|
8901
|
+
throw new Error('Calling `markRNodeAsClaimedByHydration` in prod mode ' +
|
|
8902
|
+
'is not supported and likely a mistake.');
|
|
8903
|
+
}
|
|
8904
|
+
if (checkIfAlreadyClaimed && isRNodeClaimedForHydration(node)) {
|
|
8905
|
+
throw new Error('Trying to claim a node, which was claimed already.');
|
|
8906
|
+
}
|
|
8907
|
+
node.__claimed = true;
|
|
8908
|
+
ngDevMode.hydratedNodes++;
|
|
8909
|
+
}
|
|
8910
|
+
function isRNodeClaimedForHydration(node) {
|
|
8911
|
+
return !!node.__claimed;
|
|
8912
|
+
}
|
|
8913
|
+
function storeNgContainerInfo(hydrationInfo, index, firstChild) {
|
|
8914
|
+
hydrationInfo.ngContainers ?? (hydrationInfo.ngContainers = {});
|
|
8915
|
+
hydrationInfo.ngContainers[index] = { firstChild };
|
|
8916
|
+
}
|
|
8917
|
+
function getNgContainerSize(hydrationInfo, index) {
|
|
8918
|
+
return hydrationInfo.data[ELEMENT_CONTAINERS]?.[index] ?? null;
|
|
8919
|
+
}
|
|
8920
|
+
|
|
8566
8921
|
/**
|
|
8567
8922
|
* Represents a component created by a `ComponentFactory`.
|
|
8568
8923
|
* Provides access to the component instance and related objects,
|
|
@@ -8742,7 +9097,7 @@ class Version {
|
|
|
8742
9097
|
/**
|
|
8743
9098
|
* @publicApi
|
|
8744
9099
|
*/
|
|
8745
|
-
const VERSION = new Version('16.0.0-next.
|
|
9100
|
+
const VERSION = new Version('16.0.0-next.2');
|
|
8746
9101
|
|
|
8747
9102
|
// This default value is when checking the hierarchy for a token.
|
|
8748
9103
|
//
|
|
@@ -8823,6 +9178,23 @@ class ErrorHandler {
|
|
|
8823
9178
|
}
|
|
8824
9179
|
}
|
|
8825
9180
|
|
|
9181
|
+
const NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
9182
|
+
/**
|
|
9183
|
+
* Internal token that specifies whether hydration is enabled.
|
|
9184
|
+
*/
|
|
9185
|
+
const IS_HYDRATION_FEATURE_ENABLED = new InjectionToken(NG_DEV_MODE ? 'IS_HYDRATION_FEATURE_ENABLED' : '');
|
|
9186
|
+
// By default (in client rendering mode), we remove all the contents
|
|
9187
|
+
// of the host element and render an application after that.
|
|
9188
|
+
const PRESERVE_HOST_CONTENT_DEFAULT = false;
|
|
9189
|
+
/**
|
|
9190
|
+
* Internal token that indicates whether host element content should be
|
|
9191
|
+
* retained during the bootstrap.
|
|
9192
|
+
*/
|
|
9193
|
+
const PRESERVE_HOST_CONTENT = new InjectionToken(NG_DEV_MODE ? 'PRESERVE_HOST_CONTENT' : '', {
|
|
9194
|
+
providedIn: 'root',
|
|
9195
|
+
factory: () => PRESERVE_HOST_CONTENT_DEFAULT,
|
|
9196
|
+
});
|
|
9197
|
+
|
|
8826
9198
|
function normalizeDebugBindingName(name) {
|
|
8827
9199
|
// Attribute names with `$` (eg `x-y$`) are valid per spec, but unsupported by some browsers
|
|
8828
9200
|
name = camelCaseToDashCase(name.replace(/[$@]/g, '_'));
|
|
@@ -10473,7 +10845,7 @@ function renderChildComponents(hostLView, components) {
|
|
|
10473
10845
|
renderComponent(hostLView, components[i]);
|
|
10474
10846
|
}
|
|
10475
10847
|
}
|
|
10476
|
-
function createLView(parentLView, tView, context, flags, host, tHostNode, rendererFactory, renderer, sanitizer, injector, embeddedViewInjector) {
|
|
10848
|
+
function createLView(parentLView, tView, context, flags, host, tHostNode, rendererFactory, renderer, sanitizer, injector, embeddedViewInjector, hydrationInfo) {
|
|
10477
10849
|
const lView = tView.blueprint.slice();
|
|
10478
10850
|
lView[HOST] = host;
|
|
10479
10851
|
lView[FLAGS] = flags | 4 /* LViewFlags.CreationMode */ | 64 /* LViewFlags.Attached */ | 8 /* LViewFlags.FirstLViewPass */;
|
|
@@ -10493,6 +10865,7 @@ function createLView(parentLView, tView, context, flags, host, tHostNode, render
|
|
|
10493
10865
|
lView[INJECTOR$1] = injector || parentLView && parentLView[INJECTOR$1] || null;
|
|
10494
10866
|
lView[T_HOST] = tHostNode;
|
|
10495
10867
|
lView[ID] = getUniqueLViewId();
|
|
10868
|
+
lView[HYDRATION] = hydrationInfo;
|
|
10496
10869
|
lView[EMBEDDED_VIEW_INJECTOR] = embeddedViewInjector;
|
|
10497
10870
|
ngDevMode &&
|
|
10498
10871
|
assertEqual(tView.type == 2 /* TViewType.Embedded */ ? parentLView !== null : true, true, 'Embedded views must have parentLView');
|
|
@@ -10555,6 +10928,7 @@ function createTNodeAtIndex(tView, index, type, name, attrs) {
|
|
|
10555
10928
|
// In the case of i18n the `currentTNode` may already be linked, in which case we don't want
|
|
10556
10929
|
// to break the links which i18n created.
|
|
10557
10930
|
currentTNode.next = tNode;
|
|
10931
|
+
tNode.prev = currentTNode;
|
|
10558
10932
|
}
|
|
10559
10933
|
}
|
|
10560
10934
|
}
|
|
@@ -10933,10 +11307,19 @@ function createViewBlueprint(bindingStartIndex, initialViewLength) {
|
|
|
10933
11307
|
* @param rendererFactory Factory function to create renderer instance.
|
|
10934
11308
|
* @param elementOrSelector Render element or CSS selector to locate the element.
|
|
10935
11309
|
* @param encapsulation View Encapsulation defined for component that requests host element.
|
|
10936
|
-
|
|
10937
|
-
|
|
10938
|
-
|
|
10939
|
-
|
|
11310
|
+
* @param injector Root view injector instance.
|
|
11311
|
+
*/
|
|
11312
|
+
function locateHostElement(renderer, elementOrSelector, encapsulation, injector) {
|
|
11313
|
+
// Note: we use default value for the `PRESERVE_HOST_CONTENT` here even though it's a
|
|
11314
|
+
// tree-shakable one (providedIn:'root'). This code path can be triggered during dynamic component
|
|
11315
|
+
// creation (after calling ViewContainerRef.createComponent) when an injector instance can be
|
|
11316
|
+
// provided. The injector instance might be disconnected from the main DI tree, thus the
|
|
11317
|
+
// `PRESERVE_HOST_CONTENT` woild not be able to instantiate. In this case, the default value will
|
|
11318
|
+
// be used.
|
|
11319
|
+
const preserveHostContent = injector.get(PRESERVE_HOST_CONTENT, PRESERVE_HOST_CONTENT_DEFAULT);
|
|
11320
|
+
// When using native Shadow DOM, do not clear host element to allow native slot
|
|
11321
|
+
// projection.
|
|
11322
|
+
const preserveContent = preserveHostContent || encapsulation === ViewEncapsulation.ShadowDom;
|
|
10940
11323
|
return renderer.selectRootElement(elementOrSelector, preserveContent);
|
|
10941
11324
|
}
|
|
10942
11325
|
/**
|
|
@@ -10945,24 +11328,24 @@ function locateHostElement(renderer, elementOrSelector, encapsulation) {
|
|
|
10945
11328
|
* On the first template pass, saves in TView:
|
|
10946
11329
|
* - Cleanup function
|
|
10947
11330
|
* - Index of context we just saved in LView.cleanupInstances
|
|
10948
|
-
*
|
|
10949
|
-
* This function can also be used to store instance specific cleanup fns. In that case the `context`
|
|
10950
|
-
* is `null` and the function is store in `LView` (rather than it `TView`).
|
|
10951
11331
|
*/
|
|
10952
11332
|
function storeCleanupWithContext(tView, lView, context, cleanupFn) {
|
|
10953
11333
|
const lCleanup = getOrCreateLViewCleanup(lView);
|
|
10954
|
-
|
|
10955
|
-
|
|
10956
|
-
|
|
10957
|
-
|
|
10958
|
-
|
|
10959
|
-
|
|
10960
|
-
|
|
11334
|
+
// Historically the `storeCleanupWithContext` was used to register both framework-level and
|
|
11335
|
+
// user-defined cleanup callbacks, but over time those two types of cleanups were separated. This
|
|
11336
|
+
// dev mode checks assures that user-level cleanup callbacks are _not_ stored in data structures
|
|
11337
|
+
// reserved for framework-specific hooks.
|
|
11338
|
+
ngDevMode &&
|
|
11339
|
+
assertDefined(context, 'Cleanup context is mandatory when registering framework-level destroy hooks');
|
|
11340
|
+
lCleanup.push(context);
|
|
11341
|
+
if (tView.firstCreatePass) {
|
|
11342
|
+
getOrCreateTViewCleanup(tView).push(cleanupFn, lCleanup.length - 1);
|
|
10961
11343
|
}
|
|
10962
11344
|
else {
|
|
10963
|
-
|
|
10964
|
-
|
|
10965
|
-
|
|
11345
|
+
// Make sure that no new framework-level cleanup functions are registered after the first
|
|
11346
|
+
// template pass is done (and TView data structures are meant to fully constructed).
|
|
11347
|
+
if (ngDevMode) {
|
|
11348
|
+
Object.freeze(getOrCreateTViewCleanup(tView));
|
|
10966
11349
|
}
|
|
10967
11350
|
}
|
|
10968
11351
|
}
|
|
@@ -10993,8 +11376,9 @@ function createTNode(tView, tParent, type, index, value, attrs) {
|
|
|
10993
11376
|
initialInputs: undefined,
|
|
10994
11377
|
inputs: null,
|
|
10995
11378
|
outputs: null,
|
|
10996
|
-
|
|
11379
|
+
tView: null,
|
|
10997
11380
|
next: null,
|
|
11381
|
+
prev: null,
|
|
10998
11382
|
projectionNext: null,
|
|
10999
11383
|
child: null,
|
|
11000
11384
|
parent: tParent,
|
|
@@ -11204,7 +11588,6 @@ function resolveDirectives(tView, lView, tNode, localRefs) {
|
|
|
11204
11588
|
// Please make sure to have explicit type for `exportsMap`. Inferred type triggers bug in
|
|
11205
11589
|
// tsickle.
|
|
11206
11590
|
ngDevMode && assertFirstCreatePass(tView);
|
|
11207
|
-
let hasDirectives = false;
|
|
11208
11591
|
if (getBindingsEnabled()) {
|
|
11209
11592
|
const exportsMap = localRefs === null ? null : { '': -1 };
|
|
11210
11593
|
const matchResult = findDirectiveDefMatches(tView, tNode);
|
|
@@ -11217,7 +11600,6 @@ function resolveDirectives(tView, lView, tNode, localRefs) {
|
|
|
11217
11600
|
[directiveDefs, hostDirectiveDefs] = matchResult;
|
|
11218
11601
|
}
|
|
11219
11602
|
if (directiveDefs !== null) {
|
|
11220
|
-
hasDirectives = true;
|
|
11221
11603
|
initializeDirectives(tView, lView, tNode, directiveDefs, exportsMap, hostDirectiveDefs);
|
|
11222
11604
|
}
|
|
11223
11605
|
if (exportsMap)
|
|
@@ -11225,7 +11607,6 @@ function resolveDirectives(tView, lView, tNode, localRefs) {
|
|
|
11225
11607
|
}
|
|
11226
11608
|
// Merge the template attrs last so that they have the highest priority.
|
|
11227
11609
|
tNode.mergedAttrs = mergeHostAttrs(tNode.mergedAttrs, tNode.attrs);
|
|
11228
|
-
return hasDirectives;
|
|
11229
11610
|
}
|
|
11230
11611
|
/** Initializes the data structures necessary for a list of directives to be instantiated. */
|
|
11231
11612
|
function initializeDirectives(tView, lView, tNode, directives, exportsMap, hostDirectiveDefs) {
|
|
@@ -11538,7 +11919,7 @@ function addComponentLogic(lView, hostTNode, def) {
|
|
|
11538
11919
|
// Only component views should be added to the view tree directly. Embedded views are
|
|
11539
11920
|
// accessed through their containers because they may be removed / re-added later.
|
|
11540
11921
|
const rendererFactory = lView[RENDERER_FACTORY];
|
|
11541
|
-
const componentView = addToViewTree(lView, createLView(lView, tView, null, def.onPush ? 32 /* LViewFlags.Dirty */ : 16 /* LViewFlags.CheckAlways */, native, hostTNode, rendererFactory, rendererFactory.createRenderer(native, def), null, null, null));
|
|
11922
|
+
const componentView = addToViewTree(lView, createLView(lView, tView, null, def.onPush ? 32 /* LViewFlags.Dirty */ : 16 /* LViewFlags.CheckAlways */, native, hostTNode, rendererFactory, rendererFactory.createRenderer(native, def), null, null, null, null));
|
|
11542
11923
|
// Component view will always be created before any injected LContainers,
|
|
11543
11924
|
// so this is a regular element, wrap it with the component view
|
|
11544
11925
|
lView[hostTNode.index] = componentView;
|
|
@@ -11783,6 +12164,11 @@ function renderComponent(hostLView, componentHostIdx) {
|
|
|
11783
12164
|
const componentView = getComponentLViewByIndex(componentHostIdx, hostLView);
|
|
11784
12165
|
const componentTView = componentView[TVIEW];
|
|
11785
12166
|
syncViewWithBlueprint(componentTView, componentView);
|
|
12167
|
+
const hostRNode = componentView[HOST];
|
|
12168
|
+
// Populate an LView with hydration info retrieved from the DOM via TransferState.
|
|
12169
|
+
if (hostRNode !== null && componentView[HYDRATION] === null) {
|
|
12170
|
+
componentView[HYDRATION] = retrieveHydrationInfo(hostRNode, componentView[INJECTOR$1]);
|
|
12171
|
+
}
|
|
11786
12172
|
renderView(componentTView, componentView, componentView[CONTEXT]);
|
|
11787
12173
|
}
|
|
11788
12174
|
/**
|
|
@@ -12156,7 +12542,7 @@ class ViewRef {
|
|
|
12156
12542
|
destroyLView(this._lView[TVIEW], this._lView);
|
|
12157
12543
|
}
|
|
12158
12544
|
onDestroy(callback) {
|
|
12159
|
-
|
|
12545
|
+
storeLViewOnDestroy(this._lView, callback);
|
|
12160
12546
|
}
|
|
12161
12547
|
/**
|
|
12162
12548
|
* Marks a view and all of its ancestors dirty.
|
|
@@ -12483,13 +12869,13 @@ class ComponentFactory extends ComponentFactory$1 {
|
|
|
12483
12869
|
// dynamically. Default to 'div' if this component did not specify any tag name in its selector.
|
|
12484
12870
|
const elementName = this.componentDef.selectors[0][0] || 'div';
|
|
12485
12871
|
const hostRNode = rootSelectorOrNode ?
|
|
12486
|
-
locateHostElement(hostRenderer, rootSelectorOrNode, this.componentDef.encapsulation) :
|
|
12872
|
+
locateHostElement(hostRenderer, rootSelectorOrNode, this.componentDef.encapsulation, rootViewInjector) :
|
|
12487
12873
|
createElementNode(hostRenderer, elementName, getNamespace(elementName));
|
|
12488
12874
|
const rootFlags = this.componentDef.onPush ? 32 /* LViewFlags.Dirty */ | 256 /* LViewFlags.IsRoot */ :
|
|
12489
12875
|
16 /* LViewFlags.CheckAlways */ | 256 /* LViewFlags.IsRoot */;
|
|
12490
12876
|
// Create the root view. Uses empty TView and ContentTemplate.
|
|
12491
12877
|
const rootTView = createTView(0 /* TViewType.Root */, null, null, 1, 0, null, null, null, null, null);
|
|
12492
|
-
const rootLView = createLView(null, rootTView, null, rootFlags, null, null, rendererFactory, hostRenderer, sanitizer, rootViewInjector, null);
|
|
12878
|
+
const rootLView = createLView(null, rootTView, null, rootFlags, null, null, rendererFactory, hostRenderer, sanitizer, rootViewInjector, null, null);
|
|
12493
12879
|
// rootView is the parent when bootstrapping
|
|
12494
12880
|
// TODO(misko): it looks like we are entering view here but we don't really need to as
|
|
12495
12881
|
// `renderView` does that. However as the code is written it is needed because
|
|
@@ -12600,7 +12986,7 @@ function createRootComponentTNode(lView, rNode) {
|
|
|
12600
12986
|
/**
|
|
12601
12987
|
* Creates the root component view and the root component node.
|
|
12602
12988
|
*
|
|
12603
|
-
* @param
|
|
12989
|
+
* @param hostRNode Render host element.
|
|
12604
12990
|
* @param rootComponentDef ComponentDef
|
|
12605
12991
|
* @param rootView The parent view where the host node is stored
|
|
12606
12992
|
* @param rendererFactory Factory to be used for creating child renderers.
|
|
@@ -12609,11 +12995,17 @@ function createRootComponentTNode(lView, rNode) {
|
|
|
12609
12995
|
*
|
|
12610
12996
|
* @returns Component view created
|
|
12611
12997
|
*/
|
|
12612
|
-
function createRootComponentView(tNode,
|
|
12998
|
+
function createRootComponentView(tNode, hostRNode, rootComponentDef, rootDirectives, rootView, rendererFactory, hostRenderer, sanitizer) {
|
|
12613
12999
|
const tView = rootView[TVIEW];
|
|
12614
|
-
applyRootComponentStyling(rootDirectives, tNode,
|
|
12615
|
-
|
|
12616
|
-
|
|
13000
|
+
applyRootComponentStyling(rootDirectives, tNode, hostRNode, hostRenderer);
|
|
13001
|
+
// Hydration info is on the host element and needs to be retreived
|
|
13002
|
+
// and passed to the component LView.
|
|
13003
|
+
let hydrationInfo = null;
|
|
13004
|
+
if (hostRNode !== null) {
|
|
13005
|
+
hydrationInfo = retrieveHydrationInfo(hostRNode, rootView[INJECTOR$1]);
|
|
13006
|
+
}
|
|
13007
|
+
const viewRenderer = rendererFactory.createRenderer(hostRNode, rootComponentDef);
|
|
13008
|
+
const componentView = createLView(rootView, getOrCreateComponentTView(rootComponentDef), null, rootComponentDef.onPush ? 32 /* LViewFlags.Dirty */ : 16 /* LViewFlags.CheckAlways */, rootView[tNode.index], tNode, rendererFactory, viewRenderer, sanitizer || null, null, null, hydrationInfo);
|
|
12617
13009
|
if (tView.firstCreatePass) {
|
|
12618
13010
|
markAsComponentHost(tView, tNode, rootDirectives.length - 1);
|
|
12619
13011
|
}
|
|
@@ -13091,41 +13483,19 @@ function validateMappings(bindingType, def, hostDirectiveBindings) {
|
|
|
13091
13483
|
}
|
|
13092
13484
|
}
|
|
13093
13485
|
|
|
13094
|
-
let _symbolIterator = null;
|
|
13095
|
-
function getSymbolIterator() {
|
|
13096
|
-
if (!_symbolIterator) {
|
|
13097
|
-
const Symbol = _global$1['Symbol'];
|
|
13098
|
-
if (Symbol && Symbol.iterator) {
|
|
13099
|
-
_symbolIterator = Symbol.iterator;
|
|
13100
|
-
}
|
|
13101
|
-
else {
|
|
13102
|
-
// es6-shim specific logic
|
|
13103
|
-
const keys = Object.getOwnPropertyNames(Map.prototype);
|
|
13104
|
-
for (let i = 0; i < keys.length; ++i) {
|
|
13105
|
-
const key = keys[i];
|
|
13106
|
-
if (key !== 'entries' && key !== 'size' &&
|
|
13107
|
-
Map.prototype[key] === Map.prototype['entries']) {
|
|
13108
|
-
_symbolIterator = key;
|
|
13109
|
-
}
|
|
13110
|
-
}
|
|
13111
|
-
}
|
|
13112
|
-
}
|
|
13113
|
-
return _symbolIterator;
|
|
13114
|
-
}
|
|
13115
|
-
|
|
13116
13486
|
function isIterable(obj) {
|
|
13117
|
-
return obj !== null && typeof obj === 'object' && obj[
|
|
13487
|
+
return obj !== null && typeof obj === 'object' && obj[Symbol.iterator] !== undefined;
|
|
13118
13488
|
}
|
|
13119
13489
|
function isListLikeIterable(obj) {
|
|
13120
13490
|
if (!isJsObject(obj))
|
|
13121
13491
|
return false;
|
|
13122
13492
|
return Array.isArray(obj) ||
|
|
13123
13493
|
(!(obj instanceof Map) && // JS Map are iterables but return entries as [k, v]
|
|
13124
|
-
|
|
13494
|
+
Symbol.iterator in obj); // JS Iterable have a Symbol.iterator prop
|
|
13125
13495
|
}
|
|
13126
13496
|
function areIterablesEqual(a, b, comparator) {
|
|
13127
|
-
const iterator1 = a[
|
|
13128
|
-
const iterator2 = b[
|
|
13497
|
+
const iterator1 = a[Symbol.iterator]();
|
|
13498
|
+
const iterator2 = b[Symbol.iterator]();
|
|
13129
13499
|
while (true) {
|
|
13130
13500
|
const item1 = iterator1.next();
|
|
13131
13501
|
const item2 = iterator2.next();
|
|
@@ -13144,7 +13514,7 @@ function iterateListLike(obj, fn) {
|
|
|
13144
13514
|
}
|
|
13145
13515
|
}
|
|
13146
13516
|
else {
|
|
13147
|
-
const iterator = obj[
|
|
13517
|
+
const iterator = obj[Symbol.iterator]();
|
|
13148
13518
|
let item;
|
|
13149
13519
|
while (!((item = iterator.next()).done)) {
|
|
13150
13520
|
fn(item.value);
|
|
@@ -13797,7 +14167,7 @@ function templateFirstCreatePass(index, tView, lView, templateFn, decls, vars, t
|
|
|
13797
14167
|
const tNode = getOrCreateTNode(tView, index, 4 /* TNodeType.Container */, tagName || null, getConstant(tViewConsts, attrsIndex));
|
|
13798
14168
|
resolveDirectives(tView, lView, tNode, getConstant(tViewConsts, localRefsIndex));
|
|
13799
14169
|
registerPostOrderHooks(tView, tNode);
|
|
13800
|
-
const embeddedTView = tNode.
|
|
14170
|
+
const embeddedTView = tNode.tView = createTView(2 /* TViewType.Embedded */, tNode, templateFn, decls, vars, tView.directiveRegistry, tView.pipeRegistry, null, tView.schemas, tViewConsts);
|
|
13801
14171
|
if (tView.queries !== null) {
|
|
13802
14172
|
tView.queries.template(tView, tNode);
|
|
13803
14173
|
embeddedTView.queries = tView.queries.embeddedTView(tNode);
|
|
@@ -13867,6 +14237,119 @@ function ɵɵreference(index) {
|
|
|
13867
14237
|
return load(contextLView, HEADER_OFFSET + index);
|
|
13868
14238
|
}
|
|
13869
14239
|
|
|
14240
|
+
/**
|
|
14241
|
+
* Verifies whether a given node matches an expected criteria,
|
|
14242
|
+
* based on internal data structure state.
|
|
14243
|
+
*/
|
|
14244
|
+
function validateMatchingNode(node, nodeType, tagName, lView, tNode) {
|
|
14245
|
+
if (node.nodeType !== nodeType ||
|
|
14246
|
+
(node.nodeType === Node.ELEMENT_NODE &&
|
|
14247
|
+
node.tagName.toLowerCase() !== tagName?.toLowerCase())) {
|
|
14248
|
+
// TODO: improve error message and use RuntimeError instead.
|
|
14249
|
+
throw new Error(`Unexpected node found during hydration.`);
|
|
14250
|
+
}
|
|
14251
|
+
}
|
|
14252
|
+
/**
|
|
14253
|
+
* Verifies whether next sibling node exists.
|
|
14254
|
+
*/
|
|
14255
|
+
function validateSiblingNodeExists(node) {
|
|
14256
|
+
if (!node.nextSibling) {
|
|
14257
|
+
// TODO: improve error message and use RuntimeError instead.
|
|
14258
|
+
throw new Error(`Unexpected state: insufficient number of sibling nodes.`);
|
|
14259
|
+
}
|
|
14260
|
+
}
|
|
14261
|
+
|
|
14262
|
+
/** Whether current TNode is a first node in an <ng-container>. */
|
|
14263
|
+
function isFirstElementInNgContainer(tNode) {
|
|
14264
|
+
return !tNode.prev && tNode.parent?.type === 8 /* TNodeType.ElementContainer */;
|
|
14265
|
+
}
|
|
14266
|
+
/** Returns first element from a DOM segment that corresponds to this <ng-container>. */
|
|
14267
|
+
function getDehydratedNgContainer(hydrationInfo, tContainerNode) {
|
|
14268
|
+
const noOffsetIndex = tContainerNode.index - HEADER_OFFSET;
|
|
14269
|
+
const ngContainer = hydrationInfo.ngContainers?.[noOffsetIndex];
|
|
14270
|
+
ngDevMode &&
|
|
14271
|
+
assertDefined(ngContainer, 'Unexpected state: no hydration info available for a given TNode, ' +
|
|
14272
|
+
'which represents an element container.');
|
|
14273
|
+
return ngContainer;
|
|
14274
|
+
}
|
|
14275
|
+
/**
|
|
14276
|
+
* Locate a node in DOM tree that corresponds to a given TNode.
|
|
14277
|
+
*
|
|
14278
|
+
* @param hydrationInfo The hydration annotation data
|
|
14279
|
+
* @param tView the current tView
|
|
14280
|
+
* @param lView the current lView
|
|
14281
|
+
* @param tNode the current tNode
|
|
14282
|
+
* @returns an RNode that represents a given tNode
|
|
14283
|
+
*/
|
|
14284
|
+
function locateNextRNode(hydrationInfo, tView, lView, tNode) {
|
|
14285
|
+
let native = null;
|
|
14286
|
+
if (tView.firstChild === tNode) {
|
|
14287
|
+
// We create a first node in this view, so we use a reference
|
|
14288
|
+
// to the first child in this DOM segment.
|
|
14289
|
+
native = hydrationInfo.firstChild;
|
|
14290
|
+
}
|
|
14291
|
+
else {
|
|
14292
|
+
// Locate a node based on a previous sibling or a parent node.
|
|
14293
|
+
const previousTNodeParent = tNode.prev === null;
|
|
14294
|
+
const previousTNode = (tNode.prev ?? tNode.parent);
|
|
14295
|
+
ngDevMode &&
|
|
14296
|
+
assertDefined(previousTNode, 'Unexpected state: current TNode does not have a connection ' +
|
|
14297
|
+
'to the previous node or a parent node.');
|
|
14298
|
+
const previousRElement = getNativeByTNode(previousTNode, lView);
|
|
14299
|
+
if (isFirstElementInNgContainer(tNode)) {
|
|
14300
|
+
const ngContainer = getDehydratedNgContainer(hydrationInfo, tNode.parent);
|
|
14301
|
+
native = ngContainer.firstChild ?? null;
|
|
14302
|
+
}
|
|
14303
|
+
else {
|
|
14304
|
+
if (previousTNodeParent) {
|
|
14305
|
+
native = previousRElement.firstChild;
|
|
14306
|
+
}
|
|
14307
|
+
else {
|
|
14308
|
+
native = previousRElement.nextSibling;
|
|
14309
|
+
}
|
|
14310
|
+
}
|
|
14311
|
+
}
|
|
14312
|
+
return native;
|
|
14313
|
+
}
|
|
14314
|
+
/**
|
|
14315
|
+
* Skips over a specified number of nodes and returns the next sibling node after that.
|
|
14316
|
+
*/
|
|
14317
|
+
function siblingAfter(skip, from) {
|
|
14318
|
+
let currentNode = from;
|
|
14319
|
+
for (let i = 0; i < skip; i++) {
|
|
14320
|
+
ngDevMode && validateSiblingNodeExists(currentNode);
|
|
14321
|
+
currentNode = currentNode.nextSibling;
|
|
14322
|
+
}
|
|
14323
|
+
return currentNode;
|
|
14324
|
+
}
|
|
14325
|
+
|
|
14326
|
+
/**
|
|
14327
|
+
* The name of an attribute that can be added to the hydration boundary node
|
|
14328
|
+
* (component host node) to disable hydration for the content within that boundary.
|
|
14329
|
+
*/
|
|
14330
|
+
const SKIP_HYDRATION_ATTR_NAME = 'ngSkipHydration';
|
|
14331
|
+
/**
|
|
14332
|
+
* Helper function to check if a given node has the 'ngSkipHydration' attribute
|
|
14333
|
+
*/
|
|
14334
|
+
function hasNgSkipHydrationAttr(tNode) {
|
|
14335
|
+
const SKIP_HYDRATION_ATTR_NAME_LOWER_CASE = SKIP_HYDRATION_ATTR_NAME.toLowerCase();
|
|
14336
|
+
const attrs = tNode.mergedAttrs;
|
|
14337
|
+
if (attrs === null)
|
|
14338
|
+
return false;
|
|
14339
|
+
// only ever look at the attribute name and skip the values
|
|
14340
|
+
for (let i = 0; i < attrs.length; i += 2) {
|
|
14341
|
+
const value = attrs[i];
|
|
14342
|
+
// This is a marker, which means that the static attributes section is over,
|
|
14343
|
+
// so we can exit early.
|
|
14344
|
+
if (typeof value === 'number')
|
|
14345
|
+
return false;
|
|
14346
|
+
if (typeof value === 'string' && value.toLowerCase() === SKIP_HYDRATION_ATTR_NAME_LOWER_CASE) {
|
|
14347
|
+
return true;
|
|
14348
|
+
}
|
|
14349
|
+
}
|
|
14350
|
+
return false;
|
|
14351
|
+
}
|
|
14352
|
+
|
|
13870
14353
|
/**
|
|
13871
14354
|
* Update a property on a selected element.
|
|
13872
14355
|
*
|
|
@@ -13907,16 +14390,13 @@ function setDirectiveInputsWhichShadowsStyling(tView, tNode, lView, value, isCla
|
|
|
13907
14390
|
setInputsForProperty(tView, lView, inputs[property], property, value);
|
|
13908
14391
|
}
|
|
13909
14392
|
|
|
13910
|
-
function elementStartFirstCreatePass(index, tView, lView,
|
|
14393
|
+
function elementStartFirstCreatePass(index, tView, lView, name, attrsIndex, localRefsIndex) {
|
|
13911
14394
|
ngDevMode && assertFirstCreatePass(tView);
|
|
13912
14395
|
ngDevMode && ngDevMode.firstCreatePass++;
|
|
13913
14396
|
const tViewConsts = tView.consts;
|
|
13914
14397
|
const attrs = getConstant(tViewConsts, attrsIndex);
|
|
13915
14398
|
const tNode = getOrCreateTNode(tView, index, 2 /* TNodeType.Element */, name, attrs);
|
|
13916
|
-
|
|
13917
|
-
if (ngDevMode) {
|
|
13918
|
-
validateElementIsKnown(native, lView, tNode.value, tView.schemas, hasDirectives);
|
|
13919
|
-
}
|
|
14399
|
+
resolveDirectives(tView, lView, tNode, getConstant(tViewConsts, localRefsIndex));
|
|
13920
14400
|
if (tNode.attrs !== null) {
|
|
13921
14401
|
computeStaticStyling(tNode, tNode.attrs, false);
|
|
13922
14402
|
}
|
|
@@ -13951,13 +14431,18 @@ function ɵɵelementStart(index, name, attrsIndex, localRefsIndex) {
|
|
|
13951
14431
|
assertEqual(getBindingIndex(), tView.bindingStartIndex, 'elements should be created before any bindings');
|
|
13952
14432
|
ngDevMode && assertIndexInRange(lView, adjustedIndex);
|
|
13953
14433
|
const renderer = lView[RENDERER];
|
|
13954
|
-
const native = lView[adjustedIndex] = createElementNode(renderer, name, getNamespace$1());
|
|
13955
14434
|
const tNode = tView.firstCreatePass ?
|
|
13956
|
-
elementStartFirstCreatePass(adjustedIndex, tView, lView,
|
|
14435
|
+
elementStartFirstCreatePass(adjustedIndex, tView, lView, name, attrsIndex, localRefsIndex) :
|
|
13957
14436
|
tView.data[adjustedIndex];
|
|
14437
|
+
const native = _locateOrCreateElementNode(tView, lView, tNode, renderer, name);
|
|
14438
|
+
lView[adjustedIndex] = native;
|
|
14439
|
+
const hasDirectives = isDirectiveHost(tNode);
|
|
14440
|
+
if (ngDevMode && tView.firstCreatePass) {
|
|
14441
|
+
validateElementIsKnown(native, lView, tNode.value, tView.schemas, hasDirectives);
|
|
14442
|
+
}
|
|
13958
14443
|
setCurrentTNode(tNode, true);
|
|
13959
14444
|
setupStaticAttributes(renderer, native, tNode);
|
|
13960
|
-
if ((tNode.flags & 32 /* TNodeFlags.isDetached */) !== 32 /* TNodeFlags.isDetached */) {
|
|
14445
|
+
if ((tNode.flags & 32 /* TNodeFlags.isDetached */) !== 32 /* TNodeFlags.isDetached */ && wasLastNodeCreated()) {
|
|
13961
14446
|
// In the i18n case, the translation may have removed this element, so only add it if it is not
|
|
13962
14447
|
// detached. See `TNodeType.Placeholder` and `LFrame.inI18n` for more context.
|
|
13963
14448
|
appendChild(tView, lView, native, tNode);
|
|
@@ -13969,7 +14454,7 @@ function ɵɵelementStart(index, name, attrsIndex, localRefsIndex) {
|
|
|
13969
14454
|
attachPatchData(native, lView);
|
|
13970
14455
|
}
|
|
13971
14456
|
increaseElementDepthCount();
|
|
13972
|
-
if (
|
|
14457
|
+
if (hasDirectives) {
|
|
13973
14458
|
createDirectivesInstances(tView, lView, tNode);
|
|
13974
14459
|
executeContentQueries(tView, tNode, lView);
|
|
13975
14460
|
}
|
|
@@ -13997,6 +14482,9 @@ function ɵɵelementEnd() {
|
|
|
13997
14482
|
}
|
|
13998
14483
|
const tNode = currentTNode;
|
|
13999
14484
|
ngDevMode && assertTNodeType(tNode, 3 /* TNodeType.AnyRNode */);
|
|
14485
|
+
if (isSkipHydrationRootTNode(tNode)) {
|
|
14486
|
+
leaveSkipHydrationBlock();
|
|
14487
|
+
}
|
|
14000
14488
|
decreaseElementDepthCount();
|
|
14001
14489
|
const tView = getTView();
|
|
14002
14490
|
if (tView.firstCreatePass) {
|
|
@@ -14029,6 +14517,40 @@ function ɵɵelement(index, name, attrsIndex, localRefsIndex) {
|
|
|
14029
14517
|
ɵɵelementEnd();
|
|
14030
14518
|
return ɵɵelement;
|
|
14031
14519
|
}
|
|
14520
|
+
let _locateOrCreateElementNode = (tView, lView, tNode, renderer, name) => {
|
|
14521
|
+
lastNodeWasCreated(true);
|
|
14522
|
+
return createElementNode(renderer, name, getNamespace$1());
|
|
14523
|
+
};
|
|
14524
|
+
/**
|
|
14525
|
+
* Enables hydration code path (to lookup existing elements in DOM)
|
|
14526
|
+
* in addition to the regular creation mode of element nodes.
|
|
14527
|
+
*/
|
|
14528
|
+
function locateOrCreateElementNodeImpl(tView, lView, tNode, renderer, name) {
|
|
14529
|
+
const hydrationInfo = lView[HYDRATION];
|
|
14530
|
+
const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock();
|
|
14531
|
+
lastNodeWasCreated(isNodeCreationMode);
|
|
14532
|
+
// Regular creation mode.
|
|
14533
|
+
if (isNodeCreationMode) {
|
|
14534
|
+
return createElementNode(renderer, name, getNamespace$1());
|
|
14535
|
+
}
|
|
14536
|
+
// Hydration mode, looking up an existing element in DOM.
|
|
14537
|
+
const native = locateNextRNode(hydrationInfo, tView, lView, tNode);
|
|
14538
|
+
ngDevMode &&
|
|
14539
|
+
validateMatchingNode(native, Node.ELEMENT_NODE, name, lView, tNode);
|
|
14540
|
+
ngDevMode && markRNodeAsClaimedByHydration(native);
|
|
14541
|
+
// Checks if the skip hydration attribute is present during hydration so we know to
|
|
14542
|
+
// skip attempting to hydrate this block.
|
|
14543
|
+
if (hydrationInfo && hasNgSkipHydrationAttr(tNode)) {
|
|
14544
|
+
enterSkipHydrationBlock(tNode);
|
|
14545
|
+
// Since this isn't hydratable, we need to empty the node
|
|
14546
|
+
// so there's no duplicate content after render
|
|
14547
|
+
clearElementContents(renderer, native);
|
|
14548
|
+
}
|
|
14549
|
+
return native;
|
|
14550
|
+
}
|
|
14551
|
+
function enableLocateOrCreateElementNodeImpl() {
|
|
14552
|
+
_locateOrCreateElementNode = locateOrCreateElementNodeImpl;
|
|
14553
|
+
}
|
|
14032
14554
|
|
|
14033
14555
|
function elementContainerStartFirstCreatePass(index, tView, lView, attrsIndex, localRefsIndex) {
|
|
14034
14556
|
ngDevMode && ngDevMode.firstCreatePass++;
|
|
@@ -14074,10 +14596,12 @@ function ɵɵelementContainerStart(index, attrsIndex, localRefsIndex) {
|
|
|
14074
14596
|
tView.data[adjustedIndex];
|
|
14075
14597
|
setCurrentTNode(tNode, true);
|
|
14076
14598
|
ngDevMode && ngDevMode.rendererCreateComment++;
|
|
14077
|
-
const
|
|
14078
|
-
|
|
14079
|
-
|
|
14080
|
-
|
|
14599
|
+
const comment = _locateOrCreateElementContainerNode(tView, lView, tNode, index);
|
|
14600
|
+
lView[adjustedIndex] = comment;
|
|
14601
|
+
if (wasLastNodeCreated()) {
|
|
14602
|
+
appendChild(tView, lView, comment, tNode);
|
|
14603
|
+
}
|
|
14604
|
+
attachPatchData(comment, lView);
|
|
14081
14605
|
if (isDirectiveHost(tNode)) {
|
|
14082
14606
|
createDirectivesInstances(tView, lView, tNode);
|
|
14083
14607
|
executeContentQueries(tView, tNode, lView);
|
|
@@ -14129,6 +14653,46 @@ function ɵɵelementContainer(index, attrsIndex, localRefsIndex) {
|
|
|
14129
14653
|
ɵɵelementContainerEnd();
|
|
14130
14654
|
return ɵɵelementContainer;
|
|
14131
14655
|
}
|
|
14656
|
+
let _locateOrCreateElementContainerNode = (tView, lView, tNode, index) => {
|
|
14657
|
+
lastNodeWasCreated(true);
|
|
14658
|
+
return createCommentNode(lView[RENDERER], ngDevMode ? 'ng-container' : '');
|
|
14659
|
+
};
|
|
14660
|
+
/**
|
|
14661
|
+
* Enables hydration code path (to lookup existing elements in DOM)
|
|
14662
|
+
* in addition to the regular creation mode of comment nodes that
|
|
14663
|
+
* represent <ng-container>'s anchor.
|
|
14664
|
+
*/
|
|
14665
|
+
function locateOrCreateElementContainerNode(tView, lView, tNode, index) {
|
|
14666
|
+
let comment;
|
|
14667
|
+
const hydrationInfo = lView[HYDRATION];
|
|
14668
|
+
const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock();
|
|
14669
|
+
lastNodeWasCreated(isNodeCreationMode);
|
|
14670
|
+
// Regular creation mode.
|
|
14671
|
+
if (isNodeCreationMode) {
|
|
14672
|
+
return createCommentNode(lView[RENDERER], ngDevMode ? 'ng-container' : '');
|
|
14673
|
+
}
|
|
14674
|
+
// Hydration mode, looking up existing elements in DOM.
|
|
14675
|
+
const currentRNode = locateNextRNode(hydrationInfo, tView, lView, tNode);
|
|
14676
|
+
const ngContainerSize = getNgContainerSize(hydrationInfo, index);
|
|
14677
|
+
ngDevMode &&
|
|
14678
|
+
assertNumber(ngContainerSize, 'Unexpected state: hydrating an <ng-container>, ' +
|
|
14679
|
+
'but no hydration info is available.');
|
|
14680
|
+
if (ngContainerSize > 0) {
|
|
14681
|
+
storeNgContainerInfo(hydrationInfo, index, currentRNode);
|
|
14682
|
+
comment = siblingAfter(ngContainerSize, currentRNode);
|
|
14683
|
+
}
|
|
14684
|
+
else {
|
|
14685
|
+
// If <ng-container> has no nodes,
|
|
14686
|
+
// the current node is an anchor (comment) node.
|
|
14687
|
+
comment = currentRNode;
|
|
14688
|
+
}
|
|
14689
|
+
ngDevMode && validateMatchingNode(comment, Node.COMMENT_NODE, null, lView, tNode);
|
|
14690
|
+
ngDevMode && markRNodeAsClaimedByHydration(comment);
|
|
14691
|
+
return comment;
|
|
14692
|
+
}
|
|
14693
|
+
function enableLocateOrCreateElementContainerNodeImpl() {
|
|
14694
|
+
_locateOrCreateElementContainerNode = locateOrCreateElementContainerNode;
|
|
14695
|
+
}
|
|
14132
14696
|
|
|
14133
14697
|
/**
|
|
14134
14698
|
* Returns the current OpaqueViewState instance.
|
|
@@ -14157,16 +14721,6 @@ function isPromise(obj) {
|
|
|
14157
14721
|
function isSubscribable(obj) {
|
|
14158
14722
|
return !!obj && typeof obj.subscribe === 'function';
|
|
14159
14723
|
}
|
|
14160
|
-
/**
|
|
14161
|
-
* Determine if the argument is an Observable
|
|
14162
|
-
*
|
|
14163
|
-
* Strictly this tests that the `obj` is `Subscribable`, since `Observable`
|
|
14164
|
-
* types need additional methods, such as `lift()`. But it is adequate for our
|
|
14165
|
-
* needs since within the Angular framework code we only ever need to use the
|
|
14166
|
-
* `subscribe()` method, and RxJS has mechanisms to wrap `Subscribable` objects
|
|
14167
|
-
* into `Observable` as needed.
|
|
14168
|
-
*/
|
|
14169
|
-
const isObservable = isSubscribable;
|
|
14170
14724
|
|
|
14171
14725
|
/**
|
|
14172
14726
|
* Adds an event listener to the current node.
|
|
@@ -14329,7 +14883,7 @@ function listenerInternal(tView, lView, renderer, tNode, eventName, listenerFn,
|
|
|
14329
14883
|
const minifiedName = props[i + 1];
|
|
14330
14884
|
const directiveInstance = lView[index];
|
|
14331
14885
|
const output = directiveInstance[minifiedName];
|
|
14332
|
-
if (ngDevMode && !
|
|
14886
|
+
if (ngDevMode && !isSubscribable(output)) {
|
|
14333
14887
|
throw new Error(`@Output ${minifiedName} not initialized in '${directiveInstance.constructor.name}'.`);
|
|
14334
14888
|
}
|
|
14335
14889
|
const subscription = output.subscribe(listenerFn);
|
|
@@ -16473,11 +17027,39 @@ function ɵɵtext(index, value = '') {
|
|
|
16473
17027
|
const tNode = tView.firstCreatePass ?
|
|
16474
17028
|
getOrCreateTNode(tView, adjustedIndex, 1 /* TNodeType.Text */, value, null) :
|
|
16475
17029
|
tView.data[adjustedIndex];
|
|
16476
|
-
const textNative =
|
|
16477
|
-
|
|
17030
|
+
const textNative = _locateOrCreateTextNode(tView, lView, tNode, value);
|
|
17031
|
+
lView[adjustedIndex] = textNative;
|
|
17032
|
+
if (wasLastNodeCreated()) {
|
|
17033
|
+
appendChild(tView, lView, textNative, tNode);
|
|
17034
|
+
}
|
|
16478
17035
|
// Text nodes are self closing.
|
|
16479
17036
|
setCurrentTNode(tNode, false);
|
|
16480
17037
|
}
|
|
17038
|
+
let _locateOrCreateTextNode = (tView, lView, tNode, value) => {
|
|
17039
|
+
lastNodeWasCreated(true);
|
|
17040
|
+
return createTextNode(lView[RENDERER], value);
|
|
17041
|
+
};
|
|
17042
|
+
/**
|
|
17043
|
+
* Enables hydration code path (to lookup existing elements in DOM)
|
|
17044
|
+
* in addition to the regular creation mode of text nodes.
|
|
17045
|
+
*/
|
|
17046
|
+
function locateOrCreateTextNodeImpl(tView, lView, tNode, value) {
|
|
17047
|
+
const hydrationInfo = lView[HYDRATION];
|
|
17048
|
+
const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock();
|
|
17049
|
+
lastNodeWasCreated(isNodeCreationMode);
|
|
17050
|
+
// Regular creation mode.
|
|
17051
|
+
if (isNodeCreationMode) {
|
|
17052
|
+
return createTextNode(lView[RENDERER], value);
|
|
17053
|
+
}
|
|
17054
|
+
// Hydration mode, looking up an existing element in DOM.
|
|
17055
|
+
const textNative = locateNextRNode(hydrationInfo, tView, lView, tNode);
|
|
17056
|
+
ngDevMode && validateMatchingNode(textNative, Node.TEXT_NODE, null, lView, tNode);
|
|
17057
|
+
ngDevMode && markRNodeAsClaimedByHydration(textNative);
|
|
17058
|
+
return textNative;
|
|
17059
|
+
}
|
|
17060
|
+
function enableLocateOrCreateTextNodeImpl() {
|
|
17061
|
+
_locateOrCreateTextNode = locateOrCreateTextNodeImpl;
|
|
17062
|
+
}
|
|
16481
17063
|
|
|
16482
17064
|
/**
|
|
16483
17065
|
*
|
|
@@ -18155,7 +18737,7 @@ function getTIcu(tView, index) {
|
|
|
18155
18737
|
if (value === null || typeof value === 'string')
|
|
18156
18738
|
return null;
|
|
18157
18739
|
if (ngDevMode &&
|
|
18158
|
-
!(value.hasOwnProperty('
|
|
18740
|
+
!(value.hasOwnProperty('tView') || value.hasOwnProperty('currentCaseLViewIndex'))) {
|
|
18159
18741
|
throwError('We expect to get \'null\'|\'TIcu\'|\'TIcuContainer\', but got: ' + value);
|
|
18160
18742
|
}
|
|
18161
18743
|
// Here the `value.hasOwnProperty('currentCaseLViewIndex')` is a polymorphic read as it can be
|
|
@@ -18184,7 +18766,7 @@ function getTIcu(tView, index) {
|
|
|
18184
18766
|
function setTIcu(tView, index, tIcu) {
|
|
18185
18767
|
const tNode = tView.data[index];
|
|
18186
18768
|
ngDevMode &&
|
|
18187
|
-
assertEqual(tNode === null || tNode.hasOwnProperty('
|
|
18769
|
+
assertEqual(tNode === null || tNode.hasOwnProperty('tView'), true, 'We expect to get \'null\'|\'TIcuContainer\'');
|
|
18188
18770
|
if (tNode === null) {
|
|
18189
18771
|
tView.data[index] = tIcu;
|
|
18190
18772
|
}
|
|
@@ -21284,7 +21866,8 @@ function _wrapInTimeout(fn) {
|
|
|
21284
21866
|
const EventEmitter = EventEmitter_;
|
|
21285
21867
|
|
|
21286
21868
|
function symbolIterator() {
|
|
21287
|
-
|
|
21869
|
+
// @ts-expect-error accessing a private member
|
|
21870
|
+
return this._results[Symbol.iterator]();
|
|
21288
21871
|
}
|
|
21289
21872
|
/**
|
|
21290
21873
|
* An unmodifiable list of items that Angular keeps up to date when the state
|
|
@@ -21336,11 +21919,10 @@ class QueryList {
|
|
|
21336
21919
|
// This function should be declared on the prototype, but doing so there will cause the class
|
|
21337
21920
|
// declaration to have side-effects and become not tree-shakable. For this reason we do it in
|
|
21338
21921
|
// the constructor.
|
|
21339
|
-
// [
|
|
21340
|
-
const symbol = getSymbolIterator();
|
|
21922
|
+
// [Symbol.iterator](): Iterator<T> { ... }
|
|
21341
21923
|
const proto = QueryList.prototype;
|
|
21342
|
-
if (!proto[
|
|
21343
|
-
proto[
|
|
21924
|
+
if (!proto[Symbol.iterator])
|
|
21925
|
+
proto[Symbol.iterator] = symbolIterator;
|
|
21344
21926
|
}
|
|
21345
21927
|
/**
|
|
21346
21928
|
* Returns the QueryList entry at `index`.
|
|
@@ -21479,8 +22061,8 @@ const R3TemplateRef = class TemplateRef extends ViewEngineTemplateRef {
|
|
|
21479
22061
|
this.elementRef = elementRef;
|
|
21480
22062
|
}
|
|
21481
22063
|
createEmbeddedView(context, injector) {
|
|
21482
|
-
const embeddedTView = this._declarationTContainer.
|
|
21483
|
-
const embeddedLView = createLView(this._declarationLView, embeddedTView, context, 16 /* LViewFlags.CheckAlways */, null, embeddedTView.declTNode, null, null, null, null, injector || null);
|
|
22064
|
+
const embeddedTView = this._declarationTContainer.tView;
|
|
22065
|
+
const embeddedLView = createLView(this._declarationLView, embeddedTView, context, 16 /* LViewFlags.CheckAlways */, null, embeddedTView.declTNode, null, null, null, null, injector || null, null);
|
|
21484
22066
|
const declarationLContainer = this._declarationLView[this._declarationTContainer.index];
|
|
21485
22067
|
ngDevMode && assertLContainer(declarationLContainer);
|
|
21486
22068
|
embeddedLView[DECLARATION_LCONTAINER] = declarationLContainer;
|
|
@@ -21509,7 +22091,7 @@ function injectTemplateRef() {
|
|
|
21509
22091
|
*/
|
|
21510
22092
|
function createTemplateRef(hostTNode, hostLView) {
|
|
21511
22093
|
if (hostTNode.type & 4 /* TNodeType.Container */) {
|
|
21512
|
-
ngDevMode && assertDefined(hostTNode.
|
|
22094
|
+
ngDevMode && assertDefined(hostTNode.tView, 'TView must be allocated');
|
|
21513
22095
|
return new R3TemplateRef(hostLView, hostTNode, createElementRef(hostTNode, hostLView));
|
|
21514
22096
|
}
|
|
21515
22097
|
return null;
|