@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/fesm2015/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
|
*/
|
|
@@ -1636,6 +1636,8 @@ function ngDevModeResetPerfCounters() {
|
|
|
1636
1636
|
rendererAppendChild: 0,
|
|
1637
1637
|
rendererInsertBefore: 0,
|
|
1638
1638
|
rendererCreateComment: 0,
|
|
1639
|
+
hydratedNodes: 0,
|
|
1640
|
+
hydratedComponents: 0,
|
|
1639
1641
|
};
|
|
1640
1642
|
// Make sure to refer to ngDevMode as ['ngDevMode'] for closure.
|
|
1641
1643
|
const allowNgDevModeTrue = locationString.indexOf('ngDevMode=false') === -1;
|
|
@@ -2115,54 +2117,6 @@ var ChangeDetectionStrategy;
|
|
|
2115
2117
|
*/
|
|
2116
2118
|
ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 1] = "Default";
|
|
2117
2119
|
})(ChangeDetectionStrategy || (ChangeDetectionStrategy = {}));
|
|
2118
|
-
/**
|
|
2119
|
-
* Defines the possible states of the default change detector.
|
|
2120
|
-
* @see `ChangeDetectorRef`
|
|
2121
|
-
*/
|
|
2122
|
-
var ChangeDetectorStatus;
|
|
2123
|
-
(function (ChangeDetectorStatus) {
|
|
2124
|
-
/**
|
|
2125
|
-
* A state in which, after calling `detectChanges()`, the change detector
|
|
2126
|
-
* state becomes `Checked`, and must be explicitly invoked or reactivated.
|
|
2127
|
-
*/
|
|
2128
|
-
ChangeDetectorStatus[ChangeDetectorStatus["CheckOnce"] = 0] = "CheckOnce";
|
|
2129
|
-
/**
|
|
2130
|
-
* A state in which change detection is skipped until the change detector mode
|
|
2131
|
-
* becomes `CheckOnce`.
|
|
2132
|
-
*/
|
|
2133
|
-
ChangeDetectorStatus[ChangeDetectorStatus["Checked"] = 1] = "Checked";
|
|
2134
|
-
/**
|
|
2135
|
-
* A state in which change detection continues automatically until explicitly
|
|
2136
|
-
* deactivated.
|
|
2137
|
-
*/
|
|
2138
|
-
ChangeDetectorStatus[ChangeDetectorStatus["CheckAlways"] = 2] = "CheckAlways";
|
|
2139
|
-
/**
|
|
2140
|
-
* A state in which a change detector sub tree is not a part of the main tree and
|
|
2141
|
-
* should be skipped.
|
|
2142
|
-
*/
|
|
2143
|
-
ChangeDetectorStatus[ChangeDetectorStatus["Detached"] = 3] = "Detached";
|
|
2144
|
-
/**
|
|
2145
|
-
* Indicates that the change detector encountered an error checking a binding
|
|
2146
|
-
* or calling a directive lifecycle method and is now in an inconsistent state. Change
|
|
2147
|
-
* detectors in this state do not detect changes.
|
|
2148
|
-
*/
|
|
2149
|
-
ChangeDetectorStatus[ChangeDetectorStatus["Errored"] = 4] = "Errored";
|
|
2150
|
-
/**
|
|
2151
|
-
* Indicates that the change detector has been destroyed.
|
|
2152
|
-
*/
|
|
2153
|
-
ChangeDetectorStatus[ChangeDetectorStatus["Destroyed"] = 5] = "Destroyed";
|
|
2154
|
-
})(ChangeDetectorStatus || (ChangeDetectorStatus = {}));
|
|
2155
|
-
/**
|
|
2156
|
-
* Reports whether a given strategy is currently the default for change detection.
|
|
2157
|
-
* @param changeDetectionStrategy The strategy to check.
|
|
2158
|
-
* @returns True if the given strategy is the current default, false otherwise.
|
|
2159
|
-
* @see `ChangeDetectorStatus`
|
|
2160
|
-
* @see `ChangeDetectorRef`
|
|
2161
|
-
*/
|
|
2162
|
-
function isDefaultChangeDetectionStrategy(changeDetectionStrategy) {
|
|
2163
|
-
return changeDetectionStrategy == null ||
|
|
2164
|
-
changeDetectionStrategy === ChangeDetectionStrategy.Default;
|
|
2165
|
-
}
|
|
2166
2120
|
|
|
2167
2121
|
/**
|
|
2168
2122
|
* Defines the CSS styles encapsulation policies for the {@link Component} decorator's
|
|
@@ -2234,6 +2188,15 @@ const NG_FACTORY_DEF = getClosureSafeProperty({ ɵfac: getClosureSafeProperty })
|
|
|
2234
2188
|
*/
|
|
2235
2189
|
// TODO(misko): This is wrong. The NG_ELEMENT_ID should never be minified.
|
|
2236
2190
|
const NG_ELEMENT_ID = getClosureSafeProperty({ __NG_ELEMENT_ID__: getClosureSafeProperty });
|
|
2191
|
+
/**
|
|
2192
|
+
* The `NG_ENV_ID` field on a DI token indicates special processing in the `EnvironmentInjector`:
|
|
2193
|
+
* getting such tokens from the `EnvironmentInjector` will bypass the standard DI resolution
|
|
2194
|
+
* strategy and instead will return implementation produced by the `NG_ENV_ID` factory function.
|
|
2195
|
+
*
|
|
2196
|
+
* This particular retrieval of DI tokens is mostly done to eliminate circular dependencies and
|
|
2197
|
+
* improve tree-shaking.
|
|
2198
|
+
*/
|
|
2199
|
+
const NG_ENV_ID = getClosureSafeProperty({ __NG_ENV_ID__: getClosureSafeProperty });
|
|
2237
2200
|
|
|
2238
2201
|
/** Counter used to generate unique IDs for component definitions. */
|
|
2239
2202
|
let componentDefCount = 0;
|
|
@@ -2588,6 +2551,8 @@ const PREORDER_HOOK_FLAGS = 18;
|
|
|
2588
2551
|
const QUERIES = 19;
|
|
2589
2552
|
const ID = 20;
|
|
2590
2553
|
const EMBEDDED_VIEW_INJECTOR = 21;
|
|
2554
|
+
const ON_DESTROY_HOOKS = 22;
|
|
2555
|
+
const HYDRATION = 23;
|
|
2591
2556
|
/**
|
|
2592
2557
|
* Size of LView's header. Necessary to adjust for it when setting slots.
|
|
2593
2558
|
*
|
|
@@ -2595,7 +2560,7 @@ const EMBEDDED_VIEW_INJECTOR = 21;
|
|
|
2595
2560
|
* instruction index into `LView` index. All other indexes should be in the `LView` index space and
|
|
2596
2561
|
* there should be no need to refer to `HEADER_OFFSET` anywhere else.
|
|
2597
2562
|
*/
|
|
2598
|
-
const HEADER_OFFSET =
|
|
2563
|
+
const HEADER_OFFSET = 24;
|
|
2599
2564
|
// Note: This hack is necessary so we don't erroneously get a circular dependency
|
|
2600
2565
|
// failure based on types.
|
|
2601
2566
|
const unusedValueExportToPlacateAjd$3 = 1;
|
|
@@ -3033,10 +2998,20 @@ function updateTransplantedViewCount(lContainer, amount) {
|
|
|
3033
2998
|
parent = parent[PARENT];
|
|
3034
2999
|
}
|
|
3035
3000
|
}
|
|
3001
|
+
/**
|
|
3002
|
+
* Stores a LView-specific destroy callback.
|
|
3003
|
+
*/
|
|
3004
|
+
function storeLViewOnDestroy(lView, onDestroyCallback) {
|
|
3005
|
+
if (lView[ON_DESTROY_HOOKS] === null) {
|
|
3006
|
+
lView[ON_DESTROY_HOOKS] = [];
|
|
3007
|
+
}
|
|
3008
|
+
lView[ON_DESTROY_HOOKS].push(onDestroyCallback);
|
|
3009
|
+
}
|
|
3036
3010
|
|
|
3037
3011
|
const instructionState = {
|
|
3038
3012
|
lFrame: createLFrame(null),
|
|
3039
3013
|
bindingsEnabled: true,
|
|
3014
|
+
skipHydrationRootTNode: null,
|
|
3040
3015
|
};
|
|
3041
3016
|
/**
|
|
3042
3017
|
* In this mode, any changes in bindings will throw an ExpressionChangedAfterChecked error.
|
|
@@ -3067,6 +3042,21 @@ function decreaseElementDepthCount() {
|
|
|
3067
3042
|
function getBindingsEnabled() {
|
|
3068
3043
|
return instructionState.bindingsEnabled;
|
|
3069
3044
|
}
|
|
3045
|
+
/**
|
|
3046
|
+
* Returns true if currently inside a skip hydration block.
|
|
3047
|
+
* @returns boolean
|
|
3048
|
+
*/
|
|
3049
|
+
function isInSkipHydrationBlock() {
|
|
3050
|
+
return instructionState.skipHydrationRootTNode !== null;
|
|
3051
|
+
}
|
|
3052
|
+
/**
|
|
3053
|
+
* Returns true if this is the root TNode of the skip hydration block.
|
|
3054
|
+
* @param tNode the current TNode
|
|
3055
|
+
* @returns boolean
|
|
3056
|
+
*/
|
|
3057
|
+
function isSkipHydrationRootTNode(tNode) {
|
|
3058
|
+
return instructionState.skipHydrationRootTNode === tNode;
|
|
3059
|
+
}
|
|
3070
3060
|
/**
|
|
3071
3061
|
* Enables directive matching on elements.
|
|
3072
3062
|
*
|
|
@@ -3089,6 +3079,13 @@ function getBindingsEnabled() {
|
|
|
3089
3079
|
function ɵɵenableBindings() {
|
|
3090
3080
|
instructionState.bindingsEnabled = true;
|
|
3091
3081
|
}
|
|
3082
|
+
/**
|
|
3083
|
+
* Sets a flag to specify that the TNode is in a skip hydration block.
|
|
3084
|
+
* @param tNode the current TNode
|
|
3085
|
+
*/
|
|
3086
|
+
function enterSkipHydrationBlock(tNode) {
|
|
3087
|
+
instructionState.skipHydrationRootTNode = tNode;
|
|
3088
|
+
}
|
|
3092
3089
|
/**
|
|
3093
3090
|
* Disables directive matching on element.
|
|
3094
3091
|
*
|
|
@@ -3111,6 +3108,12 @@ function ɵɵenableBindings() {
|
|
|
3111
3108
|
function ɵɵdisableBindings() {
|
|
3112
3109
|
instructionState.bindingsEnabled = false;
|
|
3113
3110
|
}
|
|
3111
|
+
/**
|
|
3112
|
+
* Clears the root skip hydration node when leaving a skip hydration block.
|
|
3113
|
+
*/
|
|
3114
|
+
function leaveSkipHydrationBlock() {
|
|
3115
|
+
instructionState.skipHydrationRootTNode = null;
|
|
3116
|
+
}
|
|
3114
3117
|
/**
|
|
3115
3118
|
* Return the current `LView`.
|
|
3116
3119
|
*/
|
|
@@ -3535,6 +3538,21 @@ function namespaceHTMLInternal() {
|
|
|
3535
3538
|
function getNamespace$1() {
|
|
3536
3539
|
return instructionState.lFrame.currentNamespace;
|
|
3537
3540
|
}
|
|
3541
|
+
let _wasLastNodeCreated = true;
|
|
3542
|
+
/**
|
|
3543
|
+
* Retrieves a global flag that indicates whether the most recent DOM node
|
|
3544
|
+
* was created or hydrated.
|
|
3545
|
+
*/
|
|
3546
|
+
function wasLastNodeCreated() {
|
|
3547
|
+
return _wasLastNodeCreated;
|
|
3548
|
+
}
|
|
3549
|
+
/**
|
|
3550
|
+
* Sets a global flag to indicate whether the most recent DOM node
|
|
3551
|
+
* was created or hydrated.
|
|
3552
|
+
*/
|
|
3553
|
+
function lastNodeWasCreated(flag) {
|
|
3554
|
+
_wasLastNodeCreated = flag;
|
|
3555
|
+
}
|
|
3538
3556
|
|
|
3539
3557
|
/**
|
|
3540
3558
|
* Adds all directive lifecycle hooks from the given `DirectiveDef` to the given `TView`.
|
|
@@ -3710,8 +3728,9 @@ function callHooks(currentView, arr, initPhase, currentNodeIndex) {
|
|
|
3710
3728
|
}
|
|
3711
3729
|
else {
|
|
3712
3730
|
const isInitHook = arr[i] < 0;
|
|
3713
|
-
if (isInitHook)
|
|
3731
|
+
if (isInitHook) {
|
|
3714
3732
|
currentView[PREORDER_HOOK_FLAGS] += 65536 /* PreOrderHookFlags.NumberOfInitHooksCalledIncrementer */;
|
|
3733
|
+
}
|
|
3715
3734
|
if (lastNodeIndexFound < nodeIndexLimit || nodeIndexLimit == -1) {
|
|
3716
3735
|
callHook(currentView, initPhase, arr, i);
|
|
3717
3736
|
currentView[PREORDER_HOOK_FLAGS] =
|
|
@@ -6243,10 +6262,6 @@ function cleanUpView(tView, lView) {
|
|
|
6243
6262
|
function processCleanups(tView, lView) {
|
|
6244
6263
|
const tCleanup = tView.cleanup;
|
|
6245
6264
|
const lCleanup = lView[CLEANUP];
|
|
6246
|
-
// `LCleanup` contains both share information with `TCleanup` as well as instance specific
|
|
6247
|
-
// information appended at the end. We need to know where the end of the `TCleanup` information
|
|
6248
|
-
// is, and we track this with `lastLCleanupIndex`.
|
|
6249
|
-
let lastLCleanupIndex = -1;
|
|
6250
6265
|
if (tCleanup !== null) {
|
|
6251
6266
|
for (let i = 0; i < tCleanup.length - 1; i += 2) {
|
|
6252
6267
|
if (typeof tCleanup[i] === 'string') {
|
|
@@ -6256,29 +6271,33 @@ function processCleanups(tView, lView) {
|
|
|
6256
6271
|
ngDevMode && assertNumber(targetIdx, 'cleanup target must be a number');
|
|
6257
6272
|
if (targetIdx >= 0) {
|
|
6258
6273
|
// unregister
|
|
6259
|
-
lCleanup[
|
|
6274
|
+
lCleanup[targetIdx]();
|
|
6260
6275
|
}
|
|
6261
6276
|
else {
|
|
6262
6277
|
// Subscription
|
|
6263
|
-
lCleanup[
|
|
6278
|
+
lCleanup[-targetIdx].unsubscribe();
|
|
6264
6279
|
}
|
|
6265
6280
|
i += 2;
|
|
6266
6281
|
}
|
|
6267
6282
|
else {
|
|
6268
6283
|
// This is a cleanup function that is grouped with the index of its context
|
|
6269
|
-
const context = lCleanup[
|
|
6284
|
+
const context = lCleanup[tCleanup[i + 1]];
|
|
6270
6285
|
tCleanup[i].call(context);
|
|
6271
6286
|
}
|
|
6272
6287
|
}
|
|
6273
6288
|
}
|
|
6274
6289
|
if (lCleanup !== null) {
|
|
6275
|
-
for (let i = lastLCleanupIndex + 1; i < lCleanup.length; i++) {
|
|
6276
|
-
const instanceCleanupFn = lCleanup[i];
|
|
6277
|
-
ngDevMode && assertFunction(instanceCleanupFn, 'Expecting instance cleanup function.');
|
|
6278
|
-
instanceCleanupFn();
|
|
6279
|
-
}
|
|
6280
6290
|
lView[CLEANUP] = null;
|
|
6281
6291
|
}
|
|
6292
|
+
const destroyHooks = lView[ON_DESTROY_HOOKS];
|
|
6293
|
+
if (destroyHooks !== null) {
|
|
6294
|
+
for (let i = 0; i < destroyHooks.length; i++) {
|
|
6295
|
+
const destroyHooksFn = destroyHooks[i];
|
|
6296
|
+
ngDevMode && assertFunction(destroyHooksFn, 'Expecting destroy hook to be a function.');
|
|
6297
|
+
destroyHooksFn();
|
|
6298
|
+
}
|
|
6299
|
+
lView[ON_DESTROY_HOOKS] = null;
|
|
6300
|
+
}
|
|
6282
6301
|
}
|
|
6283
6302
|
/** Calls onDestroy hooks for this view */
|
|
6284
6303
|
function executeOnDestroys(tView, lView) {
|
|
@@ -6589,6 +6608,17 @@ function nativeRemoveNode(renderer, rNode, isHostElement) {
|
|
|
6589
6608
|
nativeRemoveChild(renderer, nativeParent, rNode, isHostElement);
|
|
6590
6609
|
}
|
|
6591
6610
|
}
|
|
6611
|
+
/**
|
|
6612
|
+
* Removes the contents of a given RElement using a given renderer.
|
|
6613
|
+
*
|
|
6614
|
+
* @param renderer A renderer to be used
|
|
6615
|
+
* @param rElement the native RElement to be cleared
|
|
6616
|
+
*/
|
|
6617
|
+
function clearElementContents(renderer, rElement) {
|
|
6618
|
+
while (rElement.firstChild) {
|
|
6619
|
+
nativeRemoveChild(renderer, rElement, rElement.firstChild, false);
|
|
6620
|
+
}
|
|
6621
|
+
}
|
|
6592
6622
|
/**
|
|
6593
6623
|
* Performs the operation of `action` on the node. Typically this involves inserting or removing
|
|
6594
6624
|
* nodes on the LView or projection boundary.
|
|
@@ -8294,6 +8324,9 @@ class R3Injector extends EnvironmentInjector {
|
|
|
8294
8324
|
}
|
|
8295
8325
|
get(token, notFoundValue = THROW_IF_NOT_FOUND, flags = InjectFlags.Default) {
|
|
8296
8326
|
this.assertNotDestroyed();
|
|
8327
|
+
if (token.hasOwnProperty(NG_ENV_ID)) {
|
|
8328
|
+
return token[NG_ENV_ID](this);
|
|
8329
|
+
}
|
|
8297
8330
|
flags = convertToBitFlags(flags);
|
|
8298
8331
|
// Set the injection context.
|
|
8299
8332
|
const previousInjector = setCurrentInjector(this);
|
|
@@ -8571,6 +8604,331 @@ function forEachSingleProvider(providers, fn) {
|
|
|
8571
8604
|
}
|
|
8572
8605
|
}
|
|
8573
8606
|
|
|
8607
|
+
/**
|
|
8608
|
+
* A [DI token](guide/glossary#di-token "DI token definition") representing a unique string ID, used
|
|
8609
|
+
* primarily for prefixing application attributes and CSS styles when
|
|
8610
|
+
* {@link ViewEncapsulation#Emulated ViewEncapsulation.Emulated} is being used.
|
|
8611
|
+
*
|
|
8612
|
+
* BY default, the value is randomly generated and assigned to the application by Angular.
|
|
8613
|
+
* To provide a custom ID value, use a DI provider <!-- TODO: provider --> to configure
|
|
8614
|
+
* the root {@link Injector} that uses this token.
|
|
8615
|
+
*
|
|
8616
|
+
* @publicApi
|
|
8617
|
+
*/
|
|
8618
|
+
const APP_ID = new InjectionToken('AppId', {
|
|
8619
|
+
providedIn: 'root',
|
|
8620
|
+
factory: _appIdRandomProviderFactory,
|
|
8621
|
+
});
|
|
8622
|
+
function _appIdRandomProviderFactory() {
|
|
8623
|
+
return `${_randomChar()}${_randomChar()}${_randomChar()}`;
|
|
8624
|
+
}
|
|
8625
|
+
/**
|
|
8626
|
+
* Providers that generate a random `APP_ID_TOKEN`.
|
|
8627
|
+
* @publicApi
|
|
8628
|
+
*/
|
|
8629
|
+
const APP_ID_RANDOM_PROVIDER = {
|
|
8630
|
+
provide: APP_ID,
|
|
8631
|
+
useFactory: _appIdRandomProviderFactory,
|
|
8632
|
+
deps: [],
|
|
8633
|
+
};
|
|
8634
|
+
function _randomChar() {
|
|
8635
|
+
return String.fromCharCode(97 + Math.floor(Math.random() * 25));
|
|
8636
|
+
}
|
|
8637
|
+
/**
|
|
8638
|
+
* A function that is executed when a platform is initialized.
|
|
8639
|
+
* @publicApi
|
|
8640
|
+
*/
|
|
8641
|
+
const PLATFORM_INITIALIZER = new InjectionToken('Platform Initializer');
|
|
8642
|
+
/**
|
|
8643
|
+
* A token that indicates an opaque platform ID.
|
|
8644
|
+
* @publicApi
|
|
8645
|
+
*/
|
|
8646
|
+
const PLATFORM_ID = new InjectionToken('Platform ID', {
|
|
8647
|
+
providedIn: 'platform',
|
|
8648
|
+
factory: () => 'unknown', // set a default platform name, when none set explicitly
|
|
8649
|
+
});
|
|
8650
|
+
/**
|
|
8651
|
+
* A [DI token](guide/glossary#di-token "DI token definition") that indicates the root directory of
|
|
8652
|
+
* the application
|
|
8653
|
+
* @publicApi
|
|
8654
|
+
*/
|
|
8655
|
+
const PACKAGE_ROOT_URL = new InjectionToken('Application Packages Root URL');
|
|
8656
|
+
// We keep this token here, rather than the animations package, so that modules that only care
|
|
8657
|
+
// about which animations module is loaded (e.g. the CDK) can retrieve it without having to
|
|
8658
|
+
// include extra dependencies. See #44970 for more context.
|
|
8659
|
+
/**
|
|
8660
|
+
* A [DI token](guide/glossary#di-token "DI token definition") that indicates which animations
|
|
8661
|
+
* module has been loaded.
|
|
8662
|
+
* @publicApi
|
|
8663
|
+
*/
|
|
8664
|
+
const ANIMATION_MODULE_TYPE = new InjectionToken('AnimationModuleType');
|
|
8665
|
+
|
|
8666
|
+
function escapeTransferStateContent(text) {
|
|
8667
|
+
const escapedText = {
|
|
8668
|
+
'&': '&a;',
|
|
8669
|
+
'"': '&q;',
|
|
8670
|
+
'\'': '&s;',
|
|
8671
|
+
'<': '&l;',
|
|
8672
|
+
'>': '&g;',
|
|
8673
|
+
};
|
|
8674
|
+
return text.replace(/[&"'<>]/g, s => escapedText[s]);
|
|
8675
|
+
}
|
|
8676
|
+
function unescapeTransferStateContent(text) {
|
|
8677
|
+
const unescapedText = {
|
|
8678
|
+
'&a;': '&',
|
|
8679
|
+
'&q;': '"',
|
|
8680
|
+
'&s;': '\'',
|
|
8681
|
+
'&l;': '<',
|
|
8682
|
+
'&g;': '>',
|
|
8683
|
+
};
|
|
8684
|
+
return text.replace(/&[^;]+;/g, s => unescapedText[s]);
|
|
8685
|
+
}
|
|
8686
|
+
/**
|
|
8687
|
+
* Create a `StateKey<T>` that can be used to store value of type T with `TransferState`.
|
|
8688
|
+
*
|
|
8689
|
+
* Example:
|
|
8690
|
+
*
|
|
8691
|
+
* ```
|
|
8692
|
+
* const COUNTER_KEY = makeStateKey<number>('counter');
|
|
8693
|
+
* let value = 10;
|
|
8694
|
+
*
|
|
8695
|
+
* transferState.set(COUNTER_KEY, value);
|
|
8696
|
+
* ```
|
|
8697
|
+
*
|
|
8698
|
+
* @publicApi
|
|
8699
|
+
*/
|
|
8700
|
+
function makeStateKey(key) {
|
|
8701
|
+
return key;
|
|
8702
|
+
}
|
|
8703
|
+
function initTransferState() {
|
|
8704
|
+
const transferState = new TransferState();
|
|
8705
|
+
transferState.store = retrieveTransferredState(getDocument(), inject$1(APP_ID));
|
|
8706
|
+
return transferState;
|
|
8707
|
+
}
|
|
8708
|
+
/**
|
|
8709
|
+
* A key value store that is transferred from the application on the server side to the application
|
|
8710
|
+
* on the client side.
|
|
8711
|
+
*
|
|
8712
|
+
* The `TransferState` is available as an injectable token.
|
|
8713
|
+
* On the client, just inject this token using DI and use it, it will be lazily initialized.
|
|
8714
|
+
* On the server it's already included if `renderApplication` function is used. Otherwise, import
|
|
8715
|
+
* the `ServerTransferStateModule` module to make the `TransferState` available.
|
|
8716
|
+
*
|
|
8717
|
+
* The values in the store are serialized/deserialized using JSON.stringify/JSON.parse. So only
|
|
8718
|
+
* boolean, number, string, null and non-class objects will be serialized and deserialized in a
|
|
8719
|
+
* non-lossy manner.
|
|
8720
|
+
*
|
|
8721
|
+
* @publicApi
|
|
8722
|
+
*/
|
|
8723
|
+
class TransferState {
|
|
8724
|
+
constructor() {
|
|
8725
|
+
/** @internal */
|
|
8726
|
+
this.store = {};
|
|
8727
|
+
this.onSerializeCallbacks = {};
|
|
8728
|
+
}
|
|
8729
|
+
/**
|
|
8730
|
+
* Get the value corresponding to a key. Return `defaultValue` if key is not found.
|
|
8731
|
+
*/
|
|
8732
|
+
get(key, defaultValue) {
|
|
8733
|
+
return this.store[key] !== undefined ? this.store[key] : defaultValue;
|
|
8734
|
+
}
|
|
8735
|
+
/**
|
|
8736
|
+
* Set the value corresponding to a key.
|
|
8737
|
+
*/
|
|
8738
|
+
set(key, value) {
|
|
8739
|
+
this.store[key] = value;
|
|
8740
|
+
}
|
|
8741
|
+
/**
|
|
8742
|
+
* Remove a key from the store.
|
|
8743
|
+
*/
|
|
8744
|
+
remove(key) {
|
|
8745
|
+
delete this.store[key];
|
|
8746
|
+
}
|
|
8747
|
+
/**
|
|
8748
|
+
* Test whether a key exists in the store.
|
|
8749
|
+
*/
|
|
8750
|
+
hasKey(key) {
|
|
8751
|
+
return this.store.hasOwnProperty(key);
|
|
8752
|
+
}
|
|
8753
|
+
/**
|
|
8754
|
+
* Indicates whether the state is empty.
|
|
8755
|
+
*/
|
|
8756
|
+
get isEmpty() {
|
|
8757
|
+
return Object.keys(this.store).length === 0;
|
|
8758
|
+
}
|
|
8759
|
+
/**
|
|
8760
|
+
* Register a callback to provide the value for a key when `toJson` is called.
|
|
8761
|
+
*/
|
|
8762
|
+
onSerialize(key, callback) {
|
|
8763
|
+
this.onSerializeCallbacks[key] = callback;
|
|
8764
|
+
}
|
|
8765
|
+
/**
|
|
8766
|
+
* Serialize the current state of the store to JSON.
|
|
8767
|
+
*/
|
|
8768
|
+
toJson() {
|
|
8769
|
+
// Call the onSerialize callbacks and put those values into the store.
|
|
8770
|
+
for (const key in this.onSerializeCallbacks) {
|
|
8771
|
+
if (this.onSerializeCallbacks.hasOwnProperty(key)) {
|
|
8772
|
+
try {
|
|
8773
|
+
this.store[key] = this.onSerializeCallbacks[key]();
|
|
8774
|
+
}
|
|
8775
|
+
catch (e) {
|
|
8776
|
+
console.warn('Exception in onSerialize callback: ', e);
|
|
8777
|
+
}
|
|
8778
|
+
}
|
|
8779
|
+
}
|
|
8780
|
+
return JSON.stringify(this.store);
|
|
8781
|
+
}
|
|
8782
|
+
}
|
|
8783
|
+
/** @nocollapse */
|
|
8784
|
+
TransferState.ɵprov =
|
|
8785
|
+
/** @pureOrBreakMyCode */ ɵɵdefineInjectable({
|
|
8786
|
+
token: TransferState,
|
|
8787
|
+
providedIn: 'root',
|
|
8788
|
+
factory: initTransferState,
|
|
8789
|
+
});
|
|
8790
|
+
function retrieveTransferredState(doc, appId) {
|
|
8791
|
+
// Locate the script tag with the JSON data transferred from the server.
|
|
8792
|
+
// The id of the script tag is set to the Angular appId + 'state'.
|
|
8793
|
+
const script = doc.getElementById(appId + '-state');
|
|
8794
|
+
let initialState = {};
|
|
8795
|
+
if (script && script.textContent) {
|
|
8796
|
+
try {
|
|
8797
|
+
// Avoid using any here as it triggers lint errors in google3 (any is not allowed).
|
|
8798
|
+
initialState = JSON.parse(unescapeTransferStateContent(script.textContent));
|
|
8799
|
+
}
|
|
8800
|
+
catch (e) {
|
|
8801
|
+
console.warn('Exception while restoring TransferState for app ' + appId, e);
|
|
8802
|
+
}
|
|
8803
|
+
}
|
|
8804
|
+
return initialState;
|
|
8805
|
+
}
|
|
8806
|
+
|
|
8807
|
+
/* Represents a key in NghDom that holds information about <ng-container>s. */
|
|
8808
|
+
const ELEMENT_CONTAINERS = 'e';
|
|
8809
|
+
|
|
8810
|
+
/**
|
|
8811
|
+
* The name of the key used in the TransferState collection,
|
|
8812
|
+
* where hydration information is located.
|
|
8813
|
+
*/
|
|
8814
|
+
const TRANSFER_STATE_TOKEN_ID = '__ɵnghData__';
|
|
8815
|
+
/**
|
|
8816
|
+
* Lookup key used to reference DOM hydration data (ngh) in `TransferState`.
|
|
8817
|
+
*/
|
|
8818
|
+
const NGH_DATA_KEY = makeStateKey(TRANSFER_STATE_TOKEN_ID);
|
|
8819
|
+
/**
|
|
8820
|
+
* The name of the attribute that would be added to host component
|
|
8821
|
+
* nodes and contain a reference to a particular slot in transferred
|
|
8822
|
+
* state that contains the necessary hydration info for this component.
|
|
8823
|
+
*/
|
|
8824
|
+
const NGH_ATTR_NAME = 'ngh';
|
|
8825
|
+
/**
|
|
8826
|
+
* Reference to a function that reads `ngh` attribute value from a given RNode
|
|
8827
|
+
* and retrieves hydration information from the TransferState using that value
|
|
8828
|
+
* as an index. Returns `null` by default, when hydration is not enabled.
|
|
8829
|
+
*
|
|
8830
|
+
* @param rNode Component's host element.
|
|
8831
|
+
* @param injector Injector that this component has access to.
|
|
8832
|
+
*/
|
|
8833
|
+
let _retrieveHydrationInfoImpl = (rNode, injector) => null;
|
|
8834
|
+
function retrieveHydrationInfoImpl(rNode, injector) {
|
|
8835
|
+
var _a;
|
|
8836
|
+
const nghAttrValue = rNode.getAttribute(NGH_ATTR_NAME);
|
|
8837
|
+
if (nghAttrValue == null)
|
|
8838
|
+
return null;
|
|
8839
|
+
let data = {};
|
|
8840
|
+
// An element might have an empty `ngh` attribute value (e.g. `<comp ngh="" />`),
|
|
8841
|
+
// which means that no special annotations are required. Do not attempt to read
|
|
8842
|
+
// from the TransferState in this case.
|
|
8843
|
+
if (nghAttrValue !== '') {
|
|
8844
|
+
const transferState = injector.get(TransferState, null, { optional: true });
|
|
8845
|
+
if (transferState !== null) {
|
|
8846
|
+
const nghData = transferState.get(NGH_DATA_KEY, []);
|
|
8847
|
+
// The nghAttrValue is always a number referencing an index
|
|
8848
|
+
// in the hydration TransferState data.
|
|
8849
|
+
data = nghData[Number(nghAttrValue)];
|
|
8850
|
+
// If the `ngh` attribute exists and has a non-empty value,
|
|
8851
|
+
// the hydration info *must* be present in the TransferState.
|
|
8852
|
+
// If there is no data for some reasons, this is an error.
|
|
8853
|
+
ngDevMode && assertDefined(data, 'Unable to retrieve hydration info from the TransferState.');
|
|
8854
|
+
}
|
|
8855
|
+
}
|
|
8856
|
+
const dehydratedView = {
|
|
8857
|
+
data,
|
|
8858
|
+
firstChild: (_a = rNode.firstChild) !== null && _a !== void 0 ? _a : null,
|
|
8859
|
+
};
|
|
8860
|
+
// The `ngh` attribute is cleared from the DOM node now
|
|
8861
|
+
// that the data has been retrieved.
|
|
8862
|
+
rNode.removeAttribute(NGH_ATTR_NAME);
|
|
8863
|
+
// Note: don't check whether this node was claimed for hydration,
|
|
8864
|
+
// because this node might've been previously claimed while processing
|
|
8865
|
+
// template instructions.
|
|
8866
|
+
ngDevMode && markRNodeAsClaimedByHydration(rNode, /* checkIfAlreadyClaimed */ false);
|
|
8867
|
+
ngDevMode && ngDevMode.hydratedComponents++;
|
|
8868
|
+
return dehydratedView;
|
|
8869
|
+
}
|
|
8870
|
+
/**
|
|
8871
|
+
* Sets the implementation for the `retrieveNghInfo` function.
|
|
8872
|
+
*/
|
|
8873
|
+
function enableRetrieveHydrationInfoImpl() {
|
|
8874
|
+
_retrieveHydrationInfoImpl = retrieveHydrationInfoImpl;
|
|
8875
|
+
}
|
|
8876
|
+
/**
|
|
8877
|
+
* Retrieves hydration info by reading the value from the `ngh` attribute
|
|
8878
|
+
* and accessing a corresponding slot in TransferState storage.
|
|
8879
|
+
*/
|
|
8880
|
+
function retrieveHydrationInfo(rNode, injector) {
|
|
8881
|
+
return _retrieveHydrationInfoImpl(rNode, injector);
|
|
8882
|
+
}
|
|
8883
|
+
/**
|
|
8884
|
+
* Retrieves an instance of a component LView from a given ViewRef.
|
|
8885
|
+
* Returns an instance of a component LView or `null` in case of an embedded view.
|
|
8886
|
+
*/
|
|
8887
|
+
function getComponentLViewForHydration(viewRef) {
|
|
8888
|
+
// Reading an internal field from `ViewRef` instance.
|
|
8889
|
+
let lView = viewRef._lView;
|
|
8890
|
+
const tView = lView[TVIEW];
|
|
8891
|
+
// A registered ViewRef might represent an instance of an
|
|
8892
|
+
// embedded view, in which case we do not need to annotate it.
|
|
8893
|
+
if (tView.type === 2 /* TViewType.Embedded */) {
|
|
8894
|
+
return null;
|
|
8895
|
+
}
|
|
8896
|
+
// Check if it's a root view and if so, retrieve component's
|
|
8897
|
+
// LView from the first slot after the header.
|
|
8898
|
+
if (isRootView(lView)) {
|
|
8899
|
+
lView = lView[HEADER_OFFSET];
|
|
8900
|
+
}
|
|
8901
|
+
return lView;
|
|
8902
|
+
}
|
|
8903
|
+
/**
|
|
8904
|
+
* Marks a node as "claimed" by hydration process.
|
|
8905
|
+
* This is needed to make assessments in tests whether
|
|
8906
|
+
* the hydration process handled all nodes.
|
|
8907
|
+
*/
|
|
8908
|
+
function markRNodeAsClaimedByHydration(node, checkIfAlreadyClaimed = true) {
|
|
8909
|
+
if (!ngDevMode) {
|
|
8910
|
+
throw new Error('Calling `markRNodeAsClaimedByHydration` in prod mode ' +
|
|
8911
|
+
'is not supported and likely a mistake.');
|
|
8912
|
+
}
|
|
8913
|
+
if (checkIfAlreadyClaimed && isRNodeClaimedForHydration(node)) {
|
|
8914
|
+
throw new Error('Trying to claim a node, which was claimed already.');
|
|
8915
|
+
}
|
|
8916
|
+
node.__claimed = true;
|
|
8917
|
+
ngDevMode.hydratedNodes++;
|
|
8918
|
+
}
|
|
8919
|
+
function isRNodeClaimedForHydration(node) {
|
|
8920
|
+
return !!node.__claimed;
|
|
8921
|
+
}
|
|
8922
|
+
function storeNgContainerInfo(hydrationInfo, index, firstChild) {
|
|
8923
|
+
var _a;
|
|
8924
|
+
(_a = hydrationInfo.ngContainers) !== null && _a !== void 0 ? _a : (hydrationInfo.ngContainers = {});
|
|
8925
|
+
hydrationInfo.ngContainers[index] = { firstChild };
|
|
8926
|
+
}
|
|
8927
|
+
function getNgContainerSize(hydrationInfo, index) {
|
|
8928
|
+
var _a, _b;
|
|
8929
|
+
return (_b = (_a = hydrationInfo.data[ELEMENT_CONTAINERS]) === null || _a === void 0 ? void 0 : _a[index]) !== null && _b !== void 0 ? _b : null;
|
|
8930
|
+
}
|
|
8931
|
+
|
|
8574
8932
|
/**
|
|
8575
8933
|
* Represents a component created by a `ComponentFactory`.
|
|
8576
8934
|
* Provides access to the component instance and related objects,
|
|
@@ -8750,7 +9108,7 @@ class Version {
|
|
|
8750
9108
|
/**
|
|
8751
9109
|
* @publicApi
|
|
8752
9110
|
*/
|
|
8753
|
-
const VERSION = new Version('16.0.0-next.
|
|
9111
|
+
const VERSION = new Version('16.0.0-next.2');
|
|
8754
9112
|
|
|
8755
9113
|
// This default value is when checking the hierarchy for a token.
|
|
8756
9114
|
//
|
|
@@ -8831,6 +9189,23 @@ class ErrorHandler {
|
|
|
8831
9189
|
}
|
|
8832
9190
|
}
|
|
8833
9191
|
|
|
9192
|
+
const NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
9193
|
+
/**
|
|
9194
|
+
* Internal token that specifies whether hydration is enabled.
|
|
9195
|
+
*/
|
|
9196
|
+
const IS_HYDRATION_FEATURE_ENABLED = new InjectionToken(NG_DEV_MODE ? 'IS_HYDRATION_FEATURE_ENABLED' : '');
|
|
9197
|
+
// By default (in client rendering mode), we remove all the contents
|
|
9198
|
+
// of the host element and render an application after that.
|
|
9199
|
+
const PRESERVE_HOST_CONTENT_DEFAULT = false;
|
|
9200
|
+
/**
|
|
9201
|
+
* Internal token that indicates whether host element content should be
|
|
9202
|
+
* retained during the bootstrap.
|
|
9203
|
+
*/
|
|
9204
|
+
const PRESERVE_HOST_CONTENT = new InjectionToken(NG_DEV_MODE ? 'PRESERVE_HOST_CONTENT' : '', {
|
|
9205
|
+
providedIn: 'root',
|
|
9206
|
+
factory: () => PRESERVE_HOST_CONTENT_DEFAULT,
|
|
9207
|
+
});
|
|
9208
|
+
|
|
8834
9209
|
function normalizeDebugBindingName(name) {
|
|
8835
9210
|
// Attribute names with `$` (eg `x-y$`) are valid per spec, but unsupported by some browsers
|
|
8836
9211
|
name = camelCaseToDashCase(name.replace(/[$@]/g, '_'));
|
|
@@ -10482,7 +10857,7 @@ function renderChildComponents(hostLView, components) {
|
|
|
10482
10857
|
renderComponent(hostLView, components[i]);
|
|
10483
10858
|
}
|
|
10484
10859
|
}
|
|
10485
|
-
function createLView(parentLView, tView, context, flags, host, tHostNode, rendererFactory, renderer, sanitizer, injector, embeddedViewInjector) {
|
|
10860
|
+
function createLView(parentLView, tView, context, flags, host, tHostNode, rendererFactory, renderer, sanitizer, injector, embeddedViewInjector, hydrationInfo) {
|
|
10486
10861
|
const lView = tView.blueprint.slice();
|
|
10487
10862
|
lView[HOST] = host;
|
|
10488
10863
|
lView[FLAGS] = flags | 4 /* LViewFlags.CreationMode */ | 64 /* LViewFlags.Attached */ | 8 /* LViewFlags.FirstLViewPass */;
|
|
@@ -10502,6 +10877,7 @@ function createLView(parentLView, tView, context, flags, host, tHostNode, render
|
|
|
10502
10877
|
lView[INJECTOR$1] = injector || parentLView && parentLView[INJECTOR$1] || null;
|
|
10503
10878
|
lView[T_HOST] = tHostNode;
|
|
10504
10879
|
lView[ID] = getUniqueLViewId();
|
|
10880
|
+
lView[HYDRATION] = hydrationInfo;
|
|
10505
10881
|
lView[EMBEDDED_VIEW_INJECTOR] = embeddedViewInjector;
|
|
10506
10882
|
ngDevMode &&
|
|
10507
10883
|
assertEqual(tView.type == 2 /* TViewType.Embedded */ ? parentLView !== null : true, true, 'Embedded views must have parentLView');
|
|
@@ -10564,6 +10940,7 @@ function createTNodeAtIndex(tView, index, type, name, attrs) {
|
|
|
10564
10940
|
// In the case of i18n the `currentTNode` may already be linked, in which case we don't want
|
|
10565
10941
|
// to break the links which i18n created.
|
|
10566
10942
|
currentTNode.next = tNode;
|
|
10943
|
+
tNode.prev = currentTNode;
|
|
10567
10944
|
}
|
|
10568
10945
|
}
|
|
10569
10946
|
}
|
|
@@ -10942,10 +11319,19 @@ function createViewBlueprint(bindingStartIndex, initialViewLength) {
|
|
|
10942
11319
|
* @param rendererFactory Factory function to create renderer instance.
|
|
10943
11320
|
* @param elementOrSelector Render element or CSS selector to locate the element.
|
|
10944
11321
|
* @param encapsulation View Encapsulation defined for component that requests host element.
|
|
10945
|
-
|
|
10946
|
-
|
|
10947
|
-
|
|
10948
|
-
|
|
11322
|
+
* @param injector Root view injector instance.
|
|
11323
|
+
*/
|
|
11324
|
+
function locateHostElement(renderer, elementOrSelector, encapsulation, injector) {
|
|
11325
|
+
// Note: we use default value for the `PRESERVE_HOST_CONTENT` here even though it's a
|
|
11326
|
+
// tree-shakable one (providedIn:'root'). This code path can be triggered during dynamic component
|
|
11327
|
+
// creation (after calling ViewContainerRef.createComponent) when an injector instance can be
|
|
11328
|
+
// provided. The injector instance might be disconnected from the main DI tree, thus the
|
|
11329
|
+
// `PRESERVE_HOST_CONTENT` woild not be able to instantiate. In this case, the default value will
|
|
11330
|
+
// be used.
|
|
11331
|
+
const preserveHostContent = injector.get(PRESERVE_HOST_CONTENT, PRESERVE_HOST_CONTENT_DEFAULT);
|
|
11332
|
+
// When using native Shadow DOM, do not clear host element to allow native slot
|
|
11333
|
+
// projection.
|
|
11334
|
+
const preserveContent = preserveHostContent || encapsulation === ViewEncapsulation.ShadowDom;
|
|
10949
11335
|
return renderer.selectRootElement(elementOrSelector, preserveContent);
|
|
10950
11336
|
}
|
|
10951
11337
|
/**
|
|
@@ -10954,24 +11340,24 @@ function locateHostElement(renderer, elementOrSelector, encapsulation) {
|
|
|
10954
11340
|
* On the first template pass, saves in TView:
|
|
10955
11341
|
* - Cleanup function
|
|
10956
11342
|
* - Index of context we just saved in LView.cleanupInstances
|
|
10957
|
-
*
|
|
10958
|
-
* This function can also be used to store instance specific cleanup fns. In that case the `context`
|
|
10959
|
-
* is `null` and the function is store in `LView` (rather than it `TView`).
|
|
10960
11343
|
*/
|
|
10961
11344
|
function storeCleanupWithContext(tView, lView, context, cleanupFn) {
|
|
10962
11345
|
const lCleanup = getOrCreateLViewCleanup(lView);
|
|
10963
|
-
|
|
10964
|
-
|
|
10965
|
-
|
|
10966
|
-
|
|
10967
|
-
|
|
10968
|
-
|
|
10969
|
-
|
|
11346
|
+
// Historically the `storeCleanupWithContext` was used to register both framework-level and
|
|
11347
|
+
// user-defined cleanup callbacks, but over time those two types of cleanups were separated. This
|
|
11348
|
+
// dev mode checks assures that user-level cleanup callbacks are _not_ stored in data structures
|
|
11349
|
+
// reserved for framework-specific hooks.
|
|
11350
|
+
ngDevMode &&
|
|
11351
|
+
assertDefined(context, 'Cleanup context is mandatory when registering framework-level destroy hooks');
|
|
11352
|
+
lCleanup.push(context);
|
|
11353
|
+
if (tView.firstCreatePass) {
|
|
11354
|
+
getOrCreateTViewCleanup(tView).push(cleanupFn, lCleanup.length - 1);
|
|
10970
11355
|
}
|
|
10971
11356
|
else {
|
|
10972
|
-
|
|
10973
|
-
|
|
10974
|
-
|
|
11357
|
+
// Make sure that no new framework-level cleanup functions are registered after the first
|
|
11358
|
+
// template pass is done (and TView data structures are meant to fully constructed).
|
|
11359
|
+
if (ngDevMode) {
|
|
11360
|
+
Object.freeze(getOrCreateTViewCleanup(tView));
|
|
10975
11361
|
}
|
|
10976
11362
|
}
|
|
10977
11363
|
}
|
|
@@ -11002,8 +11388,9 @@ function createTNode(tView, tParent, type, index, value, attrs) {
|
|
|
11002
11388
|
initialInputs: undefined,
|
|
11003
11389
|
inputs: null,
|
|
11004
11390
|
outputs: null,
|
|
11005
|
-
|
|
11391
|
+
tView: null,
|
|
11006
11392
|
next: null,
|
|
11393
|
+
prev: null,
|
|
11007
11394
|
projectionNext: null,
|
|
11008
11395
|
child: null,
|
|
11009
11396
|
parent: tParent,
|
|
@@ -11213,7 +11600,6 @@ function resolveDirectives(tView, lView, tNode, localRefs) {
|
|
|
11213
11600
|
// Please make sure to have explicit type for `exportsMap`. Inferred type triggers bug in
|
|
11214
11601
|
// tsickle.
|
|
11215
11602
|
ngDevMode && assertFirstCreatePass(tView);
|
|
11216
|
-
let hasDirectives = false;
|
|
11217
11603
|
if (getBindingsEnabled()) {
|
|
11218
11604
|
const exportsMap = localRefs === null ? null : { '': -1 };
|
|
11219
11605
|
const matchResult = findDirectiveDefMatches(tView, tNode);
|
|
@@ -11226,7 +11612,6 @@ function resolveDirectives(tView, lView, tNode, localRefs) {
|
|
|
11226
11612
|
[directiveDefs, hostDirectiveDefs] = matchResult;
|
|
11227
11613
|
}
|
|
11228
11614
|
if (directiveDefs !== null) {
|
|
11229
|
-
hasDirectives = true;
|
|
11230
11615
|
initializeDirectives(tView, lView, tNode, directiveDefs, exportsMap, hostDirectiveDefs);
|
|
11231
11616
|
}
|
|
11232
11617
|
if (exportsMap)
|
|
@@ -11234,7 +11619,6 @@ function resolveDirectives(tView, lView, tNode, localRefs) {
|
|
|
11234
11619
|
}
|
|
11235
11620
|
// Merge the template attrs last so that they have the highest priority.
|
|
11236
11621
|
tNode.mergedAttrs = mergeHostAttrs(tNode.mergedAttrs, tNode.attrs);
|
|
11237
|
-
return hasDirectives;
|
|
11238
11622
|
}
|
|
11239
11623
|
/** Initializes the data structures necessary for a list of directives to be instantiated. */
|
|
11240
11624
|
function initializeDirectives(tView, lView, tNode, directives, exportsMap, hostDirectiveDefs) {
|
|
@@ -11548,7 +11932,7 @@ function addComponentLogic(lView, hostTNode, def) {
|
|
|
11548
11932
|
// Only component views should be added to the view tree directly. Embedded views are
|
|
11549
11933
|
// accessed through their containers because they may be removed / re-added later.
|
|
11550
11934
|
const rendererFactory = lView[RENDERER_FACTORY];
|
|
11551
|
-
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));
|
|
11935
|
+
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));
|
|
11552
11936
|
// Component view will always be created before any injected LContainers,
|
|
11553
11937
|
// so this is a regular element, wrap it with the component view
|
|
11554
11938
|
lView[hostTNode.index] = componentView;
|
|
@@ -11793,6 +12177,11 @@ function renderComponent(hostLView, componentHostIdx) {
|
|
|
11793
12177
|
const componentView = getComponentLViewByIndex(componentHostIdx, hostLView);
|
|
11794
12178
|
const componentTView = componentView[TVIEW];
|
|
11795
12179
|
syncViewWithBlueprint(componentTView, componentView);
|
|
12180
|
+
const hostRNode = componentView[HOST];
|
|
12181
|
+
// Populate an LView with hydration info retrieved from the DOM via TransferState.
|
|
12182
|
+
if (hostRNode !== null && componentView[HYDRATION] === null) {
|
|
12183
|
+
componentView[HYDRATION] = retrieveHydrationInfo(hostRNode, componentView[INJECTOR$1]);
|
|
12184
|
+
}
|
|
11796
12185
|
renderView(componentTView, componentView, componentView[CONTEXT]);
|
|
11797
12186
|
}
|
|
11798
12187
|
/**
|
|
@@ -12166,7 +12555,7 @@ class ViewRef {
|
|
|
12166
12555
|
destroyLView(this._lView[TVIEW], this._lView);
|
|
12167
12556
|
}
|
|
12168
12557
|
onDestroy(callback) {
|
|
12169
|
-
|
|
12558
|
+
storeLViewOnDestroy(this._lView, callback);
|
|
12170
12559
|
}
|
|
12171
12560
|
/**
|
|
12172
12561
|
* Marks a view and all of its ancestors dirty.
|
|
@@ -12493,13 +12882,13 @@ class ComponentFactory extends ComponentFactory$1 {
|
|
|
12493
12882
|
// dynamically. Default to 'div' if this component did not specify any tag name in its selector.
|
|
12494
12883
|
const elementName = this.componentDef.selectors[0][0] || 'div';
|
|
12495
12884
|
const hostRNode = rootSelectorOrNode ?
|
|
12496
|
-
locateHostElement(hostRenderer, rootSelectorOrNode, this.componentDef.encapsulation) :
|
|
12885
|
+
locateHostElement(hostRenderer, rootSelectorOrNode, this.componentDef.encapsulation, rootViewInjector) :
|
|
12497
12886
|
createElementNode(hostRenderer, elementName, getNamespace(elementName));
|
|
12498
12887
|
const rootFlags = this.componentDef.onPush ? 32 /* LViewFlags.Dirty */ | 256 /* LViewFlags.IsRoot */ :
|
|
12499
12888
|
16 /* LViewFlags.CheckAlways */ | 256 /* LViewFlags.IsRoot */;
|
|
12500
12889
|
// Create the root view. Uses empty TView and ContentTemplate.
|
|
12501
12890
|
const rootTView = createTView(0 /* TViewType.Root */, null, null, 1, 0, null, null, null, null, null);
|
|
12502
|
-
const rootLView = createLView(null, rootTView, null, rootFlags, null, null, rendererFactory, hostRenderer, sanitizer, rootViewInjector, null);
|
|
12891
|
+
const rootLView = createLView(null, rootTView, null, rootFlags, null, null, rendererFactory, hostRenderer, sanitizer, rootViewInjector, null, null);
|
|
12503
12892
|
// rootView is the parent when bootstrapping
|
|
12504
12893
|
// TODO(misko): it looks like we are entering view here but we don't really need to as
|
|
12505
12894
|
// `renderView` does that. However as the code is written it is needed because
|
|
@@ -12610,7 +12999,7 @@ function createRootComponentTNode(lView, rNode) {
|
|
|
12610
12999
|
/**
|
|
12611
13000
|
* Creates the root component view and the root component node.
|
|
12612
13001
|
*
|
|
12613
|
-
* @param
|
|
13002
|
+
* @param hostRNode Render host element.
|
|
12614
13003
|
* @param rootComponentDef ComponentDef
|
|
12615
13004
|
* @param rootView The parent view where the host node is stored
|
|
12616
13005
|
* @param rendererFactory Factory to be used for creating child renderers.
|
|
@@ -12619,11 +13008,17 @@ function createRootComponentTNode(lView, rNode) {
|
|
|
12619
13008
|
*
|
|
12620
13009
|
* @returns Component view created
|
|
12621
13010
|
*/
|
|
12622
|
-
function createRootComponentView(tNode,
|
|
13011
|
+
function createRootComponentView(tNode, hostRNode, rootComponentDef, rootDirectives, rootView, rendererFactory, hostRenderer, sanitizer) {
|
|
12623
13012
|
const tView = rootView[TVIEW];
|
|
12624
|
-
applyRootComponentStyling(rootDirectives, tNode,
|
|
12625
|
-
|
|
12626
|
-
|
|
13013
|
+
applyRootComponentStyling(rootDirectives, tNode, hostRNode, hostRenderer);
|
|
13014
|
+
// Hydration info is on the host element and needs to be retreived
|
|
13015
|
+
// and passed to the component LView.
|
|
13016
|
+
let hydrationInfo = null;
|
|
13017
|
+
if (hostRNode !== null) {
|
|
13018
|
+
hydrationInfo = retrieveHydrationInfo(hostRNode, rootView[INJECTOR$1]);
|
|
13019
|
+
}
|
|
13020
|
+
const viewRenderer = rendererFactory.createRenderer(hostRNode, rootComponentDef);
|
|
13021
|
+
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);
|
|
12627
13022
|
if (tView.firstCreatePass) {
|
|
12628
13023
|
markAsComponentHost(tView, tNode, rootDirectives.length - 1);
|
|
12629
13024
|
}
|
|
@@ -13101,41 +13496,19 @@ function validateMappings(bindingType, def, hostDirectiveBindings) {
|
|
|
13101
13496
|
}
|
|
13102
13497
|
}
|
|
13103
13498
|
|
|
13104
|
-
let _symbolIterator = null;
|
|
13105
|
-
function getSymbolIterator() {
|
|
13106
|
-
if (!_symbolIterator) {
|
|
13107
|
-
const Symbol = _global$1['Symbol'];
|
|
13108
|
-
if (Symbol && Symbol.iterator) {
|
|
13109
|
-
_symbolIterator = Symbol.iterator;
|
|
13110
|
-
}
|
|
13111
|
-
else {
|
|
13112
|
-
// es6-shim specific logic
|
|
13113
|
-
const keys = Object.getOwnPropertyNames(Map.prototype);
|
|
13114
|
-
for (let i = 0; i < keys.length; ++i) {
|
|
13115
|
-
const key = keys[i];
|
|
13116
|
-
if (key !== 'entries' && key !== 'size' &&
|
|
13117
|
-
Map.prototype[key] === Map.prototype['entries']) {
|
|
13118
|
-
_symbolIterator = key;
|
|
13119
|
-
}
|
|
13120
|
-
}
|
|
13121
|
-
}
|
|
13122
|
-
}
|
|
13123
|
-
return _symbolIterator;
|
|
13124
|
-
}
|
|
13125
|
-
|
|
13126
13499
|
function isIterable(obj) {
|
|
13127
|
-
return obj !== null && typeof obj === 'object' && obj[
|
|
13500
|
+
return obj !== null && typeof obj === 'object' && obj[Symbol.iterator] !== undefined;
|
|
13128
13501
|
}
|
|
13129
13502
|
function isListLikeIterable(obj) {
|
|
13130
13503
|
if (!isJsObject(obj))
|
|
13131
13504
|
return false;
|
|
13132
13505
|
return Array.isArray(obj) ||
|
|
13133
13506
|
(!(obj instanceof Map) && // JS Map are iterables but return entries as [k, v]
|
|
13134
|
-
|
|
13507
|
+
Symbol.iterator in obj); // JS Iterable have a Symbol.iterator prop
|
|
13135
13508
|
}
|
|
13136
13509
|
function areIterablesEqual(a, b, comparator) {
|
|
13137
|
-
const iterator1 = a[
|
|
13138
|
-
const iterator2 = b[
|
|
13510
|
+
const iterator1 = a[Symbol.iterator]();
|
|
13511
|
+
const iterator2 = b[Symbol.iterator]();
|
|
13139
13512
|
while (true) {
|
|
13140
13513
|
const item1 = iterator1.next();
|
|
13141
13514
|
const item2 = iterator2.next();
|
|
@@ -13154,7 +13527,7 @@ function iterateListLike(obj, fn) {
|
|
|
13154
13527
|
}
|
|
13155
13528
|
}
|
|
13156
13529
|
else {
|
|
13157
|
-
const iterator = obj[
|
|
13530
|
+
const iterator = obj[Symbol.iterator]();
|
|
13158
13531
|
let item;
|
|
13159
13532
|
while (!((item = iterator.next()).done)) {
|
|
13160
13533
|
fn(item.value);
|
|
@@ -13807,7 +14180,7 @@ function templateFirstCreatePass(index, tView, lView, templateFn, decls, vars, t
|
|
|
13807
14180
|
const tNode = getOrCreateTNode(tView, index, 4 /* TNodeType.Container */, tagName || null, getConstant(tViewConsts, attrsIndex));
|
|
13808
14181
|
resolveDirectives(tView, lView, tNode, getConstant(tViewConsts, localRefsIndex));
|
|
13809
14182
|
registerPostOrderHooks(tView, tNode);
|
|
13810
|
-
const embeddedTView = tNode.
|
|
14183
|
+
const embeddedTView = tNode.tView = createTView(2 /* TViewType.Embedded */, tNode, templateFn, decls, vars, tView.directiveRegistry, tView.pipeRegistry, null, tView.schemas, tViewConsts);
|
|
13811
14184
|
if (tView.queries !== null) {
|
|
13812
14185
|
tView.queries.template(tView, tNode);
|
|
13813
14186
|
embeddedTView.queries = tView.queries.embeddedTView(tNode);
|
|
@@ -13877,6 +14250,122 @@ function ɵɵreference(index) {
|
|
|
13877
14250
|
return load(contextLView, HEADER_OFFSET + index);
|
|
13878
14251
|
}
|
|
13879
14252
|
|
|
14253
|
+
/**
|
|
14254
|
+
* Verifies whether a given node matches an expected criteria,
|
|
14255
|
+
* based on internal data structure state.
|
|
14256
|
+
*/
|
|
14257
|
+
function validateMatchingNode(node, nodeType, tagName, lView, tNode) {
|
|
14258
|
+
if (node.nodeType !== nodeType ||
|
|
14259
|
+
(node.nodeType === Node.ELEMENT_NODE &&
|
|
14260
|
+
node.tagName.toLowerCase() !== (tagName === null || tagName === void 0 ? void 0 : tagName.toLowerCase()))) {
|
|
14261
|
+
// TODO: improve error message and use RuntimeError instead.
|
|
14262
|
+
throw new Error(`Unexpected node found during hydration.`);
|
|
14263
|
+
}
|
|
14264
|
+
}
|
|
14265
|
+
/**
|
|
14266
|
+
* Verifies whether next sibling node exists.
|
|
14267
|
+
*/
|
|
14268
|
+
function validateSiblingNodeExists(node) {
|
|
14269
|
+
if (!node.nextSibling) {
|
|
14270
|
+
// TODO: improve error message and use RuntimeError instead.
|
|
14271
|
+
throw new Error(`Unexpected state: insufficient number of sibling nodes.`);
|
|
14272
|
+
}
|
|
14273
|
+
}
|
|
14274
|
+
|
|
14275
|
+
/** Whether current TNode is a first node in an <ng-container>. */
|
|
14276
|
+
function isFirstElementInNgContainer(tNode) {
|
|
14277
|
+
var _a;
|
|
14278
|
+
return !tNode.prev && ((_a = tNode.parent) === null || _a === void 0 ? void 0 : _a.type) === 8 /* TNodeType.ElementContainer */;
|
|
14279
|
+
}
|
|
14280
|
+
/** Returns first element from a DOM segment that corresponds to this <ng-container>. */
|
|
14281
|
+
function getDehydratedNgContainer(hydrationInfo, tContainerNode) {
|
|
14282
|
+
var _a;
|
|
14283
|
+
const noOffsetIndex = tContainerNode.index - HEADER_OFFSET;
|
|
14284
|
+
const ngContainer = (_a = hydrationInfo.ngContainers) === null || _a === void 0 ? void 0 : _a[noOffsetIndex];
|
|
14285
|
+
ngDevMode &&
|
|
14286
|
+
assertDefined(ngContainer, 'Unexpected state: no hydration info available for a given TNode, ' +
|
|
14287
|
+
'which represents an element container.');
|
|
14288
|
+
return ngContainer;
|
|
14289
|
+
}
|
|
14290
|
+
/**
|
|
14291
|
+
* Locate a node in DOM tree that corresponds to a given TNode.
|
|
14292
|
+
*
|
|
14293
|
+
* @param hydrationInfo The hydration annotation data
|
|
14294
|
+
* @param tView the current tView
|
|
14295
|
+
* @param lView the current lView
|
|
14296
|
+
* @param tNode the current tNode
|
|
14297
|
+
* @returns an RNode that represents a given tNode
|
|
14298
|
+
*/
|
|
14299
|
+
function locateNextRNode(hydrationInfo, tView, lView, tNode) {
|
|
14300
|
+
var _a, _b;
|
|
14301
|
+
let native = null;
|
|
14302
|
+
if (tView.firstChild === tNode) {
|
|
14303
|
+
// We create a first node in this view, so we use a reference
|
|
14304
|
+
// to the first child in this DOM segment.
|
|
14305
|
+
native = hydrationInfo.firstChild;
|
|
14306
|
+
}
|
|
14307
|
+
else {
|
|
14308
|
+
// Locate a node based on a previous sibling or a parent node.
|
|
14309
|
+
const previousTNodeParent = tNode.prev === null;
|
|
14310
|
+
const previousTNode = ((_a = tNode.prev) !== null && _a !== void 0 ? _a : tNode.parent);
|
|
14311
|
+
ngDevMode &&
|
|
14312
|
+
assertDefined(previousTNode, 'Unexpected state: current TNode does not have a connection ' +
|
|
14313
|
+
'to the previous node or a parent node.');
|
|
14314
|
+
const previousRElement = getNativeByTNode(previousTNode, lView);
|
|
14315
|
+
if (isFirstElementInNgContainer(tNode)) {
|
|
14316
|
+
const ngContainer = getDehydratedNgContainer(hydrationInfo, tNode.parent);
|
|
14317
|
+
native = (_b = ngContainer.firstChild) !== null && _b !== void 0 ? _b : null;
|
|
14318
|
+
}
|
|
14319
|
+
else {
|
|
14320
|
+
if (previousTNodeParent) {
|
|
14321
|
+
native = previousRElement.firstChild;
|
|
14322
|
+
}
|
|
14323
|
+
else {
|
|
14324
|
+
native = previousRElement.nextSibling;
|
|
14325
|
+
}
|
|
14326
|
+
}
|
|
14327
|
+
}
|
|
14328
|
+
return native;
|
|
14329
|
+
}
|
|
14330
|
+
/**
|
|
14331
|
+
* Skips over a specified number of nodes and returns the next sibling node after that.
|
|
14332
|
+
*/
|
|
14333
|
+
function siblingAfter(skip, from) {
|
|
14334
|
+
let currentNode = from;
|
|
14335
|
+
for (let i = 0; i < skip; i++) {
|
|
14336
|
+
ngDevMode && validateSiblingNodeExists(currentNode);
|
|
14337
|
+
currentNode = currentNode.nextSibling;
|
|
14338
|
+
}
|
|
14339
|
+
return currentNode;
|
|
14340
|
+
}
|
|
14341
|
+
|
|
14342
|
+
/**
|
|
14343
|
+
* The name of an attribute that can be added to the hydration boundary node
|
|
14344
|
+
* (component host node) to disable hydration for the content within that boundary.
|
|
14345
|
+
*/
|
|
14346
|
+
const SKIP_HYDRATION_ATTR_NAME = 'ngSkipHydration';
|
|
14347
|
+
/**
|
|
14348
|
+
* Helper function to check if a given node has the 'ngSkipHydration' attribute
|
|
14349
|
+
*/
|
|
14350
|
+
function hasNgSkipHydrationAttr(tNode) {
|
|
14351
|
+
const SKIP_HYDRATION_ATTR_NAME_LOWER_CASE = SKIP_HYDRATION_ATTR_NAME.toLowerCase();
|
|
14352
|
+
const attrs = tNode.mergedAttrs;
|
|
14353
|
+
if (attrs === null)
|
|
14354
|
+
return false;
|
|
14355
|
+
// only ever look at the attribute name and skip the values
|
|
14356
|
+
for (let i = 0; i < attrs.length; i += 2) {
|
|
14357
|
+
const value = attrs[i];
|
|
14358
|
+
// This is a marker, which means that the static attributes section is over,
|
|
14359
|
+
// so we can exit early.
|
|
14360
|
+
if (typeof value === 'number')
|
|
14361
|
+
return false;
|
|
14362
|
+
if (typeof value === 'string' && value.toLowerCase() === SKIP_HYDRATION_ATTR_NAME_LOWER_CASE) {
|
|
14363
|
+
return true;
|
|
14364
|
+
}
|
|
14365
|
+
}
|
|
14366
|
+
return false;
|
|
14367
|
+
}
|
|
14368
|
+
|
|
13880
14369
|
/**
|
|
13881
14370
|
* Update a property on a selected element.
|
|
13882
14371
|
*
|
|
@@ -13917,16 +14406,13 @@ function setDirectiveInputsWhichShadowsStyling(tView, tNode, lView, value, isCla
|
|
|
13917
14406
|
setInputsForProperty(tView, lView, inputs[property], property, value);
|
|
13918
14407
|
}
|
|
13919
14408
|
|
|
13920
|
-
function elementStartFirstCreatePass(index, tView, lView,
|
|
14409
|
+
function elementStartFirstCreatePass(index, tView, lView, name, attrsIndex, localRefsIndex) {
|
|
13921
14410
|
ngDevMode && assertFirstCreatePass(tView);
|
|
13922
14411
|
ngDevMode && ngDevMode.firstCreatePass++;
|
|
13923
14412
|
const tViewConsts = tView.consts;
|
|
13924
14413
|
const attrs = getConstant(tViewConsts, attrsIndex);
|
|
13925
14414
|
const tNode = getOrCreateTNode(tView, index, 2 /* TNodeType.Element */, name, attrs);
|
|
13926
|
-
|
|
13927
|
-
if (ngDevMode) {
|
|
13928
|
-
validateElementIsKnown(native, lView, tNode.value, tView.schemas, hasDirectives);
|
|
13929
|
-
}
|
|
14415
|
+
resolveDirectives(tView, lView, tNode, getConstant(tViewConsts, localRefsIndex));
|
|
13930
14416
|
if (tNode.attrs !== null) {
|
|
13931
14417
|
computeStaticStyling(tNode, tNode.attrs, false);
|
|
13932
14418
|
}
|
|
@@ -13961,13 +14447,18 @@ function ɵɵelementStart(index, name, attrsIndex, localRefsIndex) {
|
|
|
13961
14447
|
assertEqual(getBindingIndex(), tView.bindingStartIndex, 'elements should be created before any bindings');
|
|
13962
14448
|
ngDevMode && assertIndexInRange(lView, adjustedIndex);
|
|
13963
14449
|
const renderer = lView[RENDERER];
|
|
13964
|
-
const native = lView[adjustedIndex] = createElementNode(renderer, name, getNamespace$1());
|
|
13965
14450
|
const tNode = tView.firstCreatePass ?
|
|
13966
|
-
elementStartFirstCreatePass(adjustedIndex, tView, lView,
|
|
14451
|
+
elementStartFirstCreatePass(adjustedIndex, tView, lView, name, attrsIndex, localRefsIndex) :
|
|
13967
14452
|
tView.data[adjustedIndex];
|
|
14453
|
+
const native = _locateOrCreateElementNode(tView, lView, tNode, renderer, name);
|
|
14454
|
+
lView[adjustedIndex] = native;
|
|
14455
|
+
const hasDirectives = isDirectiveHost(tNode);
|
|
14456
|
+
if (ngDevMode && tView.firstCreatePass) {
|
|
14457
|
+
validateElementIsKnown(native, lView, tNode.value, tView.schemas, hasDirectives);
|
|
14458
|
+
}
|
|
13968
14459
|
setCurrentTNode(tNode, true);
|
|
13969
14460
|
setupStaticAttributes(renderer, native, tNode);
|
|
13970
|
-
if ((tNode.flags & 32 /* TNodeFlags.isDetached */) !== 32 /* TNodeFlags.isDetached */) {
|
|
14461
|
+
if ((tNode.flags & 32 /* TNodeFlags.isDetached */) !== 32 /* TNodeFlags.isDetached */ && wasLastNodeCreated()) {
|
|
13971
14462
|
// In the i18n case, the translation may have removed this element, so only add it if it is not
|
|
13972
14463
|
// detached. See `TNodeType.Placeholder` and `LFrame.inI18n` for more context.
|
|
13973
14464
|
appendChild(tView, lView, native, tNode);
|
|
@@ -13979,7 +14470,7 @@ function ɵɵelementStart(index, name, attrsIndex, localRefsIndex) {
|
|
|
13979
14470
|
attachPatchData(native, lView);
|
|
13980
14471
|
}
|
|
13981
14472
|
increaseElementDepthCount();
|
|
13982
|
-
if (
|
|
14473
|
+
if (hasDirectives) {
|
|
13983
14474
|
createDirectivesInstances(tView, lView, tNode);
|
|
13984
14475
|
executeContentQueries(tView, tNode, lView);
|
|
13985
14476
|
}
|
|
@@ -14007,6 +14498,9 @@ function ɵɵelementEnd() {
|
|
|
14007
14498
|
}
|
|
14008
14499
|
const tNode = currentTNode;
|
|
14009
14500
|
ngDevMode && assertTNodeType(tNode, 3 /* TNodeType.AnyRNode */);
|
|
14501
|
+
if (isSkipHydrationRootTNode(tNode)) {
|
|
14502
|
+
leaveSkipHydrationBlock();
|
|
14503
|
+
}
|
|
14010
14504
|
decreaseElementDepthCount();
|
|
14011
14505
|
const tView = getTView();
|
|
14012
14506
|
if (tView.firstCreatePass) {
|
|
@@ -14039,6 +14533,40 @@ function ɵɵelement(index, name, attrsIndex, localRefsIndex) {
|
|
|
14039
14533
|
ɵɵelementEnd();
|
|
14040
14534
|
return ɵɵelement;
|
|
14041
14535
|
}
|
|
14536
|
+
let _locateOrCreateElementNode = (tView, lView, tNode, renderer, name) => {
|
|
14537
|
+
lastNodeWasCreated(true);
|
|
14538
|
+
return createElementNode(renderer, name, getNamespace$1());
|
|
14539
|
+
};
|
|
14540
|
+
/**
|
|
14541
|
+
* Enables hydration code path (to lookup existing elements in DOM)
|
|
14542
|
+
* in addition to the regular creation mode of element nodes.
|
|
14543
|
+
*/
|
|
14544
|
+
function locateOrCreateElementNodeImpl(tView, lView, tNode, renderer, name) {
|
|
14545
|
+
const hydrationInfo = lView[HYDRATION];
|
|
14546
|
+
const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock();
|
|
14547
|
+
lastNodeWasCreated(isNodeCreationMode);
|
|
14548
|
+
// Regular creation mode.
|
|
14549
|
+
if (isNodeCreationMode) {
|
|
14550
|
+
return createElementNode(renderer, name, getNamespace$1());
|
|
14551
|
+
}
|
|
14552
|
+
// Hydration mode, looking up an existing element in DOM.
|
|
14553
|
+
const native = locateNextRNode(hydrationInfo, tView, lView, tNode);
|
|
14554
|
+
ngDevMode &&
|
|
14555
|
+
validateMatchingNode(native, Node.ELEMENT_NODE, name, lView, tNode);
|
|
14556
|
+
ngDevMode && markRNodeAsClaimedByHydration(native);
|
|
14557
|
+
// Checks if the skip hydration attribute is present during hydration so we know to
|
|
14558
|
+
// skip attempting to hydrate this block.
|
|
14559
|
+
if (hydrationInfo && hasNgSkipHydrationAttr(tNode)) {
|
|
14560
|
+
enterSkipHydrationBlock(tNode);
|
|
14561
|
+
// Since this isn't hydratable, we need to empty the node
|
|
14562
|
+
// so there's no duplicate content after render
|
|
14563
|
+
clearElementContents(renderer, native);
|
|
14564
|
+
}
|
|
14565
|
+
return native;
|
|
14566
|
+
}
|
|
14567
|
+
function enableLocateOrCreateElementNodeImpl() {
|
|
14568
|
+
_locateOrCreateElementNode = locateOrCreateElementNodeImpl;
|
|
14569
|
+
}
|
|
14042
14570
|
|
|
14043
14571
|
function elementContainerStartFirstCreatePass(index, tView, lView, attrsIndex, localRefsIndex) {
|
|
14044
14572
|
ngDevMode && ngDevMode.firstCreatePass++;
|
|
@@ -14084,10 +14612,12 @@ function ɵɵelementContainerStart(index, attrsIndex, localRefsIndex) {
|
|
|
14084
14612
|
tView.data[adjustedIndex];
|
|
14085
14613
|
setCurrentTNode(tNode, true);
|
|
14086
14614
|
ngDevMode && ngDevMode.rendererCreateComment++;
|
|
14087
|
-
const
|
|
14088
|
-
|
|
14089
|
-
|
|
14090
|
-
|
|
14615
|
+
const comment = _locateOrCreateElementContainerNode(tView, lView, tNode, index);
|
|
14616
|
+
lView[adjustedIndex] = comment;
|
|
14617
|
+
if (wasLastNodeCreated()) {
|
|
14618
|
+
appendChild(tView, lView, comment, tNode);
|
|
14619
|
+
}
|
|
14620
|
+
attachPatchData(comment, lView);
|
|
14091
14621
|
if (isDirectiveHost(tNode)) {
|
|
14092
14622
|
createDirectivesInstances(tView, lView, tNode);
|
|
14093
14623
|
executeContentQueries(tView, tNode, lView);
|
|
@@ -14139,6 +14669,46 @@ function ɵɵelementContainer(index, attrsIndex, localRefsIndex) {
|
|
|
14139
14669
|
ɵɵelementContainerEnd();
|
|
14140
14670
|
return ɵɵelementContainer;
|
|
14141
14671
|
}
|
|
14672
|
+
let _locateOrCreateElementContainerNode = (tView, lView, tNode, index) => {
|
|
14673
|
+
lastNodeWasCreated(true);
|
|
14674
|
+
return createCommentNode(lView[RENDERER], ngDevMode ? 'ng-container' : '');
|
|
14675
|
+
};
|
|
14676
|
+
/**
|
|
14677
|
+
* Enables hydration code path (to lookup existing elements in DOM)
|
|
14678
|
+
* in addition to the regular creation mode of comment nodes that
|
|
14679
|
+
* represent <ng-container>'s anchor.
|
|
14680
|
+
*/
|
|
14681
|
+
function locateOrCreateElementContainerNode(tView, lView, tNode, index) {
|
|
14682
|
+
let comment;
|
|
14683
|
+
const hydrationInfo = lView[HYDRATION];
|
|
14684
|
+
const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock();
|
|
14685
|
+
lastNodeWasCreated(isNodeCreationMode);
|
|
14686
|
+
// Regular creation mode.
|
|
14687
|
+
if (isNodeCreationMode) {
|
|
14688
|
+
return createCommentNode(lView[RENDERER], ngDevMode ? 'ng-container' : '');
|
|
14689
|
+
}
|
|
14690
|
+
// Hydration mode, looking up existing elements in DOM.
|
|
14691
|
+
const currentRNode = locateNextRNode(hydrationInfo, tView, lView, tNode);
|
|
14692
|
+
const ngContainerSize = getNgContainerSize(hydrationInfo, index);
|
|
14693
|
+
ngDevMode &&
|
|
14694
|
+
assertNumber(ngContainerSize, 'Unexpected state: hydrating an <ng-container>, ' +
|
|
14695
|
+
'but no hydration info is available.');
|
|
14696
|
+
if (ngContainerSize > 0) {
|
|
14697
|
+
storeNgContainerInfo(hydrationInfo, index, currentRNode);
|
|
14698
|
+
comment = siblingAfter(ngContainerSize, currentRNode);
|
|
14699
|
+
}
|
|
14700
|
+
else {
|
|
14701
|
+
// If <ng-container> has no nodes,
|
|
14702
|
+
// the current node is an anchor (comment) node.
|
|
14703
|
+
comment = currentRNode;
|
|
14704
|
+
}
|
|
14705
|
+
ngDevMode && validateMatchingNode(comment, Node.COMMENT_NODE, null, lView, tNode);
|
|
14706
|
+
ngDevMode && markRNodeAsClaimedByHydration(comment);
|
|
14707
|
+
return comment;
|
|
14708
|
+
}
|
|
14709
|
+
function enableLocateOrCreateElementContainerNodeImpl() {
|
|
14710
|
+
_locateOrCreateElementContainerNode = locateOrCreateElementContainerNode;
|
|
14711
|
+
}
|
|
14142
14712
|
|
|
14143
14713
|
/**
|
|
14144
14714
|
* Returns the current OpaqueViewState instance.
|
|
@@ -14167,16 +14737,6 @@ function isPromise(obj) {
|
|
|
14167
14737
|
function isSubscribable(obj) {
|
|
14168
14738
|
return !!obj && typeof obj.subscribe === 'function';
|
|
14169
14739
|
}
|
|
14170
|
-
/**
|
|
14171
|
-
* Determine if the argument is an Observable
|
|
14172
|
-
*
|
|
14173
|
-
* Strictly this tests that the `obj` is `Subscribable`, since `Observable`
|
|
14174
|
-
* types need additional methods, such as `lift()`. But it is adequate for our
|
|
14175
|
-
* needs since within the Angular framework code we only ever need to use the
|
|
14176
|
-
* `subscribe()` method, and RxJS has mechanisms to wrap `Subscribable` objects
|
|
14177
|
-
* into `Observable` as needed.
|
|
14178
|
-
*/
|
|
14179
|
-
const isObservable = isSubscribable;
|
|
14180
14740
|
|
|
14181
14741
|
/**
|
|
14182
14742
|
* Adds an event listener to the current node.
|
|
@@ -14339,7 +14899,7 @@ function listenerInternal(tView, lView, renderer, tNode, eventName, listenerFn,
|
|
|
14339
14899
|
const minifiedName = props[i + 1];
|
|
14340
14900
|
const directiveInstance = lView[index];
|
|
14341
14901
|
const output = directiveInstance[minifiedName];
|
|
14342
|
-
if (ngDevMode && !
|
|
14902
|
+
if (ngDevMode && !isSubscribable(output)) {
|
|
14343
14903
|
throw new Error(`@Output ${minifiedName} not initialized in '${directiveInstance.constructor.name}'.`);
|
|
14344
14904
|
}
|
|
14345
14905
|
const subscription = output.subscribe(listenerFn);
|
|
@@ -16483,11 +17043,39 @@ function ɵɵtext(index, value = '') {
|
|
|
16483
17043
|
const tNode = tView.firstCreatePass ?
|
|
16484
17044
|
getOrCreateTNode(tView, adjustedIndex, 1 /* TNodeType.Text */, value, null) :
|
|
16485
17045
|
tView.data[adjustedIndex];
|
|
16486
|
-
const textNative =
|
|
16487
|
-
|
|
17046
|
+
const textNative = _locateOrCreateTextNode(tView, lView, tNode, value);
|
|
17047
|
+
lView[adjustedIndex] = textNative;
|
|
17048
|
+
if (wasLastNodeCreated()) {
|
|
17049
|
+
appendChild(tView, lView, textNative, tNode);
|
|
17050
|
+
}
|
|
16488
17051
|
// Text nodes are self closing.
|
|
16489
17052
|
setCurrentTNode(tNode, false);
|
|
16490
17053
|
}
|
|
17054
|
+
let _locateOrCreateTextNode = (tView, lView, tNode, value) => {
|
|
17055
|
+
lastNodeWasCreated(true);
|
|
17056
|
+
return createTextNode(lView[RENDERER], value);
|
|
17057
|
+
};
|
|
17058
|
+
/**
|
|
17059
|
+
* Enables hydration code path (to lookup existing elements in DOM)
|
|
17060
|
+
* in addition to the regular creation mode of text nodes.
|
|
17061
|
+
*/
|
|
17062
|
+
function locateOrCreateTextNodeImpl(tView, lView, tNode, value) {
|
|
17063
|
+
const hydrationInfo = lView[HYDRATION];
|
|
17064
|
+
const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock();
|
|
17065
|
+
lastNodeWasCreated(isNodeCreationMode);
|
|
17066
|
+
// Regular creation mode.
|
|
17067
|
+
if (isNodeCreationMode) {
|
|
17068
|
+
return createTextNode(lView[RENDERER], value);
|
|
17069
|
+
}
|
|
17070
|
+
// Hydration mode, looking up an existing element in DOM.
|
|
17071
|
+
const textNative = locateNextRNode(hydrationInfo, tView, lView, tNode);
|
|
17072
|
+
ngDevMode && validateMatchingNode(textNative, Node.TEXT_NODE, null, lView, tNode);
|
|
17073
|
+
ngDevMode && markRNodeAsClaimedByHydration(textNative);
|
|
17074
|
+
return textNative;
|
|
17075
|
+
}
|
|
17076
|
+
function enableLocateOrCreateTextNodeImpl() {
|
|
17077
|
+
_locateOrCreateTextNode = locateOrCreateTextNodeImpl;
|
|
17078
|
+
}
|
|
16491
17079
|
|
|
16492
17080
|
/**
|
|
16493
17081
|
*
|
|
@@ -18165,7 +18753,7 @@ function getTIcu(tView, index) {
|
|
|
18165
18753
|
if (value === null || typeof value === 'string')
|
|
18166
18754
|
return null;
|
|
18167
18755
|
if (ngDevMode &&
|
|
18168
|
-
!(value.hasOwnProperty('
|
|
18756
|
+
!(value.hasOwnProperty('tView') || value.hasOwnProperty('currentCaseLViewIndex'))) {
|
|
18169
18757
|
throwError('We expect to get \'null\'|\'TIcu\'|\'TIcuContainer\', but got: ' + value);
|
|
18170
18758
|
}
|
|
18171
18759
|
// Here the `value.hasOwnProperty('currentCaseLViewIndex')` is a polymorphic read as it can be
|
|
@@ -18194,7 +18782,7 @@ function getTIcu(tView, index) {
|
|
|
18194
18782
|
function setTIcu(tView, index, tIcu) {
|
|
18195
18783
|
const tNode = tView.data[index];
|
|
18196
18784
|
ngDevMode &&
|
|
18197
|
-
assertEqual(tNode === null || tNode.hasOwnProperty('
|
|
18785
|
+
assertEqual(tNode === null || tNode.hasOwnProperty('tView'), true, 'We expect to get \'null\'|\'TIcuContainer\'');
|
|
18198
18786
|
if (tNode === null) {
|
|
18199
18787
|
tView.data[index] = tIcu;
|
|
18200
18788
|
}
|
|
@@ -21295,7 +21883,8 @@ function _wrapInTimeout(fn) {
|
|
|
21295
21883
|
const EventEmitter = EventEmitter_;
|
|
21296
21884
|
|
|
21297
21885
|
function symbolIterator() {
|
|
21298
|
-
|
|
21886
|
+
// @ts-expect-error accessing a private member
|
|
21887
|
+
return this._results[Symbol.iterator]();
|
|
21299
21888
|
}
|
|
21300
21889
|
/**
|
|
21301
21890
|
* An unmodifiable list of items that Angular keeps up to date when the state
|
|
@@ -21347,11 +21936,10 @@ class QueryList {
|
|
|
21347
21936
|
// This function should be declared on the prototype, but doing so there will cause the class
|
|
21348
21937
|
// declaration to have side-effects and become not tree-shakable. For this reason we do it in
|
|
21349
21938
|
// the constructor.
|
|
21350
|
-
// [
|
|
21351
|
-
const symbol = getSymbolIterator();
|
|
21939
|
+
// [Symbol.iterator](): Iterator<T> { ... }
|
|
21352
21940
|
const proto = QueryList.prototype;
|
|
21353
|
-
if (!proto[
|
|
21354
|
-
proto[
|
|
21941
|
+
if (!proto[Symbol.iterator])
|
|
21942
|
+
proto[Symbol.iterator] = symbolIterator;
|
|
21355
21943
|
}
|
|
21356
21944
|
/**
|
|
21357
21945
|
* Returns the QueryList entry at `index`.
|
|
@@ -21490,8 +22078,8 @@ const R3TemplateRef = class TemplateRef extends ViewEngineTemplateRef {
|
|
|
21490
22078
|
this.elementRef = elementRef;
|
|
21491
22079
|
}
|
|
21492
22080
|
createEmbeddedView(context, injector) {
|
|
21493
|
-
const embeddedTView = this._declarationTContainer.
|
|
21494
|
-
const embeddedLView = createLView(this._declarationLView, embeddedTView, context, 16 /* LViewFlags.CheckAlways */, null, embeddedTView.declTNode, null, null, null, null, injector || null);
|
|
22081
|
+
const embeddedTView = this._declarationTContainer.tView;
|
|
22082
|
+
const embeddedLView = createLView(this._declarationLView, embeddedTView, context, 16 /* LViewFlags.CheckAlways */, null, embeddedTView.declTNode, null, null, null, null, injector || null, null);
|
|
21495
22083
|
const declarationLContainer = this._declarationLView[this._declarationTContainer.index];
|
|
21496
22084
|
ngDevMode && assertLContainer(declarationLContainer);
|
|
21497
22085
|
embeddedLView[DECLARATION_LCONTAINER] = declarationLContainer;
|
|
@@ -21520,7 +22108,7 @@ function injectTemplateRef() {
|
|
|
21520
22108
|
*/
|
|
21521
22109
|
function createTemplateRef(hostTNode, hostLView) {
|
|
21522
22110
|
if (hostTNode.type & 4 /* TNodeType.Container */) {
|
|
21523
|
-
ngDevMode && assertDefined(hostTNode.
|
|
22111
|
+
ngDevMode && assertDefined(hostTNode.tView, 'TView must be allocated');
|
|
21524
22112
|
return new R3TemplateRef(hostLView, hostTNode, createElementRef(hostTNode, hostLView));
|
|
21525
22113
|
}
|
|
21526
22114
|
return null;
|