@angular/core 16.0.0-next.3 → 16.0.0-next.4
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_tokens.mjs +33 -1
- package/esm2020/src/change_detection/change_detector_ref.mjs +4 -4
- package/esm2020/src/compiler/compiler_facade_interface.mjs +1 -1
- package/esm2020/src/core.mjs +2 -2
- package/esm2020/src/core_private_export.mjs +2 -1
- package/esm2020/src/core_reactivity_export_internal.mjs +1 -1
- package/esm2020/src/core_render3_private_export.mjs +1 -2
- package/esm2020/src/di/r3_injector.mjs +8 -1
- package/esm2020/src/errors.mjs +1 -1
- package/esm2020/src/hydration/annotate.mjs +118 -5
- package/esm2020/src/hydration/api.mjs +14 -1
- package/esm2020/src/hydration/cleanup.mjs +54 -3
- package/esm2020/src/hydration/compression.mjs +69 -0
- package/esm2020/src/hydration/error_handling.mjs +357 -15
- package/esm2020/src/hydration/interfaces.mjs +17 -1
- package/esm2020/src/hydration/node_lookup_utils.mjs +199 -7
- package/esm2020/src/hydration/utils.mjs +16 -3
- package/esm2020/src/hydration/views.mjs +19 -15
- package/esm2020/src/linker/destroy_ref.mjs +5 -2
- package/esm2020/src/linker/view_container_ref.mjs +8 -7
- package/esm2020/src/metadata/directives.mjs +8 -3
- package/esm2020/src/render3/instructions/element.mjs +16 -9
- package/esm2020/src/render3/instructions/element_container.mjs +2 -5
- package/esm2020/src/render3/instructions/element_validation.mjs +2 -2
- package/esm2020/src/render3/instructions/projection.mjs +7 -4
- package/esm2020/src/render3/instructions/template.mjs +4 -7
- package/esm2020/src/render3/instructions/text.mjs +6 -6
- package/esm2020/src/render3/interfaces/public_definitions.mjs +1 -1
- package/esm2020/src/render3/interfaces/type_checks.mjs +4 -1
- package/esm2020/src/render3/node_manipulation.mjs +2 -2
- package/esm2020/src/render3/node_selector_matcher.mjs +17 -5
- package/esm2020/src/render3/util/view_utils.mjs +12 -1
- package/esm2020/src/render3/view_ref.mjs +1 -1
- package/esm2020/src/signals/index.mjs +2 -1
- package/esm2020/src/signals/src/computed.mjs +3 -3
- package/esm2020/src/signals/src/effect.mjs +1 -3
- package/esm2020/src/signals/src/signal.mjs +3 -3
- package/esm2020/src/signals/src/watch.mjs +3 -3
- package/esm2020/src/signals/src/weak_ref.mjs +18 -2
- package/esm2020/src/util/ng_dev_mode.mjs +2 -1
- package/esm2020/src/version.mjs +1 -1
- package/esm2020/testing/src/logger.mjs +3 -3
- package/esm2020/testing/src/ng_zone_mock.mjs +3 -3
- package/esm2020/testing/src/test_bed_compiler.mjs +12 -7
- package/fesm2015/core.mjs +1066 -178
- package/fesm2015/core.mjs.map +1 -1
- package/fesm2015/testing.mjs +816 -68
- package/fesm2015/testing.mjs.map +1 -1
- package/fesm2020/core.mjs +1051 -170
- package/fesm2020/core.mjs.map +1 -1
- package/fesm2020/testing.mjs +810 -67
- package/fesm2020/testing.mjs.map +1 -1
- package/index.d.ts +128 -216
- package/package.json +1 -1
- package/schematics/migrations/relative-link-resolution/bundle.js +7 -7
- package/schematics/migrations/router-link-with-href/bundle.js +10 -10
- package/schematics/ng-generate/standalone-migration/bundle.js +473 -376
- package/schematics/ng-generate/standalone-migration/bundle.js.map +2 -2
- package/testing/index.d.ts +1 -1
package/fesm2020/core.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v16.0.0-next.
|
|
2
|
+
* @license Angular v16.0.0-next.4
|
|
3
3
|
* (c) 2010-2022 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { Subject, Subscription, Observable, merge as merge$1 } from 'rxjs';
|
|
8
|
-
import { share } from 'rxjs/operators';
|
|
8
|
+
import { first, share } from 'rxjs/operators';
|
|
9
9
|
|
|
10
10
|
function getClosureSafeProperty(objWithPropertyToExtract) {
|
|
11
11
|
for (let key in objWithPropertyToExtract) {
|
|
@@ -558,6 +558,7 @@ function ngDevModeResetPerfCounters() {
|
|
|
558
558
|
hydratedNodes: 0,
|
|
559
559
|
hydratedComponents: 0,
|
|
560
560
|
dehydratedViewsRemoved: 0,
|
|
561
|
+
dehydratedViewsCleanupRuns: 0,
|
|
561
562
|
};
|
|
562
563
|
// Make sure to refer to ngDevMode as ['ngDevMode'] for closure.
|
|
563
564
|
const allowNgDevModeTrue = locationString.indexOf('ngDevMode=false') === -1;
|
|
@@ -1187,12 +1188,19 @@ function isCssClassMatching(attrs, cssClassToMatch, isProjectionMode) {
|
|
|
1187
1188
|
ngDevMode &&
|
|
1188
1189
|
assertEqual(cssClassToMatch, cssClassToMatch.toLowerCase(), 'Class name expected to be lowercase.');
|
|
1189
1190
|
let i = 0;
|
|
1191
|
+
// Indicates whether we are processing value from the implicit
|
|
1192
|
+
// attribute section (i.e. before the first marker in the array).
|
|
1193
|
+
let isImplicitAttrsSection = true;
|
|
1190
1194
|
while (i < attrs.length) {
|
|
1191
1195
|
let item = attrs[i++];
|
|
1192
|
-
if (
|
|
1193
|
-
|
|
1194
|
-
if (
|
|
1195
|
-
|
|
1196
|
+
if (typeof item === 'string' && isImplicitAttrsSection) {
|
|
1197
|
+
const value = attrs[i++];
|
|
1198
|
+
if (isProjectionMode && item === 'class') {
|
|
1199
|
+
// We found a `class` attribute in the implicit attribute section,
|
|
1200
|
+
// check if it matches the value of the `cssClassToMatch` argument.
|
|
1201
|
+
if (classIndexOf(value.toLowerCase(), cssClassToMatch, 0) !== -1) {
|
|
1202
|
+
return true;
|
|
1203
|
+
}
|
|
1196
1204
|
}
|
|
1197
1205
|
}
|
|
1198
1206
|
else if (item === 1 /* AttributeMarker.Classes */) {
|
|
@@ -1204,6 +1212,11 @@ function isCssClassMatching(attrs, cssClassToMatch, isProjectionMode) {
|
|
|
1204
1212
|
}
|
|
1205
1213
|
return false;
|
|
1206
1214
|
}
|
|
1215
|
+
else if (typeof item === 'number') {
|
|
1216
|
+
// We've came across a first marker, which indicates
|
|
1217
|
+
// that the implicit attribute section is over.
|
|
1218
|
+
isImplicitAttrsSection = false;
|
|
1219
|
+
}
|
|
1207
1220
|
}
|
|
1208
1221
|
return false;
|
|
1209
1222
|
}
|
|
@@ -2038,6 +2051,9 @@ function isComponentDef(def) {
|
|
|
2038
2051
|
function isRootView(target) {
|
|
2039
2052
|
return (target[FLAGS] & 256 /* LViewFlags.IsRoot */) !== 0;
|
|
2040
2053
|
}
|
|
2054
|
+
function isProjectionTNode(tNode) {
|
|
2055
|
+
return (tNode.type & 16 /* TNodeType.Projection */) === 16 /* TNodeType.Projection */;
|
|
2056
|
+
}
|
|
2041
2057
|
|
|
2042
2058
|
// [Assert functions do not constraint type when they are guarded by a truthy
|
|
2043
2059
|
// expression.](https://github.com/microsoft/TypeScript/issues/37295)
|
|
@@ -2451,6 +2467,17 @@ function storeLViewOnDestroy(lView, onDestroyCallback) {
|
|
|
2451
2467
|
}
|
|
2452
2468
|
lView[ON_DESTROY_HOOKS].push(onDestroyCallback);
|
|
2453
2469
|
}
|
|
2470
|
+
/**
|
|
2471
|
+
* Removes previously registered LView-specific destroy callback.
|
|
2472
|
+
*/
|
|
2473
|
+
function removeLViewOnDestroy(lView, onDestroyCallback) {
|
|
2474
|
+
if (lView[ON_DESTROY_HOOKS] === null)
|
|
2475
|
+
return;
|
|
2476
|
+
const destroyCBIdx = lView[ON_DESTROY_HOOKS].indexOf(onDestroyCallback);
|
|
2477
|
+
if (destroyCBIdx !== -1) {
|
|
2478
|
+
lView[ON_DESTROY_HOOKS].splice(destroyCBIdx, 1);
|
|
2479
|
+
}
|
|
2480
|
+
}
|
|
2454
2481
|
|
|
2455
2482
|
const instructionState = {
|
|
2456
2483
|
lFrame: createLFrame(null),
|
|
@@ -8447,6 +8474,7 @@ class R3Injector extends EnvironmentInjector {
|
|
|
8447
8474
|
}
|
|
8448
8475
|
onDestroy(callback) {
|
|
8449
8476
|
this._onDestroyHooks.push(callback);
|
|
8477
|
+
return () => this.removeOnDestroy(callback);
|
|
8450
8478
|
}
|
|
8451
8479
|
runInContext(fn) {
|
|
8452
8480
|
this.assertNotDestroyed();
|
|
@@ -8621,6 +8649,12 @@ class R3Injector extends EnvironmentInjector {
|
|
|
8621
8649
|
return this.injectorDefTypes.has(providedIn);
|
|
8622
8650
|
}
|
|
8623
8651
|
}
|
|
8652
|
+
removeOnDestroy(callback) {
|
|
8653
|
+
const destroyCBIdx = this._onDestroyHooks.indexOf(callback);
|
|
8654
|
+
if (destroyCBIdx !== -1) {
|
|
8655
|
+
this._onDestroyHooks.splice(destroyCBIdx, 1);
|
|
8656
|
+
}
|
|
8657
|
+
}
|
|
8624
8658
|
}
|
|
8625
8659
|
function injectableDefOrInjectorDefFactory(token) {
|
|
8626
8660
|
// Most tokens will have an injectable def directly on them, which specifies a factory directly.
|
|
@@ -8806,6 +8840,37 @@ const PACKAGE_ROOT_URL = new InjectionToken('Application Packages Root URL');
|
|
|
8806
8840
|
* @publicApi
|
|
8807
8841
|
*/
|
|
8808
8842
|
const ANIMATION_MODULE_TYPE = new InjectionToken('AnimationModuleType');
|
|
8843
|
+
// TODO(crisbeto): link to CSP guide here.
|
|
8844
|
+
/**
|
|
8845
|
+
* Token used to configure the [Content Security Policy](https://web.dev/strict-csp/) nonce that
|
|
8846
|
+
* Angular will apply when inserting inline styles. If not provided, Angular will look up its value
|
|
8847
|
+
* from the `ngCspNonce` attribute of the application root node.
|
|
8848
|
+
*
|
|
8849
|
+
* @publicApi
|
|
8850
|
+
*/
|
|
8851
|
+
const CSP_NONCE = new InjectionToken('CSP nonce', {
|
|
8852
|
+
providedIn: 'root',
|
|
8853
|
+
factory: () => {
|
|
8854
|
+
// Ideally we wouldn't have to use `querySelector` here since we know that the nonce will be on
|
|
8855
|
+
// the root node, but because the token value is used in renderers, it has to be available
|
|
8856
|
+
// *very* early in the bootstrapping process. This should be a fairly shallow search, because
|
|
8857
|
+
// the app won't have been added to the DOM yet. Some approaches that were considered:
|
|
8858
|
+
// 1. Find the root node through `ApplicationRef.components[i].location` - normally this would
|
|
8859
|
+
// be enough for our purposes, but the token is injected very early so the `components` array
|
|
8860
|
+
// isn't populated yet.
|
|
8861
|
+
// 2. Find the root `LView` through the current `LView` - renderers are a prerequisite to
|
|
8862
|
+
// creating the `LView`. This means that no `LView` will have been entered when this factory is
|
|
8863
|
+
// invoked for the root component.
|
|
8864
|
+
// 3. Have the token factory return `() => string` which is invoked when a nonce is requested -
|
|
8865
|
+
// the slightly later execution does allow us to get an `LView` reference, but the fact that
|
|
8866
|
+
// it is a function means that it could be executed at *any* time (including immediately) which
|
|
8867
|
+
// may lead to weird bugs.
|
|
8868
|
+
// 4. Have the `ComponentFactory` read the attribute and provide it to the injector under the
|
|
8869
|
+
// hood - has the same problem as #1 and #2 in that the renderer is used to query for the root
|
|
8870
|
+
// node and the nonce value needs to be available when the renderer is created.
|
|
8871
|
+
return getDocument().body.querySelector('[ngCspNonce]')?.getAttribute('ngCspNonce') || null;
|
|
8872
|
+
},
|
|
8873
|
+
});
|
|
8809
8874
|
|
|
8810
8875
|
function escapeTransferStateContent(text) {
|
|
8811
8876
|
const escapedText = {
|
|
@@ -8948,6 +9013,19 @@ function retrieveTransferredState(doc, appId) {
|
|
|
8948
9013
|
return initialState;
|
|
8949
9014
|
}
|
|
8950
9015
|
|
|
9016
|
+
/** Encodes that the node lookup should start from the host node of this component. */
|
|
9017
|
+
const REFERENCE_NODE_HOST = 'h';
|
|
9018
|
+
/** Encodes that the node lookup should start from the document body node. */
|
|
9019
|
+
const REFERENCE_NODE_BODY = 'b';
|
|
9020
|
+
/**
|
|
9021
|
+
* Describes navigation steps that the runtime logic need to perform,
|
|
9022
|
+
* starting from a given (known) element.
|
|
9023
|
+
*/
|
|
9024
|
+
var NodeNavigationStep;
|
|
9025
|
+
(function (NodeNavigationStep) {
|
|
9026
|
+
NodeNavigationStep["FirstChild"] = "f";
|
|
9027
|
+
NodeNavigationStep["NextSibling"] = "n";
|
|
9028
|
+
})(NodeNavigationStep || (NodeNavigationStep = {}));
|
|
8951
9029
|
/**
|
|
8952
9030
|
* Keys within serialized view data structure to represent various
|
|
8953
9031
|
* parts. See the `SerializedView` interface below for additional information.
|
|
@@ -8955,8 +9033,11 @@ function retrieveTransferredState(doc, appId) {
|
|
|
8955
9033
|
const ELEMENT_CONTAINERS = 'e';
|
|
8956
9034
|
const TEMPLATES = 't';
|
|
8957
9035
|
const CONTAINERS = 'c';
|
|
9036
|
+
const MULTIPLIER = 'x';
|
|
8958
9037
|
const NUM_ROOT_NODES = 'r';
|
|
8959
9038
|
const TEMPLATE_ID = 'i'; // as it's also an "id"
|
|
9039
|
+
const NODES = 'n';
|
|
9040
|
+
const DISCONNECTED_NODES = 'd';
|
|
8960
9041
|
|
|
8961
9042
|
/**
|
|
8962
9043
|
* The name of the key used in the TransferState collection,
|
|
@@ -9146,10 +9227,23 @@ function calcSerializedContainerSize(hydrationInfo, index) {
|
|
|
9146
9227
|
const views = getSerializedContainerViews(hydrationInfo, index) ?? [];
|
|
9147
9228
|
let numNodes = 0;
|
|
9148
9229
|
for (let view of views) {
|
|
9149
|
-
numNodes += view[NUM_ROOT_NODES];
|
|
9230
|
+
numNodes += view[NUM_ROOT_NODES] * (view[MULTIPLIER] ?? 1);
|
|
9150
9231
|
}
|
|
9151
9232
|
return numNodes;
|
|
9152
9233
|
}
|
|
9234
|
+
/**
|
|
9235
|
+
* Checks whether a node is annotated as "disconnected", i.e. not present
|
|
9236
|
+
* in the DOM at serialization time. We should not attempt hydration for
|
|
9237
|
+
* such nodes and instead, use a regular "creation mode".
|
|
9238
|
+
*/
|
|
9239
|
+
function isDisconnectedNode(hydrationInfo, index) {
|
|
9240
|
+
// Check if we are processing disconnected info for the first time.
|
|
9241
|
+
if (typeof hydrationInfo.disconnectedNodes === 'undefined') {
|
|
9242
|
+
const nodeIds = hydrationInfo.data[DISCONNECTED_NODES];
|
|
9243
|
+
hydrationInfo.disconnectedNodes = nodeIds ? (new Set(nodeIds)) : null;
|
|
9244
|
+
}
|
|
9245
|
+
return !!hydrationInfo.disconnectedNodes?.has(index);
|
|
9246
|
+
}
|
|
9153
9247
|
|
|
9154
9248
|
/**
|
|
9155
9249
|
* Represents a component created by a `ComponentFactory`.
|
|
@@ -9330,7 +9424,7 @@ class Version {
|
|
|
9330
9424
|
/**
|
|
9331
9425
|
* @publicApi
|
|
9332
9426
|
*/
|
|
9333
|
-
const VERSION = new Version('16.0.0-next.
|
|
9427
|
+
const VERSION = new Version('16.0.0-next.4');
|
|
9334
9428
|
|
|
9335
9429
|
// This default value is when checking the hierarchy for a token.
|
|
9336
9430
|
//
|
|
@@ -14070,40 +14164,443 @@ function detectChanges(component) {
|
|
|
14070
14164
|
detectChangesInternal(view[TVIEW], view, component);
|
|
14071
14165
|
}
|
|
14072
14166
|
|
|
14167
|
+
const AT_THIS_LOCATION = '<-- AT THIS LOCATION';
|
|
14073
14168
|
/**
|
|
14074
|
-
*
|
|
14075
|
-
*
|
|
14169
|
+
* Retrieves a user friendly string for a given TNodeType for use in
|
|
14170
|
+
* friendly error messages
|
|
14171
|
+
*
|
|
14172
|
+
* @param tNodeType
|
|
14173
|
+
* @returns
|
|
14076
14174
|
*/
|
|
14077
|
-
function
|
|
14078
|
-
|
|
14079
|
-
|
|
14080
|
-
|
|
14081
|
-
|
|
14082
|
-
|
|
14083
|
-
|
|
14175
|
+
function getFriendlyStringFromTNodeType(tNodeType) {
|
|
14176
|
+
switch (tNodeType) {
|
|
14177
|
+
case 4 /* TNodeType.Container */:
|
|
14178
|
+
return 'view container';
|
|
14179
|
+
case 2 /* TNodeType.Element */:
|
|
14180
|
+
return 'element';
|
|
14181
|
+
case 8 /* TNodeType.ElementContainer */:
|
|
14182
|
+
return 'ng-container';
|
|
14183
|
+
case 32 /* TNodeType.Icu */:
|
|
14184
|
+
return 'icu';
|
|
14185
|
+
case 64 /* TNodeType.Placeholder */:
|
|
14186
|
+
return 'i18n';
|
|
14187
|
+
case 16 /* TNodeType.Projection */:
|
|
14188
|
+
return 'projection';
|
|
14189
|
+
case 1 /* TNodeType.Text */:
|
|
14190
|
+
return 'text';
|
|
14191
|
+
default:
|
|
14192
|
+
// This should not happen as we cover all possible TNode types above.
|
|
14193
|
+
return '<unknown>';
|
|
14194
|
+
}
|
|
14195
|
+
}
|
|
14196
|
+
/**
|
|
14197
|
+
* Validates that provided nodes match during the hydration process.
|
|
14198
|
+
*/
|
|
14199
|
+
function validateMatchingNode(node, nodeType, tagName, lView, tNode, isViewContainerAnchor = false) {
|
|
14200
|
+
if (!node ||
|
|
14201
|
+
(node.nodeType !== nodeType ||
|
|
14202
|
+
(node.nodeType === Node.ELEMENT_NODE &&
|
|
14203
|
+
node.tagName.toLowerCase() !== tagName?.toLowerCase()))) {
|
|
14204
|
+
const expectedNode = shortRNodeDescription(nodeType, tagName, null);
|
|
14205
|
+
let header = `During hydration Angular expected ${expectedNode} but `;
|
|
14206
|
+
const hostComponentDef = getDeclarationComponentDef(lView);
|
|
14207
|
+
const componentClassName = hostComponentDef?.type?.name;
|
|
14208
|
+
const expected = `Angular expected this DOM:\n\n${describeExpectedDom(lView, tNode, isViewContainerAnchor)}\n\n`;
|
|
14209
|
+
let actual = '';
|
|
14210
|
+
if (!node) {
|
|
14211
|
+
// No node found during hydration.
|
|
14212
|
+
header += `the node was not found.\n\n`;
|
|
14213
|
+
}
|
|
14214
|
+
else {
|
|
14215
|
+
const actualNode = shortRNodeDescription(node.nodeType, node.tagName ?? null, node.textContent ?? null);
|
|
14216
|
+
header += `found ${actualNode}.\n\n`;
|
|
14217
|
+
actual = `Actual DOM is:\n\n${describeDomFromNode(node)}\n\n`;
|
|
14218
|
+
}
|
|
14219
|
+
const footer = getHydrationErrorFooter(componentClassName);
|
|
14220
|
+
const message = header + expected + actual + getHydrationAttributeNote() + footer;
|
|
14221
|
+
throw new RuntimeError(500 /* RuntimeErrorCode.HYDRATION_NODE_MISMATCH */, message);
|
|
14084
14222
|
}
|
|
14085
14223
|
}
|
|
14086
14224
|
/**
|
|
14087
|
-
*
|
|
14225
|
+
* Validates that a given node has sibling nodes
|
|
14088
14226
|
*/
|
|
14089
14227
|
function validateSiblingNodeExists(node) {
|
|
14090
14228
|
validateNodeExists(node);
|
|
14091
14229
|
if (!node.nextSibling) {
|
|
14092
|
-
|
|
14093
|
-
|
|
14230
|
+
const header = 'During hydration Angular expected more sibling nodes to be present.\n\n';
|
|
14231
|
+
const actual = `Actual DOM is:\n\n${describeDomFromNode(node)}\n\n`;
|
|
14232
|
+
const footer = getHydrationErrorFooter();
|
|
14233
|
+
const message = header + actual + footer;
|
|
14234
|
+
throw new RuntimeError(501 /* RuntimeErrorCode.HYDRATION_MISSING_SIBLINGS */, message);
|
|
14094
14235
|
}
|
|
14095
14236
|
}
|
|
14237
|
+
/**
|
|
14238
|
+
* Validates that a node exists or throws
|
|
14239
|
+
*/
|
|
14096
14240
|
function validateNodeExists(node) {
|
|
14097
14241
|
if (!node) {
|
|
14098
|
-
|
|
14099
|
-
throw new Error(`Hydration expected an element to be present at this location.`);
|
|
14242
|
+
throw new RuntimeError(502 /* RuntimeErrorCode.HYDRATION_MISSING_NODE */, `Hydration expected an element to be present at this location.`);
|
|
14100
14243
|
}
|
|
14101
14244
|
}
|
|
14245
|
+
/**
|
|
14246
|
+
* Builds the hydration error message when a node is not found
|
|
14247
|
+
*
|
|
14248
|
+
* @param lView the LView where the node exists
|
|
14249
|
+
* @param tNode the TNode
|
|
14250
|
+
*/
|
|
14251
|
+
function nodeNotFoundError(lView, tNode) {
|
|
14252
|
+
const header = 'During serialization, Angular was unable to find an element in the DOM:\n\n';
|
|
14253
|
+
const expected = `${describeExpectedDom(lView, tNode, false)}\n\n`;
|
|
14254
|
+
const footer = getHydrationErrorFooter();
|
|
14255
|
+
throw new RuntimeError(502 /* RuntimeErrorCode.HYDRATION_MISSING_NODE */, header + expected + footer);
|
|
14256
|
+
}
|
|
14257
|
+
/**
|
|
14258
|
+
* Builds a hydration error message when a node is not found at a path location
|
|
14259
|
+
*
|
|
14260
|
+
* @param host the Host Node
|
|
14261
|
+
* @param path the path to the node
|
|
14262
|
+
*/
|
|
14263
|
+
function nodeNotFoundAtPathError(host, path) {
|
|
14264
|
+
const header = `During hydration Angular was unable to locate a node ` +
|
|
14265
|
+
`using the "${path}" path, starting from the ${describeRNode(host)} node.\n\n`;
|
|
14266
|
+
const footer = getHydrationErrorFooter();
|
|
14267
|
+
throw new RuntimeError(502 /* RuntimeErrorCode.HYDRATION_MISSING_NODE */, header + footer);
|
|
14268
|
+
}
|
|
14269
|
+
/**
|
|
14270
|
+
* Builds the hydration error message in the case that dom nodes are created outside of
|
|
14271
|
+
* the Angular context and are being used as projected nodes
|
|
14272
|
+
*
|
|
14273
|
+
* @param lView the LView
|
|
14274
|
+
* @param tNode the TNode
|
|
14275
|
+
* @returns an error
|
|
14276
|
+
*/
|
|
14277
|
+
function unsupportedProjectionOfDomNodes(rNode) {
|
|
14278
|
+
const header = 'During serialization, Angular detected DOM nodes ' +
|
|
14279
|
+
'that were created outside of Angular context and provided as projectable nodes ' +
|
|
14280
|
+
'(likely via `ViewContainerRef.createComponent` or `createComponent` APIs). ' +
|
|
14281
|
+
'Hydration is not supported for such cases, consider refactoring the code to avoid ' +
|
|
14282
|
+
'this pattern or using `ngSkipHydration` on the host element of the component.\n\n';
|
|
14283
|
+
const actual = `${describeDomFromNode(rNode)}\n\n`;
|
|
14284
|
+
const message = header + actual + getHydrationAttributeNote();
|
|
14285
|
+
return new RuntimeError(503 /* RuntimeErrorCode.UNSUPPORTED_PROJECTION_DOM_NODES */, message);
|
|
14286
|
+
}
|
|
14287
|
+
/**
|
|
14288
|
+
* Builds the hydration error message in the case that ngSkipHydration was used on a
|
|
14289
|
+
* node that is not a component host element or host binding
|
|
14290
|
+
*
|
|
14291
|
+
* @param rNode the HTML Element
|
|
14292
|
+
* @returns an error
|
|
14293
|
+
*/
|
|
14294
|
+
function invalidSkipHydrationHost(rNode) {
|
|
14295
|
+
const header = 'The `ngSkipHydration` flag is applied on a node ' +
|
|
14296
|
+
'that doesn\'t act as a component host. Hydration can be ' +
|
|
14297
|
+
'skipped only on per-component basis.\n\n';
|
|
14298
|
+
const actual = `${describeDomFromNode(rNode)}\n\n`;
|
|
14299
|
+
const footer = 'Please move the `ngSkipHydration` attribute to the component host element.';
|
|
14300
|
+
const message = header + actual + footer;
|
|
14301
|
+
return new RuntimeError(504 /* RuntimeErrorCode.INVALID_SKIP_HYDRATION_HOST */, message);
|
|
14302
|
+
}
|
|
14303
|
+
/**
|
|
14304
|
+
* Builds the hydration error message in the case that a user is attempting to enable
|
|
14305
|
+
* hydration on internationalized nodes, which is not yet supported.
|
|
14306
|
+
*
|
|
14307
|
+
* @param rNode the HTML Element
|
|
14308
|
+
* @returns an error
|
|
14309
|
+
*/
|
|
14310
|
+
function notYetSupportedI18nBlockError(rNode) {
|
|
14311
|
+
const header = 'Hydration for nodes marked with `i18n` is not yet supported. ' +
|
|
14312
|
+
'You can opt-out a component that uses `i18n` in a template using ' +
|
|
14313
|
+
'the `ngSkipHydration` attribute or fall back to the previous ' +
|
|
14314
|
+
'hydration logic (which re-creates the application structure).\n\n';
|
|
14315
|
+
const actual = `${describeDomFromNode(rNode)}\n\n`;
|
|
14316
|
+
const message = header + actual;
|
|
14317
|
+
return new RuntimeError(518 /* RuntimeErrorCode.HYDRATION_I18N_NOT_YET_SUPPORTED */, message);
|
|
14318
|
+
}
|
|
14319
|
+
// Stringification methods
|
|
14320
|
+
/**
|
|
14321
|
+
* Stringifies a given TNode's attributes
|
|
14322
|
+
*
|
|
14323
|
+
* @param tNode a provided TNode
|
|
14324
|
+
* @returns string
|
|
14325
|
+
*/
|
|
14326
|
+
function stringifyTNodeAttrs(tNode) {
|
|
14327
|
+
const results = [];
|
|
14328
|
+
if (tNode.attrs) {
|
|
14329
|
+
for (let i = 0; i < tNode.attrs.length;) {
|
|
14330
|
+
const attrName = tNode.attrs[i++];
|
|
14331
|
+
// Once we reach the first flag, we know that the list of
|
|
14332
|
+
// attributes is over.
|
|
14333
|
+
if (typeof attrName == 'number') {
|
|
14334
|
+
break;
|
|
14335
|
+
}
|
|
14336
|
+
const attrValue = tNode.attrs[i++];
|
|
14337
|
+
results.push(`${attrName}="${shorten(attrValue)}"`);
|
|
14338
|
+
}
|
|
14339
|
+
}
|
|
14340
|
+
return results.join(' ');
|
|
14341
|
+
}
|
|
14342
|
+
/**
|
|
14343
|
+
* The list of internal attributes that should be filtered out while
|
|
14344
|
+
* producing an error message.
|
|
14345
|
+
*/
|
|
14346
|
+
const internalAttrs = new Set(['ngh', 'ng-version', 'ng-server-context']);
|
|
14347
|
+
/**
|
|
14348
|
+
* Stringifies an HTML Element's attributes
|
|
14349
|
+
*
|
|
14350
|
+
* @param rNode an HTML Element
|
|
14351
|
+
* @returns string
|
|
14352
|
+
*/
|
|
14353
|
+
function stringifyRNodeAttrs(rNode) {
|
|
14354
|
+
const results = [];
|
|
14355
|
+
for (let i = 0; i < rNode.attributes.length; i++) {
|
|
14356
|
+
const attr = rNode.attributes[i];
|
|
14357
|
+
if (internalAttrs.has(attr.name))
|
|
14358
|
+
continue;
|
|
14359
|
+
results.push(`${attr.name}="${shorten(attr.value)}"`);
|
|
14360
|
+
}
|
|
14361
|
+
return results.join(' ');
|
|
14362
|
+
}
|
|
14363
|
+
// Methods for Describing the DOM
|
|
14364
|
+
/**
|
|
14365
|
+
* Converts a tNode to a helpful readable string value for use in error messages
|
|
14366
|
+
*
|
|
14367
|
+
* @param tNode a given TNode
|
|
14368
|
+
* @param innerContent the content of the node
|
|
14369
|
+
* @returns string
|
|
14370
|
+
*/
|
|
14371
|
+
function describeTNode(tNode, innerContent = '…') {
|
|
14372
|
+
switch (tNode.type) {
|
|
14373
|
+
case 1 /* TNodeType.Text */:
|
|
14374
|
+
const content = tNode.value ? `(${tNode.value})` : '';
|
|
14375
|
+
return `#text${content}`;
|
|
14376
|
+
case 2 /* TNodeType.Element */:
|
|
14377
|
+
const attrs = stringifyTNodeAttrs(tNode);
|
|
14378
|
+
const tag = tNode.value.toLowerCase();
|
|
14379
|
+
return `<${tag}${attrs ? ' ' + attrs : ''}>${innerContent}</${tag}>`;
|
|
14380
|
+
case 8 /* TNodeType.ElementContainer */:
|
|
14381
|
+
return '<!-- ng-container -->';
|
|
14382
|
+
case 4 /* TNodeType.Container */:
|
|
14383
|
+
return '<!-- container -->';
|
|
14384
|
+
default:
|
|
14385
|
+
const typeAsString = getFriendlyStringFromTNodeType(tNode.type);
|
|
14386
|
+
return `#node(${typeAsString})`;
|
|
14387
|
+
}
|
|
14388
|
+
}
|
|
14389
|
+
/**
|
|
14390
|
+
* Converts an RNode to a helpful readable string value for use in error messages
|
|
14391
|
+
*
|
|
14392
|
+
* @param rNode a given RNode
|
|
14393
|
+
* @param innerContent the content of the node
|
|
14394
|
+
* @returns string
|
|
14395
|
+
*/
|
|
14396
|
+
function describeRNode(rNode, innerContent = '…') {
|
|
14397
|
+
const node = rNode;
|
|
14398
|
+
switch (node.nodeType) {
|
|
14399
|
+
case Node.ELEMENT_NODE:
|
|
14400
|
+
const tag = node.tagName.toLowerCase();
|
|
14401
|
+
const attrs = stringifyRNodeAttrs(node);
|
|
14402
|
+
return `<${tag}${attrs ? ' ' + attrs : ''}>${innerContent}</${tag}>`;
|
|
14403
|
+
case Node.TEXT_NODE:
|
|
14404
|
+
const content = node.textContent ? shorten(node.textContent) : '';
|
|
14405
|
+
return `#text${content ? `(${content})` : ''}`;
|
|
14406
|
+
case Node.COMMENT_NODE:
|
|
14407
|
+
return `<!-- ${shorten(node.textContent ?? '')} -->`;
|
|
14408
|
+
default:
|
|
14409
|
+
return `#node(${node.nodeType})`;
|
|
14410
|
+
}
|
|
14411
|
+
}
|
|
14412
|
+
/**
|
|
14413
|
+
* Builds the string containing the expected DOM present given the LView and TNode
|
|
14414
|
+
* values for a readable error message
|
|
14415
|
+
*
|
|
14416
|
+
* @param lView the lView containing the DOM
|
|
14417
|
+
* @param tNode the tNode
|
|
14418
|
+
* @param isViewContainerAnchor boolean
|
|
14419
|
+
* @returns string
|
|
14420
|
+
*/
|
|
14421
|
+
function describeExpectedDom(lView, tNode, isViewContainerAnchor) {
|
|
14422
|
+
const spacer = ' ';
|
|
14423
|
+
let content = '';
|
|
14424
|
+
if (tNode.prev) {
|
|
14425
|
+
content += spacer + '…\n';
|
|
14426
|
+
content += spacer + describeTNode(tNode.prev) + '\n';
|
|
14427
|
+
}
|
|
14428
|
+
else if (tNode.type && tNode.type & 12 /* TNodeType.AnyContainer */) {
|
|
14429
|
+
content += spacer + '…\n';
|
|
14430
|
+
}
|
|
14431
|
+
if (isViewContainerAnchor) {
|
|
14432
|
+
content += spacer + describeTNode(tNode) + '\n';
|
|
14433
|
+
content += spacer + `<!-- container --> ${AT_THIS_LOCATION}\n`;
|
|
14434
|
+
}
|
|
14435
|
+
else {
|
|
14436
|
+
content += spacer + describeTNode(tNode) + ` ${AT_THIS_LOCATION}\n`;
|
|
14437
|
+
}
|
|
14438
|
+
content += spacer + '…\n';
|
|
14439
|
+
const parentRNode = tNode.type ? getParentRElement(lView[TVIEW], tNode, lView) : null;
|
|
14440
|
+
if (parentRNode) {
|
|
14441
|
+
content = describeRNode(parentRNode, '\n' + content);
|
|
14442
|
+
}
|
|
14443
|
+
return content;
|
|
14444
|
+
}
|
|
14445
|
+
/**
|
|
14446
|
+
* Builds the string containing the DOM present around a given RNode for a
|
|
14447
|
+
* readable error message
|
|
14448
|
+
*
|
|
14449
|
+
* @param node the RNode
|
|
14450
|
+
* @returns string
|
|
14451
|
+
*/
|
|
14452
|
+
function describeDomFromNode(node) {
|
|
14453
|
+
const spacer = ' ';
|
|
14454
|
+
let content = '';
|
|
14455
|
+
const currentNode = node;
|
|
14456
|
+
if (currentNode.previousSibling) {
|
|
14457
|
+
content += spacer + '…\n';
|
|
14458
|
+
content += spacer + describeRNode(currentNode.previousSibling) + '\n';
|
|
14459
|
+
}
|
|
14460
|
+
content += spacer + describeRNode(currentNode) + ` ${AT_THIS_LOCATION}\n`;
|
|
14461
|
+
if (node.nextSibling) {
|
|
14462
|
+
content += spacer + '…\n';
|
|
14463
|
+
}
|
|
14464
|
+
if (node.parentNode) {
|
|
14465
|
+
content = describeRNode(currentNode.parentNode, '\n' + content);
|
|
14466
|
+
}
|
|
14467
|
+
return content;
|
|
14468
|
+
}
|
|
14469
|
+
/**
|
|
14470
|
+
* Shortens the description of a given RNode by its type for readability
|
|
14471
|
+
*
|
|
14472
|
+
* @param nodeType the type of node
|
|
14473
|
+
* @param tagName the node tag name
|
|
14474
|
+
* @param textContent the text content in the node
|
|
14475
|
+
* @returns string
|
|
14476
|
+
*/
|
|
14477
|
+
function shortRNodeDescription(nodeType, tagName, textContent) {
|
|
14478
|
+
switch (nodeType) {
|
|
14479
|
+
case Node.ELEMENT_NODE:
|
|
14480
|
+
return `<${tagName.toLowerCase()}>`;
|
|
14481
|
+
case Node.TEXT_NODE:
|
|
14482
|
+
const content = textContent ? ` (with the "${shorten(textContent)}" content)` : '';
|
|
14483
|
+
return `a text node${content}`;
|
|
14484
|
+
case Node.COMMENT_NODE:
|
|
14485
|
+
return 'a comment node';
|
|
14486
|
+
default:
|
|
14487
|
+
return `#node(nodeType=${nodeType})`;
|
|
14488
|
+
}
|
|
14489
|
+
}
|
|
14490
|
+
/**
|
|
14491
|
+
* Builds the footer hydration error message
|
|
14492
|
+
*
|
|
14493
|
+
* @param componentClassName the name of the component class
|
|
14494
|
+
* @returns string
|
|
14495
|
+
*/
|
|
14496
|
+
function getHydrationErrorFooter(componentClassName) {
|
|
14497
|
+
const componentInfo = componentClassName ? `the "${componentClassName}"` : 'corresponding';
|
|
14498
|
+
return `To fix this problem:\n` +
|
|
14499
|
+
` * check ${componentInfo} component for hydration-related issues\n` +
|
|
14500
|
+
` * or skip hydration by adding the \`ngSkipHydration\` attribute ` +
|
|
14501
|
+
`to its host node in a template`;
|
|
14502
|
+
}
|
|
14503
|
+
/**
|
|
14504
|
+
* An attribute related note for hydration errors
|
|
14505
|
+
*/
|
|
14506
|
+
function getHydrationAttributeNote() {
|
|
14507
|
+
return 'Note: attributes are only displayed to better represent the DOM' +
|
|
14508
|
+
' but have no effect on hydration mismatches.\n\n';
|
|
14509
|
+
}
|
|
14510
|
+
// Node string utility functions
|
|
14511
|
+
/**
|
|
14512
|
+
* Strips all newlines out of a given string
|
|
14513
|
+
*
|
|
14514
|
+
* @param input a string to be cleared of new line characters
|
|
14515
|
+
* @returns
|
|
14516
|
+
*/
|
|
14517
|
+
function stripNewlines(input) {
|
|
14518
|
+
return input.replace(/\s+/gm, '');
|
|
14519
|
+
}
|
|
14520
|
+
/**
|
|
14521
|
+
* Reduces a string down to a maximum length of characters with ellipsis for readability
|
|
14522
|
+
*
|
|
14523
|
+
* @param input a string input
|
|
14524
|
+
* @param maxLength a maximum length in characters
|
|
14525
|
+
* @returns string
|
|
14526
|
+
*/
|
|
14527
|
+
function shorten(input, maxLength = 50) {
|
|
14528
|
+
if (!input) {
|
|
14529
|
+
return '';
|
|
14530
|
+
}
|
|
14531
|
+
input = stripNewlines(input);
|
|
14532
|
+
return input.length > maxLength ? `${input.substring(0, maxLength - 1)}…` : input;
|
|
14533
|
+
}
|
|
14534
|
+
|
|
14535
|
+
/**
|
|
14536
|
+
* Regexp that extracts a reference node information from the compressed node location.
|
|
14537
|
+
* The reference node is represented as either:
|
|
14538
|
+
* - a number which points to an LView slot
|
|
14539
|
+
* - the `b` char which indicates that the lookup should start from the `document.body`
|
|
14540
|
+
* - the `h` char to start lookup from the component host node (`lView[HOST]`)
|
|
14541
|
+
*/
|
|
14542
|
+
const REF_EXTRACTOR_REGEXP = new RegExp(`^(\\d+)*(${REFERENCE_NODE_BODY}|${REFERENCE_NODE_HOST})*(.*)`);
|
|
14543
|
+
/**
|
|
14544
|
+
* Helper function that takes a reference node location and a set of navigation steps
|
|
14545
|
+
* (from the reference node) to a target node and outputs a string that represents
|
|
14546
|
+
* a location.
|
|
14547
|
+
*
|
|
14548
|
+
* For example, given: referenceNode = 'b' (body) and path = ['firstChild', 'firstChild',
|
|
14549
|
+
* 'nextSibling'], the function returns: `bf2n`.
|
|
14550
|
+
*/
|
|
14551
|
+
function compressNodeLocation(referenceNode, path) {
|
|
14552
|
+
const result = [referenceNode];
|
|
14553
|
+
for (const segment of path) {
|
|
14554
|
+
const lastIdx = result.length - 1;
|
|
14555
|
+
if (lastIdx > 0 && result[lastIdx - 1] === segment) {
|
|
14556
|
+
// An empty string in a count slot represents 1 occurrence of an instruction.
|
|
14557
|
+
const value = (result[lastIdx] || 1);
|
|
14558
|
+
result[lastIdx] = value + 1;
|
|
14559
|
+
}
|
|
14560
|
+
else {
|
|
14561
|
+
// Adding a new segment to the path.
|
|
14562
|
+
// Using an empty string in a counter field to avoid encoding `1`s
|
|
14563
|
+
// into the path, since they are implicit (e.g. `f1n1` vs `fn`), so
|
|
14564
|
+
// it's enough to have a single char in this case.
|
|
14565
|
+
result.push(segment, '');
|
|
14566
|
+
}
|
|
14567
|
+
}
|
|
14568
|
+
return result.join('');
|
|
14569
|
+
}
|
|
14570
|
+
/**
|
|
14571
|
+
* Helper function that reverts the `compressNodeLocation` and transforms a given
|
|
14572
|
+
* string into an array where at 0th position there is a reference node info and
|
|
14573
|
+
* after that it contains information (in pairs) about a navigation step and the
|
|
14574
|
+
* number of repetitions.
|
|
14575
|
+
*
|
|
14576
|
+
* For example, the path like 'bf2n' will be transformed to:
|
|
14577
|
+
* ['b', 'firstChild', 2, 'nextSibling', 1].
|
|
14578
|
+
*
|
|
14579
|
+
* This information is later consumed by the code that navigates the DOM to find
|
|
14580
|
+
* a given node by its location.
|
|
14581
|
+
*/
|
|
14582
|
+
function decompressNodeLocation(path) {
|
|
14583
|
+
const matches = path.match(REF_EXTRACTOR_REGEXP);
|
|
14584
|
+
const [_, refNodeId, refNodeName, rest] = matches;
|
|
14585
|
+
// If a reference node is represented by an index, transform it to a number.
|
|
14586
|
+
const ref = refNodeId ? parseInt(refNodeId, 10) : refNodeName;
|
|
14587
|
+
const steps = [];
|
|
14588
|
+
// Match all segments in a path.
|
|
14589
|
+
for (const [_, step, count] of rest.matchAll(/(f|n)(\d*)/g)) {
|
|
14590
|
+
const repeat = parseInt(count, 10) || 1;
|
|
14591
|
+
steps.push(step, repeat);
|
|
14592
|
+
}
|
|
14593
|
+
return [ref, ...steps];
|
|
14594
|
+
}
|
|
14102
14595
|
|
|
14103
14596
|
/** Whether current TNode is a first node in an <ng-container>. */
|
|
14104
14597
|
function isFirstElementInNgContainer(tNode) {
|
|
14105
14598
|
return !tNode.prev && tNode.parent?.type === 8 /* TNodeType.ElementContainer */;
|
|
14106
14599
|
}
|
|
14600
|
+
/** Returns an instruction index (subtracting HEADER_OFFSET). */
|
|
14601
|
+
function getNoOffsetIndex(tNode) {
|
|
14602
|
+
return tNode.index - HEADER_OFFSET;
|
|
14603
|
+
}
|
|
14107
14604
|
/**
|
|
14108
14605
|
* Locate a node in DOM tree that corresponds to a given TNode.
|
|
14109
14606
|
*
|
|
@@ -14115,7 +14612,13 @@ function isFirstElementInNgContainer(tNode) {
|
|
|
14115
14612
|
*/
|
|
14116
14613
|
function locateNextRNode(hydrationInfo, tView, lView, tNode) {
|
|
14117
14614
|
let native = null;
|
|
14118
|
-
|
|
14615
|
+
const noOffsetIndex = getNoOffsetIndex(tNode);
|
|
14616
|
+
const nodes = hydrationInfo.data[NODES];
|
|
14617
|
+
if (nodes?.[noOffsetIndex]) {
|
|
14618
|
+
// We know the exact location of the node.
|
|
14619
|
+
native = locateRNodeByPath(nodes[noOffsetIndex], lView);
|
|
14620
|
+
}
|
|
14621
|
+
else if (tView.firstChild === tNode) {
|
|
14119
14622
|
// We create a first node in this view, so we use a reference
|
|
14120
14623
|
// to the first child in this DOM segment.
|
|
14121
14624
|
native = hydrationInfo.firstChild;
|
|
@@ -14128,7 +14631,7 @@ function locateNextRNode(hydrationInfo, tView, lView, tNode) {
|
|
|
14128
14631
|
assertDefined(previousTNode, 'Unexpected state: current TNode does not have a connection ' +
|
|
14129
14632
|
'to the previous node or a parent node.');
|
|
14130
14633
|
if (isFirstElementInNgContainer(tNode)) {
|
|
14131
|
-
const noOffsetParentIndex = tNode.parent
|
|
14634
|
+
const noOffsetParentIndex = getNoOffsetIndex(tNode.parent);
|
|
14132
14635
|
native = getSegmentHead(hydrationInfo, noOffsetParentIndex);
|
|
14133
14636
|
}
|
|
14134
14637
|
else {
|
|
@@ -14142,7 +14645,7 @@ function locateNextRNode(hydrationInfo, tView, lView, tNode) {
|
|
|
14142
14645
|
// represented in the DOM as `<div></div>...<!--container-->`.
|
|
14143
14646
|
// In this case, there are nodes *after* this element and we need to skip
|
|
14144
14647
|
// all of them to reach an element that we are looking for.
|
|
14145
|
-
const noOffsetPrevSiblingIndex = previousTNode
|
|
14648
|
+
const noOffsetPrevSiblingIndex = getNoOffsetIndex(previousTNode);
|
|
14146
14649
|
const segmentHead = getSegmentHead(hydrationInfo, noOffsetPrevSiblingIndex);
|
|
14147
14650
|
if (previousTNode.type === 2 /* TNodeType.Element */ && segmentHead) {
|
|
14148
14651
|
const numRootNodesToSkip = calcSerializedContainerSize(hydrationInfo, noOffsetPrevSiblingIndex);
|
|
@@ -14170,6 +14673,183 @@ function siblingAfter(skip, from) {
|
|
|
14170
14673
|
}
|
|
14171
14674
|
return currentNode;
|
|
14172
14675
|
}
|
|
14676
|
+
/**
|
|
14677
|
+
* Helper function to produce a string representation of the navigation steps
|
|
14678
|
+
* (in terms of `nextSibling` and `firstChild` navigations). Used in error
|
|
14679
|
+
* messages in dev mode.
|
|
14680
|
+
*/
|
|
14681
|
+
function stringifyNavigationInstructions(instructions) {
|
|
14682
|
+
const container = [];
|
|
14683
|
+
let i = 0;
|
|
14684
|
+
while (i < instructions.length) {
|
|
14685
|
+
const step = instructions[i++];
|
|
14686
|
+
const repeat = instructions[i++];
|
|
14687
|
+
for (let r = 0; r < repeat; r++) {
|
|
14688
|
+
container.push(step === NodeNavigationStep.FirstChild ? 'firstChild' : 'nextSibling');
|
|
14689
|
+
}
|
|
14690
|
+
}
|
|
14691
|
+
return container.join('.');
|
|
14692
|
+
}
|
|
14693
|
+
/**
|
|
14694
|
+
* Helper function that navigates from a starting point node (the `from` node)
|
|
14695
|
+
* using provided set of navigation instructions (within `path` argument).
|
|
14696
|
+
*/
|
|
14697
|
+
function navigateToNode(from, instructions) {
|
|
14698
|
+
let node = from;
|
|
14699
|
+
let i = 0;
|
|
14700
|
+
while (i < instructions.length) {
|
|
14701
|
+
const step = instructions[i++];
|
|
14702
|
+
const repeat = instructions[i++];
|
|
14703
|
+
for (let r = 0; r < repeat; r++) {
|
|
14704
|
+
if (ngDevMode && !node) {
|
|
14705
|
+
throw nodeNotFoundAtPathError(from, stringifyNavigationInstructions(instructions));
|
|
14706
|
+
}
|
|
14707
|
+
switch (step) {
|
|
14708
|
+
case NodeNavigationStep.FirstChild:
|
|
14709
|
+
node = node.firstChild;
|
|
14710
|
+
break;
|
|
14711
|
+
case NodeNavigationStep.NextSibling:
|
|
14712
|
+
node = node.nextSibling;
|
|
14713
|
+
break;
|
|
14714
|
+
}
|
|
14715
|
+
}
|
|
14716
|
+
}
|
|
14717
|
+
if (ngDevMode && !node) {
|
|
14718
|
+
throw nodeNotFoundAtPathError(from, stringifyNavigationInstructions(instructions));
|
|
14719
|
+
}
|
|
14720
|
+
return node;
|
|
14721
|
+
}
|
|
14722
|
+
/**
|
|
14723
|
+
* Locates an RNode given a set of navigation instructions (which also contains
|
|
14724
|
+
* a starting point node info).
|
|
14725
|
+
*/
|
|
14726
|
+
function locateRNodeByPath(path, lView) {
|
|
14727
|
+
const [referenceNode, ...navigationInstructions] = decompressNodeLocation(path);
|
|
14728
|
+
let ref;
|
|
14729
|
+
if (referenceNode === REFERENCE_NODE_HOST) {
|
|
14730
|
+
ref = lView[0];
|
|
14731
|
+
}
|
|
14732
|
+
else if (referenceNode === REFERENCE_NODE_BODY) {
|
|
14733
|
+
ref = ɵɵresolveBody(lView[0]);
|
|
14734
|
+
}
|
|
14735
|
+
else {
|
|
14736
|
+
const parentElementId = Number(referenceNode);
|
|
14737
|
+
ref = unwrapRNode(lView[parentElementId + HEADER_OFFSET]);
|
|
14738
|
+
}
|
|
14739
|
+
return navigateToNode(ref, navigationInstructions);
|
|
14740
|
+
}
|
|
14741
|
+
/**
|
|
14742
|
+
* Generate a list of DOM navigation operations to get from node `start` to node `finish`.
|
|
14743
|
+
*
|
|
14744
|
+
* Note: assumes that node `start` occurs before node `finish` in an in-order traversal of the DOM
|
|
14745
|
+
* tree. That is, we should be able to get from `start` to `finish` purely by using `.firstChild`
|
|
14746
|
+
* and `.nextSibling` operations.
|
|
14747
|
+
*/
|
|
14748
|
+
function navigateBetween(start, finish) {
|
|
14749
|
+
if (start === finish) {
|
|
14750
|
+
return [];
|
|
14751
|
+
}
|
|
14752
|
+
else if (start.parentElement == null || finish.parentElement == null) {
|
|
14753
|
+
return null;
|
|
14754
|
+
}
|
|
14755
|
+
else if (start.parentElement === finish.parentElement) {
|
|
14756
|
+
return navigateBetweenSiblings(start, finish);
|
|
14757
|
+
}
|
|
14758
|
+
else {
|
|
14759
|
+
// `finish` is a child of its parent, so the parent will always have a child.
|
|
14760
|
+
const parent = finish.parentElement;
|
|
14761
|
+
const parentPath = navigateBetween(start, parent);
|
|
14762
|
+
const childPath = navigateBetween(parent.firstChild, finish);
|
|
14763
|
+
if (!parentPath || !childPath)
|
|
14764
|
+
return null;
|
|
14765
|
+
return [
|
|
14766
|
+
// First navigate to `finish`'s parent
|
|
14767
|
+
...parentPath,
|
|
14768
|
+
// Then to its first child.
|
|
14769
|
+
NodeNavigationStep.FirstChild,
|
|
14770
|
+
// And finally from that node to `finish` (maybe a no-op if we're already there).
|
|
14771
|
+
...childPath,
|
|
14772
|
+
];
|
|
14773
|
+
}
|
|
14774
|
+
}
|
|
14775
|
+
/**
|
|
14776
|
+
* Calculates a path between 2 sibling nodes (generates a number of `NextSibling` navigations).
|
|
14777
|
+
*/
|
|
14778
|
+
function navigateBetweenSiblings(start, finish) {
|
|
14779
|
+
const nav = [];
|
|
14780
|
+
let node = null;
|
|
14781
|
+
for (node = start; node != null && node !== finish; node = node.nextSibling) {
|
|
14782
|
+
nav.push(NodeNavigationStep.NextSibling);
|
|
14783
|
+
}
|
|
14784
|
+
return node === null ? [] : nav;
|
|
14785
|
+
}
|
|
14786
|
+
/**
|
|
14787
|
+
* Calculates a path between 2 nodes in terms of `nextSibling` and `firstChild`
|
|
14788
|
+
* navigations:
|
|
14789
|
+
* - the `from` node is a known node, used as an starting point for the lookup
|
|
14790
|
+
* (the `fromNodeName` argument is a string representation of the node).
|
|
14791
|
+
* - the `to` node is a node that the runtime logic would be looking up,
|
|
14792
|
+
* using the path generated by this function.
|
|
14793
|
+
*/
|
|
14794
|
+
function calcPathBetween(from, to, fromNodeName) {
|
|
14795
|
+
const path = navigateBetween(from, to);
|
|
14796
|
+
return path === null ? null : compressNodeLocation(fromNodeName, path);
|
|
14797
|
+
}
|
|
14798
|
+
/**
|
|
14799
|
+
* Invoked at serialization time (on the server) when a set of navigation
|
|
14800
|
+
* instructions needs to be generated for a TNode.
|
|
14801
|
+
*/
|
|
14802
|
+
function calcPathForNode(tNode, lView) {
|
|
14803
|
+
const parentTNode = tNode.parent;
|
|
14804
|
+
let parentIndex;
|
|
14805
|
+
let parentRNode;
|
|
14806
|
+
let referenceNodeName;
|
|
14807
|
+
if (parentTNode === null) {
|
|
14808
|
+
// No parent TNode - use host element as a reference node.
|
|
14809
|
+
parentIndex = referenceNodeName = REFERENCE_NODE_HOST;
|
|
14810
|
+
parentRNode = lView[HOST];
|
|
14811
|
+
}
|
|
14812
|
+
else {
|
|
14813
|
+
// Use parent TNode as a reference node.
|
|
14814
|
+
parentIndex = parentTNode.index;
|
|
14815
|
+
parentRNode = unwrapRNode(lView[parentIndex]);
|
|
14816
|
+
referenceNodeName = renderStringify(parentIndex - HEADER_OFFSET);
|
|
14817
|
+
}
|
|
14818
|
+
let rNode = unwrapRNode(lView[tNode.index]);
|
|
14819
|
+
if (tNode.type & 12 /* TNodeType.AnyContainer */) {
|
|
14820
|
+
// For <ng-container> nodes, instead of serializing a reference
|
|
14821
|
+
// to the anchor comment node, serialize a location of the first
|
|
14822
|
+
// DOM element. Paired with the container size (serialized as a part
|
|
14823
|
+
// of `ngh.containers`), it should give enough information for runtime
|
|
14824
|
+
// to hydrate nodes in this container.
|
|
14825
|
+
const firstRNode = getFirstNativeNode(lView, tNode);
|
|
14826
|
+
// If container is not empty, use a reference to the first element,
|
|
14827
|
+
// otherwise, rNode would point to an anchor comment node.
|
|
14828
|
+
if (firstRNode) {
|
|
14829
|
+
rNode = firstRNode;
|
|
14830
|
+
}
|
|
14831
|
+
}
|
|
14832
|
+
let path = calcPathBetween(parentRNode, rNode, referenceNodeName);
|
|
14833
|
+
if (path === null && parentRNode !== rNode) {
|
|
14834
|
+
// Searching for a path between elements within a host node failed.
|
|
14835
|
+
// Trying to find a path to an element starting from the `document.body` instead.
|
|
14836
|
+
//
|
|
14837
|
+
// Important note: this type of reference is relatively unstable, since Angular
|
|
14838
|
+
// may not be able to control parts of the page that the runtime logic navigates
|
|
14839
|
+
// through. This is mostly needed to cover "portals" use-case (like menus, dialog boxes,
|
|
14840
|
+
// etc), where nodes are content-projected (including direct DOM manipulations) outside
|
|
14841
|
+
// of the host node. The better solution is to provide APIs to work with "portals",
|
|
14842
|
+
// at which point this code path would not be needed.
|
|
14843
|
+
const body = parentRNode.ownerDocument.body;
|
|
14844
|
+
path = calcPathBetween(body, rNode, REFERENCE_NODE_BODY);
|
|
14845
|
+
if (path === null) {
|
|
14846
|
+
// If the path is still empty, it's likely that this node is detached and
|
|
14847
|
+
// won't be found during hydration.
|
|
14848
|
+
throw nodeNotFoundError(lView, tNode);
|
|
14849
|
+
}
|
|
14850
|
+
}
|
|
14851
|
+
return path;
|
|
14852
|
+
}
|
|
14173
14853
|
|
|
14174
14854
|
function templateFirstCreatePass(index, tView, lView, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex) {
|
|
14175
14855
|
ngDevMode && assertFirstCreatePass(tView);
|
|
@@ -14246,7 +14926,7 @@ function createContainerAnchorImpl(tView, lView, tNode, index) {
|
|
|
14246
14926
|
*/
|
|
14247
14927
|
function locateOrCreateContainerAnchorImpl(tView, lView, tNode, index) {
|
|
14248
14928
|
const hydrationInfo = lView[HYDRATION];
|
|
14249
|
-
const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock$1();
|
|
14929
|
+
const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock$1() || isDisconnectedNode(hydrationInfo, index);
|
|
14250
14930
|
lastNodeWasCreated(isNodeCreationMode);
|
|
14251
14931
|
// Regular creation mode.
|
|
14252
14932
|
if (isNodeCreationMode) {
|
|
@@ -14255,11 +14935,8 @@ function locateOrCreateContainerAnchorImpl(tView, lView, tNode, index) {
|
|
|
14255
14935
|
// Hydration mode, looking up existing elements in DOM.
|
|
14256
14936
|
const currentRNode = locateNextRNode(hydrationInfo, tView, lView, tNode);
|
|
14257
14937
|
ngDevMode && validateNodeExists(currentRNode);
|
|
14938
|
+
setSegmentHead(hydrationInfo, index, currentRNode);
|
|
14258
14939
|
const viewContainerSize = calcSerializedContainerSize(hydrationInfo, index);
|
|
14259
|
-
// If this container is non-empty, store the first node as a segment head,
|
|
14260
|
-
// otherwise, this node is an anchor and segment head doesn't exist (thus `null`).
|
|
14261
|
-
const segmentHead = viewContainerSize > 0 ? currentRNode : null;
|
|
14262
|
-
setSegmentHead(hydrationInfo, index, segmentHead);
|
|
14263
14940
|
const comment = siblingAfter(viewContainerSize, currentRNode);
|
|
14264
14941
|
if (ngDevMode) {
|
|
14265
14942
|
validateMatchingNode(comment, Node.COMMENT_NODE, null, lView, tNode);
|
|
@@ -14515,7 +15192,7 @@ let _locateOrCreateElementNode = (tView, lView, tNode, renderer, name, index) =>
|
|
|
14515
15192
|
*/
|
|
14516
15193
|
function locateOrCreateElementNodeImpl(tView, lView, tNode, renderer, name, index) {
|
|
14517
15194
|
const hydrationInfo = lView[HYDRATION];
|
|
14518
|
-
const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock$1();
|
|
15195
|
+
const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock$1() || isDisconnectedNode(hydrationInfo, index);
|
|
14519
15196
|
lastNodeWasCreated(isNodeCreationMode);
|
|
14520
15197
|
// Regular creation mode.
|
|
14521
15198
|
if (isNodeCreationMode) {
|
|
@@ -14539,10 +15216,17 @@ function locateOrCreateElementNodeImpl(tView, lView, tNode, renderer, name, inde
|
|
|
14539
15216
|
// Checks if the skip hydration attribute is present during hydration so we know to
|
|
14540
15217
|
// skip attempting to hydrate this block.
|
|
14541
15218
|
if (hydrationInfo && hasNgSkipHydrationAttr(tNode)) {
|
|
14542
|
-
|
|
14543
|
-
|
|
14544
|
-
|
|
14545
|
-
|
|
15219
|
+
if (isComponentHost(tNode)) {
|
|
15220
|
+
enterSkipHydrationBlock(tNode);
|
|
15221
|
+
// Since this isn't hydratable, we need to empty the node
|
|
15222
|
+
// so there's no duplicate content after render
|
|
15223
|
+
clearElementContents(renderer, native);
|
|
15224
|
+
}
|
|
15225
|
+
else if (ngDevMode) {
|
|
15226
|
+
// If this is not a component host, throw an error.
|
|
15227
|
+
// Hydration can be skipped on per-component basis only.
|
|
15228
|
+
throw invalidSkipHydrationHost(native);
|
|
15229
|
+
}
|
|
14546
15230
|
}
|
|
14547
15231
|
return native;
|
|
14548
15232
|
}
|
|
@@ -14676,10 +15360,7 @@ function locateOrCreateElementContainerNode(tView, lView, tNode, index) {
|
|
|
14676
15360
|
ngDevMode &&
|
|
14677
15361
|
assertNumber(ngContainerSize, 'Unexpected state: hydrating an <ng-container>, ' +
|
|
14678
15362
|
'but no hydration info is available.');
|
|
14679
|
-
|
|
14680
|
-
// otherwise, this node is an anchor and segment head doesn't exist (thus `null`).
|
|
14681
|
-
const segmentHead = ngContainerSize > 0 ? currentRNode : null;
|
|
14682
|
-
setSegmentHead(hydrationInfo, index, segmentHead);
|
|
15363
|
+
setSegmentHead(hydrationInfo, index, currentRNode);
|
|
14683
15364
|
comment = siblingAfter(ngContainerSize, currentRNode);
|
|
14684
15365
|
if (ngDevMode) {
|
|
14685
15366
|
validateMatchingNode(comment, Node.COMMENT_NODE, null, lView, tNode);
|
|
@@ -15061,7 +15742,10 @@ function ɵɵprojection(nodeIndex, selectorIndex = 0, attrs) {
|
|
|
15061
15742
|
tProjectionNode.projection = selectorIndex;
|
|
15062
15743
|
// `<ng-content>` has no content
|
|
15063
15744
|
setCurrentTNodeAsNotParent();
|
|
15064
|
-
|
|
15745
|
+
const hydrationInfo = lView[HYDRATION];
|
|
15746
|
+
const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock$1();
|
|
15747
|
+
if (isNodeCreationMode &&
|
|
15748
|
+
(tProjectionNode.flags & 32 /* TNodeFlags.isDetached */) !== 32 /* TNodeFlags.isDetached */) {
|
|
15065
15749
|
// re-distribution of projectable nodes is stored on a component's view level
|
|
15066
15750
|
applyProjection(tView, lView, tProjectionNode);
|
|
15067
15751
|
}
|
|
@@ -17024,7 +17708,7 @@ function ɵɵtext(index, value = '') {
|
|
|
17024
17708
|
const tNode = tView.firstCreatePass ?
|
|
17025
17709
|
getOrCreateTNode(tView, adjustedIndex, 1 /* TNodeType.Text */, value, null) :
|
|
17026
17710
|
tView.data[adjustedIndex];
|
|
17027
|
-
const textNative = _locateOrCreateTextNode(tView, lView, tNode, value);
|
|
17711
|
+
const textNative = _locateOrCreateTextNode(tView, lView, tNode, value, index);
|
|
17028
17712
|
lView[adjustedIndex] = textNative;
|
|
17029
17713
|
if (wasLastNodeCreated()) {
|
|
17030
17714
|
appendChild(tView, lView, textNative, tNode);
|
|
@@ -17032,7 +17716,7 @@ function ɵɵtext(index, value = '') {
|
|
|
17032
17716
|
// Text nodes are self closing.
|
|
17033
17717
|
setCurrentTNode(tNode, false);
|
|
17034
17718
|
}
|
|
17035
|
-
let _locateOrCreateTextNode = (tView, lView, tNode, value) => {
|
|
17719
|
+
let _locateOrCreateTextNode = (tView, lView, tNode, value, index) => {
|
|
17036
17720
|
lastNodeWasCreated(true);
|
|
17037
17721
|
return createTextNode(lView[RENDERER], value);
|
|
17038
17722
|
};
|
|
@@ -17040,9 +17724,9 @@ let _locateOrCreateTextNode = (tView, lView, tNode, value) => {
|
|
|
17040
17724
|
* Enables hydration code path (to lookup existing elements in DOM)
|
|
17041
17725
|
* in addition to the regular creation mode of text nodes.
|
|
17042
17726
|
*/
|
|
17043
|
-
function locateOrCreateTextNodeImpl(tView, lView, tNode, value) {
|
|
17727
|
+
function locateOrCreateTextNodeImpl(tView, lView, tNode, value, index) {
|
|
17044
17728
|
const hydrationInfo = lView[HYDRATION];
|
|
17045
|
-
const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock$1();
|
|
17729
|
+
const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock$1() || isDisconnectedNode(hydrationInfo, index);
|
|
17046
17730
|
lastNodeWasCreated(isNodeCreationMode);
|
|
17047
17731
|
// Regular creation mode.
|
|
17048
17732
|
if (isNodeCreationMode) {
|
|
@@ -22150,6 +22834,54 @@ function removeDehydratedView(dehydratedView, renderer) {
|
|
|
22150
22834
|
}
|
|
22151
22835
|
}
|
|
22152
22836
|
}
|
|
22837
|
+
/**
|
|
22838
|
+
* Walks over all views within this LContainer invokes dehydrated views
|
|
22839
|
+
* cleanup function for each one.
|
|
22840
|
+
*/
|
|
22841
|
+
function cleanupLContainer(lContainer) {
|
|
22842
|
+
removeDehydratedViews(lContainer);
|
|
22843
|
+
for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
|
|
22844
|
+
cleanupLView(lContainer[i]);
|
|
22845
|
+
}
|
|
22846
|
+
}
|
|
22847
|
+
/**
|
|
22848
|
+
* Walks over `LContainer`s and components registered within
|
|
22849
|
+
* this LView and invokes dehydrated views cleanup function for each one.
|
|
22850
|
+
*/
|
|
22851
|
+
function cleanupLView(lView) {
|
|
22852
|
+
const tView = lView[TVIEW];
|
|
22853
|
+
for (let i = HEADER_OFFSET; i < tView.bindingStartIndex; i++) {
|
|
22854
|
+
if (isLContainer(lView[i])) {
|
|
22855
|
+
const lContainer = lView[i];
|
|
22856
|
+
cleanupLContainer(lContainer);
|
|
22857
|
+
}
|
|
22858
|
+
else if (Array.isArray(lView[i])) {
|
|
22859
|
+
// This is a component, enter the `cleanupLView` recursively.
|
|
22860
|
+
cleanupLView(lView[i]);
|
|
22861
|
+
}
|
|
22862
|
+
}
|
|
22863
|
+
}
|
|
22864
|
+
/**
|
|
22865
|
+
* Walks over all views registered within the ApplicationRef and removes
|
|
22866
|
+
* all dehydrated views from all `LContainer`s along the way.
|
|
22867
|
+
*/
|
|
22868
|
+
function cleanupDehydratedViews(appRef) {
|
|
22869
|
+
// Wait once an app becomes stable and cleanup all views that
|
|
22870
|
+
// were not claimed during the application bootstrap process.
|
|
22871
|
+
// The timing is similar to when we kick off serialization on the server.
|
|
22872
|
+
return appRef.isStable.pipe(first((isStable) => isStable)).toPromise().then(() => {
|
|
22873
|
+
const viewRefs = appRef._views;
|
|
22874
|
+
for (const viewRef of viewRefs) {
|
|
22875
|
+
const lView = getComponentLViewForHydration(viewRef);
|
|
22876
|
+
// An `lView` might be `null` if a `ViewRef` represents
|
|
22877
|
+
// an embedded view (not a component view).
|
|
22878
|
+
if (lView !== null && lView[HOST] !== null) {
|
|
22879
|
+
cleanupLView(lView);
|
|
22880
|
+
ngDevMode && ngDevMode.dehydratedViewsCleanupRuns++;
|
|
22881
|
+
}
|
|
22882
|
+
}
|
|
22883
|
+
});
|
|
22884
|
+
}
|
|
22153
22885
|
|
|
22154
22886
|
/**
|
|
22155
22887
|
* Given a current DOM node and a serialized information about the views
|
|
@@ -22159,20 +22891,24 @@ function removeDehydratedView(dehydratedView, renderer) {
|
|
|
22159
22891
|
function locateDehydratedViewsInContainer(currentRNode, serializedViews) {
|
|
22160
22892
|
const dehydratedViews = [];
|
|
22161
22893
|
for (const serializedView of serializedViews) {
|
|
22162
|
-
|
|
22163
|
-
|
|
22164
|
-
|
|
22165
|
-
|
|
22166
|
-
|
|
22167
|
-
|
|
22168
|
-
|
|
22169
|
-
|
|
22170
|
-
|
|
22171
|
-
|
|
22172
|
-
|
|
22173
|
-
|
|
22894
|
+
// Repeats a view multiple times as needed, based on the serialized information
|
|
22895
|
+
// (for example, for *ngFor-produced views).
|
|
22896
|
+
for (let i = 0; i < (serializedView[MULTIPLIER] ?? 1); i++) {
|
|
22897
|
+
const view = {
|
|
22898
|
+
data: serializedView,
|
|
22899
|
+
firstChild: null,
|
|
22900
|
+
};
|
|
22901
|
+
if (serializedView[NUM_ROOT_NODES] > 0) {
|
|
22902
|
+
// Keep reference to the first node in this view,
|
|
22903
|
+
// so it can be accessed while invoking template instructions.
|
|
22904
|
+
view.firstChild = currentRNode;
|
|
22905
|
+
// Move over to the next node after this view, which can
|
|
22906
|
+
// either be a first node of the next view or an anchor comment
|
|
22907
|
+
// node after the last view in a container.
|
|
22908
|
+
currentRNode = siblingAfter(serializedView[NUM_ROOT_NODES], currentRNode);
|
|
22909
|
+
}
|
|
22910
|
+
dehydratedViews.push(view);
|
|
22174
22911
|
}
|
|
22175
|
-
dehydratedViews.push(view);
|
|
22176
22912
|
}
|
|
22177
22913
|
return [currentRNode, dehydratedViews];
|
|
22178
22914
|
}
|
|
@@ -22553,21 +23289,22 @@ function locateOrCreateAnchorNode(lContainer, hostLView, hostTNode, slotValue) {
|
|
|
22553
23289
|
if (lContainer[NATIVE] && lContainer[DEHYDRATED_VIEWS])
|
|
22554
23290
|
return;
|
|
22555
23291
|
const hydrationInfo = hostLView[HYDRATION];
|
|
22556
|
-
const
|
|
23292
|
+
const noOffsetIndex = hostTNode.index - HEADER_OFFSET;
|
|
23293
|
+
const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock(hostTNode) ||
|
|
23294
|
+
isDisconnectedNode(hydrationInfo, noOffsetIndex);
|
|
22557
23295
|
// Regular creation mode.
|
|
22558
23296
|
if (isNodeCreationMode) {
|
|
22559
23297
|
return createAnchorNode(lContainer, hostLView, hostTNode, slotValue);
|
|
22560
23298
|
}
|
|
22561
23299
|
// Hydration mode, looking up an anchor node and dehydrated views in DOM.
|
|
22562
|
-
const
|
|
22563
|
-
const
|
|
22564
|
-
const serializedViews = hydrationInfo.data[CONTAINERS]?.[index];
|
|
23300
|
+
const currentRNode = getSegmentHead(hydrationInfo, noOffsetIndex);
|
|
23301
|
+
const serializedViews = hydrationInfo.data[CONTAINERS]?.[noOffsetIndex];
|
|
22565
23302
|
ngDevMode &&
|
|
22566
23303
|
assertDefined(serializedViews, 'Unexpected state: no hydration info available for a given TNode, ' +
|
|
22567
23304
|
'which represents a view container.');
|
|
22568
23305
|
const [commentNode, dehydratedViews] = locateDehydratedViewsInContainer(currentRNode, serializedViews);
|
|
22569
23306
|
if (ngDevMode) {
|
|
22570
|
-
validateMatchingNode(commentNode, Node.COMMENT_NODE, null, hostLView, hostTNode);
|
|
23307
|
+
validateMatchingNode(commentNode, Node.COMMENT_NODE, null, hostLView, hostTNode, true);
|
|
22571
23308
|
// Do not throw in case this node is already claimed (thus `false` as a second
|
|
22572
23309
|
// argument). If this container is created based on an `<ng-template>`, the comment
|
|
22573
23310
|
// node would be already claimed from the `template` instruction. If an element acts
|
|
@@ -24276,12 +25013,17 @@ const Pipe = makeDecorator('Pipe', (p) => ({ pure: true, ...p }), undefined, und
|
|
|
24276
25013
|
* @Annotation
|
|
24277
25014
|
* @publicApi
|
|
24278
25015
|
*/
|
|
24279
|
-
const Input = makePropDecorator('Input', (
|
|
25016
|
+
const Input = makePropDecorator('Input', (arg) => {
|
|
25017
|
+
if (!arg) {
|
|
25018
|
+
return {};
|
|
25019
|
+
}
|
|
25020
|
+
return typeof arg === 'string' ? { alias: arg } : arg;
|
|
25021
|
+
});
|
|
24280
25022
|
/**
|
|
24281
25023
|
* @Annotation
|
|
24282
25024
|
* @publicApi
|
|
24283
25025
|
*/
|
|
24284
|
-
const Output = makePropDecorator('Output', (
|
|
25026
|
+
const Output = makePropDecorator('Output', (alias) => ({ alias }));
|
|
24285
25027
|
/**
|
|
24286
25028
|
* @Annotation
|
|
24287
25029
|
* @publicApi
|
|
@@ -26604,6 +27346,8 @@ function enableProdMode() {
|
|
|
26604
27346
|
* The scope of this destruction depends on where `DestroyRef` is injected. If `DestroyRef`
|
|
26605
27347
|
* is injected in a component or directive, the callbacks run when that component or
|
|
26606
27348
|
* directive is destroyed. Otherwise the callbacks run when a corresponding injector is destroyed.
|
|
27349
|
+
*
|
|
27350
|
+
* @publicApi
|
|
26607
27351
|
*/
|
|
26608
27352
|
class DestroyRef {
|
|
26609
27353
|
}
|
|
@@ -26624,6 +27368,7 @@ class NodeInjectorDestroyRef extends DestroyRef {
|
|
|
26624
27368
|
}
|
|
26625
27369
|
onDestroy(callback) {
|
|
26626
27370
|
storeLViewOnDestroy(this._lView, callback);
|
|
27371
|
+
return () => removeLViewOnDestroy(this._lView, callback);
|
|
26627
27372
|
}
|
|
26628
27373
|
}
|
|
26629
27374
|
function injectDestroyRef() {
|
|
@@ -28549,6 +29294,7 @@ function annotateForHydration(appRef, doc) {
|
|
|
28549
29294
|
*/
|
|
28550
29295
|
function serializeLContainer(lContainer, context) {
|
|
28551
29296
|
const views = [];
|
|
29297
|
+
let lastViewAsString = '';
|
|
28552
29298
|
for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
|
|
28553
29299
|
let childLView = lContainer[i];
|
|
28554
29300
|
// If this is a root view, get an LView for the underlying component,
|
|
@@ -28574,10 +29320,42 @@ function serializeLContainer(lContainer, context) {
|
|
|
28574
29320
|
[NUM_ROOT_NODES]: numRootNodes,
|
|
28575
29321
|
...serializeLView(lContainer[i], context),
|
|
28576
29322
|
};
|
|
28577
|
-
|
|
29323
|
+
// Check if the previous view has the same shape (for example, it was
|
|
29324
|
+
// produced by the *ngFor), in which case bump the counter on the previous
|
|
29325
|
+
// view instead of including the same information again.
|
|
29326
|
+
const currentViewAsString = JSON.stringify(view);
|
|
29327
|
+
if (views.length > 0 && currentViewAsString === lastViewAsString) {
|
|
29328
|
+
const previousView = views[views.length - 1];
|
|
29329
|
+
previousView[MULTIPLIER] ?? (previousView[MULTIPLIER] = 1);
|
|
29330
|
+
previousView[MULTIPLIER]++;
|
|
29331
|
+
}
|
|
29332
|
+
else {
|
|
29333
|
+
// Record this view as most recently added.
|
|
29334
|
+
lastViewAsString = currentViewAsString;
|
|
29335
|
+
views.push(view);
|
|
29336
|
+
}
|
|
28578
29337
|
}
|
|
28579
29338
|
return views;
|
|
28580
29339
|
}
|
|
29340
|
+
/**
|
|
29341
|
+
* Helper function to produce a node path (which navigation steps runtime logic
|
|
29342
|
+
* needs to take to locate a node) and stores it in the `NODES` section of the
|
|
29343
|
+
* current serialized view.
|
|
29344
|
+
*/
|
|
29345
|
+
function appendSerializedNodePath(ngh, tNode, lView) {
|
|
29346
|
+
const noOffsetIndex = tNode.index - HEADER_OFFSET;
|
|
29347
|
+
ngh[NODES] ?? (ngh[NODES] = {});
|
|
29348
|
+
ngh[NODES][noOffsetIndex] = calcPathForNode(tNode, lView);
|
|
29349
|
+
}
|
|
29350
|
+
/**
|
|
29351
|
+
* There is no special TNode type for an i18n block, so we verify
|
|
29352
|
+
* whether the structure that we store at the `TView.data[idx]` position
|
|
29353
|
+
* has the `TI18n` shape.
|
|
29354
|
+
*/
|
|
29355
|
+
function isTI18nNode(obj) {
|
|
29356
|
+
const tI18n = obj;
|
|
29357
|
+
return tI18n.hasOwnProperty('create') && tI18n.hasOwnProperty('update');
|
|
29358
|
+
}
|
|
28581
29359
|
/**
|
|
28582
29360
|
* Serializes the lView data into a SerializedView object that will later be added
|
|
28583
29361
|
* to the TransferState storage and referenced using the `ngh` attribute on a host
|
|
@@ -28601,6 +29379,51 @@ function serializeLView(lView, context) {
|
|
|
28601
29379
|
if (!tNode) {
|
|
28602
29380
|
continue;
|
|
28603
29381
|
}
|
|
29382
|
+
// Check if a native node that represents a given TNode is disconnected from the DOM tree.
|
|
29383
|
+
// Such nodes must be excluded from the hydration (since the hydration won't be able to
|
|
29384
|
+
// find them), so the TNode ids are collected and used at runtime to skip the hydration.
|
|
29385
|
+
//
|
|
29386
|
+
// This situation may happen during the content projection, when some nodes don't make it
|
|
29387
|
+
// into one of the content projection slots (for example, when there is no default
|
|
29388
|
+
// <ng-content /> slot in projector component's template).
|
|
29389
|
+
//
|
|
29390
|
+
// Note: we leverage the fact that we have this information available in the DOM emulation
|
|
29391
|
+
// layer (in Domino) for now. Longer-term solution should not rely on the DOM emulation and
|
|
29392
|
+
// only use internal data structures and state to compute this information.
|
|
29393
|
+
if (!(tNode.type & 16 /* TNodeType.Projection */) && !!lView[i] &&
|
|
29394
|
+
!unwrapRNode(lView[i]).isConnected) {
|
|
29395
|
+
ngh[DISCONNECTED_NODES] ?? (ngh[DISCONNECTED_NODES] = []);
|
|
29396
|
+
ngh[DISCONNECTED_NODES].push(noOffsetIndex);
|
|
29397
|
+
continue;
|
|
29398
|
+
}
|
|
29399
|
+
if (Array.isArray(tNode.projection)) {
|
|
29400
|
+
for (const projectionHeadTNode of tNode.projection) {
|
|
29401
|
+
// We may have `null`s in slots with no projected content.
|
|
29402
|
+
if (!projectionHeadTNode)
|
|
29403
|
+
continue;
|
|
29404
|
+
if (!Array.isArray(projectionHeadTNode)) {
|
|
29405
|
+
// If we process re-projected content (i.e. `<ng-content>`
|
|
29406
|
+
// appears at projection location), skip annotations for this content
|
|
29407
|
+
// since all DOM nodes in this projection were handled while processing
|
|
29408
|
+
// a parent lView, which contains those nodes.
|
|
29409
|
+
if (!isProjectionTNode(projectionHeadTNode) &&
|
|
29410
|
+
!isInSkipHydrationBlock(projectionHeadTNode)) {
|
|
29411
|
+
appendSerializedNodePath(ngh, projectionHeadTNode, lView);
|
|
29412
|
+
}
|
|
29413
|
+
}
|
|
29414
|
+
else {
|
|
29415
|
+
// If a value is an array, it means that we are processing a projection
|
|
29416
|
+
// where projectable nodes were passed in as DOM nodes (for example, when
|
|
29417
|
+
// calling `ViewContainerRef.createComponent(CmpA, {projectableNodes: [...]})`).
|
|
29418
|
+
//
|
|
29419
|
+
// In this scenario, nodes can come from anywhere (either created manually,
|
|
29420
|
+
// accessed via `document.querySelector`, etc) and may be in any state
|
|
29421
|
+
// (attached or detached from the DOM tree). As a result, we can not reliably
|
|
29422
|
+
// restore the state for such cases during hydration.
|
|
29423
|
+
throw unsupportedProjectionOfDomNodes(unwrapRNode(lView[i]));
|
|
29424
|
+
}
|
|
29425
|
+
}
|
|
29426
|
+
}
|
|
28604
29427
|
if (isLContainer(lView[i])) {
|
|
28605
29428
|
// Serialize information about a template.
|
|
28606
29429
|
const embeddedTView = tNode.tView;
|
|
@@ -28630,6 +29453,18 @@ function serializeLView(lView, context) {
|
|
|
28630
29453
|
annotateHostElementForHydration(targetNode, lView[i], context);
|
|
28631
29454
|
}
|
|
28632
29455
|
}
|
|
29456
|
+
else if (isTI18nNode(tNode)) {
|
|
29457
|
+
// Hydration for i18n nodes is not *yet* supported.
|
|
29458
|
+
// Produce an error message which would also describe possible
|
|
29459
|
+
// solutions (switching back to the "destructive" hydration or
|
|
29460
|
+
// excluding a component from hydration via `ngSkipHydration`).
|
|
29461
|
+
//
|
|
29462
|
+
// TODO(akushnir): we should find a better way to get a hold of the node that has the `i18n`
|
|
29463
|
+
// attribute on it. For now, we either refer to the host element of the component or to the
|
|
29464
|
+
// previous element in the LView.
|
|
29465
|
+
const targetNode = (i === HEADER_OFFSET) ? lView[HOST] : unwrapRNode(lView[i - 1]);
|
|
29466
|
+
throw notYetSupportedI18nBlockError(targetNode);
|
|
29467
|
+
}
|
|
28633
29468
|
else {
|
|
28634
29469
|
// <ng-container> case
|
|
28635
29470
|
if (tNode.type & 8 /* TNodeType.ElementContainer */) {
|
|
@@ -28639,6 +29474,20 @@ function serializeLView(lView, context) {
|
|
|
28639
29474
|
ngh[ELEMENT_CONTAINERS] ?? (ngh[ELEMENT_CONTAINERS] = {});
|
|
28640
29475
|
ngh[ELEMENT_CONTAINERS][noOffsetIndex] = calcNumRootNodes(tView, lView, tNode.child);
|
|
28641
29476
|
}
|
|
29477
|
+
else if (tNode.type & 16 /* TNodeType.Projection */) {
|
|
29478
|
+
// Current TNode represents an `<ng-content>` slot, thus it has no
|
|
29479
|
+
// DOM elements associated with it, so the **next sibling** node would
|
|
29480
|
+
// not be able to find an anchor. In this case, use full path instead.
|
|
29481
|
+
let nextTNode = tNode.next;
|
|
29482
|
+
// Skip over all `<ng-content>` slots in a row.
|
|
29483
|
+
while (nextTNode !== null && (nextTNode.type & 16 /* TNodeType.Projection */)) {
|
|
29484
|
+
nextTNode = nextTNode.next;
|
|
29485
|
+
}
|
|
29486
|
+
if (nextTNode && !isInSkipHydrationBlock(nextTNode)) {
|
|
29487
|
+
// Handle a tNode after the `<ng-content>` slot.
|
|
29488
|
+
appendSerializedNodePath(ngh, nextTNode, lView);
|
|
29489
|
+
}
|
|
29490
|
+
}
|
|
28642
29491
|
else {
|
|
28643
29492
|
// Handle cases where text nodes can be lost after DOM serialization:
|
|
28644
29493
|
// 1. When there is an *empty text node* in DOM: in this case, this
|
|
@@ -28675,6 +29524,13 @@ function serializeLView(lView, context) {
|
|
|
28675
29524
|
context.corruptedTextNodes.set(rNode, "ngtns" /* TextNodeMarker.Separator */);
|
|
28676
29525
|
}
|
|
28677
29526
|
}
|
|
29527
|
+
if (tNode.projectionNext && tNode.projectionNext !== tNode.next &&
|
|
29528
|
+
!isInSkipHydrationBlock(tNode.projectionNext)) {
|
|
29529
|
+
// Check if projection next is not the same as next, in which case
|
|
29530
|
+
// the node would not be found at creation time at runtime and we
|
|
29531
|
+
// need to provide a location for that node.
|
|
29532
|
+
appendSerializedNodePath(ngh, tNode.projectionNext, lView);
|
|
29533
|
+
}
|
|
28678
29534
|
}
|
|
28679
29535
|
}
|
|
28680
29536
|
}
|
|
@@ -28813,108 +29669,21 @@ function provideHydrationSupport() {
|
|
|
28813
29669
|
// environment. On a server, an application is rendered
|
|
28814
29670
|
// from scratch, so the host content needs to be empty.
|
|
28815
29671
|
useFactory: () => isBrowser(),
|
|
29672
|
+
},
|
|
29673
|
+
{
|
|
29674
|
+
provide: APP_BOOTSTRAP_LISTENER,
|
|
29675
|
+
useFactory: () => {
|
|
29676
|
+
if (isBrowser()) {
|
|
29677
|
+
const appRef = inject(ApplicationRef);
|
|
29678
|
+
return () => cleanupDehydratedViews(appRef);
|
|
29679
|
+
}
|
|
29680
|
+
return () => { }; // noop
|
|
29681
|
+
},
|
|
29682
|
+
multi: true,
|
|
28816
29683
|
}
|
|
28817
29684
|
]);
|
|
28818
29685
|
}
|
|
28819
29686
|
|
|
28820
|
-
/** Coerces a value (typically a string) to a boolean. */
|
|
28821
|
-
function coerceToBoolean(value) {
|
|
28822
|
-
return typeof value === 'boolean' ? value : (value != null && value !== 'false');
|
|
28823
|
-
}
|
|
28824
|
-
|
|
28825
|
-
/**
|
|
28826
|
-
* Compiles a partial directive declaration object into a full directive definition object.
|
|
28827
|
-
*
|
|
28828
|
-
* @codeGenApi
|
|
28829
|
-
*/
|
|
28830
|
-
function ɵɵngDeclareDirective(decl) {
|
|
28831
|
-
const compiler = getCompilerFacade({ usage: 1 /* JitCompilerUsage.PartialDeclaration */, kind: 'directive', type: decl.type });
|
|
28832
|
-
return compiler.compileDirectiveDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵfac.js`, decl);
|
|
28833
|
-
}
|
|
28834
|
-
/**
|
|
28835
|
-
* Evaluates the class metadata declaration.
|
|
28836
|
-
*
|
|
28837
|
-
* @codeGenApi
|
|
28838
|
-
*/
|
|
28839
|
-
function ɵɵngDeclareClassMetadata(decl) {
|
|
28840
|
-
setClassMetadata(decl.type, decl.decorators, decl.ctorParameters ?? null, decl.propDecorators ?? null);
|
|
28841
|
-
}
|
|
28842
|
-
/**
|
|
28843
|
-
* Compiles a partial component declaration object into a full component definition object.
|
|
28844
|
-
*
|
|
28845
|
-
* @codeGenApi
|
|
28846
|
-
*/
|
|
28847
|
-
function ɵɵngDeclareComponent(decl) {
|
|
28848
|
-
const compiler = getCompilerFacade({ usage: 1 /* JitCompilerUsage.PartialDeclaration */, kind: 'component', type: decl.type });
|
|
28849
|
-
return compiler.compileComponentDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵcmp.js`, decl);
|
|
28850
|
-
}
|
|
28851
|
-
/**
|
|
28852
|
-
* Compiles a partial pipe declaration object into a full pipe definition object.
|
|
28853
|
-
*
|
|
28854
|
-
* @codeGenApi
|
|
28855
|
-
*/
|
|
28856
|
-
function ɵɵngDeclareFactory(decl) {
|
|
28857
|
-
const compiler = getCompilerFacade({
|
|
28858
|
-
usage: 1 /* JitCompilerUsage.PartialDeclaration */,
|
|
28859
|
-
kind: getFactoryKind(decl.target),
|
|
28860
|
-
type: decl.type
|
|
28861
|
-
});
|
|
28862
|
-
return compiler.compileFactoryDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵfac.js`, decl);
|
|
28863
|
-
}
|
|
28864
|
-
function getFactoryKind(target) {
|
|
28865
|
-
switch (target) {
|
|
28866
|
-
case FactoryTarget.Directive:
|
|
28867
|
-
return 'directive';
|
|
28868
|
-
case FactoryTarget.Component:
|
|
28869
|
-
return 'component';
|
|
28870
|
-
case FactoryTarget.Injectable:
|
|
28871
|
-
return 'injectable';
|
|
28872
|
-
case FactoryTarget.Pipe:
|
|
28873
|
-
return 'pipe';
|
|
28874
|
-
case FactoryTarget.NgModule:
|
|
28875
|
-
return 'NgModule';
|
|
28876
|
-
}
|
|
28877
|
-
}
|
|
28878
|
-
/**
|
|
28879
|
-
* Compiles a partial injectable declaration object into a full injectable definition object.
|
|
28880
|
-
*
|
|
28881
|
-
* @codeGenApi
|
|
28882
|
-
*/
|
|
28883
|
-
function ɵɵngDeclareInjectable(decl) {
|
|
28884
|
-
const compiler = getCompilerFacade({ usage: 1 /* JitCompilerUsage.PartialDeclaration */, kind: 'injectable', type: decl.type });
|
|
28885
|
-
return compiler.compileInjectableDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵprov.js`, decl);
|
|
28886
|
-
}
|
|
28887
|
-
/**
|
|
28888
|
-
* Compiles a partial injector declaration object into a full injector definition object.
|
|
28889
|
-
*
|
|
28890
|
-
* @codeGenApi
|
|
28891
|
-
*/
|
|
28892
|
-
function ɵɵngDeclareInjector(decl) {
|
|
28893
|
-
const compiler = getCompilerFacade({ usage: 1 /* JitCompilerUsage.PartialDeclaration */, kind: 'NgModule', type: decl.type });
|
|
28894
|
-
return compiler.compileInjectorDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵinj.js`, decl);
|
|
28895
|
-
}
|
|
28896
|
-
/**
|
|
28897
|
-
* Compiles a partial NgModule declaration object into a full NgModule definition object.
|
|
28898
|
-
*
|
|
28899
|
-
* @codeGenApi
|
|
28900
|
-
*/
|
|
28901
|
-
function ɵɵngDeclareNgModule(decl) {
|
|
28902
|
-
const compiler = getCompilerFacade({ usage: 1 /* JitCompilerUsage.PartialDeclaration */, kind: 'NgModule', type: decl.type });
|
|
28903
|
-
return compiler.compileNgModuleDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵmod.js`, decl);
|
|
28904
|
-
}
|
|
28905
|
-
/**
|
|
28906
|
-
* Compiles a partial pipe declaration object into a full pipe definition object.
|
|
28907
|
-
*
|
|
28908
|
-
* @codeGenApi
|
|
28909
|
-
*/
|
|
28910
|
-
function ɵɵngDeclarePipe(decl) {
|
|
28911
|
-
const compiler = getCompilerFacade({ usage: 1 /* JitCompilerUsage.PartialDeclaration */, kind: 'pipe', type: decl.type });
|
|
28912
|
-
return compiler.compilePipeDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵpipe.js`, decl);
|
|
28913
|
-
}
|
|
28914
|
-
|
|
28915
|
-
// clang-format off
|
|
28916
|
-
// clang-format on
|
|
28917
|
-
|
|
28918
29687
|
/**
|
|
28919
29688
|
* Symbol used to tell `Signal`s apart from other functions.
|
|
28920
29689
|
*
|
|
@@ -29061,8 +29830,24 @@ function consumerPollValueStatus(consumer) {
|
|
|
29061
29830
|
return false;
|
|
29062
29831
|
}
|
|
29063
29832
|
|
|
29833
|
+
// `WeakRef` is not always defined in every TS environment where Angular is compiled. Instead,
|
|
29834
|
+
// read it off of the global context if available.
|
|
29064
29835
|
// tslint:disable-next-line: no-toplevel-property-access
|
|
29065
|
-
|
|
29836
|
+
let WeakRefImpl = _global['WeakRef'];
|
|
29837
|
+
function newWeakRef(value) {
|
|
29838
|
+
if (typeof ngDevMode !== 'undefined' && ngDevMode && WeakRefImpl === undefined) {
|
|
29839
|
+
throw new Error(`Angular requires a browser which supports the 'WeakRef' API`);
|
|
29840
|
+
}
|
|
29841
|
+
return new WeakRefImpl(value);
|
|
29842
|
+
}
|
|
29843
|
+
/**
|
|
29844
|
+
* Use an alternate implementation of `WeakRef` if a platform implementation isn't available.
|
|
29845
|
+
*/
|
|
29846
|
+
function setAlternateWeakRefImpl(impl) {
|
|
29847
|
+
if (!WeakRefImpl) {
|
|
29848
|
+
WeakRefImpl = impl;
|
|
29849
|
+
}
|
|
29850
|
+
}
|
|
29066
29851
|
|
|
29067
29852
|
/**
|
|
29068
29853
|
* Create a computed `Signal` which derives a reactive value from an expression.
|
|
@@ -29119,7 +29904,7 @@ class ComputedImpl {
|
|
|
29119
29904
|
*/
|
|
29120
29905
|
this.stale = true;
|
|
29121
29906
|
this.id = nextReactiveId();
|
|
29122
|
-
this.ref =
|
|
29907
|
+
this.ref = newWeakRef(this);
|
|
29123
29908
|
this.producers = new Map();
|
|
29124
29909
|
this.consumers = new Map();
|
|
29125
29910
|
this.trackingVersion = 0;
|
|
@@ -29208,7 +29993,7 @@ class Watch {
|
|
|
29208
29993
|
this.watch = watch;
|
|
29209
29994
|
this.schedule = schedule;
|
|
29210
29995
|
this.id = nextReactiveId();
|
|
29211
|
-
this.ref =
|
|
29996
|
+
this.ref = newWeakRef(this);
|
|
29212
29997
|
this.producers = new Map();
|
|
29213
29998
|
this.trackingVersion = 0;
|
|
29214
29999
|
this.dirty = false;
|
|
@@ -29252,8 +30037,6 @@ function effect(effectFn) {
|
|
|
29252
30037
|
// Effects start dirty.
|
|
29253
30038
|
watch.notify();
|
|
29254
30039
|
return {
|
|
29255
|
-
consumer: watch,
|
|
29256
|
-
schedule: watch.notify.bind(watch),
|
|
29257
30040
|
destroy: () => {
|
|
29258
30041
|
queuedWatches.delete(watch);
|
|
29259
30042
|
globalWatches.delete(watch);
|
|
@@ -29310,7 +30093,7 @@ class SettableSignalImpl {
|
|
|
29310
30093
|
this.value = value;
|
|
29311
30094
|
this.equal = equal;
|
|
29312
30095
|
this.id = nextReactiveId();
|
|
29313
|
-
this.ref =
|
|
30096
|
+
this.ref = newWeakRef(this);
|
|
29314
30097
|
this.consumers = new Map();
|
|
29315
30098
|
this.valueVersion = 0;
|
|
29316
30099
|
}
|
|
@@ -29388,6 +30171,104 @@ function untracked(nonReactiveReadsFn) {
|
|
|
29388
30171
|
}
|
|
29389
30172
|
}
|
|
29390
30173
|
|
|
30174
|
+
/** Coerces a value (typically a string) to a boolean. */
|
|
30175
|
+
function coerceToBoolean(value) {
|
|
30176
|
+
return typeof value === 'boolean' ? value : (value != null && value !== 'false');
|
|
30177
|
+
}
|
|
30178
|
+
|
|
30179
|
+
/**
|
|
30180
|
+
* Compiles a partial directive declaration object into a full directive definition object.
|
|
30181
|
+
*
|
|
30182
|
+
* @codeGenApi
|
|
30183
|
+
*/
|
|
30184
|
+
function ɵɵngDeclareDirective(decl) {
|
|
30185
|
+
const compiler = getCompilerFacade({ usage: 1 /* JitCompilerUsage.PartialDeclaration */, kind: 'directive', type: decl.type });
|
|
30186
|
+
return compiler.compileDirectiveDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵfac.js`, decl);
|
|
30187
|
+
}
|
|
30188
|
+
/**
|
|
30189
|
+
* Evaluates the class metadata declaration.
|
|
30190
|
+
*
|
|
30191
|
+
* @codeGenApi
|
|
30192
|
+
*/
|
|
30193
|
+
function ɵɵngDeclareClassMetadata(decl) {
|
|
30194
|
+
setClassMetadata(decl.type, decl.decorators, decl.ctorParameters ?? null, decl.propDecorators ?? null);
|
|
30195
|
+
}
|
|
30196
|
+
/**
|
|
30197
|
+
* Compiles a partial component declaration object into a full component definition object.
|
|
30198
|
+
*
|
|
30199
|
+
* @codeGenApi
|
|
30200
|
+
*/
|
|
30201
|
+
function ɵɵngDeclareComponent(decl) {
|
|
30202
|
+
const compiler = getCompilerFacade({ usage: 1 /* JitCompilerUsage.PartialDeclaration */, kind: 'component', type: decl.type });
|
|
30203
|
+
return compiler.compileComponentDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵcmp.js`, decl);
|
|
30204
|
+
}
|
|
30205
|
+
/**
|
|
30206
|
+
* Compiles a partial pipe declaration object into a full pipe definition object.
|
|
30207
|
+
*
|
|
30208
|
+
* @codeGenApi
|
|
30209
|
+
*/
|
|
30210
|
+
function ɵɵngDeclareFactory(decl) {
|
|
30211
|
+
const compiler = getCompilerFacade({
|
|
30212
|
+
usage: 1 /* JitCompilerUsage.PartialDeclaration */,
|
|
30213
|
+
kind: getFactoryKind(decl.target),
|
|
30214
|
+
type: decl.type
|
|
30215
|
+
});
|
|
30216
|
+
return compiler.compileFactoryDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵfac.js`, decl);
|
|
30217
|
+
}
|
|
30218
|
+
function getFactoryKind(target) {
|
|
30219
|
+
switch (target) {
|
|
30220
|
+
case FactoryTarget.Directive:
|
|
30221
|
+
return 'directive';
|
|
30222
|
+
case FactoryTarget.Component:
|
|
30223
|
+
return 'component';
|
|
30224
|
+
case FactoryTarget.Injectable:
|
|
30225
|
+
return 'injectable';
|
|
30226
|
+
case FactoryTarget.Pipe:
|
|
30227
|
+
return 'pipe';
|
|
30228
|
+
case FactoryTarget.NgModule:
|
|
30229
|
+
return 'NgModule';
|
|
30230
|
+
}
|
|
30231
|
+
}
|
|
30232
|
+
/**
|
|
30233
|
+
* Compiles a partial injectable declaration object into a full injectable definition object.
|
|
30234
|
+
*
|
|
30235
|
+
* @codeGenApi
|
|
30236
|
+
*/
|
|
30237
|
+
function ɵɵngDeclareInjectable(decl) {
|
|
30238
|
+
const compiler = getCompilerFacade({ usage: 1 /* JitCompilerUsage.PartialDeclaration */, kind: 'injectable', type: decl.type });
|
|
30239
|
+
return compiler.compileInjectableDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵprov.js`, decl);
|
|
30240
|
+
}
|
|
30241
|
+
/**
|
|
30242
|
+
* Compiles a partial injector declaration object into a full injector definition object.
|
|
30243
|
+
*
|
|
30244
|
+
* @codeGenApi
|
|
30245
|
+
*/
|
|
30246
|
+
function ɵɵngDeclareInjector(decl) {
|
|
30247
|
+
const compiler = getCompilerFacade({ usage: 1 /* JitCompilerUsage.PartialDeclaration */, kind: 'NgModule', type: decl.type });
|
|
30248
|
+
return compiler.compileInjectorDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵinj.js`, decl);
|
|
30249
|
+
}
|
|
30250
|
+
/**
|
|
30251
|
+
* Compiles a partial NgModule declaration object into a full NgModule definition object.
|
|
30252
|
+
*
|
|
30253
|
+
* @codeGenApi
|
|
30254
|
+
*/
|
|
30255
|
+
function ɵɵngDeclareNgModule(decl) {
|
|
30256
|
+
const compiler = getCompilerFacade({ usage: 1 /* JitCompilerUsage.PartialDeclaration */, kind: 'NgModule', type: decl.type });
|
|
30257
|
+
return compiler.compileNgModuleDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵmod.js`, decl);
|
|
30258
|
+
}
|
|
30259
|
+
/**
|
|
30260
|
+
* Compiles a partial pipe declaration object into a full pipe definition object.
|
|
30261
|
+
*
|
|
30262
|
+
* @codeGenApi
|
|
30263
|
+
*/
|
|
30264
|
+
function ɵɵngDeclarePipe(decl) {
|
|
30265
|
+
const compiler = getCompilerFacade({ usage: 1 /* JitCompilerUsage.PartialDeclaration */, kind: 'pipe', type: decl.type });
|
|
30266
|
+
return compiler.compilePipeDeclaration(angularCoreEnv, `ng:///${decl.type.name}/ɵpipe.js`, decl);
|
|
30267
|
+
}
|
|
30268
|
+
|
|
30269
|
+
// clang-format off
|
|
30270
|
+
// clang-format on
|
|
30271
|
+
|
|
29391
30272
|
// This file exists to allow the set of reactivity exports to be modified in g3, as these APIs are
|
|
29392
30273
|
|
|
29393
30274
|
/**
|
|
@@ -29571,5 +30452,5 @@ if (typeof ngDevMode !== 'undefined' && ngDevMode) {
|
|
|
29571
30452
|
* Generated bundle index. Do not edit.
|
|
29572
30453
|
*/
|
|
29573
30454
|
|
|
29574
|
-
export { ANALYZE_FOR_ENTRY_COMPONENTS, ANIMATION_MODULE_TYPE, APP_BOOTSTRAP_LISTENER, APP_ID, APP_INITIALIZER, ApplicationInitStatus, ApplicationModule, ApplicationRef, Attribute, COMPILER_OPTIONS, CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, ChangeDetectorRef, Compiler, CompilerFactory, Component, ComponentFactory$1 as ComponentFactory, ComponentFactoryResolver$1 as ComponentFactoryResolver, ComponentRef$1 as ComponentRef, ContentChild, ContentChildren, DEFAULT_CURRENCY_CODE, DebugElement, DebugEventListener, DebugNode, DefaultIterableDiffer, DestroyRef, Directive, ENVIRONMENT_INITIALIZER, ElementRef, EmbeddedViewRef, EnvironmentInjector, ErrorHandler, EventEmitter, Host, HostBinding, HostListener, INJECTOR, Inject, InjectFlags, Injectable, InjectionToken, Injector, Input, IterableDiffers, KeyValueDiffers, LOCALE_ID, MissingTranslationStrategy, ModuleWithComponentFactories, NO_ERRORS_SCHEMA, NgModule, NgModuleFactory$1 as NgModuleFactory, NgModuleRef$1 as NgModuleRef, NgProbeToken, NgZone, Optional, Output, PACKAGE_ROOT_URL, PLATFORM_ID, PLATFORM_INITIALIZER, Pipe, PlatformRef, Query, QueryList, ReflectiveInjector, ReflectiveKey, Renderer2, RendererFactory2, RendererStyleFlags2, ResolvedReflectiveFactory, Sanitizer, SecurityContext, Self, SimpleChange, SkipSelf, TRANSLATIONS, TRANSLATIONS_FORMAT, TemplateRef, Testability, TestabilityRegistry, Type, VERSION, Version, ViewChild, ViewChildren, ViewContainerRef, ViewEncapsulation$1 as ViewEncapsulation, ViewRef, asNativeElements, assertPlatform, computed, createComponent, createEnvironmentInjector, createNgModule, createNgModuleRef, createPlatform, createPlatformFactory, defineInjectable, destroyPlatform, effect, enableProdMode, forwardRef, getDebugNode, getModuleFactory, getNgModuleById, getPlatform, importProvidersFrom, inject, isDevMode, isSignal, isStandalone, makeEnvironmentProviders, mergeApplicationConfig, platformCore, reflectComponentType, resolveForwardRef, runInInjectionContext, setTestabilityGetter, signal, untracked, ALLOW_MULTIPLE_PLATFORMS as ɵALLOW_MULTIPLE_PLATFORMS, ComponentFactory$1 as ɵComponentFactory, Console as ɵConsole, DEFAULT_LOCALE_ID as ɵDEFAULT_LOCALE_ID, INJECTOR_SCOPE as ɵINJECTOR_SCOPE, IS_HYDRATION_FEATURE_ENABLED as ɵIS_HYDRATION_FEATURE_ENABLED, LContext as ɵLContext, LifecycleHooksFeature as ɵLifecycleHooksFeature, LocaleDataIndex as ɵLocaleDataIndex, NG_COMP_DEF as ɵNG_COMP_DEF, NG_DIR_DEF as ɵNG_DIR_DEF, NG_ELEMENT_ID as ɵNG_ELEMENT_ID, NG_INJ_DEF as ɵNG_INJ_DEF, NG_MOD_DEF as ɵNG_MOD_DEF, NG_PIPE_DEF as ɵNG_PIPE_DEF, NG_PROV_DEF as ɵNG_PROV_DEF, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR as ɵNOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR, NO_CHANGE as ɵNO_CHANGE, NgModuleFactory as ɵNgModuleFactory, NoopNgZone as ɵNoopNgZone, ReflectionCapabilities as ɵReflectionCapabilities, ComponentFactory as ɵRender3ComponentFactory, ComponentRef as ɵRender3ComponentRef, NgModuleRef as ɵRender3NgModuleRef, RuntimeError as ɵRuntimeError, TESTABILITY as ɵTESTABILITY, TESTABILITY_GETTER as ɵTESTABILITY_GETTER, TransferState as ɵTransferState, ViewRef$1 as ɵViewRef, XSS_SECURITY_URL as ɵXSS_SECURITY_URL, _sanitizeHtml as ɵ_sanitizeHtml, _sanitizeUrl as ɵ_sanitizeUrl, allowSanitizationBypassAndThrow as ɵallowSanitizationBypassAndThrow, annotateForHydration as ɵannotateForHydration, bypassSanitizationTrustHtml as ɵbypassSanitizationTrustHtml, bypassSanitizationTrustResourceUrl as ɵbypassSanitizationTrustResourceUrl, bypassSanitizationTrustScript as ɵbypassSanitizationTrustScript, bypassSanitizationTrustStyle as ɵbypassSanitizationTrustStyle, bypassSanitizationTrustUrl as ɵbypassSanitizationTrustUrl, clearResolutionOfComponentResourcesQueue as ɵclearResolutionOfComponentResourcesQueue, coerceToBoolean as ɵcoerceToBoolean, compileComponent as ɵcompileComponent, compileDirective as ɵcompileDirective, compileNgModule as ɵcompileNgModule, compileNgModuleDefs as ɵcompileNgModuleDefs, compileNgModuleFactory as ɵcompileNgModuleFactory, compilePipe as ɵcompilePipe, convertToBitFlags as ɵconvertToBitFlags, createInjector as ɵcreateInjector, defaultIterableDiffers as ɵdefaultIterableDiffers, defaultKeyValueDiffers as ɵdefaultKeyValueDiffers, detectChanges as ɵdetectChanges, devModeEqual as ɵdevModeEqual, escapeTransferStateContent as ɵescapeTransferStateContent, findLocaleData as ɵfindLocaleData, flushModuleScopingQueueAsMuchAsPossible as ɵflushModuleScopingQueueAsMuchAsPossible, formatRuntimeError as ɵformatRuntimeError,
|
|
30455
|
+
export { ANALYZE_FOR_ENTRY_COMPONENTS, ANIMATION_MODULE_TYPE, APP_BOOTSTRAP_LISTENER, APP_ID, APP_INITIALIZER, ApplicationInitStatus, ApplicationModule, ApplicationRef, Attribute, COMPILER_OPTIONS, CSP_NONCE, CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, ChangeDetectorRef, Compiler, CompilerFactory, Component, ComponentFactory$1 as ComponentFactory, ComponentFactoryResolver$1 as ComponentFactoryResolver, ComponentRef$1 as ComponentRef, ContentChild, ContentChildren, DEFAULT_CURRENCY_CODE, DebugElement, DebugEventListener, DebugNode, DefaultIterableDiffer, DestroyRef, Directive, ENVIRONMENT_INITIALIZER, ElementRef, EmbeddedViewRef, EnvironmentInjector, ErrorHandler, EventEmitter, Host, HostBinding, HostListener, INJECTOR, Inject, InjectFlags, Injectable, InjectionToken, Injector, Input, IterableDiffers, KeyValueDiffers, LOCALE_ID, MissingTranslationStrategy, ModuleWithComponentFactories, NO_ERRORS_SCHEMA, NgModule, NgModuleFactory$1 as NgModuleFactory, NgModuleRef$1 as NgModuleRef, NgProbeToken, NgZone, Optional, Output, PACKAGE_ROOT_URL, PLATFORM_ID, PLATFORM_INITIALIZER, Pipe, PlatformRef, Query, QueryList, ReflectiveInjector, ReflectiveKey, Renderer2, RendererFactory2, RendererStyleFlags2, ResolvedReflectiveFactory, Sanitizer, SecurityContext, Self, SimpleChange, SkipSelf, TRANSLATIONS, TRANSLATIONS_FORMAT, TemplateRef, Testability, TestabilityRegistry, Type, VERSION, Version, ViewChild, ViewChildren, ViewContainerRef, ViewEncapsulation$1 as ViewEncapsulation, ViewRef, asNativeElements, assertPlatform, computed, createComponent, createEnvironmentInjector, createNgModule, createNgModuleRef, createPlatform, createPlatformFactory, defineInjectable, destroyPlatform, effect, enableProdMode, forwardRef, getDebugNode, getModuleFactory, getNgModuleById, getPlatform, importProvidersFrom, inject, isDevMode, isSignal, isStandalone, makeEnvironmentProviders, mergeApplicationConfig, platformCore, reflectComponentType, resolveForwardRef, runInInjectionContext, setTestabilityGetter, signal, untracked, ALLOW_MULTIPLE_PLATFORMS as ɵALLOW_MULTIPLE_PLATFORMS, ComponentFactory$1 as ɵComponentFactory, Console as ɵConsole, DEFAULT_LOCALE_ID as ɵDEFAULT_LOCALE_ID, INJECTOR_SCOPE as ɵINJECTOR_SCOPE, IS_HYDRATION_FEATURE_ENABLED as ɵIS_HYDRATION_FEATURE_ENABLED, LContext as ɵLContext, LifecycleHooksFeature as ɵLifecycleHooksFeature, LocaleDataIndex as ɵLocaleDataIndex, NG_COMP_DEF as ɵNG_COMP_DEF, NG_DIR_DEF as ɵNG_DIR_DEF, NG_ELEMENT_ID as ɵNG_ELEMENT_ID, NG_INJ_DEF as ɵNG_INJ_DEF, NG_MOD_DEF as ɵNG_MOD_DEF, NG_PIPE_DEF as ɵNG_PIPE_DEF, NG_PROV_DEF as ɵNG_PROV_DEF, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR as ɵNOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR, NO_CHANGE as ɵNO_CHANGE, NgModuleFactory as ɵNgModuleFactory, NoopNgZone as ɵNoopNgZone, ReflectionCapabilities as ɵReflectionCapabilities, ComponentFactory as ɵRender3ComponentFactory, ComponentRef as ɵRender3ComponentRef, NgModuleRef as ɵRender3NgModuleRef, RuntimeError as ɵRuntimeError, TESTABILITY as ɵTESTABILITY, TESTABILITY_GETTER as ɵTESTABILITY_GETTER, TransferState as ɵTransferState, ViewRef$1 as ɵViewRef, XSS_SECURITY_URL as ɵXSS_SECURITY_URL, _sanitizeHtml as ɵ_sanitizeHtml, _sanitizeUrl as ɵ_sanitizeUrl, allowSanitizationBypassAndThrow as ɵallowSanitizationBypassAndThrow, annotateForHydration as ɵannotateForHydration, bypassSanitizationTrustHtml as ɵbypassSanitizationTrustHtml, bypassSanitizationTrustResourceUrl as ɵbypassSanitizationTrustResourceUrl, bypassSanitizationTrustScript as ɵbypassSanitizationTrustScript, bypassSanitizationTrustStyle as ɵbypassSanitizationTrustStyle, bypassSanitizationTrustUrl as ɵbypassSanitizationTrustUrl, clearResolutionOfComponentResourcesQueue as ɵclearResolutionOfComponentResourcesQueue, coerceToBoolean as ɵcoerceToBoolean, compileComponent as ɵcompileComponent, compileDirective as ɵcompileDirective, compileNgModule as ɵcompileNgModule, compileNgModuleDefs as ɵcompileNgModuleDefs, compileNgModuleFactory as ɵcompileNgModuleFactory, compilePipe as ɵcompilePipe, convertToBitFlags as ɵconvertToBitFlags, createInjector as ɵcreateInjector, defaultIterableDiffers as ɵdefaultIterableDiffers, defaultKeyValueDiffers as ɵdefaultKeyValueDiffers, detectChanges as ɵdetectChanges, devModeEqual as ɵdevModeEqual, escapeTransferStateContent as ɵescapeTransferStateContent, findLocaleData as ɵfindLocaleData, flushModuleScopingQueueAsMuchAsPossible as ɵflushModuleScopingQueueAsMuchAsPossible, formatRuntimeError as ɵformatRuntimeError, getDebugNode as ɵgetDebugNode, getDirectives as ɵgetDirectives, getHostElement as ɵgetHostElement, getInjectableDef as ɵgetInjectableDef, getLContext as ɵgetLContext, getLocaleCurrencyCode as ɵgetLocaleCurrencyCode, getLocalePluralCase as ɵgetLocalePluralCase, getSanitizationBypassType as ɵgetSanitizationBypassType, ɵgetUnknownElementStrictMode, ɵgetUnknownPropertyStrictMode, _global as ɵglobal, injectChangeDetectorRef as ɵinjectChangeDetectorRef, internalCreateApplication as ɵinternalCreateApplication, isBoundToModule as ɵisBoundToModule, isEnvironmentProviders as ɵisEnvironmentProviders, isInjectable as ɵisInjectable, isNgModule as ɵisNgModule, isPromise as ɵisPromise, isSubscribable as ɵisSubscribable, makeDecorator as ɵmakeDecorator, makeStateKey as ɵmakeStateKey, noSideEffects as ɵnoSideEffects, patchComponentDefWithScope as ɵpatchComponentDefWithScope, provideHydrationSupport as ɵprovideHydrationSupport, provideNgZoneChangeDetection as ɵprovideNgZoneChangeDetection, publishDefaultGlobalUtils$1 as ɵpublishDefaultGlobalUtils, publishGlobalUtil as ɵpublishGlobalUtil, registerLocaleData as ɵregisterLocaleData, resetCompiledComponents as ɵresetCompiledComponents, resetJitOptions as ɵresetJitOptions, resolveComponentResources as ɵresolveComponentResources, setAllowDuplicateNgModuleIdsForTest as ɵsetAllowDuplicateNgModuleIdsForTest, setAlternateWeakRefImpl as ɵsetAlternateWeakRefImpl, setClassMetadata as ɵsetClassMetadata, setCurrentInjector as ɵsetCurrentInjector, setDocument as ɵsetDocument, setLocaleId as ɵsetLocaleId, ɵsetUnknownElementStrictMode, ɵsetUnknownPropertyStrictMode, store as ɵstore, stringify as ɵstringify, transitiveScopesFor as ɵtransitiveScopesFor, unescapeTransferStateContent as ɵunescapeTransferStateContent, unregisterAllLocaleData as ɵunregisterLocaleData, unwrapSafeValue as ɵunwrapSafeValue, ɵɵCopyDefinitionFeature, FactoryTarget as ɵɵFactoryTarget, ɵɵHostDirectivesFeature, ɵɵInheritDefinitionFeature, ɵɵNgOnChangesFeature, ɵɵProvidersFeature, ɵɵStandaloneFeature, ɵɵadvance, ɵɵattribute, ɵɵattributeInterpolate1, ɵɵattributeInterpolate2, ɵɵattributeInterpolate3, ɵɵattributeInterpolate4, ɵɵattributeInterpolate5, ɵɵattributeInterpolate6, ɵɵattributeInterpolate7, ɵɵattributeInterpolate8, ɵɵattributeInterpolateV, ɵɵclassMap, ɵɵclassMapInterpolate1, ɵɵclassMapInterpolate2, ɵɵclassMapInterpolate3, ɵɵclassMapInterpolate4, ɵɵclassMapInterpolate5, ɵɵclassMapInterpolate6, ɵɵclassMapInterpolate7, ɵɵclassMapInterpolate8, ɵɵclassMapInterpolateV, ɵɵclassProp, ɵɵcontentQuery, ɵɵdefineComponent, ɵɵdefineDirective, ɵɵdefineInjectable, ɵɵdefineInjector, ɵɵdefineNgModule, ɵɵdefinePipe, ɵɵdirectiveInject, ɵɵdisableBindings, ɵɵelement, ɵɵelementContainer, ɵɵelementContainerEnd, ɵɵelementContainerStart, ɵɵelementEnd, ɵɵelementStart, ɵɵenableBindings, ɵɵgetCurrentView, ɵɵgetInheritedFactory, ɵɵhostProperty, ɵɵi18n, ɵɵi18nApply, ɵɵi18nAttributes, ɵɵi18nEnd, ɵɵi18nExp, ɵɵi18nPostprocess, ɵɵi18nStart, ɵɵinject, ɵɵinjectAttribute, ɵɵinvalidFactory, ɵɵinvalidFactoryDep, ɵɵlistener, ɵɵloadQuery, ɵɵnamespaceHTML, ɵɵnamespaceMathML, ɵɵnamespaceSVG, ɵɵnextContext, ɵɵngDeclareClassMetadata, ɵɵngDeclareComponent, ɵɵngDeclareDirective, ɵɵngDeclareFactory, ɵɵngDeclareInjectable, ɵɵngDeclareInjector, ɵɵngDeclareNgModule, ɵɵngDeclarePipe, ɵɵpipe, ɵɵpipeBind1, ɵɵpipeBind2, ɵɵpipeBind3, ɵɵpipeBind4, ɵɵpipeBindV, ɵɵprojection, ɵɵprojectionDef, ɵɵproperty, ɵɵpropertyInterpolate, ɵɵpropertyInterpolate1, ɵɵpropertyInterpolate2, ɵɵpropertyInterpolate3, ɵɵpropertyInterpolate4, ɵɵpropertyInterpolate5, ɵɵpropertyInterpolate6, ɵɵpropertyInterpolate7, ɵɵpropertyInterpolate8, ɵɵpropertyInterpolateV, ɵɵpureFunction0, ɵɵpureFunction1, ɵɵpureFunction2, ɵɵpureFunction3, ɵɵpureFunction4, ɵɵpureFunction5, ɵɵpureFunction6, ɵɵpureFunction7, ɵɵpureFunction8, ɵɵpureFunctionV, ɵɵqueryRefresh, ɵɵreference, registerNgModuleType as ɵɵregisterNgModuleType, ɵɵresetView, ɵɵresolveBody, ɵɵresolveDocument, ɵɵresolveWindow, ɵɵrestoreView, ɵɵsanitizeHtml, ɵɵsanitizeResourceUrl, ɵɵsanitizeScript, ɵɵsanitizeStyle, ɵɵsanitizeUrl, ɵɵsanitizeUrlOrResourceUrl, ɵɵsetComponentScope, ɵɵsetNgModuleScope, ɵɵstyleMap, ɵɵstyleMapInterpolate1, ɵɵstyleMapInterpolate2, ɵɵstyleMapInterpolate3, ɵɵstyleMapInterpolate4, ɵɵstyleMapInterpolate5, ɵɵstyleMapInterpolate6, ɵɵstyleMapInterpolate7, ɵɵstyleMapInterpolate8, ɵɵstyleMapInterpolateV, ɵɵstyleProp, ɵɵstylePropInterpolate1, ɵɵstylePropInterpolate2, ɵɵstylePropInterpolate3, ɵɵstylePropInterpolate4, ɵɵstylePropInterpolate5, ɵɵstylePropInterpolate6, ɵɵstylePropInterpolate7, ɵɵstylePropInterpolate8, ɵɵstylePropInterpolateV, ɵɵsyntheticHostListener, ɵɵsyntheticHostProperty, ɵɵtemplate, ɵɵtemplateRefExtractor, ɵɵtext, ɵɵtextInterpolate, ɵɵtextInterpolate1, ɵɵtextInterpolate2, ɵɵtextInterpolate3, ɵɵtextInterpolate4, ɵɵtextInterpolate5, ɵɵtextInterpolate6, ɵɵtextInterpolate7, ɵɵtextInterpolate8, ɵɵtextInterpolateV, ɵɵtrustConstantHtml, ɵɵtrustConstantResourceUrl, ɵɵvalidateIframeAttribute, ɵɵviewQuery };
|
|
29575
30456
|
//# sourceMappingURL=core.mjs.map
|