@angular/core 17.0.5 → 17.0.7
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/esm2022/primitives/signals/src/signal.mjs +2 -9
- package/esm2022/src/application/application_config.mjs +21 -0
- package/esm2022/src/application/application_init.mjs +188 -0
- package/esm2022/src/application/application_module.mjs +29 -0
- package/esm2022/src/application/application_ref.mjs +509 -0
- package/esm2022/src/application/application_tokens.mjs +121 -0
- package/esm2022/src/application/create_application.mjs +102 -0
- package/esm2022/src/change_detection/scheduling.mjs +103 -0
- package/esm2022/src/core.mjs +10 -7
- package/esm2022/src/core_private_export.mjs +5 -3
- package/esm2022/src/core_reactivity_export_internal.mjs +2 -2
- package/esm2022/src/core_render3_private_export.mjs +2 -2
- package/esm2022/src/error_handler.mjs +15 -1
- package/esm2022/src/hydration/annotate.mjs +30 -20
- package/esm2022/src/hydration/api.mjs +2 -2
- package/esm2022/src/hydration/cleanup.mjs +1 -1
- package/esm2022/src/hydration/interfaces.mjs +1 -1
- package/esm2022/src/hydration/node_lookup_utils.mjs +23 -2
- package/esm2022/src/image_performance_warning.mjs +2 -2
- package/esm2022/src/linker/query_list.mjs +8 -6
- package/esm2022/src/metadata/do_bootstrap.mjs +1 -1
- package/esm2022/src/platform/platform.mjs +135 -0
- package/esm2022/src/platform/platform_core_providers.mjs +15 -0
- package/esm2022/src/platform/platform_ref.mjs +179 -0
- package/esm2022/src/render3/instructions/change_detection.mjs +2 -4
- package/esm2022/src/render3/list_reconciliation.mjs +58 -24
- package/esm2022/src/render3/node_manipulation.mjs +2 -2
- package/esm2022/src/render3/util/change_detection_utils.mjs +3 -1
- package/esm2022/src/render3/util/misc_utils.mjs +2 -2
- package/esm2022/src/render3/view_manipulation.mjs +13 -5
- package/esm2022/src/render3/view_ref.mjs +7 -1
- package/esm2022/src/transfer_state.mjs +2 -2
- package/esm2022/src/util/performance.mjs +2 -2
- package/esm2022/src/version.mjs +1 -1
- package/esm2022/src/zone/ng_zone.mjs +10 -1
- package/esm2022/testing/src/component_fixture.mjs +20 -36
- package/esm2022/testing/src/logger.mjs +3 -3
- package/esm2022/testing/src/test_bed.mjs +5 -6
- package/fesm2022/core.mjs +1263 -1191
- package/fesm2022/core.mjs.map +1 -1
- package/fesm2022/primitives/signals.mjs +2 -9
- package/fesm2022/primitives/signals.mjs.map +1 -1
- package/fesm2022/rxjs-interop.mjs +1 -1
- package/fesm2022/testing.mjs +46 -64
- package/fesm2022/testing.mjs.map +1 -1
- package/index.d.ts +18 -14
- package/package.json +1 -1
- package/primitives/signals/index.d.ts +1 -1
- package/rxjs-interop/index.d.ts +1 -1
- package/schematics/migrations/block-template-entities/bundle.js +958 -457
- package/schematics/migrations/block-template-entities/bundle.js.map +4 -4
- package/schematics/ng-generate/control-flow-migration/bundle.js +1221 -525
- package/schematics/ng-generate/control-flow-migration/bundle.js.map +4 -4
- package/schematics/ng-generate/standalone-migration/bundle.js +1143 -509
- package/schematics/ng-generate/standalone-migration/bundle.js.map +4 -4
- package/testing/index.d.ts +6 -10
- package/esm2022/src/application_config.mjs +0 -21
- package/esm2022/src/application_init.mjs +0 -188
- package/esm2022/src/application_module.mjs +0 -29
- package/esm2022/src/application_ref.mjs +0 -997
- package/esm2022/src/application_tokens.mjs +0 -121
- package/esm2022/src/platform_core_providers.mjs +0 -15
package/fesm2022/core.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v17.0.
|
|
2
|
+
* @license Angular v17.0.7
|
|
3
3
|
* (c) 2010-2022 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -8267,7 +8267,6 @@ function detachView(lContainer, removeIndex) {
|
|
|
8267
8267
|
function destroyLView(tView, lView) {
|
|
8268
8268
|
if (!(lView[FLAGS] & 256 /* LViewFlags.Destroyed */)) {
|
|
8269
8269
|
const renderer = lView[RENDERER];
|
|
8270
|
-
lView[REACTIVE_TEMPLATE_CONSUMER] && consumerDestroy$1(lView[REACTIVE_TEMPLATE_CONSUMER]);
|
|
8271
8270
|
if (renderer.destroyNode) {
|
|
8272
8271
|
applyView(tView, lView, renderer, 3 /* WalkTNodeTreeAction.Destroy */, null, null);
|
|
8273
8272
|
}
|
|
@@ -8293,6 +8292,7 @@ function cleanUpView(tView, lView) {
|
|
|
8293
8292
|
// This also aligns with the ViewEngine behavior. It also means that the onDestroy hook is
|
|
8294
8293
|
// really more of an "afterDestroy" hook if you think about it.
|
|
8295
8294
|
lView[FLAGS] |= 256 /* LViewFlags.Destroyed */;
|
|
8295
|
+
lView[REACTIVE_TEMPLATE_CONSUMER] && consumerDestroy$1(lView[REACTIVE_TEMPLATE_CONSUMER]);
|
|
8296
8296
|
executeOnDestroys(tView, lView);
|
|
8297
8297
|
processCleanups(tView, lView);
|
|
8298
8298
|
// For component views only, the local renderer is destroyed at clean up time.
|
|
@@ -10427,7 +10427,7 @@ class Version {
|
|
|
10427
10427
|
/**
|
|
10428
10428
|
* @publicApi
|
|
10429
10429
|
*/
|
|
10430
|
-
const VERSION = new Version('17.0.
|
|
10430
|
+
const VERSION = new Version('17.0.7');
|
|
10431
10431
|
|
|
10432
10432
|
// This default value is when checking the hierarchy for a token.
|
|
10433
10433
|
//
|
|
@@ -11762,6 +11762,19 @@ class ErrorHandler {
|
|
|
11762
11762
|
return e || null;
|
|
11763
11763
|
}
|
|
11764
11764
|
}
|
|
11765
|
+
/**
|
|
11766
|
+
* `InjectionToken` used to configure how to call the `ErrorHandler`.
|
|
11767
|
+
*
|
|
11768
|
+
* `NgZone` is provided by default today so the default (and only) implementation for this
|
|
11769
|
+
* is calling `ErrorHandler.handleError` outside of the Angular zone.
|
|
11770
|
+
*/
|
|
11771
|
+
const INTERNAL_APPLICATION_ERROR_HANDLER = new InjectionToken((typeof ngDevMode === 'undefined' || ngDevMode) ? 'internal error handler' : '', {
|
|
11772
|
+
providedIn: 'root',
|
|
11773
|
+
factory: () => {
|
|
11774
|
+
const userErrorHandler = inject(ErrorHandler);
|
|
11775
|
+
return userErrorHandler.handleError.bind(undefined);
|
|
11776
|
+
}
|
|
11777
|
+
});
|
|
11765
11778
|
|
|
11766
11779
|
/**
|
|
11767
11780
|
* Internal token that specifies whether DOM reuse logic
|
|
@@ -13306,9 +13319,6 @@ function detectChangesInternal(lView, notifyErrorHandler = true) {
|
|
|
13306
13319
|
afterRenderEventManager?.begin();
|
|
13307
13320
|
}
|
|
13308
13321
|
try {
|
|
13309
|
-
const tView = lView[TVIEW];
|
|
13310
|
-
const context = lView[CONTEXT];
|
|
13311
|
-
refreshView(tView, lView, tView.template, context);
|
|
13312
13322
|
detectChangesInViewWhileDirty(lView);
|
|
13313
13323
|
}
|
|
13314
13324
|
catch (error) {
|
|
@@ -13329,6 +13339,7 @@ function detectChangesInternal(lView, notifyErrorHandler = true) {
|
|
|
13329
13339
|
}
|
|
13330
13340
|
}
|
|
13331
13341
|
function detectChangesInViewWhileDirty(lView) {
|
|
13342
|
+
detectChangesInView(lView, 0 /* ChangeDetectionMode.Global */);
|
|
13332
13343
|
let retries = 0;
|
|
13333
13344
|
// If after running change detection, this view still needs to be refreshed or there are
|
|
13334
13345
|
// descendants views that need to be refreshed due to re-dirtying during the change detection
|
|
@@ -13900,6 +13911,12 @@ class ViewRef$1 {
|
|
|
13900
13911
|
* See {@link ChangeDetectorRef#detach} for more information.
|
|
13901
13912
|
*/
|
|
13902
13913
|
detectChanges() {
|
|
13914
|
+
// Add `RefreshView` flag to ensure this view is refreshed if not already dirty.
|
|
13915
|
+
// `RefreshView` flag is used intentionally over `Dirty` because it gets cleared before
|
|
13916
|
+
// executing any of the actual refresh code while the `Dirty` flag doesn't get cleared
|
|
13917
|
+
// until the end of the refresh. Using `RefreshView` prevents creating a potential difference
|
|
13918
|
+
// in the state of the LViewFlags during template execution.
|
|
13919
|
+
this._lView[FLAGS] |= 1024 /* LViewFlags.RefreshView */;
|
|
13903
13920
|
detectChangesInternal(this._lView, this.notifyErrorHandler);
|
|
13904
13921
|
}
|
|
13905
13922
|
/**
|
|
@@ -14269,7 +14286,7 @@ function performanceMarkFeature(feature) {
|
|
|
14269
14286
|
return;
|
|
14270
14287
|
}
|
|
14271
14288
|
markedFeatures.add(feature);
|
|
14272
|
-
performance?.mark?.('
|
|
14289
|
+
performance?.mark?.('mark_feature_usage', { detail: { feature } });
|
|
14273
14290
|
}
|
|
14274
14291
|
|
|
14275
14292
|
/// <reference types="rxjs" />
|
|
@@ -14840,6 +14857,15 @@ function shouldBeIgnoredByZone(applyArgs) {
|
|
|
14840
14857
|
// Prevent triggering change detection when the __ignore_ng_zone__ flag is detected.
|
|
14841
14858
|
return applyArgs[0].data?.['__ignore_ng_zone__'] === true;
|
|
14842
14859
|
}
|
|
14860
|
+
function getNgZone(ngZoneToUse = 'zone.js', options) {
|
|
14861
|
+
if (ngZoneToUse === 'noop') {
|
|
14862
|
+
return new NoopNgZone();
|
|
14863
|
+
}
|
|
14864
|
+
if (ngZoneToUse === 'zone.js') {
|
|
14865
|
+
return new NgZone(options);
|
|
14866
|
+
}
|
|
14867
|
+
return ngZoneToUse;
|
|
14868
|
+
}
|
|
14843
14869
|
|
|
14844
14870
|
// Public API for Zone
|
|
14845
14871
|
|
|
@@ -19117,6 +19143,17 @@ function isFirstElementInNgContainer(tNode) {
|
|
|
19117
19143
|
function getNoOffsetIndex(tNode) {
|
|
19118
19144
|
return tNode.index - HEADER_OFFSET;
|
|
19119
19145
|
}
|
|
19146
|
+
/**
|
|
19147
|
+
* Check whether a given node exists, but is disconnected from the DOM.
|
|
19148
|
+
*
|
|
19149
|
+
* Note: we leverage the fact that we have this information available in the DOM emulation
|
|
19150
|
+
* layer (in Domino) for now. Longer-term solution should not rely on the DOM emulation and
|
|
19151
|
+
* only use internal data structures and state to compute this information.
|
|
19152
|
+
*/
|
|
19153
|
+
function isDisconnectedNode(tNode, lView) {
|
|
19154
|
+
return !(tNode.type & 16 /* TNodeType.Projection */) && !!lView[tNode.index] &&
|
|
19155
|
+
!unwrapRNode(lView[tNode.index])?.isConnected;
|
|
19156
|
+
}
|
|
19120
19157
|
/**
|
|
19121
19158
|
* Locate a node in DOM tree that corresponds to a given TNode.
|
|
19122
19159
|
*
|
|
@@ -19318,10 +19355,20 @@ function calcPathBetween(from, to, fromNodeName) {
|
|
|
19318
19355
|
* instructions needs to be generated for a TNode.
|
|
19319
19356
|
*/
|
|
19320
19357
|
function calcPathForNode(tNode, lView) {
|
|
19321
|
-
|
|
19358
|
+
let parentTNode = tNode.parent;
|
|
19322
19359
|
let parentIndex;
|
|
19323
19360
|
let parentRNode;
|
|
19324
19361
|
let referenceNodeName;
|
|
19362
|
+
// Skip over all parent nodes that are disconnected from the DOM, such nodes
|
|
19363
|
+
// can not be used as anchors.
|
|
19364
|
+
//
|
|
19365
|
+
// This might happen in certain content projection-based use-cases, where
|
|
19366
|
+
// a content of an element is projected and used, when a parent element
|
|
19367
|
+
// itself remains detached from DOM. In this scenario we try to find a parent
|
|
19368
|
+
// element that is attached to DOM and can act as an anchor instead.
|
|
19369
|
+
while (parentTNode !== null && isDisconnectedNode(parentTNode, lView)) {
|
|
19370
|
+
parentTNode = parentTNode.parent;
|
|
19371
|
+
}
|
|
19325
19372
|
if (parentTNode === null || !(parentTNode.type & 3 /* TNodeType.AnyRNode */)) {
|
|
19326
19373
|
// If there is no parent TNode or a parent TNode does not represent an RNode
|
|
19327
19374
|
// (i.e. not a DOM node), use component host element as a reference node.
|
|
@@ -19565,7 +19612,7 @@ function reconcile(liveCollection, newCollection, trackByFn) {
|
|
|
19565
19612
|
}
|
|
19566
19613
|
// Fallback to the slow path: we need to learn more about the content of the live and new
|
|
19567
19614
|
// collections.
|
|
19568
|
-
detachedItems ??= new
|
|
19615
|
+
detachedItems ??= new UniqueValueMultiKeyMap();
|
|
19569
19616
|
liveKeysInTheFuture ??=
|
|
19570
19617
|
initLiveItemsInTheFuture(liveCollection, liveStartIdx, liveEndIdx, trackByFn);
|
|
19571
19618
|
// Check if I'm inserting a previously detached item: if so, attach it here
|
|
@@ -19613,7 +19660,7 @@ function reconcile(liveCollection, newCollection, trackByFn) {
|
|
|
19613
19660
|
newIterationResult = newCollectionIterator.next();
|
|
19614
19661
|
}
|
|
19615
19662
|
else {
|
|
19616
|
-
detachedItems ??= new
|
|
19663
|
+
detachedItems ??= new UniqueValueMultiKeyMap();
|
|
19617
19664
|
liveKeysInTheFuture ??=
|
|
19618
19665
|
initLiveItemsInTheFuture(liveCollection, liveStartIdx, liveEndIdx, trackByFn);
|
|
19619
19666
|
// Check if I'm inserting a previously detached item: if so, attach it here
|
|
@@ -19679,40 +19726,73 @@ function initLiveItemsInTheFuture(liveCollection, start, end, trackByFn) {
|
|
|
19679
19726
|
}
|
|
19680
19727
|
return keys;
|
|
19681
19728
|
}
|
|
19682
|
-
|
|
19729
|
+
/**
|
|
19730
|
+
* A specific, partial implementation of the Map interface with the following characteristics:
|
|
19731
|
+
* - allows multiple values for a given key;
|
|
19732
|
+
* - maintain FIFO order for multiple values corresponding to a given key;
|
|
19733
|
+
* - assumes that all values are unique.
|
|
19734
|
+
*
|
|
19735
|
+
* The implementation aims at having the minimal overhead for cases where keys are _not_ duplicated
|
|
19736
|
+
* (the most common case in the list reconciliation algorithm). To achieve this, the first value for
|
|
19737
|
+
* a given key is stored in a regular map. Then, when more values are set for a given key, we
|
|
19738
|
+
* maintain a form of linked list in a separate map. To maintain this linked list we assume that all
|
|
19739
|
+
* values (in the entire collection) are unique.
|
|
19740
|
+
*/
|
|
19741
|
+
class UniqueValueMultiKeyMap {
|
|
19683
19742
|
constructor() {
|
|
19684
|
-
|
|
19743
|
+
// A map from a key to the first value corresponding to this key.
|
|
19744
|
+
this.kvMap = new Map();
|
|
19745
|
+
// A map that acts as a linked list of values - each value maps to the next value in this "linked
|
|
19746
|
+
// list" (this only works if values are unique). Allocated lazily to avoid memory consumption when
|
|
19747
|
+
// there are no duplicated values.
|
|
19748
|
+
this._vMap = undefined;
|
|
19685
19749
|
}
|
|
19686
19750
|
has(key) {
|
|
19687
|
-
|
|
19688
|
-
return listOfKeys !== undefined && listOfKeys.length > 0;
|
|
19751
|
+
return this.kvMap.has(key);
|
|
19689
19752
|
}
|
|
19690
19753
|
delete(key) {
|
|
19691
|
-
|
|
19692
|
-
|
|
19693
|
-
|
|
19694
|
-
|
|
19754
|
+
if (!this.has(key))
|
|
19755
|
+
return false;
|
|
19756
|
+
const value = this.kvMap.get(key);
|
|
19757
|
+
if (this._vMap !== undefined && this._vMap.has(value)) {
|
|
19758
|
+
this.kvMap.set(key, this._vMap.get(value));
|
|
19759
|
+
this._vMap.delete(value);
|
|
19695
19760
|
}
|
|
19696
|
-
|
|
19761
|
+
else {
|
|
19762
|
+
this.kvMap.delete(key);
|
|
19763
|
+
}
|
|
19764
|
+
return true;
|
|
19697
19765
|
}
|
|
19698
19766
|
get(key) {
|
|
19699
|
-
|
|
19700
|
-
return listOfKeys !== undefined && listOfKeys.length > 0 ? listOfKeys[0] : undefined;
|
|
19767
|
+
return this.kvMap.get(key);
|
|
19701
19768
|
}
|
|
19702
19769
|
set(key, value) {
|
|
19703
|
-
|
|
19704
|
-
|
|
19705
|
-
|
|
19706
|
-
|
|
19770
|
+
if (this.kvMap.has(key)) {
|
|
19771
|
+
let prevValue = this.kvMap.get(key);
|
|
19772
|
+
ngDevMode &&
|
|
19773
|
+
assertNotSame(prevValue, value, `Detected a duplicated value ${value} for the key ${key}`);
|
|
19774
|
+
if (this._vMap === undefined) {
|
|
19775
|
+
this._vMap = new Map();
|
|
19776
|
+
}
|
|
19777
|
+
const vMap = this._vMap;
|
|
19778
|
+
while (vMap.has(prevValue)) {
|
|
19779
|
+
prevValue = vMap.get(prevValue);
|
|
19780
|
+
}
|
|
19781
|
+
vMap.set(prevValue, value);
|
|
19782
|
+
}
|
|
19783
|
+
else {
|
|
19784
|
+
this.kvMap.set(key, value);
|
|
19707
19785
|
}
|
|
19708
|
-
// THINK: this allows duplicate values, but I guess this is fine?
|
|
19709
|
-
// Is the existing key an array or not?
|
|
19710
|
-
this.map.get(key)?.push(value);
|
|
19711
19786
|
}
|
|
19712
19787
|
forEach(cb) {
|
|
19713
|
-
for (
|
|
19714
|
-
|
|
19715
|
-
|
|
19788
|
+
for (let [key, value] of this.kvMap) {
|
|
19789
|
+
cb(value, key);
|
|
19790
|
+
if (this._vMap !== undefined) {
|
|
19791
|
+
const vMap = this._vMap;
|
|
19792
|
+
while (vMap.has(value)) {
|
|
19793
|
+
value = vMap.get(value);
|
|
19794
|
+
cb(value, key);
|
|
19795
|
+
}
|
|
19716
19796
|
}
|
|
19717
19797
|
}
|
|
19718
19798
|
}
|
|
@@ -19755,13 +19835,14 @@ function getLViewFromLContainer(lContainer, index) {
|
|
|
19755
19835
|
* block (in which case view contents was re-created, thus needing insertion).
|
|
19756
19836
|
*/
|
|
19757
19837
|
function shouldAddViewToDom(tNode, dehydratedView) {
|
|
19758
|
-
return !dehydratedView ||
|
|
19838
|
+
return !dehydratedView || dehydratedView.firstChild === null ||
|
|
19839
|
+
hasInSkipHydrationBlockFlag(tNode);
|
|
19759
19840
|
}
|
|
19760
19841
|
function addLViewToLContainer(lContainer, lView, index, addToDOM = true) {
|
|
19761
19842
|
const tView = lView[TVIEW];
|
|
19762
|
-
//
|
|
19843
|
+
// Insert into the view tree so the new view can be change-detected
|
|
19763
19844
|
insertView(tView, lView, lContainer, index);
|
|
19764
|
-
//
|
|
19845
|
+
// Insert elements that belong to this view into the DOM tree
|
|
19765
19846
|
if (addToDOM) {
|
|
19766
19847
|
const beforeNode = getBeforeNodeForView(index, lContainer);
|
|
19767
19848
|
const renderer = lView[RENDERER];
|
|
@@ -19770,6 +19851,13 @@ function addLViewToLContainer(lContainer, lView, index, addToDOM = true) {
|
|
|
19770
19851
|
addViewToDOM(tView, lContainer[T_HOST], renderer, lView, parentRNode, beforeNode);
|
|
19771
19852
|
}
|
|
19772
19853
|
}
|
|
19854
|
+
// When in hydration mode, reset the pointer to the first child in
|
|
19855
|
+
// the dehydrated view. This indicates that the view was hydrated and
|
|
19856
|
+
// further attaching/detaching should work with this view as normal.
|
|
19857
|
+
const hydrationInfo = lView[HYDRATION];
|
|
19858
|
+
if (hydrationInfo !== null && hydrationInfo.firstChild !== null) {
|
|
19859
|
+
hydrationInfo.firstChild = null;
|
|
19860
|
+
}
|
|
19773
19861
|
}
|
|
19774
19862
|
function removeLViewFromLContainer(lContainer, index) {
|
|
19775
19863
|
const lView = detachView(lContainer, index);
|
|
@@ -27846,7 +27934,7 @@ class QueryList {
|
|
|
27846
27934
|
* Returns `Observable` of `QueryList` notifying the subscriber of changes.
|
|
27847
27935
|
*/
|
|
27848
27936
|
get changes() {
|
|
27849
|
-
return this._changes
|
|
27937
|
+
return this._changes ??= new EventEmitter();
|
|
27850
27938
|
}
|
|
27851
27939
|
/**
|
|
27852
27940
|
* @param emitDistinctChangesOnly Whether `QueryList.changes` should fire only when actual change
|
|
@@ -27858,7 +27946,7 @@ class QueryList {
|
|
|
27858
27946
|
this.dirty = true;
|
|
27859
27947
|
this._results = [];
|
|
27860
27948
|
this._changesDetected = false;
|
|
27861
|
-
this._changes =
|
|
27949
|
+
this._changes = undefined;
|
|
27862
27950
|
this.length = 0;
|
|
27863
27951
|
this.first = undefined;
|
|
27864
27952
|
this.last = undefined;
|
|
@@ -27949,7 +28037,7 @@ class QueryList {
|
|
|
27949
28037
|
* Triggers a change event by emitting on the `changes` {@link EventEmitter}.
|
|
27950
28038
|
*/
|
|
27951
28039
|
notifyOnChanges() {
|
|
27952
|
-
if (this._changes && (this._changesDetected || !this._emitDistinctChangesOnly))
|
|
28040
|
+
if (this._changes !== undefined && (this._changesDetected || !this._emitDistinctChangesOnly))
|
|
27953
28041
|
this._changes.emit(this);
|
|
27954
28042
|
}
|
|
27955
28043
|
/** internal */
|
|
@@ -27958,8 +28046,10 @@ class QueryList {
|
|
|
27958
28046
|
}
|
|
27959
28047
|
/** internal */
|
|
27960
28048
|
destroy() {
|
|
27961
|
-
this.
|
|
27962
|
-
|
|
28049
|
+
if (this._changes !== undefined) {
|
|
28050
|
+
this._changes.complete();
|
|
28051
|
+
this._changes.unsubscribe();
|
|
28052
|
+
}
|
|
27963
28053
|
}
|
|
27964
28054
|
}
|
|
27965
28055
|
|
|
@@ -29899,190 +29989,6 @@ const NgModule = makeDecorator('NgModule', (ngModule) => ngModule, undefined, un
|
|
|
29899
29989
|
*/
|
|
29900
29990
|
const ITS_JUST_ANGULAR = true;
|
|
29901
29991
|
|
|
29902
|
-
/**
|
|
29903
|
-
* A [DI token](guide/glossary#di-token "DI token definition") that you can use to provide
|
|
29904
|
-
* one or more initialization functions.
|
|
29905
|
-
*
|
|
29906
|
-
* The provided functions are injected at application startup and executed during
|
|
29907
|
-
* app initialization. If any of these functions returns a Promise or an Observable, initialization
|
|
29908
|
-
* does not complete until the Promise is resolved or the Observable is completed.
|
|
29909
|
-
*
|
|
29910
|
-
* You can, for example, create a factory function that loads language data
|
|
29911
|
-
* or an external configuration, and provide that function to the `APP_INITIALIZER` token.
|
|
29912
|
-
* The function is executed during the application bootstrap process,
|
|
29913
|
-
* and the needed data is available on startup.
|
|
29914
|
-
*
|
|
29915
|
-
* @see {@link ApplicationInitStatus}
|
|
29916
|
-
*
|
|
29917
|
-
* @usageNotes
|
|
29918
|
-
*
|
|
29919
|
-
* The following example illustrates how to configure a multi-provider using `APP_INITIALIZER` token
|
|
29920
|
-
* and a function returning a promise.
|
|
29921
|
-
* ### Example with NgModule-based application
|
|
29922
|
-
* ```
|
|
29923
|
-
* function initializeApp(): Promise<any> {
|
|
29924
|
-
* return new Promise((resolve, reject) => {
|
|
29925
|
-
* // Do some asynchronous stuff
|
|
29926
|
-
* resolve();
|
|
29927
|
-
* });
|
|
29928
|
-
* }
|
|
29929
|
-
*
|
|
29930
|
-
* @NgModule({
|
|
29931
|
-
* imports: [BrowserModule],
|
|
29932
|
-
* declarations: [AppComponent],
|
|
29933
|
-
* bootstrap: [AppComponent],
|
|
29934
|
-
* providers: [{
|
|
29935
|
-
* provide: APP_INITIALIZER,
|
|
29936
|
-
* useFactory: () => initializeApp,
|
|
29937
|
-
* multi: true
|
|
29938
|
-
* }]
|
|
29939
|
-
* })
|
|
29940
|
-
* export class AppModule {}
|
|
29941
|
-
* ```
|
|
29942
|
-
*
|
|
29943
|
-
* ### Example with standalone application
|
|
29944
|
-
* ```
|
|
29945
|
-
* export function initializeApp(http: HttpClient) {
|
|
29946
|
-
* return (): Promise<any> =>
|
|
29947
|
-
* firstValueFrom(
|
|
29948
|
-
* http
|
|
29949
|
-
* .get("https://someUrl.com/api/user")
|
|
29950
|
-
* .pipe(tap(user => { ... }))
|
|
29951
|
-
* );
|
|
29952
|
-
* }
|
|
29953
|
-
*
|
|
29954
|
-
* bootstrapApplication(App, {
|
|
29955
|
-
* providers: [
|
|
29956
|
-
* provideHttpClient(),
|
|
29957
|
-
* {
|
|
29958
|
-
* provide: APP_INITIALIZER,
|
|
29959
|
-
* useFactory: initializeApp,
|
|
29960
|
-
* multi: true,
|
|
29961
|
-
* deps: [HttpClient],
|
|
29962
|
-
* },
|
|
29963
|
-
* ],
|
|
29964
|
-
* });
|
|
29965
|
-
|
|
29966
|
-
* ```
|
|
29967
|
-
*
|
|
29968
|
-
*
|
|
29969
|
-
* It's also possible to configure a multi-provider using `APP_INITIALIZER` token and a function
|
|
29970
|
-
* returning an observable, see an example below. Note: the `HttpClient` in this example is used for
|
|
29971
|
-
* demo purposes to illustrate how the factory function can work with other providers available
|
|
29972
|
-
* through DI.
|
|
29973
|
-
*
|
|
29974
|
-
* ### Example with NgModule-based application
|
|
29975
|
-
* ```
|
|
29976
|
-
* function initializeAppFactory(httpClient: HttpClient): () => Observable<any> {
|
|
29977
|
-
* return () => httpClient.get("https://someUrl.com/api/user")
|
|
29978
|
-
* .pipe(
|
|
29979
|
-
* tap(user => { ... })
|
|
29980
|
-
* );
|
|
29981
|
-
* }
|
|
29982
|
-
*
|
|
29983
|
-
* @NgModule({
|
|
29984
|
-
* imports: [BrowserModule, HttpClientModule],
|
|
29985
|
-
* declarations: [AppComponent],
|
|
29986
|
-
* bootstrap: [AppComponent],
|
|
29987
|
-
* providers: [{
|
|
29988
|
-
* provide: APP_INITIALIZER,
|
|
29989
|
-
* useFactory: initializeAppFactory,
|
|
29990
|
-
* deps: [HttpClient],
|
|
29991
|
-
* multi: true
|
|
29992
|
-
* }]
|
|
29993
|
-
* })
|
|
29994
|
-
* export class AppModule {}
|
|
29995
|
-
* ```
|
|
29996
|
-
*
|
|
29997
|
-
* ### Example with standalone application
|
|
29998
|
-
* ```
|
|
29999
|
-
* function initializeAppFactory(httpClient: HttpClient): () => Observable<any> {
|
|
30000
|
-
* return () => httpClient.get("https://someUrl.com/api/user")
|
|
30001
|
-
* .pipe(
|
|
30002
|
-
* tap(user => { ... })
|
|
30003
|
-
* );
|
|
30004
|
-
* }
|
|
30005
|
-
*
|
|
30006
|
-
* bootstrapApplication(App, {
|
|
30007
|
-
* providers: [
|
|
30008
|
-
* provideHttpClient(),
|
|
30009
|
-
* {
|
|
30010
|
-
* provide: APP_INITIALIZER,
|
|
30011
|
-
* useFactory: initializeAppFactory,
|
|
30012
|
-
* multi: true,
|
|
30013
|
-
* deps: [HttpClient],
|
|
30014
|
-
* },
|
|
30015
|
-
* ],
|
|
30016
|
-
* });
|
|
30017
|
-
* ```
|
|
30018
|
-
*
|
|
30019
|
-
* @publicApi
|
|
30020
|
-
*/
|
|
30021
|
-
const APP_INITIALIZER = new InjectionToken('Application Initializer');
|
|
30022
|
-
/**
|
|
30023
|
-
* A class that reflects the state of running {@link APP_INITIALIZER} functions.
|
|
30024
|
-
*
|
|
30025
|
-
* @publicApi
|
|
30026
|
-
*/
|
|
30027
|
-
class ApplicationInitStatus {
|
|
30028
|
-
constructor() {
|
|
30029
|
-
this.initialized = false;
|
|
30030
|
-
this.done = false;
|
|
30031
|
-
this.donePromise = new Promise((res, rej) => {
|
|
30032
|
-
this.resolve = res;
|
|
30033
|
-
this.reject = rej;
|
|
30034
|
-
});
|
|
30035
|
-
this.appInits = inject(APP_INITIALIZER, { optional: true }) ?? [];
|
|
30036
|
-
if ((typeof ngDevMode === 'undefined' || ngDevMode) && !Array.isArray(this.appInits)) {
|
|
30037
|
-
throw new RuntimeError(-209 /* RuntimeErrorCode.INVALID_MULTI_PROVIDER */, 'Unexpected type of the `APP_INITIALIZER` token value ' +
|
|
30038
|
-
`(expected an array, but got ${typeof this.appInits}). ` +
|
|
30039
|
-
'Please check that the `APP_INITIALIZER` token is configured as a ' +
|
|
30040
|
-
'`multi: true` provider.');
|
|
30041
|
-
}
|
|
30042
|
-
}
|
|
30043
|
-
/** @internal */
|
|
30044
|
-
runInitializers() {
|
|
30045
|
-
if (this.initialized) {
|
|
30046
|
-
return;
|
|
30047
|
-
}
|
|
30048
|
-
const asyncInitPromises = [];
|
|
30049
|
-
for (const appInits of this.appInits) {
|
|
30050
|
-
const initResult = appInits();
|
|
30051
|
-
if (isPromise(initResult)) {
|
|
30052
|
-
asyncInitPromises.push(initResult);
|
|
30053
|
-
}
|
|
30054
|
-
else if (isSubscribable(initResult)) {
|
|
30055
|
-
const observableAsPromise = new Promise((resolve, reject) => {
|
|
30056
|
-
initResult.subscribe({ complete: resolve, error: reject });
|
|
30057
|
-
});
|
|
30058
|
-
asyncInitPromises.push(observableAsPromise);
|
|
30059
|
-
}
|
|
30060
|
-
}
|
|
30061
|
-
const complete = () => {
|
|
30062
|
-
// @ts-expect-error overwriting a readonly
|
|
30063
|
-
this.done = true;
|
|
30064
|
-
this.resolve();
|
|
30065
|
-
};
|
|
30066
|
-
Promise.all(asyncInitPromises)
|
|
30067
|
-
.then(() => {
|
|
30068
|
-
complete();
|
|
30069
|
-
})
|
|
30070
|
-
.catch(e => {
|
|
30071
|
-
this.reject(e);
|
|
30072
|
-
});
|
|
30073
|
-
if (asyncInitPromises.length === 0) {
|
|
30074
|
-
complete();
|
|
30075
|
-
}
|
|
30076
|
-
this.initialized = true;
|
|
30077
|
-
}
|
|
30078
|
-
static { this.ɵfac = function ApplicationInitStatus_Factory(t) { return new (t || ApplicationInitStatus)(); }; }
|
|
30079
|
-
static { this.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: ApplicationInitStatus, factory: ApplicationInitStatus.ɵfac, providedIn: 'root' }); }
|
|
30080
|
-
}
|
|
30081
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ApplicationInitStatus, [{
|
|
30082
|
-
type: Injectable,
|
|
30083
|
-
args: [{ providedIn: 'root' }]
|
|
30084
|
-
}], () => [], null); })();
|
|
30085
|
-
|
|
30086
29992
|
class Console {
|
|
30087
29993
|
log(message) {
|
|
30088
29994
|
// tslint:disable-next-line:no-console
|
|
@@ -30102,563 +30008,234 @@ class Console {
|
|
|
30102
30008
|
}], null, null); })();
|
|
30103
30009
|
|
|
30104
30010
|
/**
|
|
30105
|
-
*
|
|
30011
|
+
* *Internal* service that keeps track of pending tasks happening in the system
|
|
30012
|
+
* during the initial rendering. No tasks are tracked after an initial
|
|
30013
|
+
* rendering.
|
|
30106
30014
|
*
|
|
30107
|
-
*
|
|
30108
|
-
*
|
|
30015
|
+
* This information is needed to make sure that the serialization on the server
|
|
30016
|
+
* is delayed until all tasks in the queue (such as an initial navigation or a
|
|
30017
|
+
* pending HTTP request) are completed.
|
|
30109
30018
|
*/
|
|
30110
|
-
|
|
30111
|
-
|
|
30112
|
-
|
|
30113
|
-
|
|
30114
|
-
|
|
30115
|
-
// Closure Compiler's one.
|
|
30116
|
-
return goog.LOCALE;
|
|
30019
|
+
class InitialRenderPendingTasks {
|
|
30020
|
+
constructor() {
|
|
30021
|
+
this.taskId = 0;
|
|
30022
|
+
this.pendingTasks = new Set();
|
|
30023
|
+
this.hasPendingTasks = new BehaviorSubject(false);
|
|
30117
30024
|
}
|
|
30118
|
-
|
|
30119
|
-
|
|
30120
|
-
|
|
30121
|
-
|
|
30122
|
-
|
|
30123
|
-
|
|
30124
|
-
|
|
30125
|
-
|
|
30126
|
-
|
|
30127
|
-
|
|
30128
|
-
|
|
30025
|
+
add() {
|
|
30026
|
+
this.hasPendingTasks.next(true);
|
|
30027
|
+
const taskId = this.taskId++;
|
|
30028
|
+
this.pendingTasks.add(taskId);
|
|
30029
|
+
return taskId;
|
|
30030
|
+
}
|
|
30031
|
+
remove(taskId) {
|
|
30032
|
+
this.pendingTasks.delete(taskId);
|
|
30033
|
+
if (this.pendingTasks.size === 0) {
|
|
30034
|
+
this.hasPendingTasks.next(false);
|
|
30035
|
+
}
|
|
30036
|
+
}
|
|
30037
|
+
ngOnDestroy() {
|
|
30038
|
+
this.pendingTasks.clear();
|
|
30039
|
+
this.hasPendingTasks.next(false);
|
|
30129
30040
|
}
|
|
30041
|
+
static { this.ɵfac = function InitialRenderPendingTasks_Factory(t) { return new (t || InitialRenderPendingTasks)(); }; }
|
|
30042
|
+
static { this.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: InitialRenderPendingTasks, factory: InitialRenderPendingTasks.ɵfac, providedIn: 'root' }); }
|
|
30130
30043
|
}
|
|
30044
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(InitialRenderPendingTasks, [{
|
|
30045
|
+
type: Injectable,
|
|
30046
|
+
args: [{ providedIn: 'root' }]
|
|
30047
|
+
}], null, null); })();
|
|
30048
|
+
|
|
30131
30049
|
/**
|
|
30132
|
-
*
|
|
30133
|
-
* It is used for i18n extraction, by i18n pipes (DatePipe, I18nPluralPipe, CurrencyPipe,
|
|
30134
|
-
* DecimalPipe and PercentPipe) and by ICU expressions.
|
|
30135
|
-
*
|
|
30136
|
-
* See the [i18n guide](guide/i18n-common-locale-id) for more information.
|
|
30050
|
+
* Combination of NgModuleFactory and ComponentFactories.
|
|
30137
30051
|
*
|
|
30138
|
-
* @
|
|
30139
|
-
* ### Example
|
|
30052
|
+
* @publicApi
|
|
30140
30053
|
*
|
|
30141
|
-
*
|
|
30142
|
-
*
|
|
30143
|
-
*
|
|
30144
|
-
*
|
|
30054
|
+
* @deprecated
|
|
30055
|
+
* Ivy JIT mode doesn't require accessing this symbol.
|
|
30056
|
+
* See [JIT API changes due to ViewEngine deprecation](guide/deprecations#jit-api-changes) for
|
|
30057
|
+
* additional context.
|
|
30058
|
+
*/
|
|
30059
|
+
class ModuleWithComponentFactories {
|
|
30060
|
+
constructor(ngModuleFactory, componentFactories) {
|
|
30061
|
+
this.ngModuleFactory = ngModuleFactory;
|
|
30062
|
+
this.componentFactories = componentFactories;
|
|
30063
|
+
}
|
|
30064
|
+
}
|
|
30065
|
+
/**
|
|
30066
|
+
* Low-level service for running the angular compiler during runtime
|
|
30067
|
+
* to create {@link ComponentFactory}s, which
|
|
30068
|
+
* can later be used to create and render a Component instance.
|
|
30145
30069
|
*
|
|
30146
|
-
*
|
|
30147
|
-
*
|
|
30148
|
-
*
|
|
30149
|
-
* ```
|
|
30070
|
+
* Each `@NgModule` provides an own `Compiler` to its injector,
|
|
30071
|
+
* that will use the directives/pipes of the ng module for compilation
|
|
30072
|
+
* of components.
|
|
30150
30073
|
*
|
|
30151
30074
|
* @publicApi
|
|
30075
|
+
*
|
|
30076
|
+
* @deprecated
|
|
30077
|
+
* Ivy JIT mode doesn't require accessing this symbol.
|
|
30078
|
+
* See [JIT API changes due to ViewEngine deprecation](guide/deprecations#jit-api-changes) for
|
|
30079
|
+
* additional context.
|
|
30152
30080
|
*/
|
|
30153
|
-
|
|
30154
|
-
|
|
30155
|
-
|
|
30156
|
-
|
|
30081
|
+
class Compiler {
|
|
30082
|
+
/**
|
|
30083
|
+
* Compiles the given NgModule and all of its components. All templates of the components
|
|
30084
|
+
* have to be inlined.
|
|
30085
|
+
*/
|
|
30086
|
+
compileModuleSync(moduleType) {
|
|
30087
|
+
return new NgModuleFactory(moduleType);
|
|
30088
|
+
}
|
|
30089
|
+
/**
|
|
30090
|
+
* Compiles the given NgModule and all of its components
|
|
30091
|
+
*/
|
|
30092
|
+
compileModuleAsync(moduleType) {
|
|
30093
|
+
return Promise.resolve(this.compileModuleSync(moduleType));
|
|
30094
|
+
}
|
|
30095
|
+
/**
|
|
30096
|
+
* Same as {@link #compileModuleSync} but also creates ComponentFactories for all components.
|
|
30097
|
+
*/
|
|
30098
|
+
compileModuleAndAllComponentsSync(moduleType) {
|
|
30099
|
+
const ngModuleFactory = this.compileModuleSync(moduleType);
|
|
30100
|
+
const moduleDef = getNgModuleDef(moduleType);
|
|
30101
|
+
const componentFactories = maybeUnwrapFn(moduleDef.declarations)
|
|
30102
|
+
.reduce((factories, declaration) => {
|
|
30103
|
+
const componentDef = getComponentDef(declaration);
|
|
30104
|
+
componentDef && factories.push(new ComponentFactory(componentDef));
|
|
30105
|
+
return factories;
|
|
30106
|
+
}, []);
|
|
30107
|
+
return new ModuleWithComponentFactories(ngModuleFactory, componentFactories);
|
|
30108
|
+
}
|
|
30109
|
+
/**
|
|
30110
|
+
* Same as {@link #compileModuleAsync} but also creates ComponentFactories for all components.
|
|
30111
|
+
*/
|
|
30112
|
+
compileModuleAndAllComponentsAsync(moduleType) {
|
|
30113
|
+
return Promise.resolve(this.compileModuleAndAllComponentsSync(moduleType));
|
|
30114
|
+
}
|
|
30115
|
+
/**
|
|
30116
|
+
* Clears all caches.
|
|
30117
|
+
*/
|
|
30118
|
+
clearCache() { }
|
|
30119
|
+
/**
|
|
30120
|
+
* Clears the cache for the given component/ngModule.
|
|
30121
|
+
*/
|
|
30122
|
+
clearCacheFor(type) { }
|
|
30123
|
+
/**
|
|
30124
|
+
* Returns the id for a given NgModule, if one is defined and known to the compiler.
|
|
30125
|
+
*/
|
|
30126
|
+
getModuleId(moduleType) {
|
|
30127
|
+
return undefined;
|
|
30128
|
+
}
|
|
30129
|
+
static { this.ɵfac = function Compiler_Factory(t) { return new (t || Compiler)(); }; }
|
|
30130
|
+
static { this.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: Compiler, factory: Compiler.ɵfac, providedIn: 'root' }); }
|
|
30131
|
+
}
|
|
30132
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(Compiler, [{
|
|
30133
|
+
type: Injectable,
|
|
30134
|
+
args: [{ providedIn: 'root' }]
|
|
30135
|
+
}], null, null); })();
|
|
30157
30136
|
/**
|
|
30158
|
-
*
|
|
30159
|
-
* CurrencyPipe when there is no currency code passed into it. This is only used by
|
|
30160
|
-
* CurrencyPipe and has no relation to locale currency. Defaults to USD if not configured.
|
|
30137
|
+
* Token to provide CompilerOptions in the platform injector.
|
|
30161
30138
|
*
|
|
30162
|
-
*
|
|
30139
|
+
* @publicApi
|
|
30140
|
+
*/
|
|
30141
|
+
const COMPILER_OPTIONS = new InjectionToken('compilerOptions');
|
|
30142
|
+
/**
|
|
30143
|
+
* A factory for creating a Compiler
|
|
30163
30144
|
*
|
|
30164
|
-
*
|
|
30145
|
+
* @publicApi
|
|
30165
30146
|
*
|
|
30166
|
-
*
|
|
30147
|
+
* @deprecated
|
|
30148
|
+
* Ivy JIT mode doesn't require accessing this symbol.
|
|
30149
|
+
* See [JIT API changes due to ViewEngine deprecation](guide/deprecations#jit-api-changes) for
|
|
30150
|
+
* additional context.
|
|
30151
|
+
*/
|
|
30152
|
+
class CompilerFactory {
|
|
30153
|
+
}
|
|
30154
|
+
|
|
30155
|
+
/**
|
|
30156
|
+
* These are the data structures that our framework injector profiler will fill with data in order
|
|
30157
|
+
* to support DI debugging APIs.
|
|
30167
30158
|
*
|
|
30168
|
-
*
|
|
30159
|
+
* resolverToTokenToDependencies: Maps an injector to a Map of tokens to an Array of
|
|
30160
|
+
* dependencies. Injector -> Token -> Dependencies This is used to support the
|
|
30161
|
+
* getDependenciesFromInjectable API, which takes in an injector and a token and returns it's
|
|
30162
|
+
* dependencies.
|
|
30169
30163
|
*
|
|
30170
|
-
*
|
|
30164
|
+
* resolverToProviders: Maps a DI resolver (an Injector or a TNode) to the providers configured
|
|
30165
|
+
* within it This is used to support the getInjectorProviders API, which takes in an injector and
|
|
30166
|
+
* returns the providers that it was configured with. Note that for the element injector case we
|
|
30167
|
+
* use the TNode instead of the LView as the DI resolver. This is because the registration of
|
|
30168
|
+
* providers happens only once per type of TNode. If an injector is created with an identical TNode,
|
|
30169
|
+
* the providers for that injector will not be reconfigured.
|
|
30171
30170
|
*
|
|
30172
|
-
*
|
|
30173
|
-
*
|
|
30171
|
+
* standaloneInjectorToComponent: Maps the injector of a standalone component to the standalone
|
|
30172
|
+
* component that it is associated with. Used in the getInjectorProviders API, specificially in the
|
|
30173
|
+
* discovery of import paths for each provider. This is necessary because the imports array of a
|
|
30174
|
+
* standalone component is processed and configured in its standalone injector, but exists within
|
|
30175
|
+
* the component's definition. Because getInjectorProviders takes in an injector, if that injector
|
|
30176
|
+
* is the injector of a standalone component, we need to be able to discover the place where the
|
|
30177
|
+
* imports array is located (the component) in order to flatten the imports array within it to
|
|
30178
|
+
* discover all of it's providers.
|
|
30174
30179
|
*
|
|
30175
|
-
* ```ts
|
|
30176
|
-
* {provide: DEFAULT_CURRENCY_CODE, useValue: 'USD'}
|
|
30177
|
-
* ```
|
|
30178
30180
|
*
|
|
30179
|
-
*
|
|
30181
|
+
* All of these data structures are instantiated with WeakMaps. This will ensure that the presence
|
|
30182
|
+
* of any object in the keys of these maps does not prevent the garbage collector from collecting
|
|
30183
|
+
* those objects. Because of this property of WeakMaps, these data structures will never be the
|
|
30184
|
+
* source of a memory leak.
|
|
30180
30185
|
*
|
|
30181
|
-
*
|
|
30182
|
-
*
|
|
30186
|
+
* An example of this advantage: When components are destroyed, we don't need to do
|
|
30187
|
+
* any additional work to remove that component from our mappings.
|
|
30183
30188
|
*
|
|
30184
|
-
|
|
30185
|
-
|
|
30186
|
-
|
|
30189
|
+
*/
|
|
30190
|
+
class DIDebugData {
|
|
30191
|
+
constructor() {
|
|
30192
|
+
this.resolverToTokenToDependencies = new WeakMap();
|
|
30193
|
+
this.resolverToProviders = new WeakMap();
|
|
30194
|
+
this.standaloneInjectorToComponent = new WeakMap();
|
|
30195
|
+
}
|
|
30196
|
+
reset() {
|
|
30197
|
+
this.resolverToTokenToDependencies =
|
|
30198
|
+
new WeakMap();
|
|
30199
|
+
this.resolverToProviders = new WeakMap();
|
|
30200
|
+
this.standaloneInjectorToComponent = new WeakMap();
|
|
30201
|
+
}
|
|
30202
|
+
}
|
|
30203
|
+
let frameworkDIDebugData = new DIDebugData();
|
|
30204
|
+
function getFrameworkDIDebugData() {
|
|
30205
|
+
return frameworkDIDebugData;
|
|
30206
|
+
}
|
|
30207
|
+
/**
|
|
30208
|
+
* Initalize default handling of injector events. This handling parses events
|
|
30209
|
+
* as they are emitted and constructs the data structures necessary to support
|
|
30210
|
+
* some of debug APIs.
|
|
30187
30211
|
*
|
|
30188
|
-
*
|
|
30189
|
-
*
|
|
30190
|
-
* });
|
|
30191
|
-
* ```
|
|
30212
|
+
* See handleInjectEvent, handleCreateEvent and handleProviderConfiguredEvent
|
|
30213
|
+
* for descriptions of each handler
|
|
30192
30214
|
*
|
|
30193
|
-
*
|
|
30215
|
+
* Supported APIs:
|
|
30216
|
+
* - getDependenciesFromInjectable
|
|
30217
|
+
* - getInjectorProviders
|
|
30194
30218
|
*/
|
|
30195
|
-
|
|
30196
|
-
|
|
30197
|
-
|
|
30198
|
-
}
|
|
30219
|
+
function setupFrameworkInjectorProfiler() {
|
|
30220
|
+
frameworkDIDebugData.reset();
|
|
30221
|
+
setInjectorProfiler((injectorProfilerEvent) => handleInjectorProfilerEvent(injectorProfilerEvent));
|
|
30222
|
+
}
|
|
30223
|
+
function handleInjectorProfilerEvent(injectorProfilerEvent) {
|
|
30224
|
+
const { context, type } = injectorProfilerEvent;
|
|
30225
|
+
if (type === 0 /* InjectorProfilerEventType.Inject */) {
|
|
30226
|
+
handleInjectEvent(context, injectorProfilerEvent.service);
|
|
30227
|
+
}
|
|
30228
|
+
else if (type === 1 /* InjectorProfilerEventType.InstanceCreatedByInjector */) {
|
|
30229
|
+
handleInstanceCreatedByInjectorEvent(context, injectorProfilerEvent.instance);
|
|
30230
|
+
}
|
|
30231
|
+
else if (type === 2 /* InjectorProfilerEventType.ProviderConfigured */) {
|
|
30232
|
+
handleProviderConfiguredEvent(context, injectorProfilerEvent.providerRecord);
|
|
30233
|
+
}
|
|
30234
|
+
}
|
|
30199
30235
|
/**
|
|
30200
|
-
* Use this token at bootstrap to provide the content of your translation file (`xtb`,
|
|
30201
|
-
* `xlf` or `xlf2`) when you want to translate your application in another language.
|
|
30202
30236
|
*
|
|
30203
|
-
*
|
|
30204
|
-
*
|
|
30205
|
-
* @usageNotes
|
|
30206
|
-
* ### Example
|
|
30207
|
-
*
|
|
30208
|
-
* ```typescript
|
|
30209
|
-
* import { TRANSLATIONS } from '@angular/core';
|
|
30210
|
-
* import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
|
30211
|
-
* import { AppModule } from './app/app.module';
|
|
30212
|
-
*
|
|
30213
|
-
* // content of your translation file
|
|
30214
|
-
* const translations = '....';
|
|
30215
|
-
*
|
|
30216
|
-
* platformBrowserDynamic().bootstrapModule(AppModule, {
|
|
30217
|
-
* providers: [{provide: TRANSLATIONS, useValue: translations }]
|
|
30218
|
-
* });
|
|
30219
|
-
* ```
|
|
30220
|
-
*
|
|
30221
|
-
* @publicApi
|
|
30222
|
-
*/
|
|
30223
|
-
const TRANSLATIONS = new InjectionToken('Translations');
|
|
30224
|
-
/**
|
|
30225
|
-
* Provide this token at bootstrap to set the format of your {@link TRANSLATIONS}: `xtb`,
|
|
30226
|
-
* `xlf` or `xlf2`.
|
|
30227
|
-
*
|
|
30228
|
-
* See the [i18n guide](guide/i18n-common-merge) for more information.
|
|
30229
|
-
*
|
|
30230
|
-
* @usageNotes
|
|
30231
|
-
* ### Example
|
|
30232
|
-
*
|
|
30233
|
-
* ```typescript
|
|
30234
|
-
* import { TRANSLATIONS_FORMAT } from '@angular/core';
|
|
30235
|
-
* import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
|
30236
|
-
* import { AppModule } from './app/app.module';
|
|
30237
|
-
*
|
|
30238
|
-
* platformBrowserDynamic().bootstrapModule(AppModule, {
|
|
30239
|
-
* providers: [{provide: TRANSLATIONS_FORMAT, useValue: 'xlf' }]
|
|
30240
|
-
* });
|
|
30241
|
-
* ```
|
|
30242
|
-
*
|
|
30243
|
-
* @publicApi
|
|
30244
|
-
*/
|
|
30245
|
-
const TRANSLATIONS_FORMAT = new InjectionToken('TranslationsFormat');
|
|
30246
|
-
/**
|
|
30247
|
-
* Use this enum at bootstrap as an option of `bootstrapModule` to define the strategy
|
|
30248
|
-
* that the compiler should use in case of missing translations:
|
|
30249
|
-
* - Error: throw if you have missing translations.
|
|
30250
|
-
* - Warning (default): show a warning in the console and/or shell.
|
|
30251
|
-
* - Ignore: do nothing.
|
|
30252
|
-
*
|
|
30253
|
-
* See the [i18n guide](guide/i18n-common-merge#report-missing-translations) for more information.
|
|
30254
|
-
*
|
|
30255
|
-
* @usageNotes
|
|
30256
|
-
* ### Example
|
|
30257
|
-
* ```typescript
|
|
30258
|
-
* import { MissingTranslationStrategy } from '@angular/core';
|
|
30259
|
-
* import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
|
30260
|
-
* import { AppModule } from './app/app.module';
|
|
30261
|
-
*
|
|
30262
|
-
* platformBrowserDynamic().bootstrapModule(AppModule, {
|
|
30263
|
-
* missingTranslation: MissingTranslationStrategy.Error
|
|
30264
|
-
* });
|
|
30265
|
-
* ```
|
|
30266
|
-
*
|
|
30267
|
-
* @publicApi
|
|
30268
|
-
*/
|
|
30269
|
-
var MissingTranslationStrategy;
|
|
30270
|
-
(function (MissingTranslationStrategy) {
|
|
30271
|
-
MissingTranslationStrategy[MissingTranslationStrategy["Error"] = 0] = "Error";
|
|
30272
|
-
MissingTranslationStrategy[MissingTranslationStrategy["Warning"] = 1] = "Warning";
|
|
30273
|
-
MissingTranslationStrategy[MissingTranslationStrategy["Ignore"] = 2] = "Ignore";
|
|
30274
|
-
})(MissingTranslationStrategy || (MissingTranslationStrategy = {}));
|
|
30275
|
-
|
|
30276
|
-
// A delay in milliseconds before the scan is run after onLoad, to avoid any
|
|
30277
|
-
// potential race conditions with other LCP-related functions. This delay
|
|
30278
|
-
// happens outside of the main JavaScript execution and will only effect the timing
|
|
30279
|
-
// on when the warning becomes visible in the console.
|
|
30280
|
-
const SCAN_DELAY = 200;
|
|
30281
|
-
const OVERSIZED_IMAGE_TOLERANCE = 1200;
|
|
30282
|
-
class ImagePerformanceWarning {
|
|
30283
|
-
constructor() {
|
|
30284
|
-
// Map of full image URLs -> original `ngSrc` values.
|
|
30285
|
-
this.window = null;
|
|
30286
|
-
this.observer = null;
|
|
30287
|
-
this.options = inject(IMAGE_CONFIG);
|
|
30288
|
-
this.ngZone = inject(NgZone);
|
|
30289
|
-
}
|
|
30290
|
-
start() {
|
|
30291
|
-
if (typeof PerformanceObserver === 'undefined' ||
|
|
30292
|
-
(this.options?.disableImageSizeWarning && this.options?.disableImageLazyLoadWarning)) {
|
|
30293
|
-
return;
|
|
30294
|
-
}
|
|
30295
|
-
this.observer = this.initPerformanceObserver();
|
|
30296
|
-
const doc = getDocument();
|
|
30297
|
-
const win = doc.defaultView;
|
|
30298
|
-
if (typeof win !== 'undefined') {
|
|
30299
|
-
this.window = win;
|
|
30300
|
-
// Wait to avoid race conditions where LCP image triggers
|
|
30301
|
-
// load event before it's recorded by the performance observer
|
|
30302
|
-
const waitToScan = () => {
|
|
30303
|
-
setTimeout(this.scanImages.bind(this), SCAN_DELAY);
|
|
30304
|
-
};
|
|
30305
|
-
// Angular doesn't have to run change detection whenever any asynchronous tasks are invoked in
|
|
30306
|
-
// the scope of this functionality.
|
|
30307
|
-
this.ngZone.runOutsideAngular(() => {
|
|
30308
|
-
// Consider the case when the application is created and destroyed multiple times.
|
|
30309
|
-
// Typically, applications are created instantly once the page is loaded, and the
|
|
30310
|
-
// `window.load` listener is always triggered. However, the `window.load` event will never
|
|
30311
|
-
// be fired if the page is loaded, and the application is created later. Checking for
|
|
30312
|
-
// `readyState` is the easiest way to determine whether the page has been loaded or not.
|
|
30313
|
-
if (doc.readyState === 'complete') {
|
|
30314
|
-
waitToScan();
|
|
30315
|
-
}
|
|
30316
|
-
else {
|
|
30317
|
-
this.window?.addEventListener('load', waitToScan, { once: true });
|
|
30318
|
-
}
|
|
30319
|
-
});
|
|
30320
|
-
}
|
|
30321
|
-
}
|
|
30322
|
-
ngOnDestroy() {
|
|
30323
|
-
this.observer?.disconnect();
|
|
30324
|
-
}
|
|
30325
|
-
initPerformanceObserver() {
|
|
30326
|
-
if (typeof PerformanceObserver === 'undefined') {
|
|
30327
|
-
return null;
|
|
30328
|
-
}
|
|
30329
|
-
const observer = new PerformanceObserver((entryList) => {
|
|
30330
|
-
const entries = entryList.getEntries();
|
|
30331
|
-
if (entries.length === 0)
|
|
30332
|
-
return;
|
|
30333
|
-
// We use the latest entry produced by the `PerformanceObserver` as the best
|
|
30334
|
-
// signal on which element is actually an LCP one. As an example, the first image to load on
|
|
30335
|
-
// a page, by virtue of being the only thing on the page so far, is often a LCP candidate
|
|
30336
|
-
// and gets reported by PerformanceObserver, but isn't necessarily the LCP element.
|
|
30337
|
-
const lcpElement = entries[entries.length - 1];
|
|
30338
|
-
// Cast to `any` due to missing `element` on the `LargestContentfulPaint` type of entry.
|
|
30339
|
-
// See https://developer.mozilla.org/en-US/docs/Web/API/LargestContentfulPaint
|
|
30340
|
-
const imgSrc = lcpElement.element?.src ?? '';
|
|
30341
|
-
// Exclude `data:` and `blob:` URLs, since they are fetched resources.
|
|
30342
|
-
if (imgSrc.startsWith('data:') || imgSrc.startsWith('blob:'))
|
|
30343
|
-
return;
|
|
30344
|
-
this.lcpImageUrl = imgSrc;
|
|
30345
|
-
});
|
|
30346
|
-
observer.observe({ type: 'largest-contentful-paint', buffered: true });
|
|
30347
|
-
return observer;
|
|
30348
|
-
}
|
|
30349
|
-
scanImages() {
|
|
30350
|
-
const images = getDocument().querySelectorAll('img');
|
|
30351
|
-
let lcpElementFound, lcpElementLoadedCorrectly = false;
|
|
30352
|
-
images.forEach(image => {
|
|
30353
|
-
if (!this.options?.disableImageSizeWarning) {
|
|
30354
|
-
for (const image of images) {
|
|
30355
|
-
// Image elements using the NgOptimizedImage directive are excluded,
|
|
30356
|
-
// as that directive has its own version of this check.
|
|
30357
|
-
if (!image.getAttribute('ng-img') && this.isOversized(image)) {
|
|
30358
|
-
logOversizedImageWarning(image.src);
|
|
30359
|
-
}
|
|
30360
|
-
}
|
|
30361
|
-
}
|
|
30362
|
-
if (!this.options?.disableImageLazyLoadWarning && this.lcpImageUrl) {
|
|
30363
|
-
if (image.src === this.lcpImageUrl) {
|
|
30364
|
-
lcpElementFound = true;
|
|
30365
|
-
if (image.loading !== 'lazy' || image.getAttribute('ng-img')) {
|
|
30366
|
-
// This variable is set to true and never goes back to false to account
|
|
30367
|
-
// for the case where multiple images have the same src url, and some
|
|
30368
|
-
// have lazy loading while others don't.
|
|
30369
|
-
// Also ignore NgOptimizedImage because there's a different warning for that.
|
|
30370
|
-
lcpElementLoadedCorrectly = true;
|
|
30371
|
-
}
|
|
30372
|
-
}
|
|
30373
|
-
}
|
|
30374
|
-
});
|
|
30375
|
-
if (lcpElementFound && !lcpElementLoadedCorrectly && this.lcpImageUrl &&
|
|
30376
|
-
!this.options?.disableImageLazyLoadWarning) {
|
|
30377
|
-
logLazyLCPWarning(this.lcpImageUrl);
|
|
30378
|
-
}
|
|
30379
|
-
}
|
|
30380
|
-
isOversized(image) {
|
|
30381
|
-
if (!this.window) {
|
|
30382
|
-
return false;
|
|
30383
|
-
}
|
|
30384
|
-
const computedStyle = this.window.getComputedStyle(image);
|
|
30385
|
-
let renderedWidth = parseFloat(computedStyle.getPropertyValue('width'));
|
|
30386
|
-
let renderedHeight = parseFloat(computedStyle.getPropertyValue('height'));
|
|
30387
|
-
const boxSizing = computedStyle.getPropertyValue('box-sizing');
|
|
30388
|
-
const objectFit = computedStyle.getPropertyValue('object-fit');
|
|
30389
|
-
if (objectFit === `cover`) {
|
|
30390
|
-
// Object fit cover may indicate a use case such as a sprite sheet where
|
|
30391
|
-
// this warning does not apply.
|
|
30392
|
-
return false;
|
|
30393
|
-
}
|
|
30394
|
-
if (boxSizing === 'border-box') {
|
|
30395
|
-
const paddingTop = computedStyle.getPropertyValue('padding-top');
|
|
30396
|
-
const paddingRight = computedStyle.getPropertyValue('padding-right');
|
|
30397
|
-
const paddingBottom = computedStyle.getPropertyValue('padding-bottom');
|
|
30398
|
-
const paddingLeft = computedStyle.getPropertyValue('padding-left');
|
|
30399
|
-
renderedWidth -= parseFloat(paddingRight) + parseFloat(paddingLeft);
|
|
30400
|
-
renderedHeight -= parseFloat(paddingTop) + parseFloat(paddingBottom);
|
|
30401
|
-
}
|
|
30402
|
-
const intrinsicWidth = image.naturalWidth;
|
|
30403
|
-
const intrinsicHeight = image.naturalHeight;
|
|
30404
|
-
const recommendedWidth = this.window.devicePixelRatio * renderedWidth;
|
|
30405
|
-
const recommendedHeight = this.window.devicePixelRatio * renderedHeight;
|
|
30406
|
-
const oversizedWidth = (intrinsicWidth - recommendedWidth) >= OVERSIZED_IMAGE_TOLERANCE;
|
|
30407
|
-
const oversizedHeight = (intrinsicHeight - recommendedHeight) >= OVERSIZED_IMAGE_TOLERANCE;
|
|
30408
|
-
return oversizedWidth || oversizedHeight;
|
|
30409
|
-
}
|
|
30410
|
-
static { this.ɵfac = function ImagePerformanceWarning_Factory(t) { return new (t || ImagePerformanceWarning)(); }; }
|
|
30411
|
-
static { this.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: ImagePerformanceWarning, factory: ImagePerformanceWarning.ɵfac, providedIn: 'root' }); }
|
|
30412
|
-
}
|
|
30413
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ImagePerformanceWarning, [{
|
|
30414
|
-
type: Injectable,
|
|
30415
|
-
args: [{ providedIn: 'root' }]
|
|
30416
|
-
}], null, null); })();
|
|
30417
|
-
function logLazyLCPWarning(src) {
|
|
30418
|
-
console.warn(formatRuntimeError(-913 /* RuntimeErrorCode.IMAGE_PERFORMANCE_WARNING */, `An image with src ${src} is the Largest Contentful Paint (LCP) element ` +
|
|
30419
|
-
`but was given a "loading" value of "lazy", which can negatively impact ` +
|
|
30420
|
-
`application loading performance. This warning can be addressed by ` +
|
|
30421
|
-
`changing the loading value of the LCP image to "eager", or by using the ` +
|
|
30422
|
-
`NgOptimizedImage directive's prioritization utilities. For more ` +
|
|
30423
|
-
`information about addressing or disabling this warning, see ` +
|
|
30424
|
-
`https://angular.io/errors/NG0913`));
|
|
30425
|
-
}
|
|
30426
|
-
function logOversizedImageWarning(src) {
|
|
30427
|
-
console.warn(formatRuntimeError(-913 /* RuntimeErrorCode.IMAGE_PERFORMANCE_WARNING */, `An image with src ${src} has intrinsic file dimensions much larger than its ` +
|
|
30428
|
-
`rendered size. This can negatively impact application loading performance. ` +
|
|
30429
|
-
`For more information about addressing or disabling this warning, see ` +
|
|
30430
|
-
`https://angular.io/errors/NG0913`));
|
|
30431
|
-
}
|
|
30432
|
-
|
|
30433
|
-
/**
|
|
30434
|
-
* *Internal* service that keeps track of pending tasks happening in the system
|
|
30435
|
-
* during the initial rendering. No tasks are tracked after an initial
|
|
30436
|
-
* rendering.
|
|
30437
|
-
*
|
|
30438
|
-
* This information is needed to make sure that the serialization on the server
|
|
30439
|
-
* is delayed until all tasks in the queue (such as an initial navigation or a
|
|
30440
|
-
* pending HTTP request) are completed.
|
|
30441
|
-
*/
|
|
30442
|
-
class InitialRenderPendingTasks {
|
|
30443
|
-
constructor() {
|
|
30444
|
-
this.taskId = 0;
|
|
30445
|
-
this.pendingTasks = new Set();
|
|
30446
|
-
this.hasPendingTasks = new BehaviorSubject(false);
|
|
30447
|
-
}
|
|
30448
|
-
add() {
|
|
30449
|
-
this.hasPendingTasks.next(true);
|
|
30450
|
-
const taskId = this.taskId++;
|
|
30451
|
-
this.pendingTasks.add(taskId);
|
|
30452
|
-
return taskId;
|
|
30453
|
-
}
|
|
30454
|
-
remove(taskId) {
|
|
30455
|
-
this.pendingTasks.delete(taskId);
|
|
30456
|
-
if (this.pendingTasks.size === 0) {
|
|
30457
|
-
this.hasPendingTasks.next(false);
|
|
30458
|
-
}
|
|
30459
|
-
}
|
|
30460
|
-
ngOnDestroy() {
|
|
30461
|
-
this.pendingTasks.clear();
|
|
30462
|
-
this.hasPendingTasks.next(false);
|
|
30463
|
-
}
|
|
30464
|
-
static { this.ɵfac = function InitialRenderPendingTasks_Factory(t) { return new (t || InitialRenderPendingTasks)(); }; }
|
|
30465
|
-
static { this.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: InitialRenderPendingTasks, factory: InitialRenderPendingTasks.ɵfac, providedIn: 'root' }); }
|
|
30466
|
-
}
|
|
30467
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(InitialRenderPendingTasks, [{
|
|
30468
|
-
type: Injectable,
|
|
30469
|
-
args: [{ providedIn: 'root' }]
|
|
30470
|
-
}], null, null); })();
|
|
30471
|
-
|
|
30472
|
-
/**
|
|
30473
|
-
* Combination of NgModuleFactory and ComponentFactories.
|
|
30474
|
-
*
|
|
30475
|
-
* @publicApi
|
|
30476
|
-
*
|
|
30477
|
-
* @deprecated
|
|
30478
|
-
* Ivy JIT mode doesn't require accessing this symbol.
|
|
30479
|
-
* See [JIT API changes due to ViewEngine deprecation](guide/deprecations#jit-api-changes) for
|
|
30480
|
-
* additional context.
|
|
30481
|
-
*/
|
|
30482
|
-
class ModuleWithComponentFactories {
|
|
30483
|
-
constructor(ngModuleFactory, componentFactories) {
|
|
30484
|
-
this.ngModuleFactory = ngModuleFactory;
|
|
30485
|
-
this.componentFactories = componentFactories;
|
|
30486
|
-
}
|
|
30487
|
-
}
|
|
30488
|
-
/**
|
|
30489
|
-
* Low-level service for running the angular compiler during runtime
|
|
30490
|
-
* to create {@link ComponentFactory}s, which
|
|
30491
|
-
* can later be used to create and render a Component instance.
|
|
30492
|
-
*
|
|
30493
|
-
* Each `@NgModule` provides an own `Compiler` to its injector,
|
|
30494
|
-
* that will use the directives/pipes of the ng module for compilation
|
|
30495
|
-
* of components.
|
|
30496
|
-
*
|
|
30497
|
-
* @publicApi
|
|
30498
|
-
*
|
|
30499
|
-
* @deprecated
|
|
30500
|
-
* Ivy JIT mode doesn't require accessing this symbol.
|
|
30501
|
-
* See [JIT API changes due to ViewEngine deprecation](guide/deprecations#jit-api-changes) for
|
|
30502
|
-
* additional context.
|
|
30503
|
-
*/
|
|
30504
|
-
class Compiler {
|
|
30505
|
-
/**
|
|
30506
|
-
* Compiles the given NgModule and all of its components. All templates of the components
|
|
30507
|
-
* have to be inlined.
|
|
30508
|
-
*/
|
|
30509
|
-
compileModuleSync(moduleType) {
|
|
30510
|
-
return new NgModuleFactory(moduleType);
|
|
30511
|
-
}
|
|
30512
|
-
/**
|
|
30513
|
-
* Compiles the given NgModule and all of its components
|
|
30514
|
-
*/
|
|
30515
|
-
compileModuleAsync(moduleType) {
|
|
30516
|
-
return Promise.resolve(this.compileModuleSync(moduleType));
|
|
30517
|
-
}
|
|
30518
|
-
/**
|
|
30519
|
-
* Same as {@link #compileModuleSync} but also creates ComponentFactories for all components.
|
|
30520
|
-
*/
|
|
30521
|
-
compileModuleAndAllComponentsSync(moduleType) {
|
|
30522
|
-
const ngModuleFactory = this.compileModuleSync(moduleType);
|
|
30523
|
-
const moduleDef = getNgModuleDef(moduleType);
|
|
30524
|
-
const componentFactories = maybeUnwrapFn(moduleDef.declarations)
|
|
30525
|
-
.reduce((factories, declaration) => {
|
|
30526
|
-
const componentDef = getComponentDef(declaration);
|
|
30527
|
-
componentDef && factories.push(new ComponentFactory(componentDef));
|
|
30528
|
-
return factories;
|
|
30529
|
-
}, []);
|
|
30530
|
-
return new ModuleWithComponentFactories(ngModuleFactory, componentFactories);
|
|
30531
|
-
}
|
|
30532
|
-
/**
|
|
30533
|
-
* Same as {@link #compileModuleAsync} but also creates ComponentFactories for all components.
|
|
30534
|
-
*/
|
|
30535
|
-
compileModuleAndAllComponentsAsync(moduleType) {
|
|
30536
|
-
return Promise.resolve(this.compileModuleAndAllComponentsSync(moduleType));
|
|
30537
|
-
}
|
|
30538
|
-
/**
|
|
30539
|
-
* Clears all caches.
|
|
30540
|
-
*/
|
|
30541
|
-
clearCache() { }
|
|
30542
|
-
/**
|
|
30543
|
-
* Clears the cache for the given component/ngModule.
|
|
30544
|
-
*/
|
|
30545
|
-
clearCacheFor(type) { }
|
|
30546
|
-
/**
|
|
30547
|
-
* Returns the id for a given NgModule, if one is defined and known to the compiler.
|
|
30548
|
-
*/
|
|
30549
|
-
getModuleId(moduleType) {
|
|
30550
|
-
return undefined;
|
|
30551
|
-
}
|
|
30552
|
-
static { this.ɵfac = function Compiler_Factory(t) { return new (t || Compiler)(); }; }
|
|
30553
|
-
static { this.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: Compiler, factory: Compiler.ɵfac, providedIn: 'root' }); }
|
|
30554
|
-
}
|
|
30555
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(Compiler, [{
|
|
30556
|
-
type: Injectable,
|
|
30557
|
-
args: [{ providedIn: 'root' }]
|
|
30558
|
-
}], null, null); })();
|
|
30559
|
-
/**
|
|
30560
|
-
* Token to provide CompilerOptions in the platform injector.
|
|
30561
|
-
*
|
|
30562
|
-
* @publicApi
|
|
30563
|
-
*/
|
|
30564
|
-
const COMPILER_OPTIONS = new InjectionToken('compilerOptions');
|
|
30565
|
-
/**
|
|
30566
|
-
* A factory for creating a Compiler
|
|
30567
|
-
*
|
|
30568
|
-
* @publicApi
|
|
30569
|
-
*
|
|
30570
|
-
* @deprecated
|
|
30571
|
-
* Ivy JIT mode doesn't require accessing this symbol.
|
|
30572
|
-
* See [JIT API changes due to ViewEngine deprecation](guide/deprecations#jit-api-changes) for
|
|
30573
|
-
* additional context.
|
|
30574
|
-
*/
|
|
30575
|
-
class CompilerFactory {
|
|
30576
|
-
}
|
|
30577
|
-
|
|
30578
|
-
/**
|
|
30579
|
-
* These are the data structures that our framework injector profiler will fill with data in order
|
|
30580
|
-
* to support DI debugging APIs.
|
|
30581
|
-
*
|
|
30582
|
-
* resolverToTokenToDependencies: Maps an injector to a Map of tokens to an Array of
|
|
30583
|
-
* dependencies. Injector -> Token -> Dependencies This is used to support the
|
|
30584
|
-
* getDependenciesFromInjectable API, which takes in an injector and a token and returns it's
|
|
30585
|
-
* dependencies.
|
|
30586
|
-
*
|
|
30587
|
-
* resolverToProviders: Maps a DI resolver (an Injector or a TNode) to the providers configured
|
|
30588
|
-
* within it This is used to support the getInjectorProviders API, which takes in an injector and
|
|
30589
|
-
* returns the providers that it was configured with. Note that for the element injector case we
|
|
30590
|
-
* use the TNode instead of the LView as the DI resolver. This is because the registration of
|
|
30591
|
-
* providers happens only once per type of TNode. If an injector is created with an identical TNode,
|
|
30592
|
-
* the providers for that injector will not be reconfigured.
|
|
30593
|
-
*
|
|
30594
|
-
* standaloneInjectorToComponent: Maps the injector of a standalone component to the standalone
|
|
30595
|
-
* component that it is associated with. Used in the getInjectorProviders API, specificially in the
|
|
30596
|
-
* discovery of import paths for each provider. This is necessary because the imports array of a
|
|
30597
|
-
* standalone component is processed and configured in its standalone injector, but exists within
|
|
30598
|
-
* the component's definition. Because getInjectorProviders takes in an injector, if that injector
|
|
30599
|
-
* is the injector of a standalone component, we need to be able to discover the place where the
|
|
30600
|
-
* imports array is located (the component) in order to flatten the imports array within it to
|
|
30601
|
-
* discover all of it's providers.
|
|
30602
|
-
*
|
|
30603
|
-
*
|
|
30604
|
-
* All of these data structures are instantiated with WeakMaps. This will ensure that the presence
|
|
30605
|
-
* of any object in the keys of these maps does not prevent the garbage collector from collecting
|
|
30606
|
-
* those objects. Because of this property of WeakMaps, these data structures will never be the
|
|
30607
|
-
* source of a memory leak.
|
|
30608
|
-
*
|
|
30609
|
-
* An example of this advantage: When components are destroyed, we don't need to do
|
|
30610
|
-
* any additional work to remove that component from our mappings.
|
|
30611
|
-
*
|
|
30612
|
-
*/
|
|
30613
|
-
class DIDebugData {
|
|
30614
|
-
constructor() {
|
|
30615
|
-
this.resolverToTokenToDependencies = new WeakMap();
|
|
30616
|
-
this.resolverToProviders = new WeakMap();
|
|
30617
|
-
this.standaloneInjectorToComponent = new WeakMap();
|
|
30618
|
-
}
|
|
30619
|
-
reset() {
|
|
30620
|
-
this.resolverToTokenToDependencies =
|
|
30621
|
-
new WeakMap();
|
|
30622
|
-
this.resolverToProviders = new WeakMap();
|
|
30623
|
-
this.standaloneInjectorToComponent = new WeakMap();
|
|
30624
|
-
}
|
|
30625
|
-
}
|
|
30626
|
-
let frameworkDIDebugData = new DIDebugData();
|
|
30627
|
-
function getFrameworkDIDebugData() {
|
|
30628
|
-
return frameworkDIDebugData;
|
|
30629
|
-
}
|
|
30630
|
-
/**
|
|
30631
|
-
* Initalize default handling of injector events. This handling parses events
|
|
30632
|
-
* as they are emitted and constructs the data structures necessary to support
|
|
30633
|
-
* some of debug APIs.
|
|
30634
|
-
*
|
|
30635
|
-
* See handleInjectEvent, handleCreateEvent and handleProviderConfiguredEvent
|
|
30636
|
-
* for descriptions of each handler
|
|
30637
|
-
*
|
|
30638
|
-
* Supported APIs:
|
|
30639
|
-
* - getDependenciesFromInjectable
|
|
30640
|
-
* - getInjectorProviders
|
|
30641
|
-
*/
|
|
30642
|
-
function setupFrameworkInjectorProfiler() {
|
|
30643
|
-
frameworkDIDebugData.reset();
|
|
30644
|
-
setInjectorProfiler((injectorProfilerEvent) => handleInjectorProfilerEvent(injectorProfilerEvent));
|
|
30645
|
-
}
|
|
30646
|
-
function handleInjectorProfilerEvent(injectorProfilerEvent) {
|
|
30647
|
-
const { context, type } = injectorProfilerEvent;
|
|
30648
|
-
if (type === 0 /* InjectorProfilerEventType.Inject */) {
|
|
30649
|
-
handleInjectEvent(context, injectorProfilerEvent.service);
|
|
30650
|
-
}
|
|
30651
|
-
else if (type === 1 /* InjectorProfilerEventType.InstanceCreatedByInjector */) {
|
|
30652
|
-
handleInstanceCreatedByInjectorEvent(context, injectorProfilerEvent.instance);
|
|
30653
|
-
}
|
|
30654
|
-
else if (type === 2 /* InjectorProfilerEventType.ProviderConfigured */) {
|
|
30655
|
-
handleProviderConfiguredEvent(context, injectorProfilerEvent.providerRecord);
|
|
30656
|
-
}
|
|
30657
|
-
}
|
|
30658
|
-
/**
|
|
30659
|
-
*
|
|
30660
|
-
* Stores the injected service in frameworkDIDebugData.resolverToTokenToDependencies
|
|
30661
|
-
* based on it's injector and token.
|
|
30237
|
+
* Stores the injected service in frameworkDIDebugData.resolverToTokenToDependencies
|
|
30238
|
+
* based on it's injector and token.
|
|
30662
30239
|
*
|
|
30663
30240
|
* @param context InjectorProfilerContext the injection context that this event occurred in.
|
|
30664
30241
|
* @param data InjectedService the service associated with this inject event.
|
|
@@ -30835,6 +30412,7 @@ function applyChanges(component) {
|
|
|
30835
30412
|
*/
|
|
30836
30413
|
function detectChanges(component) {
|
|
30837
30414
|
const view = getComponentViewByInstance(component);
|
|
30415
|
+
view[FLAGS] |= 1024 /* LViewFlags.RefreshView */;
|
|
30838
30416
|
detectChangesInternal(view);
|
|
30839
30417
|
}
|
|
30840
30418
|
|
|
@@ -31730,19 +31308,190 @@ function setTestabilityGetter(getter) {
|
|
|
31730
31308
|
}
|
|
31731
31309
|
let _testabilityGetter;
|
|
31732
31310
|
|
|
31733
|
-
let _platformInjector = null;
|
|
31734
31311
|
/**
|
|
31735
|
-
*
|
|
31736
|
-
* one
|
|
31312
|
+
* A [DI token](guide/glossary#di-token "DI token definition") that you can use to provide
|
|
31313
|
+
* one or more initialization functions.
|
|
31314
|
+
*
|
|
31315
|
+
* The provided functions are injected at application startup and executed during
|
|
31316
|
+
* app initialization. If any of these functions returns a Promise or an Observable, initialization
|
|
31317
|
+
* does not complete until the Promise is resolved or the Observable is completed.
|
|
31318
|
+
*
|
|
31319
|
+
* You can, for example, create a factory function that loads language data
|
|
31320
|
+
* or an external configuration, and provide that function to the `APP_INITIALIZER` token.
|
|
31321
|
+
* The function is executed during the application bootstrap process,
|
|
31322
|
+
* and the needed data is available on startup.
|
|
31323
|
+
*
|
|
31324
|
+
* @see {@link ApplicationInitStatus}
|
|
31325
|
+
*
|
|
31326
|
+
* @usageNotes
|
|
31327
|
+
*
|
|
31328
|
+
* The following example illustrates how to configure a multi-provider using `APP_INITIALIZER` token
|
|
31329
|
+
* and a function returning a promise.
|
|
31330
|
+
* ### Example with NgModule-based application
|
|
31331
|
+
* ```
|
|
31332
|
+
* function initializeApp(): Promise<any> {
|
|
31333
|
+
* return new Promise((resolve, reject) => {
|
|
31334
|
+
* // Do some asynchronous stuff
|
|
31335
|
+
* resolve();
|
|
31336
|
+
* });
|
|
31337
|
+
* }
|
|
31338
|
+
*
|
|
31339
|
+
* @NgModule({
|
|
31340
|
+
* imports: [BrowserModule],
|
|
31341
|
+
* declarations: [AppComponent],
|
|
31342
|
+
* bootstrap: [AppComponent],
|
|
31343
|
+
* providers: [{
|
|
31344
|
+
* provide: APP_INITIALIZER,
|
|
31345
|
+
* useFactory: () => initializeApp,
|
|
31346
|
+
* multi: true
|
|
31347
|
+
* }]
|
|
31348
|
+
* })
|
|
31349
|
+
* export class AppModule {}
|
|
31350
|
+
* ```
|
|
31351
|
+
*
|
|
31352
|
+
* ### Example with standalone application
|
|
31353
|
+
* ```
|
|
31354
|
+
* export function initializeApp(http: HttpClient) {
|
|
31355
|
+
* return (): Promise<any> =>
|
|
31356
|
+
* firstValueFrom(
|
|
31357
|
+
* http
|
|
31358
|
+
* .get("https://someUrl.com/api/user")
|
|
31359
|
+
* .pipe(tap(user => { ... }))
|
|
31360
|
+
* );
|
|
31361
|
+
* }
|
|
31362
|
+
*
|
|
31363
|
+
* bootstrapApplication(App, {
|
|
31364
|
+
* providers: [
|
|
31365
|
+
* provideHttpClient(),
|
|
31366
|
+
* {
|
|
31367
|
+
* provide: APP_INITIALIZER,
|
|
31368
|
+
* useFactory: initializeApp,
|
|
31369
|
+
* multi: true,
|
|
31370
|
+
* deps: [HttpClient],
|
|
31371
|
+
* },
|
|
31372
|
+
* ],
|
|
31373
|
+
* });
|
|
31374
|
+
|
|
31375
|
+
* ```
|
|
31376
|
+
*
|
|
31377
|
+
*
|
|
31378
|
+
* It's also possible to configure a multi-provider using `APP_INITIALIZER` token and a function
|
|
31379
|
+
* returning an observable, see an example below. Note: the `HttpClient` in this example is used for
|
|
31380
|
+
* demo purposes to illustrate how the factory function can work with other providers available
|
|
31381
|
+
* through DI.
|
|
31382
|
+
*
|
|
31383
|
+
* ### Example with NgModule-based application
|
|
31384
|
+
* ```
|
|
31385
|
+
* function initializeAppFactory(httpClient: HttpClient): () => Observable<any> {
|
|
31386
|
+
* return () => httpClient.get("https://someUrl.com/api/user")
|
|
31387
|
+
* .pipe(
|
|
31388
|
+
* tap(user => { ... })
|
|
31389
|
+
* );
|
|
31390
|
+
* }
|
|
31391
|
+
*
|
|
31392
|
+
* @NgModule({
|
|
31393
|
+
* imports: [BrowserModule, HttpClientModule],
|
|
31394
|
+
* declarations: [AppComponent],
|
|
31395
|
+
* bootstrap: [AppComponent],
|
|
31396
|
+
* providers: [{
|
|
31397
|
+
* provide: APP_INITIALIZER,
|
|
31398
|
+
* useFactory: initializeAppFactory,
|
|
31399
|
+
* deps: [HttpClient],
|
|
31400
|
+
* multi: true
|
|
31401
|
+
* }]
|
|
31402
|
+
* })
|
|
31403
|
+
* export class AppModule {}
|
|
31404
|
+
* ```
|
|
31405
|
+
*
|
|
31406
|
+
* ### Example with standalone application
|
|
31407
|
+
* ```
|
|
31408
|
+
* function initializeAppFactory(httpClient: HttpClient): () => Observable<any> {
|
|
31409
|
+
* return () => httpClient.get("https://someUrl.com/api/user")
|
|
31410
|
+
* .pipe(
|
|
31411
|
+
* tap(user => { ... })
|
|
31412
|
+
* );
|
|
31413
|
+
* }
|
|
31414
|
+
*
|
|
31415
|
+
* bootstrapApplication(App, {
|
|
31416
|
+
* providers: [
|
|
31417
|
+
* provideHttpClient(),
|
|
31418
|
+
* {
|
|
31419
|
+
* provide: APP_INITIALIZER,
|
|
31420
|
+
* useFactory: initializeAppFactory,
|
|
31421
|
+
* multi: true,
|
|
31422
|
+
* deps: [HttpClient],
|
|
31423
|
+
* },
|
|
31424
|
+
* ],
|
|
31425
|
+
* });
|
|
31426
|
+
* ```
|
|
31427
|
+
*
|
|
31428
|
+
* @publicApi
|
|
31737
31429
|
*/
|
|
31738
|
-
const
|
|
31430
|
+
const APP_INITIALIZER = new InjectionToken('Application Initializer');
|
|
31739
31431
|
/**
|
|
31740
|
-
*
|
|
31741
|
-
*
|
|
31742
|
-
*
|
|
31743
|
-
* entire class tree-shakeable.
|
|
31432
|
+
* A class that reflects the state of running {@link APP_INITIALIZER} functions.
|
|
31433
|
+
*
|
|
31434
|
+
* @publicApi
|
|
31744
31435
|
*/
|
|
31745
|
-
|
|
31436
|
+
class ApplicationInitStatus {
|
|
31437
|
+
constructor() {
|
|
31438
|
+
this.initialized = false;
|
|
31439
|
+
this.done = false;
|
|
31440
|
+
this.donePromise = new Promise((res, rej) => {
|
|
31441
|
+
this.resolve = res;
|
|
31442
|
+
this.reject = rej;
|
|
31443
|
+
});
|
|
31444
|
+
this.appInits = inject(APP_INITIALIZER, { optional: true }) ?? [];
|
|
31445
|
+
if ((typeof ngDevMode === 'undefined' || ngDevMode) && !Array.isArray(this.appInits)) {
|
|
31446
|
+
throw new RuntimeError(-209 /* RuntimeErrorCode.INVALID_MULTI_PROVIDER */, 'Unexpected type of the `APP_INITIALIZER` token value ' +
|
|
31447
|
+
`(expected an array, but got ${typeof this.appInits}). ` +
|
|
31448
|
+
'Please check that the `APP_INITIALIZER` token is configured as a ' +
|
|
31449
|
+
'`multi: true` provider.');
|
|
31450
|
+
}
|
|
31451
|
+
}
|
|
31452
|
+
/** @internal */
|
|
31453
|
+
runInitializers() {
|
|
31454
|
+
if (this.initialized) {
|
|
31455
|
+
return;
|
|
31456
|
+
}
|
|
31457
|
+
const asyncInitPromises = [];
|
|
31458
|
+
for (const appInits of this.appInits) {
|
|
31459
|
+
const initResult = appInits();
|
|
31460
|
+
if (isPromise(initResult)) {
|
|
31461
|
+
asyncInitPromises.push(initResult);
|
|
31462
|
+
}
|
|
31463
|
+
else if (isSubscribable(initResult)) {
|
|
31464
|
+
const observableAsPromise = new Promise((resolve, reject) => {
|
|
31465
|
+
initResult.subscribe({ complete: resolve, error: reject });
|
|
31466
|
+
});
|
|
31467
|
+
asyncInitPromises.push(observableAsPromise);
|
|
31468
|
+
}
|
|
31469
|
+
}
|
|
31470
|
+
const complete = () => {
|
|
31471
|
+
// @ts-expect-error overwriting a readonly
|
|
31472
|
+
this.done = true;
|
|
31473
|
+
this.resolve();
|
|
31474
|
+
};
|
|
31475
|
+
Promise.all(asyncInitPromises)
|
|
31476
|
+
.then(() => {
|
|
31477
|
+
complete();
|
|
31478
|
+
})
|
|
31479
|
+
.catch(e => {
|
|
31480
|
+
this.reject(e);
|
|
31481
|
+
});
|
|
31482
|
+
if (asyncInitPromises.length === 0) {
|
|
31483
|
+
complete();
|
|
31484
|
+
}
|
|
31485
|
+
this.initialized = true;
|
|
31486
|
+
}
|
|
31487
|
+
static { this.ɵfac = function ApplicationInitStatus_Factory(t) { return new (t || ApplicationInitStatus)(); }; }
|
|
31488
|
+
static { this.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: ApplicationInitStatus, factory: ApplicationInitStatus.ɵfac, providedIn: 'root' }); }
|
|
31489
|
+
}
|
|
31490
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ApplicationInitStatus, [{
|
|
31491
|
+
type: Injectable,
|
|
31492
|
+
args: [{ providedIn: 'root' }]
|
|
31493
|
+
}], () => [], null); })();
|
|
31494
|
+
|
|
31746
31495
|
/**
|
|
31747
31496
|
* A [DI token](guide/glossary#di-token "DI token definition") that provides a set of callbacks to
|
|
31748
31497
|
* be called for every component that is bootstrapped.
|
|
@@ -31810,383 +31559,15 @@ function isBoundToModule(cf) {
|
|
|
31810
31559
|
}
|
|
31811
31560
|
/**
|
|
31812
31561
|
* A token for third-party components that can register themselves with NgProbe.
|
|
31813
|
-
*
|
|
31814
|
-
* @deprecated
|
|
31815
|
-
* @publicApi
|
|
31816
|
-
*/
|
|
31817
|
-
class NgProbeToken {
|
|
31818
|
-
constructor(name, token) {
|
|
31819
|
-
this.name = name;
|
|
31820
|
-
this.token = token;
|
|
31821
|
-
}
|
|
31822
|
-
}
|
|
31823
|
-
/**
|
|
31824
|
-
* Creates a platform.
|
|
31825
|
-
* Platforms must be created on launch using this function.
|
|
31826
|
-
*
|
|
31827
|
-
* @publicApi
|
|
31828
|
-
*/
|
|
31829
|
-
function createPlatform(injector) {
|
|
31830
|
-
if (_platformInjector && !_platformInjector.get(ALLOW_MULTIPLE_PLATFORMS, false)) {
|
|
31831
|
-
throw new RuntimeError(400 /* RuntimeErrorCode.MULTIPLE_PLATFORMS */, ngDevMode &&
|
|
31832
|
-
'There can be only one platform. Destroy the previous one to create a new one.');
|
|
31833
|
-
}
|
|
31834
|
-
publishDefaultGlobalUtils();
|
|
31835
|
-
publishSignalConfiguration();
|
|
31836
|
-
_platformInjector = injector;
|
|
31837
|
-
const platform = injector.get(PlatformRef);
|
|
31838
|
-
runPlatformInitializers(injector);
|
|
31839
|
-
return platform;
|
|
31840
|
-
}
|
|
31841
|
-
/**
|
|
31842
|
-
* The goal of this function is to bootstrap a platform injector,
|
|
31843
|
-
* but avoid referencing `PlatformRef` class.
|
|
31844
|
-
* This function is needed for bootstrapping a Standalone Component.
|
|
31845
|
-
*/
|
|
31846
|
-
function createOrReusePlatformInjector(providers = []) {
|
|
31847
|
-
// If a platform injector already exists, it means that the platform
|
|
31848
|
-
// is already bootstrapped and no additional actions are required.
|
|
31849
|
-
if (_platformInjector)
|
|
31850
|
-
return _platformInjector;
|
|
31851
|
-
publishDefaultGlobalUtils();
|
|
31852
|
-
// Otherwise, setup a new platform injector and run platform initializers.
|
|
31853
|
-
const injector = createPlatformInjector(providers);
|
|
31854
|
-
_platformInjector = injector;
|
|
31855
|
-
publishSignalConfiguration();
|
|
31856
|
-
runPlatformInitializers(injector);
|
|
31857
|
-
return injector;
|
|
31858
|
-
}
|
|
31859
|
-
function runPlatformInitializers(injector) {
|
|
31860
|
-
const inits = injector.get(PLATFORM_INITIALIZER, null);
|
|
31861
|
-
inits?.forEach((init) => init());
|
|
31862
|
-
}
|
|
31863
|
-
/**
|
|
31864
|
-
* Internal create application API that implements the core application creation logic and optional
|
|
31865
|
-
* bootstrap logic.
|
|
31866
|
-
*
|
|
31867
|
-
* Platforms (such as `platform-browser`) may require different set of application and platform
|
|
31868
|
-
* providers for an application to function correctly. As a result, platforms may use this function
|
|
31869
|
-
* internally and supply the necessary providers during the bootstrap, while exposing
|
|
31870
|
-
* platform-specific APIs as a part of their public API.
|
|
31871
|
-
*
|
|
31872
|
-
* @returns A promise that returns an `ApplicationRef` instance once resolved.
|
|
31873
|
-
*/
|
|
31874
|
-
function internalCreateApplication(config) {
|
|
31875
|
-
try {
|
|
31876
|
-
const { rootComponent, appProviders, platformProviders } = config;
|
|
31877
|
-
if ((typeof ngDevMode === 'undefined' || ngDevMode) && rootComponent !== undefined) {
|
|
31878
|
-
assertStandaloneComponentType(rootComponent);
|
|
31879
|
-
}
|
|
31880
|
-
const platformInjector = createOrReusePlatformInjector(platformProviders);
|
|
31881
|
-
// Create root application injector based on a set of providers configured at the platform
|
|
31882
|
-
// bootstrap level as well as providers passed to the bootstrap call by a user.
|
|
31883
|
-
const allAppProviders = [
|
|
31884
|
-
provideZoneChangeDetection(),
|
|
31885
|
-
...(appProviders || []),
|
|
31886
|
-
];
|
|
31887
|
-
const adapter = new EnvironmentNgModuleRefAdapter({
|
|
31888
|
-
providers: allAppProviders,
|
|
31889
|
-
parent: platformInjector,
|
|
31890
|
-
debugName: (typeof ngDevMode === 'undefined' || ngDevMode) ? 'Environment Injector' : '',
|
|
31891
|
-
// We skip environment initializers because we need to run them inside the NgZone, which
|
|
31892
|
-
// happens after we get the NgZone instance from the Injector.
|
|
31893
|
-
runEnvironmentInitializers: false,
|
|
31894
|
-
});
|
|
31895
|
-
const envInjector = adapter.injector;
|
|
31896
|
-
const ngZone = envInjector.get(NgZone);
|
|
31897
|
-
return ngZone.run(() => {
|
|
31898
|
-
envInjector.resolveInjectorInitializers();
|
|
31899
|
-
const exceptionHandler = envInjector.get(ErrorHandler, null);
|
|
31900
|
-
if ((typeof ngDevMode === 'undefined' || ngDevMode) && !exceptionHandler) {
|
|
31901
|
-
throw new RuntimeError(402 /* RuntimeErrorCode.MISSING_REQUIRED_INJECTABLE_IN_BOOTSTRAP */, 'No `ErrorHandler` found in the Dependency Injection tree.');
|
|
31902
|
-
}
|
|
31903
|
-
let onErrorSubscription;
|
|
31904
|
-
ngZone.runOutsideAngular(() => {
|
|
31905
|
-
onErrorSubscription = ngZone.onError.subscribe({
|
|
31906
|
-
next: (error) => {
|
|
31907
|
-
exceptionHandler.handleError(error);
|
|
31908
|
-
}
|
|
31909
|
-
});
|
|
31910
|
-
});
|
|
31911
|
-
// If the whole platform is destroyed, invoke the `destroy` method
|
|
31912
|
-
// for all bootstrapped applications as well.
|
|
31913
|
-
const destroyListener = () => envInjector.destroy();
|
|
31914
|
-
const onPlatformDestroyListeners = platformInjector.get(PLATFORM_DESTROY_LISTENERS);
|
|
31915
|
-
onPlatformDestroyListeners.add(destroyListener);
|
|
31916
|
-
envInjector.onDestroy(() => {
|
|
31917
|
-
onErrorSubscription.unsubscribe();
|
|
31918
|
-
onPlatformDestroyListeners.delete(destroyListener);
|
|
31919
|
-
});
|
|
31920
|
-
return _callAndReportToErrorHandler(exceptionHandler, ngZone, () => {
|
|
31921
|
-
const initStatus = envInjector.get(ApplicationInitStatus);
|
|
31922
|
-
initStatus.runInitializers();
|
|
31923
|
-
return initStatus.donePromise.then(() => {
|
|
31924
|
-
const localeId = envInjector.get(LOCALE_ID, DEFAULT_LOCALE_ID);
|
|
31925
|
-
setLocaleId(localeId || DEFAULT_LOCALE_ID);
|
|
31926
|
-
const appRef = envInjector.get(ApplicationRef);
|
|
31927
|
-
if (rootComponent !== undefined) {
|
|
31928
|
-
appRef.bootstrap(rootComponent);
|
|
31929
|
-
}
|
|
31930
|
-
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
31931
|
-
const imagePerformanceService = envInjector.get(ImagePerformanceWarning);
|
|
31932
|
-
imagePerformanceService.start();
|
|
31933
|
-
}
|
|
31934
|
-
return appRef;
|
|
31935
|
-
});
|
|
31936
|
-
});
|
|
31937
|
-
});
|
|
31938
|
-
}
|
|
31939
|
-
catch (e) {
|
|
31940
|
-
return Promise.reject(e);
|
|
31941
|
-
}
|
|
31942
|
-
}
|
|
31943
|
-
/**
|
|
31944
|
-
* Creates a factory for a platform. Can be used to provide or override `Providers` specific to
|
|
31945
|
-
* your application's runtime needs, such as `PLATFORM_INITIALIZER` and `PLATFORM_ID`.
|
|
31946
|
-
* @param parentPlatformFactory Another platform factory to modify. Allows you to compose factories
|
|
31947
|
-
* to build up configurations that might be required by different libraries or parts of the
|
|
31948
|
-
* application.
|
|
31949
|
-
* @param name Identifies the new platform factory.
|
|
31950
|
-
* @param providers A set of dependency providers for platforms created with the new factory.
|
|
31951
|
-
*
|
|
31952
|
-
* @publicApi
|
|
31953
|
-
*/
|
|
31954
|
-
function createPlatformFactory(parentPlatformFactory, name, providers = []) {
|
|
31955
|
-
const desc = `Platform: ${name}`;
|
|
31956
|
-
const marker = new InjectionToken(desc);
|
|
31957
|
-
return (extraProviders = []) => {
|
|
31958
|
-
let platform = getPlatform();
|
|
31959
|
-
if (!platform || platform.injector.get(ALLOW_MULTIPLE_PLATFORMS, false)) {
|
|
31960
|
-
const platformProviders = [
|
|
31961
|
-
...providers,
|
|
31962
|
-
...extraProviders,
|
|
31963
|
-
{ provide: marker, useValue: true }
|
|
31964
|
-
];
|
|
31965
|
-
if (parentPlatformFactory) {
|
|
31966
|
-
parentPlatformFactory(platformProviders);
|
|
31967
|
-
}
|
|
31968
|
-
else {
|
|
31969
|
-
createPlatform(createPlatformInjector(platformProviders, desc));
|
|
31970
|
-
}
|
|
31971
|
-
}
|
|
31972
|
-
return assertPlatform(marker);
|
|
31973
|
-
};
|
|
31974
|
-
}
|
|
31975
|
-
/**
|
|
31976
|
-
* Checks that there is currently a platform that contains the given token as a provider.
|
|
31977
|
-
*
|
|
31978
|
-
* @publicApi
|
|
31979
|
-
*/
|
|
31980
|
-
function assertPlatform(requiredToken) {
|
|
31981
|
-
const platform = getPlatform();
|
|
31982
|
-
if (!platform) {
|
|
31983
|
-
throw new RuntimeError(401 /* RuntimeErrorCode.PLATFORM_NOT_FOUND */, ngDevMode && 'No platform exists!');
|
|
31984
|
-
}
|
|
31985
|
-
if ((typeof ngDevMode === 'undefined' || ngDevMode) &&
|
|
31986
|
-
!platform.injector.get(requiredToken, null)) {
|
|
31987
|
-
throw new RuntimeError(400 /* RuntimeErrorCode.MULTIPLE_PLATFORMS */, 'A platform with a different configuration has been created. Please destroy it first.');
|
|
31988
|
-
}
|
|
31989
|
-
return platform;
|
|
31990
|
-
}
|
|
31991
|
-
/**
|
|
31992
|
-
* Helper function to create an instance of a platform injector (that maintains the 'platform'
|
|
31993
|
-
* scope).
|
|
31994
|
-
*/
|
|
31995
|
-
function createPlatformInjector(providers = [], name) {
|
|
31996
|
-
return Injector.create({
|
|
31997
|
-
name,
|
|
31998
|
-
providers: [
|
|
31999
|
-
{ provide: INJECTOR_SCOPE, useValue: 'platform' },
|
|
32000
|
-
{ provide: PLATFORM_DESTROY_LISTENERS, useValue: new Set([() => _platformInjector = null]) },
|
|
32001
|
-
...providers
|
|
32002
|
-
],
|
|
32003
|
-
});
|
|
32004
|
-
}
|
|
32005
|
-
/**
|
|
32006
|
-
* Destroys the current Angular platform and all Angular applications on the page.
|
|
32007
|
-
* Destroys all modules and listeners registered with the platform.
|
|
32008
|
-
*
|
|
32009
|
-
* @publicApi
|
|
32010
|
-
*/
|
|
32011
|
-
function destroyPlatform() {
|
|
32012
|
-
getPlatform()?.destroy();
|
|
32013
|
-
}
|
|
32014
|
-
/**
|
|
32015
|
-
* Returns the current platform.
|
|
32016
|
-
*
|
|
32017
|
-
* @publicApi
|
|
32018
|
-
*/
|
|
32019
|
-
function getPlatform() {
|
|
32020
|
-
return _platformInjector?.get(PlatformRef) ?? null;
|
|
32021
|
-
}
|
|
32022
|
-
/**
|
|
32023
|
-
* The Angular platform is the entry point for Angular on a web page.
|
|
32024
|
-
* Each page has exactly one platform. Services (such as reflection) which are common
|
|
32025
|
-
* to every Angular application running on the page are bound in its scope.
|
|
32026
|
-
* A page's platform is initialized implicitly when a platform is created using a platform
|
|
32027
|
-
* factory such as `PlatformBrowser`, or explicitly by calling the `createPlatform()` function.
|
|
32028
|
-
*
|
|
32029
|
-
* @publicApi
|
|
32030
|
-
*/
|
|
32031
|
-
class PlatformRef {
|
|
32032
|
-
/** @internal */
|
|
32033
|
-
constructor(_injector) {
|
|
32034
|
-
this._injector = _injector;
|
|
32035
|
-
this._modules = [];
|
|
32036
|
-
this._destroyListeners = [];
|
|
32037
|
-
this._destroyed = false;
|
|
32038
|
-
}
|
|
32039
|
-
/**
|
|
32040
|
-
* Creates an instance of an `@NgModule` for the given platform.
|
|
32041
|
-
*
|
|
32042
|
-
* @deprecated Passing NgModule factories as the `PlatformRef.bootstrapModuleFactory` function
|
|
32043
|
-
* argument is deprecated. Use the `PlatformRef.bootstrapModule` API instead.
|
|
32044
|
-
*/
|
|
32045
|
-
bootstrapModuleFactory(moduleFactory, options) {
|
|
32046
|
-
// Note: We need to create the NgZone _before_ we instantiate the module,
|
|
32047
|
-
// as instantiating the module creates some providers eagerly.
|
|
32048
|
-
// So we create a mini parent injector that just contains the new NgZone and
|
|
32049
|
-
// pass that as parent to the NgModuleFactory.
|
|
32050
|
-
const ngZone = getNgZone(options?.ngZone, getNgZoneOptions({
|
|
32051
|
-
eventCoalescing: options?.ngZoneEventCoalescing,
|
|
32052
|
-
runCoalescing: options?.ngZoneRunCoalescing
|
|
32053
|
-
}));
|
|
32054
|
-
// Note: Create ngZoneInjector within ngZone.run so that all of the instantiated services are
|
|
32055
|
-
// created within the Angular zone
|
|
32056
|
-
// Do not try to replace ngZone.run with ApplicationRef#run because ApplicationRef would then be
|
|
32057
|
-
// created outside of the Angular zone.
|
|
32058
|
-
return ngZone.run(() => {
|
|
32059
|
-
const moduleRef = createNgModuleRefWithProviders(moduleFactory.moduleType, this.injector, internalProvideZoneChangeDetection(() => ngZone));
|
|
32060
|
-
if ((typeof ngDevMode === 'undefined' || ngDevMode) &&
|
|
32061
|
-
moduleRef.injector.get(PROVIDED_NG_ZONE, null) !== null) {
|
|
32062
|
-
throw new RuntimeError(207 /* RuntimeErrorCode.PROVIDER_IN_WRONG_CONTEXT */, '`bootstrapModule` does not support `provideZoneChangeDetection`. Use `BootstrapOptions` instead.');
|
|
32063
|
-
}
|
|
32064
|
-
const exceptionHandler = moduleRef.injector.get(ErrorHandler, null);
|
|
32065
|
-
if ((typeof ngDevMode === 'undefined' || ngDevMode) && exceptionHandler === null) {
|
|
32066
|
-
throw new RuntimeError(402 /* RuntimeErrorCode.MISSING_REQUIRED_INJECTABLE_IN_BOOTSTRAP */, 'No ErrorHandler. Is platform module (BrowserModule) included?');
|
|
32067
|
-
}
|
|
32068
|
-
ngZone.runOutsideAngular(() => {
|
|
32069
|
-
const subscription = ngZone.onError.subscribe({
|
|
32070
|
-
next: (error) => {
|
|
32071
|
-
exceptionHandler.handleError(error);
|
|
32072
|
-
}
|
|
32073
|
-
});
|
|
32074
|
-
moduleRef.onDestroy(() => {
|
|
32075
|
-
remove(this._modules, moduleRef);
|
|
32076
|
-
subscription.unsubscribe();
|
|
32077
|
-
});
|
|
32078
|
-
});
|
|
32079
|
-
return _callAndReportToErrorHandler(exceptionHandler, ngZone, () => {
|
|
32080
|
-
const initStatus = moduleRef.injector.get(ApplicationInitStatus);
|
|
32081
|
-
initStatus.runInitializers();
|
|
32082
|
-
return initStatus.donePromise.then(() => {
|
|
32083
|
-
// If the `LOCALE_ID` provider is defined at bootstrap then we set the value for ivy
|
|
32084
|
-
const localeId = moduleRef.injector.get(LOCALE_ID, DEFAULT_LOCALE_ID);
|
|
32085
|
-
setLocaleId(localeId || DEFAULT_LOCALE_ID);
|
|
32086
|
-
this._moduleDoBootstrap(moduleRef);
|
|
32087
|
-
return moduleRef;
|
|
32088
|
-
});
|
|
32089
|
-
});
|
|
32090
|
-
});
|
|
32091
|
-
}
|
|
32092
|
-
/**
|
|
32093
|
-
* Creates an instance of an `@NgModule` for a given platform.
|
|
32094
|
-
*
|
|
32095
|
-
* @usageNotes
|
|
32096
|
-
* ### Simple Example
|
|
32097
|
-
*
|
|
32098
|
-
* ```typescript
|
|
32099
|
-
* @NgModule({
|
|
32100
|
-
* imports: [BrowserModule]
|
|
32101
|
-
* })
|
|
32102
|
-
* class MyModule {}
|
|
32103
|
-
*
|
|
32104
|
-
* let moduleRef = platformBrowser().bootstrapModule(MyModule);
|
|
32105
|
-
* ```
|
|
32106
|
-
*
|
|
32107
|
-
*/
|
|
32108
|
-
bootstrapModule(moduleType, compilerOptions = []) {
|
|
32109
|
-
const options = optionsReducer({}, compilerOptions);
|
|
32110
|
-
return compileNgModuleFactory(this.injector, options, moduleType)
|
|
32111
|
-
.then(moduleFactory => this.bootstrapModuleFactory(moduleFactory, options));
|
|
32112
|
-
}
|
|
32113
|
-
_moduleDoBootstrap(moduleRef) {
|
|
32114
|
-
const appRef = moduleRef.injector.get(ApplicationRef);
|
|
32115
|
-
if (moduleRef._bootstrapComponents.length > 0) {
|
|
32116
|
-
moduleRef._bootstrapComponents.forEach(f => appRef.bootstrap(f));
|
|
32117
|
-
}
|
|
32118
|
-
else if (moduleRef.instance.ngDoBootstrap) {
|
|
32119
|
-
moduleRef.instance.ngDoBootstrap(appRef);
|
|
32120
|
-
}
|
|
32121
|
-
else {
|
|
32122
|
-
throw new RuntimeError(-403 /* RuntimeErrorCode.BOOTSTRAP_COMPONENTS_NOT_FOUND */, ngDevMode &&
|
|
32123
|
-
`The module ${stringify(moduleRef.instance.constructor)} was bootstrapped, ` +
|
|
32124
|
-
`but it does not declare "@NgModule.bootstrap" components nor a "ngDoBootstrap" method. ` +
|
|
32125
|
-
`Please define one of these.`);
|
|
32126
|
-
}
|
|
32127
|
-
this._modules.push(moduleRef);
|
|
32128
|
-
}
|
|
32129
|
-
/**
|
|
32130
|
-
* Registers a listener to be called when the platform is destroyed.
|
|
32131
|
-
*/
|
|
32132
|
-
onDestroy(callback) {
|
|
32133
|
-
this._destroyListeners.push(callback);
|
|
32134
|
-
}
|
|
32135
|
-
/**
|
|
32136
|
-
* Retrieves the platform {@link Injector}, which is the parent injector for
|
|
32137
|
-
* every Angular application on the page and provides singleton providers.
|
|
32138
|
-
*/
|
|
32139
|
-
get injector() {
|
|
32140
|
-
return this._injector;
|
|
32141
|
-
}
|
|
32142
|
-
/**
|
|
32143
|
-
* Destroys the current Angular platform and all Angular applications on the page.
|
|
32144
|
-
* Destroys all modules and listeners registered with the platform.
|
|
32145
|
-
*/
|
|
32146
|
-
destroy() {
|
|
32147
|
-
if (this._destroyed) {
|
|
32148
|
-
throw new RuntimeError(404 /* RuntimeErrorCode.PLATFORM_ALREADY_DESTROYED */, ngDevMode && 'The platform has already been destroyed!');
|
|
32149
|
-
}
|
|
32150
|
-
this._modules.slice().forEach(module => module.destroy());
|
|
32151
|
-
this._destroyListeners.forEach(listener => listener());
|
|
32152
|
-
const destroyListeners = this._injector.get(PLATFORM_DESTROY_LISTENERS, null);
|
|
32153
|
-
if (destroyListeners) {
|
|
32154
|
-
destroyListeners.forEach(listener => listener());
|
|
32155
|
-
destroyListeners.clear();
|
|
32156
|
-
}
|
|
32157
|
-
this._destroyed = true;
|
|
32158
|
-
}
|
|
32159
|
-
/**
|
|
32160
|
-
* Indicates whether this instance was destroyed.
|
|
32161
|
-
*/
|
|
32162
|
-
get destroyed() {
|
|
32163
|
-
return this._destroyed;
|
|
32164
|
-
}
|
|
32165
|
-
static { this.ɵfac = function PlatformRef_Factory(t) { return new (t || PlatformRef)(ɵɵinject(Injector)); }; }
|
|
32166
|
-
static { this.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: PlatformRef, factory: PlatformRef.ɵfac, providedIn: 'platform' }); }
|
|
32167
|
-
}
|
|
32168
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(PlatformRef, [{
|
|
32169
|
-
type: Injectable,
|
|
32170
|
-
args: [{ providedIn: 'platform' }]
|
|
32171
|
-
}], () => [{ type: Injector }], null); })();
|
|
32172
|
-
// Transforms a set of `BootstrapOptions` (supported by the NgModule-based bootstrap APIs) ->
|
|
32173
|
-
// `NgZoneOptions` that are recognized by the NgZone constructor. Passing no options will result in
|
|
32174
|
-
// a set of default options returned.
|
|
32175
|
-
function getNgZoneOptions(options) {
|
|
32176
|
-
return {
|
|
32177
|
-
enableLongStackTrace: typeof ngDevMode === 'undefined' ? false : !!ngDevMode,
|
|
32178
|
-
shouldCoalesceEventChangeDetection: options?.eventCoalescing ?? false,
|
|
32179
|
-
shouldCoalesceRunChangeDetection: options?.runCoalescing ?? false,
|
|
32180
|
-
};
|
|
32181
|
-
}
|
|
32182
|
-
function getNgZone(ngZoneToUse = 'zone.js', options) {
|
|
32183
|
-
if (ngZoneToUse === 'noop') {
|
|
32184
|
-
return new NoopNgZone();
|
|
32185
|
-
}
|
|
32186
|
-
if (ngZoneToUse === 'zone.js') {
|
|
32187
|
-
return new NgZone(options);
|
|
31562
|
+
*
|
|
31563
|
+
* @deprecated
|
|
31564
|
+
* @publicApi
|
|
31565
|
+
*/
|
|
31566
|
+
class NgProbeToken {
|
|
31567
|
+
constructor(name, token) {
|
|
31568
|
+
this.name = name;
|
|
31569
|
+
this.token = token;
|
|
32188
31570
|
}
|
|
32189
|
-
return ngZoneToUse;
|
|
32190
31571
|
}
|
|
32191
31572
|
function _callAndReportToErrorHandler(errorHandler, ngZone, callback) {
|
|
32192
31573
|
try {
|
|
@@ -32328,7 +31709,7 @@ class ApplicationRef {
|
|
|
32328
31709
|
* Returns an Observable that indicates when the application is stable or unstable.
|
|
32329
31710
|
*/
|
|
32330
31711
|
this.isStable = inject(InitialRenderPendingTasks)
|
|
32331
|
-
.hasPendingTasks.pipe(switchMap(hasPendingTasks => hasPendingTasks ? of(false) : this.zoneIsStable), distinctUntilChanged()
|
|
31712
|
+
.hasPendingTasks.pipe(switchMap(hasPendingTasks => hasPendingTasks ? of(false) : this.zoneIsStable), distinctUntilChanged());
|
|
32332
31713
|
this._injector = inject(EnvironmentInjector);
|
|
32333
31714
|
}
|
|
32334
31715
|
/**
|
|
@@ -32566,24 +31947,24 @@ function _lastDefined(args) {
|
|
|
32566
31947
|
}
|
|
32567
31948
|
return undefined;
|
|
32568
31949
|
}
|
|
31950
|
+
let whenStableStore;
|
|
32569
31951
|
/**
|
|
32570
|
-
*
|
|
32571
|
-
*
|
|
32572
|
-
* `NgZone` is provided by default today so the default (and only) implementation for this
|
|
32573
|
-
* is calling `ErrorHandler.handleError` outside of the Angular zone.
|
|
31952
|
+
* Returns a Promise that resolves when the application becomes stable after this method is called
|
|
31953
|
+
* the first time.
|
|
32574
31954
|
*/
|
|
32575
|
-
|
|
32576
|
-
|
|
32577
|
-
|
|
32578
|
-
|
|
32579
|
-
return
|
|
31955
|
+
function whenStable(applicationRef) {
|
|
31956
|
+
whenStableStore ??= new WeakMap();
|
|
31957
|
+
const cachedWhenStable = whenStableStore.get(applicationRef);
|
|
31958
|
+
if (cachedWhenStable) {
|
|
31959
|
+
return cachedWhenStable;
|
|
32580
31960
|
}
|
|
32581
|
-
|
|
32582
|
-
|
|
32583
|
-
|
|
32584
|
-
|
|
32585
|
-
return
|
|
31961
|
+
const whenStablePromise = applicationRef.isStable.pipe(first((isStable) => isStable)).toPromise().then(() => void 0);
|
|
31962
|
+
whenStableStore.set(applicationRef, whenStablePromise);
|
|
31963
|
+
// Be a good citizen and clean the store `onDestroy` even though we are using `WeakMap`.
|
|
31964
|
+
applicationRef.onDestroy(() => whenStableStore?.delete(applicationRef));
|
|
31965
|
+
return whenStablePromise;
|
|
32586
31966
|
}
|
|
31967
|
+
|
|
32587
31968
|
class NgZoneChangeDetectionScheduler {
|
|
32588
31969
|
constructor() {
|
|
32589
31970
|
this.zone = inject(NgZone);
|
|
@@ -32636,6 +32017,11 @@ function internalProvideZoneChangeDetection(ngZoneFactory) {
|
|
|
32636
32017
|
{ provide: ZONE_IS_STABLE_OBSERVABLE, useFactory: isStableFactory },
|
|
32637
32018
|
];
|
|
32638
32019
|
}
|
|
32020
|
+
function ngZoneApplicationErrorHandlerFactory() {
|
|
32021
|
+
const zone = inject(NgZone);
|
|
32022
|
+
const userErrorHandler = inject(ErrorHandler);
|
|
32023
|
+
return (e) => zone.runOutsideAngular(() => userErrorHandler.handleError(e));
|
|
32024
|
+
}
|
|
32639
32025
|
/**
|
|
32640
32026
|
* Provides `NgZone`-based change detection for the application bootstrapped using
|
|
32641
32027
|
* `bootstrapApplication`.
|
|
@@ -32664,22 +32050,467 @@ function provideZoneChangeDetection(options) {
|
|
|
32664
32050
|
zoneProviders,
|
|
32665
32051
|
]);
|
|
32666
32052
|
}
|
|
32667
|
-
|
|
32053
|
+
// Transforms a set of `BootstrapOptions` (supported by the NgModule-based bootstrap APIs) ->
|
|
32054
|
+
// `NgZoneOptions` that are recognized by the NgZone constructor. Passing no options will result in
|
|
32055
|
+
// a set of default options returned.
|
|
32056
|
+
function getNgZoneOptions(options) {
|
|
32057
|
+
return {
|
|
32058
|
+
enableLongStackTrace: typeof ngDevMode === 'undefined' ? false : !!ngDevMode,
|
|
32059
|
+
shouldCoalesceEventChangeDetection: options?.eventCoalescing ?? false,
|
|
32060
|
+
shouldCoalesceRunChangeDetection: options?.runCoalescing ?? false,
|
|
32061
|
+
};
|
|
32062
|
+
}
|
|
32063
|
+
|
|
32668
32064
|
/**
|
|
32669
|
-
*
|
|
32670
|
-
*
|
|
32065
|
+
* Work out the locale from the potential global properties.
|
|
32066
|
+
*
|
|
32067
|
+
* * Closure Compiler: use `goog.LOCALE`.
|
|
32068
|
+
* * Ivy enabled: use `$localize.locale`
|
|
32671
32069
|
*/
|
|
32672
|
-
function
|
|
32673
|
-
|
|
32674
|
-
|
|
32675
|
-
|
|
32676
|
-
|
|
32070
|
+
function getGlobalLocale() {
|
|
32071
|
+
if (typeof ngI18nClosureMode !== 'undefined' && ngI18nClosureMode &&
|
|
32072
|
+
typeof goog !== 'undefined' && goog.LOCALE !== 'en') {
|
|
32073
|
+
// * The default `goog.LOCALE` value is `en`, while Angular used `en-US`.
|
|
32074
|
+
// * In order to preserve backwards compatibility, we use Angular default value over
|
|
32075
|
+
// Closure Compiler's one.
|
|
32076
|
+
return goog.LOCALE;
|
|
32677
32077
|
}
|
|
32678
|
-
|
|
32679
|
-
|
|
32680
|
-
|
|
32681
|
-
|
|
32682
|
-
|
|
32078
|
+
else {
|
|
32079
|
+
// KEEP `typeof $localize !== 'undefined' && $localize.locale` IN SYNC WITH THE LOCALIZE
|
|
32080
|
+
// COMPILE-TIME INLINER.
|
|
32081
|
+
//
|
|
32082
|
+
// * During compile time inlining of translations the expression will be replaced
|
|
32083
|
+
// with a string literal that is the current locale. Other forms of this expression are not
|
|
32084
|
+
// guaranteed to be replaced.
|
|
32085
|
+
//
|
|
32086
|
+
// * During runtime translation evaluation, the developer is required to set `$localize.locale`
|
|
32087
|
+
// if required, or just to provide their own `LOCALE_ID` provider.
|
|
32088
|
+
return (typeof $localize !== 'undefined' && $localize.locale) || DEFAULT_LOCALE_ID;
|
|
32089
|
+
}
|
|
32090
|
+
}
|
|
32091
|
+
/**
|
|
32092
|
+
* Provide this token to set the locale of your application.
|
|
32093
|
+
* It is used for i18n extraction, by i18n pipes (DatePipe, I18nPluralPipe, CurrencyPipe,
|
|
32094
|
+
* DecimalPipe and PercentPipe) and by ICU expressions.
|
|
32095
|
+
*
|
|
32096
|
+
* See the [i18n guide](guide/i18n-common-locale-id) for more information.
|
|
32097
|
+
*
|
|
32098
|
+
* @usageNotes
|
|
32099
|
+
* ### Example
|
|
32100
|
+
*
|
|
32101
|
+
* ```typescript
|
|
32102
|
+
* import { LOCALE_ID } from '@angular/core';
|
|
32103
|
+
* import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
|
32104
|
+
* import { AppModule } from './app/app.module';
|
|
32105
|
+
*
|
|
32106
|
+
* platformBrowserDynamic().bootstrapModule(AppModule, {
|
|
32107
|
+
* providers: [{provide: LOCALE_ID, useValue: 'en-US' }]
|
|
32108
|
+
* });
|
|
32109
|
+
* ```
|
|
32110
|
+
*
|
|
32111
|
+
* @publicApi
|
|
32112
|
+
*/
|
|
32113
|
+
const LOCALE_ID = new InjectionToken('LocaleId', {
|
|
32114
|
+
providedIn: 'root',
|
|
32115
|
+
factory: () => inject(LOCALE_ID, InjectFlags.Optional | InjectFlags.SkipSelf) || getGlobalLocale(),
|
|
32116
|
+
});
|
|
32117
|
+
/**
|
|
32118
|
+
* Provide this token to set the default currency code your application uses for
|
|
32119
|
+
* CurrencyPipe when there is no currency code passed into it. This is only used by
|
|
32120
|
+
* CurrencyPipe and has no relation to locale currency. Defaults to USD if not configured.
|
|
32121
|
+
*
|
|
32122
|
+
* See the [i18n guide](guide/i18n-common-locale-id) for more information.
|
|
32123
|
+
*
|
|
32124
|
+
* <div class="alert is-helpful">
|
|
32125
|
+
*
|
|
32126
|
+
* **Deprecation notice:**
|
|
32127
|
+
*
|
|
32128
|
+
* The default currency code is currently always `USD` but this is deprecated from v9.
|
|
32129
|
+
*
|
|
32130
|
+
* **In v10 the default currency code will be taken from the current locale.**
|
|
32131
|
+
*
|
|
32132
|
+
* If you need the previous behavior then set it by creating a `DEFAULT_CURRENCY_CODE` provider in
|
|
32133
|
+
* your application `NgModule`:
|
|
32134
|
+
*
|
|
32135
|
+
* ```ts
|
|
32136
|
+
* {provide: DEFAULT_CURRENCY_CODE, useValue: 'USD'}
|
|
32137
|
+
* ```
|
|
32138
|
+
*
|
|
32139
|
+
* </div>
|
|
32140
|
+
*
|
|
32141
|
+
* @usageNotes
|
|
32142
|
+
* ### Example
|
|
32143
|
+
*
|
|
32144
|
+
* ```typescript
|
|
32145
|
+
* import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
|
32146
|
+
* import { AppModule } from './app/app.module';
|
|
32147
|
+
*
|
|
32148
|
+
* platformBrowserDynamic().bootstrapModule(AppModule, {
|
|
32149
|
+
* providers: [{provide: DEFAULT_CURRENCY_CODE, useValue: 'EUR' }]
|
|
32150
|
+
* });
|
|
32151
|
+
* ```
|
|
32152
|
+
*
|
|
32153
|
+
* @publicApi
|
|
32154
|
+
*/
|
|
32155
|
+
const DEFAULT_CURRENCY_CODE = new InjectionToken('DefaultCurrencyCode', {
|
|
32156
|
+
providedIn: 'root',
|
|
32157
|
+
factory: () => USD_CURRENCY_CODE,
|
|
32158
|
+
});
|
|
32159
|
+
/**
|
|
32160
|
+
* Use this token at bootstrap to provide the content of your translation file (`xtb`,
|
|
32161
|
+
* `xlf` or `xlf2`) when you want to translate your application in another language.
|
|
32162
|
+
*
|
|
32163
|
+
* See the [i18n guide](guide/i18n-common-merge) for more information.
|
|
32164
|
+
*
|
|
32165
|
+
* @usageNotes
|
|
32166
|
+
* ### Example
|
|
32167
|
+
*
|
|
32168
|
+
* ```typescript
|
|
32169
|
+
* import { TRANSLATIONS } from '@angular/core';
|
|
32170
|
+
* import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
|
32171
|
+
* import { AppModule } from './app/app.module';
|
|
32172
|
+
*
|
|
32173
|
+
* // content of your translation file
|
|
32174
|
+
* const translations = '....';
|
|
32175
|
+
*
|
|
32176
|
+
* platformBrowserDynamic().bootstrapModule(AppModule, {
|
|
32177
|
+
* providers: [{provide: TRANSLATIONS, useValue: translations }]
|
|
32178
|
+
* });
|
|
32179
|
+
* ```
|
|
32180
|
+
*
|
|
32181
|
+
* @publicApi
|
|
32182
|
+
*/
|
|
32183
|
+
const TRANSLATIONS = new InjectionToken('Translations');
|
|
32184
|
+
/**
|
|
32185
|
+
* Provide this token at bootstrap to set the format of your {@link TRANSLATIONS}: `xtb`,
|
|
32186
|
+
* `xlf` or `xlf2`.
|
|
32187
|
+
*
|
|
32188
|
+
* See the [i18n guide](guide/i18n-common-merge) for more information.
|
|
32189
|
+
*
|
|
32190
|
+
* @usageNotes
|
|
32191
|
+
* ### Example
|
|
32192
|
+
*
|
|
32193
|
+
* ```typescript
|
|
32194
|
+
* import { TRANSLATIONS_FORMAT } from '@angular/core';
|
|
32195
|
+
* import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
|
32196
|
+
* import { AppModule } from './app/app.module';
|
|
32197
|
+
*
|
|
32198
|
+
* platformBrowserDynamic().bootstrapModule(AppModule, {
|
|
32199
|
+
* providers: [{provide: TRANSLATIONS_FORMAT, useValue: 'xlf' }]
|
|
32200
|
+
* });
|
|
32201
|
+
* ```
|
|
32202
|
+
*
|
|
32203
|
+
* @publicApi
|
|
32204
|
+
*/
|
|
32205
|
+
const TRANSLATIONS_FORMAT = new InjectionToken('TranslationsFormat');
|
|
32206
|
+
/**
|
|
32207
|
+
* Use this enum at bootstrap as an option of `bootstrapModule` to define the strategy
|
|
32208
|
+
* that the compiler should use in case of missing translations:
|
|
32209
|
+
* - Error: throw if you have missing translations.
|
|
32210
|
+
* - Warning (default): show a warning in the console and/or shell.
|
|
32211
|
+
* - Ignore: do nothing.
|
|
32212
|
+
*
|
|
32213
|
+
* See the [i18n guide](guide/i18n-common-merge#report-missing-translations) for more information.
|
|
32214
|
+
*
|
|
32215
|
+
* @usageNotes
|
|
32216
|
+
* ### Example
|
|
32217
|
+
* ```typescript
|
|
32218
|
+
* import { MissingTranslationStrategy } from '@angular/core';
|
|
32219
|
+
* import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
|
32220
|
+
* import { AppModule } from './app/app.module';
|
|
32221
|
+
*
|
|
32222
|
+
* platformBrowserDynamic().bootstrapModule(AppModule, {
|
|
32223
|
+
* missingTranslation: MissingTranslationStrategy.Error
|
|
32224
|
+
* });
|
|
32225
|
+
* ```
|
|
32226
|
+
*
|
|
32227
|
+
* @publicApi
|
|
32228
|
+
*/
|
|
32229
|
+
var MissingTranslationStrategy;
|
|
32230
|
+
(function (MissingTranslationStrategy) {
|
|
32231
|
+
MissingTranslationStrategy[MissingTranslationStrategy["Error"] = 0] = "Error";
|
|
32232
|
+
MissingTranslationStrategy[MissingTranslationStrategy["Warning"] = 1] = "Warning";
|
|
32233
|
+
MissingTranslationStrategy[MissingTranslationStrategy["Ignore"] = 2] = "Ignore";
|
|
32234
|
+
})(MissingTranslationStrategy || (MissingTranslationStrategy = {}));
|
|
32235
|
+
|
|
32236
|
+
/**
|
|
32237
|
+
* Internal token that allows to register extra callbacks that should be invoked during the
|
|
32238
|
+
* `PlatformRef.destroy` operation. This token is needed to avoid a direct reference to the
|
|
32239
|
+
* `PlatformRef` class (i.e. register the callback via `PlatformRef.onDestroy`), thus making the
|
|
32240
|
+
* entire class tree-shakeable.
|
|
32241
|
+
*/
|
|
32242
|
+
const PLATFORM_DESTROY_LISTENERS = new InjectionToken('PlatformDestroyListeners');
|
|
32243
|
+
/**
|
|
32244
|
+
* The Angular platform is the entry point for Angular on a web page.
|
|
32245
|
+
* Each page has exactly one platform. Services (such as reflection) which are common
|
|
32246
|
+
* to every Angular application running on the page are bound in its scope.
|
|
32247
|
+
* A page's platform is initialized implicitly when a platform is created using a platform
|
|
32248
|
+
* factory such as `PlatformBrowser`, or explicitly by calling the `createPlatform()` function.
|
|
32249
|
+
*
|
|
32250
|
+
* @publicApi
|
|
32251
|
+
*/
|
|
32252
|
+
class PlatformRef {
|
|
32253
|
+
/** @internal */
|
|
32254
|
+
constructor(_injector) {
|
|
32255
|
+
this._injector = _injector;
|
|
32256
|
+
this._modules = [];
|
|
32257
|
+
this._destroyListeners = [];
|
|
32258
|
+
this._destroyed = false;
|
|
32259
|
+
}
|
|
32260
|
+
/**
|
|
32261
|
+
* Creates an instance of an `@NgModule` for the given platform.
|
|
32262
|
+
*
|
|
32263
|
+
* @deprecated Passing NgModule factories as the `PlatformRef.bootstrapModuleFactory` function
|
|
32264
|
+
* argument is deprecated. Use the `PlatformRef.bootstrapModule` API instead.
|
|
32265
|
+
*/
|
|
32266
|
+
bootstrapModuleFactory(moduleFactory, options) {
|
|
32267
|
+
// Note: We need to create the NgZone _before_ we instantiate the module,
|
|
32268
|
+
// as instantiating the module creates some providers eagerly.
|
|
32269
|
+
// So we create a mini parent injector that just contains the new NgZone and
|
|
32270
|
+
// pass that as parent to the NgModuleFactory.
|
|
32271
|
+
const ngZone = getNgZone(options?.ngZone, getNgZoneOptions({
|
|
32272
|
+
eventCoalescing: options?.ngZoneEventCoalescing,
|
|
32273
|
+
runCoalescing: options?.ngZoneRunCoalescing
|
|
32274
|
+
}));
|
|
32275
|
+
// Note: Create ngZoneInjector within ngZone.run so that all of the instantiated services are
|
|
32276
|
+
// created within the Angular zone
|
|
32277
|
+
// Do not try to replace ngZone.run with ApplicationRef#run because ApplicationRef would then be
|
|
32278
|
+
// created outside of the Angular zone.
|
|
32279
|
+
return ngZone.run(() => {
|
|
32280
|
+
const moduleRef = createNgModuleRefWithProviders(moduleFactory.moduleType, this.injector, internalProvideZoneChangeDetection(() => ngZone));
|
|
32281
|
+
if ((typeof ngDevMode === 'undefined' || ngDevMode) &&
|
|
32282
|
+
moduleRef.injector.get(PROVIDED_NG_ZONE, null) !== null) {
|
|
32283
|
+
throw new RuntimeError(207 /* RuntimeErrorCode.PROVIDER_IN_WRONG_CONTEXT */, '`bootstrapModule` does not support `provideZoneChangeDetection`. Use `BootstrapOptions` instead.');
|
|
32284
|
+
}
|
|
32285
|
+
const exceptionHandler = moduleRef.injector.get(ErrorHandler, null);
|
|
32286
|
+
if ((typeof ngDevMode === 'undefined' || ngDevMode) && exceptionHandler === null) {
|
|
32287
|
+
throw new RuntimeError(402 /* RuntimeErrorCode.MISSING_REQUIRED_INJECTABLE_IN_BOOTSTRAP */, 'No ErrorHandler. Is platform module (BrowserModule) included?');
|
|
32288
|
+
}
|
|
32289
|
+
ngZone.runOutsideAngular(() => {
|
|
32290
|
+
const subscription = ngZone.onError.subscribe({
|
|
32291
|
+
next: (error) => {
|
|
32292
|
+
exceptionHandler.handleError(error);
|
|
32293
|
+
}
|
|
32294
|
+
});
|
|
32295
|
+
moduleRef.onDestroy(() => {
|
|
32296
|
+
remove(this._modules, moduleRef);
|
|
32297
|
+
subscription.unsubscribe();
|
|
32298
|
+
});
|
|
32299
|
+
});
|
|
32300
|
+
return _callAndReportToErrorHandler(exceptionHandler, ngZone, () => {
|
|
32301
|
+
const initStatus = moduleRef.injector.get(ApplicationInitStatus);
|
|
32302
|
+
initStatus.runInitializers();
|
|
32303
|
+
return initStatus.donePromise.then(() => {
|
|
32304
|
+
// If the `LOCALE_ID` provider is defined at bootstrap then we set the value for ivy
|
|
32305
|
+
const localeId = moduleRef.injector.get(LOCALE_ID, DEFAULT_LOCALE_ID);
|
|
32306
|
+
setLocaleId(localeId || DEFAULT_LOCALE_ID);
|
|
32307
|
+
this._moduleDoBootstrap(moduleRef);
|
|
32308
|
+
return moduleRef;
|
|
32309
|
+
});
|
|
32310
|
+
});
|
|
32311
|
+
});
|
|
32312
|
+
}
|
|
32313
|
+
/**
|
|
32314
|
+
* Creates an instance of an `@NgModule` for a given platform.
|
|
32315
|
+
*
|
|
32316
|
+
* @usageNotes
|
|
32317
|
+
* ### Simple Example
|
|
32318
|
+
*
|
|
32319
|
+
* ```typescript
|
|
32320
|
+
* @NgModule({
|
|
32321
|
+
* imports: [BrowserModule]
|
|
32322
|
+
* })
|
|
32323
|
+
* class MyModule {}
|
|
32324
|
+
*
|
|
32325
|
+
* let moduleRef = platformBrowser().bootstrapModule(MyModule);
|
|
32326
|
+
* ```
|
|
32327
|
+
*
|
|
32328
|
+
*/
|
|
32329
|
+
bootstrapModule(moduleType, compilerOptions = []) {
|
|
32330
|
+
const options = optionsReducer({}, compilerOptions);
|
|
32331
|
+
return compileNgModuleFactory(this.injector, options, moduleType)
|
|
32332
|
+
.then(moduleFactory => this.bootstrapModuleFactory(moduleFactory, options));
|
|
32333
|
+
}
|
|
32334
|
+
_moduleDoBootstrap(moduleRef) {
|
|
32335
|
+
const appRef = moduleRef.injector.get(ApplicationRef);
|
|
32336
|
+
if (moduleRef._bootstrapComponents.length > 0) {
|
|
32337
|
+
moduleRef._bootstrapComponents.forEach(f => appRef.bootstrap(f));
|
|
32338
|
+
}
|
|
32339
|
+
else if (moduleRef.instance.ngDoBootstrap) {
|
|
32340
|
+
moduleRef.instance.ngDoBootstrap(appRef);
|
|
32341
|
+
}
|
|
32342
|
+
else {
|
|
32343
|
+
throw new RuntimeError(-403 /* RuntimeErrorCode.BOOTSTRAP_COMPONENTS_NOT_FOUND */, ngDevMode &&
|
|
32344
|
+
`The module ${stringify(moduleRef.instance.constructor)} was bootstrapped, ` +
|
|
32345
|
+
`but it does not declare "@NgModule.bootstrap" components nor a "ngDoBootstrap" method. ` +
|
|
32346
|
+
`Please define one of these.`);
|
|
32347
|
+
}
|
|
32348
|
+
this._modules.push(moduleRef);
|
|
32349
|
+
}
|
|
32350
|
+
/**
|
|
32351
|
+
* Registers a listener to be called when the platform is destroyed.
|
|
32352
|
+
*/
|
|
32353
|
+
onDestroy(callback) {
|
|
32354
|
+
this._destroyListeners.push(callback);
|
|
32355
|
+
}
|
|
32356
|
+
/**
|
|
32357
|
+
* Retrieves the platform {@link Injector}, which is the parent injector for
|
|
32358
|
+
* every Angular application on the page and provides singleton providers.
|
|
32359
|
+
*/
|
|
32360
|
+
get injector() {
|
|
32361
|
+
return this._injector;
|
|
32362
|
+
}
|
|
32363
|
+
/**
|
|
32364
|
+
* Destroys the current Angular platform and all Angular applications on the page.
|
|
32365
|
+
* Destroys all modules and listeners registered with the platform.
|
|
32366
|
+
*/
|
|
32367
|
+
destroy() {
|
|
32368
|
+
if (this._destroyed) {
|
|
32369
|
+
throw new RuntimeError(404 /* RuntimeErrorCode.PLATFORM_ALREADY_DESTROYED */, ngDevMode && 'The platform has already been destroyed!');
|
|
32370
|
+
}
|
|
32371
|
+
this._modules.slice().forEach(module => module.destroy());
|
|
32372
|
+
this._destroyListeners.forEach(listener => listener());
|
|
32373
|
+
const destroyListeners = this._injector.get(PLATFORM_DESTROY_LISTENERS, null);
|
|
32374
|
+
if (destroyListeners) {
|
|
32375
|
+
destroyListeners.forEach(listener => listener());
|
|
32376
|
+
destroyListeners.clear();
|
|
32377
|
+
}
|
|
32378
|
+
this._destroyed = true;
|
|
32379
|
+
}
|
|
32380
|
+
/**
|
|
32381
|
+
* Indicates whether this instance was destroyed.
|
|
32382
|
+
*/
|
|
32383
|
+
get destroyed() {
|
|
32384
|
+
return this._destroyed;
|
|
32385
|
+
}
|
|
32386
|
+
static { this.ɵfac = function PlatformRef_Factory(t) { return new (t || PlatformRef)(ɵɵinject(Injector)); }; }
|
|
32387
|
+
static { this.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: PlatformRef, factory: PlatformRef.ɵfac, providedIn: 'platform' }); }
|
|
32388
|
+
}
|
|
32389
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(PlatformRef, [{
|
|
32390
|
+
type: Injectable,
|
|
32391
|
+
args: [{ providedIn: 'platform' }]
|
|
32392
|
+
}], () => [{ type: Injector }], null); })();
|
|
32393
|
+
|
|
32394
|
+
let _platformInjector = null;
|
|
32395
|
+
/**
|
|
32396
|
+
* Internal token to indicate whether having multiple bootstrapped platform should be allowed (only
|
|
32397
|
+
* one bootstrapped platform is allowed by default). This token helps to support SSR scenarios.
|
|
32398
|
+
*/
|
|
32399
|
+
const ALLOW_MULTIPLE_PLATFORMS = new InjectionToken('AllowMultipleToken');
|
|
32400
|
+
/**
|
|
32401
|
+
* Creates a platform.
|
|
32402
|
+
* Platforms must be created on launch using this function.
|
|
32403
|
+
*
|
|
32404
|
+
* @publicApi
|
|
32405
|
+
*/
|
|
32406
|
+
function createPlatform(injector) {
|
|
32407
|
+
if (_platformInjector && !_platformInjector.get(ALLOW_MULTIPLE_PLATFORMS, false)) {
|
|
32408
|
+
throw new RuntimeError(400 /* RuntimeErrorCode.MULTIPLE_PLATFORMS */, ngDevMode &&
|
|
32409
|
+
'There can be only one platform. Destroy the previous one to create a new one.');
|
|
32410
|
+
}
|
|
32411
|
+
publishDefaultGlobalUtils();
|
|
32412
|
+
publishSignalConfiguration();
|
|
32413
|
+
_platformInjector = injector;
|
|
32414
|
+
const platform = injector.get(PlatformRef);
|
|
32415
|
+
runPlatformInitializers(injector);
|
|
32416
|
+
return platform;
|
|
32417
|
+
}
|
|
32418
|
+
/**
|
|
32419
|
+
* Creates a factory for a platform. Can be used to provide or override `Providers` specific to
|
|
32420
|
+
* your application's runtime needs, such as `PLATFORM_INITIALIZER` and `PLATFORM_ID`.
|
|
32421
|
+
* @param parentPlatformFactory Another platform factory to modify. Allows you to compose factories
|
|
32422
|
+
* to build up configurations that might be required by different libraries or parts of the
|
|
32423
|
+
* application.
|
|
32424
|
+
* @param name Identifies the new platform factory.
|
|
32425
|
+
* @param providers A set of dependency providers for platforms created with the new factory.
|
|
32426
|
+
*
|
|
32427
|
+
* @publicApi
|
|
32428
|
+
*/
|
|
32429
|
+
function createPlatformFactory(parentPlatformFactory, name, providers = []) {
|
|
32430
|
+
const desc = `Platform: ${name}`;
|
|
32431
|
+
const marker = new InjectionToken(desc);
|
|
32432
|
+
return (extraProviders = []) => {
|
|
32433
|
+
let platform = getPlatform();
|
|
32434
|
+
if (!platform || platform.injector.get(ALLOW_MULTIPLE_PLATFORMS, false)) {
|
|
32435
|
+
const platformProviders = [...providers, ...extraProviders, { provide: marker, useValue: true }];
|
|
32436
|
+
if (parentPlatformFactory) {
|
|
32437
|
+
parentPlatformFactory(platformProviders);
|
|
32438
|
+
}
|
|
32439
|
+
else {
|
|
32440
|
+
createPlatform(createPlatformInjector(platformProviders, desc));
|
|
32441
|
+
}
|
|
32442
|
+
}
|
|
32443
|
+
return assertPlatform(marker);
|
|
32444
|
+
};
|
|
32445
|
+
}
|
|
32446
|
+
/**
|
|
32447
|
+
* Helper function to create an instance of a platform injector (that maintains the 'platform'
|
|
32448
|
+
* scope).
|
|
32449
|
+
*/
|
|
32450
|
+
function createPlatformInjector(providers = [], name) {
|
|
32451
|
+
return Injector.create({
|
|
32452
|
+
name,
|
|
32453
|
+
providers: [
|
|
32454
|
+
{ provide: INJECTOR_SCOPE, useValue: 'platform' },
|
|
32455
|
+
{ provide: PLATFORM_DESTROY_LISTENERS, useValue: new Set([() => _platformInjector = null]) },
|
|
32456
|
+
...providers
|
|
32457
|
+
],
|
|
32458
|
+
});
|
|
32459
|
+
}
|
|
32460
|
+
/**
|
|
32461
|
+
* Checks that there is currently a platform that contains the given token as a provider.
|
|
32462
|
+
*
|
|
32463
|
+
* @publicApi
|
|
32464
|
+
*/
|
|
32465
|
+
function assertPlatform(requiredToken) {
|
|
32466
|
+
const platform = getPlatform();
|
|
32467
|
+
if (!platform) {
|
|
32468
|
+
throw new RuntimeError(401 /* RuntimeErrorCode.PLATFORM_NOT_FOUND */, ngDevMode && 'No platform exists!');
|
|
32469
|
+
}
|
|
32470
|
+
if ((typeof ngDevMode === 'undefined' || ngDevMode) &&
|
|
32471
|
+
!platform.injector.get(requiredToken, null)) {
|
|
32472
|
+
throw new RuntimeError(400 /* RuntimeErrorCode.MULTIPLE_PLATFORMS */, 'A platform with a different configuration has been created. Please destroy it first.');
|
|
32473
|
+
}
|
|
32474
|
+
return platform;
|
|
32475
|
+
}
|
|
32476
|
+
/**
|
|
32477
|
+
* Returns the current platform.
|
|
32478
|
+
*
|
|
32479
|
+
* @publicApi
|
|
32480
|
+
*/
|
|
32481
|
+
function getPlatform() {
|
|
32482
|
+
return _platformInjector?.get(PlatformRef) ?? null;
|
|
32483
|
+
}
|
|
32484
|
+
/**
|
|
32485
|
+
* Destroys the current Angular platform and all Angular applications on the page.
|
|
32486
|
+
* Destroys all modules and listeners registered with the platform.
|
|
32487
|
+
*
|
|
32488
|
+
* @publicApi
|
|
32489
|
+
*/
|
|
32490
|
+
function destroyPlatform() {
|
|
32491
|
+
getPlatform()?.destroy();
|
|
32492
|
+
}
|
|
32493
|
+
/**
|
|
32494
|
+
* The goal of this function is to bootstrap a platform injector,
|
|
32495
|
+
* but avoid referencing `PlatformRef` class.
|
|
32496
|
+
* This function is needed for bootstrapping a Standalone Component.
|
|
32497
|
+
*/
|
|
32498
|
+
function createOrReusePlatformInjector(providers = []) {
|
|
32499
|
+
// If a platform injector already exists, it means that the platform
|
|
32500
|
+
// is already bootstrapped and no additional actions are required.
|
|
32501
|
+
if (_platformInjector)
|
|
32502
|
+
return _platformInjector;
|
|
32503
|
+
publishDefaultGlobalUtils();
|
|
32504
|
+
// Otherwise, setup a new platform injector and run platform initializers.
|
|
32505
|
+
const injector = createPlatformInjector(providers);
|
|
32506
|
+
_platformInjector = injector;
|
|
32507
|
+
publishSignalConfiguration();
|
|
32508
|
+
runPlatformInitializers(injector);
|
|
32509
|
+
return injector;
|
|
32510
|
+
}
|
|
32511
|
+
function runPlatformInitializers(injector) {
|
|
32512
|
+
const inits = injector.get(PLATFORM_INITIALIZER, null);
|
|
32513
|
+
inits?.forEach((init) => init());
|
|
32683
32514
|
}
|
|
32684
32515
|
|
|
32685
32516
|
/**
|
|
@@ -33839,14 +33670,7 @@ function signalSetFn(node, newValue) {
|
|
|
33839
33670
|
if (!producerUpdatesAllowed()) {
|
|
33840
33671
|
throwInvalidWriteToSignalError();
|
|
33841
33672
|
}
|
|
33842
|
-
|
|
33843
|
-
if (Object.is(value, newValue)) {
|
|
33844
|
-
if (typeof ngDevMode !== 'undefined' && ngDevMode && !node.equal(value, newValue)) {
|
|
33845
|
-
console.warn('Signal value equality implementations should always return `true` for' +
|
|
33846
|
-
' values that are the same according to `Object.is` but returned `false` instead.');
|
|
33847
|
-
}
|
|
33848
|
-
}
|
|
33849
|
-
else if (!node.equal(value, newValue)) {
|
|
33673
|
+
if (!node.equal(node.value, newValue)) {
|
|
33850
33674
|
node.value = newValue;
|
|
33851
33675
|
signalValueChanged(node);
|
|
33852
33676
|
}
|
|
@@ -33960,6 +33784,244 @@ function setAlternateWeakRefImpl(impl) {
|
|
|
33960
33784
|
// TODO: remove this function
|
|
33961
33785
|
}
|
|
33962
33786
|
|
|
33787
|
+
// A delay in milliseconds before the scan is run after onLoad, to avoid any
|
|
33788
|
+
// potential race conditions with other LCP-related functions. This delay
|
|
33789
|
+
// happens outside of the main JavaScript execution and will only effect the timing
|
|
33790
|
+
// on when the warning becomes visible in the console.
|
|
33791
|
+
const SCAN_DELAY = 200;
|
|
33792
|
+
const OVERSIZED_IMAGE_TOLERANCE = 1200;
|
|
33793
|
+
class ImagePerformanceWarning {
|
|
33794
|
+
constructor() {
|
|
33795
|
+
// Map of full image URLs -> original `ngSrc` values.
|
|
33796
|
+
this.window = null;
|
|
33797
|
+
this.observer = null;
|
|
33798
|
+
this.options = inject(IMAGE_CONFIG);
|
|
33799
|
+
this.ngZone = inject(NgZone);
|
|
33800
|
+
}
|
|
33801
|
+
start() {
|
|
33802
|
+
if (typeof PerformanceObserver === 'undefined' ||
|
|
33803
|
+
(this.options?.disableImageSizeWarning && this.options?.disableImageLazyLoadWarning)) {
|
|
33804
|
+
return;
|
|
33805
|
+
}
|
|
33806
|
+
this.observer = this.initPerformanceObserver();
|
|
33807
|
+
const doc = getDocument();
|
|
33808
|
+
const win = doc.defaultView;
|
|
33809
|
+
if (typeof win !== 'undefined') {
|
|
33810
|
+
this.window = win;
|
|
33811
|
+
// Wait to avoid race conditions where LCP image triggers
|
|
33812
|
+
// load event before it's recorded by the performance observer
|
|
33813
|
+
const waitToScan = () => {
|
|
33814
|
+
setTimeout(this.scanImages.bind(this), SCAN_DELAY);
|
|
33815
|
+
};
|
|
33816
|
+
// Angular doesn't have to run change detection whenever any asynchronous tasks are invoked in
|
|
33817
|
+
// the scope of this functionality.
|
|
33818
|
+
this.ngZone.runOutsideAngular(() => {
|
|
33819
|
+
// Consider the case when the application is created and destroyed multiple times.
|
|
33820
|
+
// Typically, applications are created instantly once the page is loaded, and the
|
|
33821
|
+
// `window.load` listener is always triggered. However, the `window.load` event will never
|
|
33822
|
+
// be fired if the page is loaded, and the application is created later. Checking for
|
|
33823
|
+
// `readyState` is the easiest way to determine whether the page has been loaded or not.
|
|
33824
|
+
if (doc.readyState === 'complete') {
|
|
33825
|
+
waitToScan();
|
|
33826
|
+
}
|
|
33827
|
+
else {
|
|
33828
|
+
this.window?.addEventListener('load', waitToScan, { once: true });
|
|
33829
|
+
}
|
|
33830
|
+
});
|
|
33831
|
+
}
|
|
33832
|
+
}
|
|
33833
|
+
ngOnDestroy() {
|
|
33834
|
+
this.observer?.disconnect();
|
|
33835
|
+
}
|
|
33836
|
+
initPerformanceObserver() {
|
|
33837
|
+
if (typeof PerformanceObserver === 'undefined') {
|
|
33838
|
+
return null;
|
|
33839
|
+
}
|
|
33840
|
+
const observer = new PerformanceObserver((entryList) => {
|
|
33841
|
+
const entries = entryList.getEntries();
|
|
33842
|
+
if (entries.length === 0)
|
|
33843
|
+
return;
|
|
33844
|
+
// We use the latest entry produced by the `PerformanceObserver` as the best
|
|
33845
|
+
// signal on which element is actually an LCP one. As an example, the first image to load on
|
|
33846
|
+
// a page, by virtue of being the only thing on the page so far, is often a LCP candidate
|
|
33847
|
+
// and gets reported by PerformanceObserver, but isn't necessarily the LCP element.
|
|
33848
|
+
const lcpElement = entries[entries.length - 1];
|
|
33849
|
+
// Cast to `any` due to missing `element` on the `LargestContentfulPaint` type of entry.
|
|
33850
|
+
// See https://developer.mozilla.org/en-US/docs/Web/API/LargestContentfulPaint
|
|
33851
|
+
const imgSrc = lcpElement.element?.src ?? '';
|
|
33852
|
+
// Exclude `data:` and `blob:` URLs, since they are fetched resources.
|
|
33853
|
+
if (imgSrc.startsWith('data:') || imgSrc.startsWith('blob:'))
|
|
33854
|
+
return;
|
|
33855
|
+
this.lcpImageUrl = imgSrc;
|
|
33856
|
+
});
|
|
33857
|
+
observer.observe({ type: 'largest-contentful-paint', buffered: true });
|
|
33858
|
+
return observer;
|
|
33859
|
+
}
|
|
33860
|
+
scanImages() {
|
|
33861
|
+
const images = getDocument().querySelectorAll('img');
|
|
33862
|
+
let lcpElementFound, lcpElementLoadedCorrectly = false;
|
|
33863
|
+
images.forEach(image => {
|
|
33864
|
+
if (!this.options?.disableImageSizeWarning) {
|
|
33865
|
+
for (const image of images) {
|
|
33866
|
+
// Image elements using the NgOptimizedImage directive are excluded,
|
|
33867
|
+
// as that directive has its own version of this check.
|
|
33868
|
+
if (!image.getAttribute('ng-img') && this.isOversized(image)) {
|
|
33869
|
+
logOversizedImageWarning(image.src);
|
|
33870
|
+
}
|
|
33871
|
+
}
|
|
33872
|
+
}
|
|
33873
|
+
if (!this.options?.disableImageLazyLoadWarning && this.lcpImageUrl) {
|
|
33874
|
+
if (image.src === this.lcpImageUrl) {
|
|
33875
|
+
lcpElementFound = true;
|
|
33876
|
+
if (image.loading !== 'lazy' || image.getAttribute('ng-img')) {
|
|
33877
|
+
// This variable is set to true and never goes back to false to account
|
|
33878
|
+
// for the case where multiple images have the same src url, and some
|
|
33879
|
+
// have lazy loading while others don't.
|
|
33880
|
+
// Also ignore NgOptimizedImage because there's a different warning for that.
|
|
33881
|
+
lcpElementLoadedCorrectly = true;
|
|
33882
|
+
}
|
|
33883
|
+
}
|
|
33884
|
+
}
|
|
33885
|
+
});
|
|
33886
|
+
if (lcpElementFound && !lcpElementLoadedCorrectly && this.lcpImageUrl &&
|
|
33887
|
+
!this.options?.disableImageLazyLoadWarning) {
|
|
33888
|
+
logLazyLCPWarning(this.lcpImageUrl);
|
|
33889
|
+
}
|
|
33890
|
+
}
|
|
33891
|
+
isOversized(image) {
|
|
33892
|
+
if (!this.window) {
|
|
33893
|
+
return false;
|
|
33894
|
+
}
|
|
33895
|
+
const computedStyle = this.window.getComputedStyle(image);
|
|
33896
|
+
let renderedWidth = parseFloat(computedStyle.getPropertyValue('width'));
|
|
33897
|
+
let renderedHeight = parseFloat(computedStyle.getPropertyValue('height'));
|
|
33898
|
+
const boxSizing = computedStyle.getPropertyValue('box-sizing');
|
|
33899
|
+
const objectFit = computedStyle.getPropertyValue('object-fit');
|
|
33900
|
+
if (objectFit === `cover`) {
|
|
33901
|
+
// Object fit cover may indicate a use case such as a sprite sheet where
|
|
33902
|
+
// this warning does not apply.
|
|
33903
|
+
return false;
|
|
33904
|
+
}
|
|
33905
|
+
if (boxSizing === 'border-box') {
|
|
33906
|
+
const paddingTop = computedStyle.getPropertyValue('padding-top');
|
|
33907
|
+
const paddingRight = computedStyle.getPropertyValue('padding-right');
|
|
33908
|
+
const paddingBottom = computedStyle.getPropertyValue('padding-bottom');
|
|
33909
|
+
const paddingLeft = computedStyle.getPropertyValue('padding-left');
|
|
33910
|
+
renderedWidth -= parseFloat(paddingRight) + parseFloat(paddingLeft);
|
|
33911
|
+
renderedHeight -= parseFloat(paddingTop) + parseFloat(paddingBottom);
|
|
33912
|
+
}
|
|
33913
|
+
const intrinsicWidth = image.naturalWidth;
|
|
33914
|
+
const intrinsicHeight = image.naturalHeight;
|
|
33915
|
+
const recommendedWidth = this.window.devicePixelRatio * renderedWidth;
|
|
33916
|
+
const recommendedHeight = this.window.devicePixelRatio * renderedHeight;
|
|
33917
|
+
const oversizedWidth = (intrinsicWidth - recommendedWidth) >= OVERSIZED_IMAGE_TOLERANCE;
|
|
33918
|
+
const oversizedHeight = (intrinsicHeight - recommendedHeight) >= OVERSIZED_IMAGE_TOLERANCE;
|
|
33919
|
+
return oversizedWidth || oversizedHeight;
|
|
33920
|
+
}
|
|
33921
|
+
static { this.ɵfac = function ImagePerformanceWarning_Factory(t) { return new (t || ImagePerformanceWarning)(); }; }
|
|
33922
|
+
static { this.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: ImagePerformanceWarning, factory: ImagePerformanceWarning.ɵfac, providedIn: 'root' }); }
|
|
33923
|
+
}
|
|
33924
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(ImagePerformanceWarning, [{
|
|
33925
|
+
type: Injectable,
|
|
33926
|
+
args: [{ providedIn: 'root' }]
|
|
33927
|
+
}], null, null); })();
|
|
33928
|
+
function logLazyLCPWarning(src) {
|
|
33929
|
+
console.warn(formatRuntimeError(-913 /* RuntimeErrorCode.IMAGE_PERFORMANCE_WARNING */, `An image with src ${src} is the Largest Contentful Paint (LCP) element ` +
|
|
33930
|
+
`but was given a "loading" value of "lazy", which can negatively impact ` +
|
|
33931
|
+
`application loading performance. This warning can be addressed by ` +
|
|
33932
|
+
`changing the loading value of the LCP image to "eager", or by using the ` +
|
|
33933
|
+
`NgOptimizedImage directive's prioritization utilities. For more ` +
|
|
33934
|
+
`information about addressing or disabling this warning, see ` +
|
|
33935
|
+
`https://angular.io/errors/NG0913`));
|
|
33936
|
+
}
|
|
33937
|
+
function logOversizedImageWarning(src) {
|
|
33938
|
+
console.warn(formatRuntimeError(-913 /* RuntimeErrorCode.IMAGE_PERFORMANCE_WARNING */, `An image with src ${src} has intrinsic file dimensions much larger than its ` +
|
|
33939
|
+
`rendered size. This can negatively impact application loading performance. ` +
|
|
33940
|
+
`For more information about addressing or disabling this warning, see ` +
|
|
33941
|
+
`https://angular.io/errors/NG0913`));
|
|
33942
|
+
}
|
|
33943
|
+
|
|
33944
|
+
/**
|
|
33945
|
+
* Internal create application API that implements the core application creation logic and optional
|
|
33946
|
+
* bootstrap logic.
|
|
33947
|
+
*
|
|
33948
|
+
* Platforms (such as `platform-browser`) may require different set of application and platform
|
|
33949
|
+
* providers for an application to function correctly. As a result, platforms may use this function
|
|
33950
|
+
* internally and supply the necessary providers during the bootstrap, while exposing
|
|
33951
|
+
* platform-specific APIs as a part of their public API.
|
|
33952
|
+
*
|
|
33953
|
+
* @returns A promise that returns an `ApplicationRef` instance once resolved.
|
|
33954
|
+
*/
|
|
33955
|
+
function internalCreateApplication(config) {
|
|
33956
|
+
try {
|
|
33957
|
+
const { rootComponent, appProviders, platformProviders } = config;
|
|
33958
|
+
if ((typeof ngDevMode === 'undefined' || ngDevMode) && rootComponent !== undefined) {
|
|
33959
|
+
assertStandaloneComponentType(rootComponent);
|
|
33960
|
+
}
|
|
33961
|
+
const platformInjector = createOrReusePlatformInjector(platformProviders);
|
|
33962
|
+
// Create root application injector based on a set of providers configured at the platform
|
|
33963
|
+
// bootstrap level as well as providers passed to the bootstrap call by a user.
|
|
33964
|
+
const allAppProviders = [
|
|
33965
|
+
provideZoneChangeDetection(),
|
|
33966
|
+
...(appProviders || []),
|
|
33967
|
+
];
|
|
33968
|
+
const adapter = new EnvironmentNgModuleRefAdapter({
|
|
33969
|
+
providers: allAppProviders,
|
|
33970
|
+
parent: platformInjector,
|
|
33971
|
+
debugName: (typeof ngDevMode === 'undefined' || ngDevMode) ? 'Environment Injector' : '',
|
|
33972
|
+
// We skip environment initializers because we need to run them inside the NgZone, which
|
|
33973
|
+
// happens after we get the NgZone instance from the Injector.
|
|
33974
|
+
runEnvironmentInitializers: false,
|
|
33975
|
+
});
|
|
33976
|
+
const envInjector = adapter.injector;
|
|
33977
|
+
const ngZone = envInjector.get(NgZone);
|
|
33978
|
+
return ngZone.run(() => {
|
|
33979
|
+
envInjector.resolveInjectorInitializers();
|
|
33980
|
+
const exceptionHandler = envInjector.get(ErrorHandler, null);
|
|
33981
|
+
if ((typeof ngDevMode === 'undefined' || ngDevMode) && !exceptionHandler) {
|
|
33982
|
+
throw new RuntimeError(402 /* RuntimeErrorCode.MISSING_REQUIRED_INJECTABLE_IN_BOOTSTRAP */, 'No `ErrorHandler` found in the Dependency Injection tree.');
|
|
33983
|
+
}
|
|
33984
|
+
let onErrorSubscription;
|
|
33985
|
+
ngZone.runOutsideAngular(() => {
|
|
33986
|
+
onErrorSubscription = ngZone.onError.subscribe({
|
|
33987
|
+
next: (error) => {
|
|
33988
|
+
exceptionHandler.handleError(error);
|
|
33989
|
+
}
|
|
33990
|
+
});
|
|
33991
|
+
});
|
|
33992
|
+
// If the whole platform is destroyed, invoke the `destroy` method
|
|
33993
|
+
// for all bootstrapped applications as well.
|
|
33994
|
+
const destroyListener = () => envInjector.destroy();
|
|
33995
|
+
const onPlatformDestroyListeners = platformInjector.get(PLATFORM_DESTROY_LISTENERS);
|
|
33996
|
+
onPlatformDestroyListeners.add(destroyListener);
|
|
33997
|
+
envInjector.onDestroy(() => {
|
|
33998
|
+
onErrorSubscription.unsubscribe();
|
|
33999
|
+
onPlatformDestroyListeners.delete(destroyListener);
|
|
34000
|
+
});
|
|
34001
|
+
return _callAndReportToErrorHandler(exceptionHandler, ngZone, () => {
|
|
34002
|
+
const initStatus = envInjector.get(ApplicationInitStatus);
|
|
34003
|
+
initStatus.runInitializers();
|
|
34004
|
+
return initStatus.donePromise.then(() => {
|
|
34005
|
+
const localeId = envInjector.get(LOCALE_ID, DEFAULT_LOCALE_ID);
|
|
34006
|
+
setLocaleId(localeId || DEFAULT_LOCALE_ID);
|
|
34007
|
+
const appRef = envInjector.get(ApplicationRef);
|
|
34008
|
+
if (rootComponent !== undefined) {
|
|
34009
|
+
appRef.bootstrap(rootComponent);
|
|
34010
|
+
}
|
|
34011
|
+
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
34012
|
+
const imagePerformanceService = envInjector.get(ImagePerformanceWarning);
|
|
34013
|
+
imagePerformanceService.start();
|
|
34014
|
+
}
|
|
34015
|
+
return appRef;
|
|
34016
|
+
});
|
|
34017
|
+
});
|
|
34018
|
+
});
|
|
34019
|
+
}
|
|
34020
|
+
catch (e) {
|
|
34021
|
+
return Promise.reject(e);
|
|
34022
|
+
}
|
|
34023
|
+
}
|
|
34024
|
+
|
|
33963
34025
|
/**
|
|
33964
34026
|
* Retrieves all defer blocks in a given LView.
|
|
33965
34027
|
*
|
|
@@ -34304,6 +34366,7 @@ function serializeLView(lView, context) {
|
|
|
34304
34366
|
}
|
|
34305
34367
|
}
|
|
34306
34368
|
}
|
|
34369
|
+
conditionallyAnnotateNodePath(ngh, tNode, lView);
|
|
34307
34370
|
if (isLContainer(lView[i])) {
|
|
34308
34371
|
// Serialize information about a template.
|
|
34309
34372
|
const embeddedTView = tNode.tView;
|
|
@@ -34395,18 +34458,38 @@ function serializeLView(lView, context) {
|
|
|
34395
34458
|
context.corruptedTextNodes.set(rNode, "ngtns" /* TextNodeMarker.Separator */);
|
|
34396
34459
|
}
|
|
34397
34460
|
}
|
|
34398
|
-
if (tNode.projectionNext && tNode.projectionNext !== tNode.next &&
|
|
34399
|
-
!isInSkipHydrationBlock(tNode.projectionNext)) {
|
|
34400
|
-
// Check if projection next is not the same as next, in which case
|
|
34401
|
-
// the node would not be found at creation time at runtime and we
|
|
34402
|
-
// need to provide a location for that node.
|
|
34403
|
-
appendSerializedNodePath(ngh, tNode.projectionNext, lView);
|
|
34404
|
-
}
|
|
34405
34461
|
}
|
|
34406
34462
|
}
|
|
34407
34463
|
}
|
|
34408
34464
|
return ngh;
|
|
34409
34465
|
}
|
|
34466
|
+
/**
|
|
34467
|
+
* Serializes node location in cases when it's needed, specifically:
|
|
34468
|
+
*
|
|
34469
|
+
* 1. If `tNode.projectionNext` is different from `tNode.next` - it means that
|
|
34470
|
+
* the next `tNode` after projection is different from the one in the original
|
|
34471
|
+
* template. Since hydration relies on `tNode.next`, this serialized info
|
|
34472
|
+
* if required to help runtime code find the node at the correct location.
|
|
34473
|
+
* 2. In certain content projection-based use-cases, it's possible that only
|
|
34474
|
+
* a content of a projected element is rendered. In this case, content nodes
|
|
34475
|
+
* require an extra annotation, since runtime logic can't rely on parent-child
|
|
34476
|
+
* connection to identify the location of a node.
|
|
34477
|
+
*/
|
|
34478
|
+
function conditionallyAnnotateNodePath(ngh, tNode, lView) {
|
|
34479
|
+
// Handle case #1 described above.
|
|
34480
|
+
if (tNode.projectionNext && tNode.projectionNext !== tNode.next &&
|
|
34481
|
+
!isInSkipHydrationBlock(tNode.projectionNext)) {
|
|
34482
|
+
appendSerializedNodePath(ngh, tNode.projectionNext, lView);
|
|
34483
|
+
}
|
|
34484
|
+
// Handle case #2 described above.
|
|
34485
|
+
// Note: we only do that for the first node (i.e. when `tNode.prev === null`),
|
|
34486
|
+
// the rest of the nodes would rely on the current node location, so no extra
|
|
34487
|
+
// annotation is needed.
|
|
34488
|
+
if (tNode.prev === null && tNode.parent !== null && isDisconnectedNode(tNode.parent, lView) &&
|
|
34489
|
+
!isDisconnectedNode(tNode, lView)) {
|
|
34490
|
+
appendSerializedNodePath(ngh, tNode, lView);
|
|
34491
|
+
}
|
|
34492
|
+
}
|
|
34410
34493
|
/**
|
|
34411
34494
|
* Determines whether a component instance that is represented
|
|
34412
34495
|
* by a given LView uses `ViewEncapsulation.ShadowDom`.
|
|
@@ -34478,17 +34561,6 @@ function isContentProjectedNode(tNode) {
|
|
|
34478
34561
|
}
|
|
34479
34562
|
return false;
|
|
34480
34563
|
}
|
|
34481
|
-
/**
|
|
34482
|
-
* Check whether a given node exists, but is disconnected from the DOM.
|
|
34483
|
-
*
|
|
34484
|
-
* Note: we leverage the fact that we have this information available in the DOM emulation
|
|
34485
|
-
* layer (in Domino) for now. Longer-term solution should not rely on the DOM emulation and
|
|
34486
|
-
* only use internal data structures and state to compute this information.
|
|
34487
|
-
*/
|
|
34488
|
-
function isDisconnectedNode(tNode, lView) {
|
|
34489
|
-
return !(tNode.type & 16 /* TNodeType.Projection */) && !!lView[tNode.index] &&
|
|
34490
|
-
!unwrapRNode(lView[tNode.index]).isConnected;
|
|
34491
|
-
}
|
|
34492
34564
|
|
|
34493
34565
|
/**
|
|
34494
34566
|
* Indicates whether the hydration-related code was added,
|