@angular/core 17.0.0-next.8 → 17.0.0-rc.1
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/src/application_init.mjs +3 -2
- package/esm2022/src/application_ref.mjs +4 -3
- package/esm2022/src/application_tokens.mjs +1 -11
- package/esm2022/src/core.mjs +2 -2
- package/esm2022/src/core_private_export.mjs +5 -4
- package/esm2022/src/core_render3_private_export.mjs +2 -2
- package/esm2022/src/debug/debug_node.mjs +5 -9
- package/esm2022/src/defer/cleanup.mjs +40 -0
- package/esm2022/src/defer/discovery.mjs +47 -0
- package/esm2022/src/defer/dom_triggers.mjs +256 -0
- package/esm2022/src/defer/idle_scheduler.mjs +112 -0
- package/esm2022/src/defer/instructions.mjs +662 -0
- package/esm2022/src/defer/interfaces.mjs +81 -0
- package/esm2022/src/defer/timer_scheduler.mjs +201 -0
- package/esm2022/src/defer/utils.mjs +122 -0
- package/esm2022/src/di/r3_injector.mjs +6 -1
- package/esm2022/src/errors.mjs +1 -1
- package/esm2022/src/hydration/api.mjs +2 -4
- package/esm2022/src/hydration/skip_hydration.mjs +7 -7
- package/esm2022/src/hydration/utils.mjs +2 -2
- package/esm2022/src/linker/view_container_ref.mjs +4 -6
- package/esm2022/src/metadata/directives.mjs +1 -1
- package/esm2022/src/render/api.mjs +1 -1
- package/esm2022/src/render3/after_render_hooks.mjs +55 -21
- package/esm2022/src/render3/debug/injector_profiler.mjs +26 -8
- package/esm2022/src/render3/index.mjs +3 -2
- package/esm2022/src/render3/instructions/all.mjs +2 -2
- package/esm2022/src/render3/instructions/change_detection.mjs +24 -3
- package/esm2022/src/render3/instructions/control_flow.mjs +25 -15
- package/esm2022/src/render3/interfaces/container.mjs +1 -4
- package/esm2022/src/render3/interfaces/definition.mjs +2 -4
- package/esm2022/src/render3/interfaces/i18n.mjs +1 -4
- package/esm2022/src/render3/interfaces/injector.mjs +1 -4
- package/esm2022/src/render3/interfaces/node.mjs +1 -4
- package/esm2022/src/render3/interfaces/projection.mjs +2 -4
- package/esm2022/src/render3/interfaces/query.mjs +2 -4
- package/esm2022/src/render3/interfaces/renderer.mjs +2 -4
- package/esm2022/src/render3/interfaces/renderer_dom.mjs +2 -4
- package/esm2022/src/render3/interfaces/view.mjs +1 -4
- package/esm2022/src/render3/list_reconciliation.mjs +58 -34
- package/esm2022/src/render3/reactive_lview_consumer.mjs +2 -7
- package/esm2022/src/render3/util/injector_discovery_utils.mjs +26 -2
- package/esm2022/src/render3/util/view_utils.mjs +1 -4
- package/esm2022/src/version.mjs +1 -1
- package/esm2022/testing/src/defer.mjs +6 -3
- package/esm2022/testing/src/logger.mjs +3 -3
- package/fesm2022/core.mjs +1015 -932
- package/fesm2022/core.mjs.map +1 -1
- package/fesm2022/primitives/signals.mjs +1 -1
- package/fesm2022/rxjs-interop.mjs +1 -1
- package/fesm2022/testing.mjs +6 -3
- package/fesm2022/testing.mjs.map +1 -1
- package/index.d.ts +54 -18
- 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 +1051 -467
- package/schematics/migrations/block-template-entities/bundle.js.map +4 -4
- package/schematics/migrations/compiler-options/bundle.js +13 -13
- package/schematics/migrations/transfer-state/bundle.js +13 -13
- package/schematics/ng-generate/control-flow-migration/bundle.js +1284 -612
- package/schematics/ng-generate/control-flow-migration/bundle.js.map +4 -4
- package/schematics/ng-generate/standalone-migration/bundle.js +1300 -708
- package/schematics/ng-generate/standalone-migration/bundle.js.map +4 -4
- package/testing/index.d.ts +1 -1
- package/esm2022/src/render3/instructions/defer.mjs +0 -1225
- package/esm2022/src/render3/instructions/defer_events.mjs +0 -174
- package/esm2022/src/render3/interfaces/defer.mjs +0 -79
package/fesm2022/core.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v17.0.0-
|
|
2
|
+
* @license Angular v17.0.0-rc.1
|
|
3
3
|
* (c) 2010-2022 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -673,6 +673,93 @@ function initNgDevMode() {
|
|
|
673
673
|
return false;
|
|
674
674
|
}
|
|
675
675
|
|
|
676
|
+
/**
|
|
677
|
+
* Creates a token that can be used in a DI Provider.
|
|
678
|
+
*
|
|
679
|
+
* Use an `InjectionToken` whenever the type you are injecting is not reified (does not have a
|
|
680
|
+
* runtime representation) such as when injecting an interface, callable type, array or
|
|
681
|
+
* parameterized type.
|
|
682
|
+
*
|
|
683
|
+
* `InjectionToken` is parameterized on `T` which is the type of object which will be returned by
|
|
684
|
+
* the `Injector`. This provides an additional level of type safety.
|
|
685
|
+
*
|
|
686
|
+
* <div class="alert is-helpful">
|
|
687
|
+
*
|
|
688
|
+
* **Important Note**: Ensure that you use the same instance of the `InjectionToken` in both the
|
|
689
|
+
* provider and the injection call. Creating a new instance of `InjectionToken` in different places,
|
|
690
|
+
* even with the same description, will be treated as different tokens by Angular's DI system,
|
|
691
|
+
* leading to a `NullInjectorError`.
|
|
692
|
+
*
|
|
693
|
+
* </div>
|
|
694
|
+
*
|
|
695
|
+
* <code-example format="typescript" language="typescript" path="injection-token/src/main.ts"
|
|
696
|
+
* region="InjectionToken"></code-example>
|
|
697
|
+
*
|
|
698
|
+
* When creating an `InjectionToken`, you can optionally specify a factory function which returns
|
|
699
|
+
* (possibly by creating) a default value of the parameterized type `T`. This sets up the
|
|
700
|
+
* `InjectionToken` using this factory as a provider as if it was defined explicitly in the
|
|
701
|
+
* application's root injector. If the factory function, which takes zero arguments, needs to inject
|
|
702
|
+
* dependencies, it can do so using the [`inject`](api/core/inject) function.
|
|
703
|
+
* As you can see in the Tree-shakable InjectionToken example below.
|
|
704
|
+
*
|
|
705
|
+
* Additionally, if a `factory` is specified you can also specify the `providedIn` option, which
|
|
706
|
+
* overrides the above behavior and marks the token as belonging to a particular `@NgModule` (note:
|
|
707
|
+
* this option is now deprecated). As mentioned above, `'root'` is the default value for
|
|
708
|
+
* `providedIn`.
|
|
709
|
+
*
|
|
710
|
+
* The `providedIn: NgModule` and `providedIn: 'any'` options are deprecated.
|
|
711
|
+
*
|
|
712
|
+
* @usageNotes
|
|
713
|
+
* ### Basic Examples
|
|
714
|
+
*
|
|
715
|
+
* ### Plain InjectionToken
|
|
716
|
+
*
|
|
717
|
+
* {@example core/di/ts/injector_spec.ts region='InjectionToken'}
|
|
718
|
+
*
|
|
719
|
+
* ### Tree-shakable InjectionToken
|
|
720
|
+
*
|
|
721
|
+
* {@example core/di/ts/injector_spec.ts region='ShakableInjectionToken'}
|
|
722
|
+
*
|
|
723
|
+
* @publicApi
|
|
724
|
+
*/
|
|
725
|
+
class InjectionToken {
|
|
726
|
+
/**
|
|
727
|
+
* @param _desc Description for the token,
|
|
728
|
+
* used only for debugging purposes,
|
|
729
|
+
* it should but does not need to be unique
|
|
730
|
+
* @param options Options for the token's usage, as described above
|
|
731
|
+
*/
|
|
732
|
+
constructor(_desc, options) {
|
|
733
|
+
this._desc = _desc;
|
|
734
|
+
/** @internal */
|
|
735
|
+
this.ngMetadataName = 'InjectionToken';
|
|
736
|
+
this.ɵprov = undefined;
|
|
737
|
+
if (typeof options == 'number') {
|
|
738
|
+
(typeof ngDevMode === 'undefined' || ngDevMode) &&
|
|
739
|
+
assertLessThan(options, 0, 'Only negative numbers are supported here');
|
|
740
|
+
// This is a special hack to assign __NG_ELEMENT_ID__ to this instance.
|
|
741
|
+
// See `InjectorMarkers`
|
|
742
|
+
this.__NG_ELEMENT_ID__ = options;
|
|
743
|
+
}
|
|
744
|
+
else if (options !== undefined) {
|
|
745
|
+
this.ɵprov = ɵɵdefineInjectable({
|
|
746
|
+
token: this,
|
|
747
|
+
providedIn: options.providedIn || 'root',
|
|
748
|
+
factory: options.factory,
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
/**
|
|
753
|
+
* @internal
|
|
754
|
+
*/
|
|
755
|
+
get multi() {
|
|
756
|
+
return this;
|
|
757
|
+
}
|
|
758
|
+
toString() {
|
|
759
|
+
return `InjectionToken ${this._desc}`;
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
|
|
676
763
|
let _injectorProfilerContext;
|
|
677
764
|
function getInjectorProfilerContext() {
|
|
678
765
|
!ngDevMode && throwError('getInjectorProfilerContext should never be called in production mode');
|
|
@@ -714,18 +801,35 @@ function injectorProfiler(event) {
|
|
|
714
801
|
* Emits an InjectorProfilerEventType.ProviderConfigured to the injector profiler. The data in the
|
|
715
802
|
* emitted event includes the raw provider, as well as the token that provider is providing.
|
|
716
803
|
*
|
|
717
|
-
* @param
|
|
804
|
+
* @param eventProvider A provider object
|
|
718
805
|
*/
|
|
719
|
-
function emitProviderConfiguredEvent(
|
|
806
|
+
function emitProviderConfiguredEvent(eventProvider, isViewProvider = false) {
|
|
720
807
|
!ngDevMode && throwError('Injector profiler should never be called in production mode');
|
|
808
|
+
let token;
|
|
809
|
+
// if the provider is a TypeProvider (typeof provider is function) then the token is the
|
|
810
|
+
// provider itself
|
|
811
|
+
if (typeof eventProvider === 'function') {
|
|
812
|
+
token = eventProvider;
|
|
813
|
+
}
|
|
814
|
+
// if the provider is an injection token, then the token is the injection token.
|
|
815
|
+
else if (eventProvider instanceof InjectionToken) {
|
|
816
|
+
token = eventProvider;
|
|
817
|
+
}
|
|
818
|
+
// in all other cases we can access the token via the `provide` property of the provider
|
|
819
|
+
else {
|
|
820
|
+
token = resolveForwardRef(eventProvider.provide);
|
|
821
|
+
}
|
|
822
|
+
let provider = eventProvider;
|
|
823
|
+
// Injection tokens may define their own default provider which gets attached to the token itself
|
|
824
|
+
// as `ɵprov`. In this case, we want to emit the provider that is attached to the token, not the
|
|
825
|
+
// token itself.
|
|
826
|
+
if (eventProvider instanceof InjectionToken) {
|
|
827
|
+
provider = eventProvider.ɵprov || eventProvider;
|
|
828
|
+
}
|
|
721
829
|
injectorProfiler({
|
|
722
830
|
type: 2 /* InjectorProfilerEventType.ProviderConfigured */,
|
|
723
831
|
context: getInjectorProfilerContext(),
|
|
724
|
-
providerRecord: {
|
|
725
|
-
token: typeof provider === 'function' ? provider : resolveForwardRef(provider.provide),
|
|
726
|
-
provider,
|
|
727
|
-
isViewProvider
|
|
728
|
-
}
|
|
832
|
+
providerRecord: { token, provider, isViewProvider }
|
|
729
833
|
});
|
|
730
834
|
}
|
|
731
835
|
/**
|
|
@@ -2107,9 +2211,6 @@ const REACTIVE_HOST_BINDING_CONSUMER = 24;
|
|
|
2107
2211
|
* there should be no need to refer to `HEADER_OFFSET` anywhere else.
|
|
2108
2212
|
*/
|
|
2109
2213
|
const HEADER_OFFSET = 25;
|
|
2110
|
-
// Note: This hack is necessary so we don't erroneously get a circular dependency
|
|
2111
|
-
// failure based on types.
|
|
2112
|
-
const unusedValueExportToPlacateAjd$4 = 1;
|
|
2113
2214
|
|
|
2114
2215
|
/**
|
|
2115
2216
|
* Special location which allows easy identification of type. If we have an array which was
|
|
@@ -2147,9 +2248,6 @@ const DEHYDRATED_VIEWS = 10;
|
|
|
2147
2248
|
* remove views from the DOM when they are no longer required.
|
|
2148
2249
|
*/
|
|
2149
2250
|
const CONTAINER_HEADER_OFFSET = 11;
|
|
2150
|
-
// Note: This hack is necessary so we don't erroneously get a circular dependency
|
|
2151
|
-
// failure based on types.
|
|
2152
|
-
const unusedValueExportToPlacateAjd$3 = 1;
|
|
2153
2251
|
|
|
2154
2252
|
/**
|
|
2155
2253
|
* True if `value` is `LView`.
|
|
@@ -2643,9 +2741,6 @@ function updateAncestorTraversalFlagsOnAttach(lView) {
|
|
|
2643
2741
|
*/
|
|
2644
2742
|
function markAncestorsForTraversal(lView) {
|
|
2645
2743
|
let parent = lView[PARENT];
|
|
2646
|
-
if (parent === null) {
|
|
2647
|
-
return;
|
|
2648
|
-
}
|
|
2649
2744
|
while (parent !== null) {
|
|
2650
2745
|
// We stop adding markers to the ancestors once we reach one that already has the marker. This
|
|
2651
2746
|
// is to avoid needlessly traversing all the way to the root when the marker already exists.
|
|
@@ -3576,9 +3671,6 @@ class NodeInjectorFactory {
|
|
|
3576
3671
|
function isFactory(obj) {
|
|
3577
3672
|
return obj instanceof NodeInjectorFactory;
|
|
3578
3673
|
}
|
|
3579
|
-
// Note: This hack is necessary so we don't erroneously get a circular dependency
|
|
3580
|
-
// failure based on types.
|
|
3581
|
-
const unusedValueExportToPlacateAjd$2 = 1;
|
|
3582
3674
|
|
|
3583
3675
|
/**
|
|
3584
3676
|
* Converts `TNodeType` into human readable text.
|
|
@@ -3610,9 +3702,6 @@ function isTNodeShape(value) {
|
|
|
3610
3702
|
typeof value.insertBeforeIndex === 'number' ||
|
|
3611
3703
|
Array.isArray(value.insertBeforeIndex));
|
|
3612
3704
|
}
|
|
3613
|
-
// Note: This hack is necessary so we don't erroneously get a circular dependency
|
|
3614
|
-
// failure based on types.
|
|
3615
|
-
const unusedValueExportToPlacateAjd$1 = 1;
|
|
3616
3705
|
/**
|
|
3617
3706
|
* Returns `true` if the `TNode` has a directive which has `@Input()` for `class` binding.
|
|
3618
3707
|
*
|
|
@@ -5483,93 +5572,6 @@ function componentDefResolved(type) {
|
|
|
5483
5572
|
componentDefPendingResolution.delete(type);
|
|
5484
5573
|
}
|
|
5485
5574
|
|
|
5486
|
-
/**
|
|
5487
|
-
* Creates a token that can be used in a DI Provider.
|
|
5488
|
-
*
|
|
5489
|
-
* Use an `InjectionToken` whenever the type you are injecting is not reified (does not have a
|
|
5490
|
-
* runtime representation) such as when injecting an interface, callable type, array or
|
|
5491
|
-
* parameterized type.
|
|
5492
|
-
*
|
|
5493
|
-
* `InjectionToken` is parameterized on `T` which is the type of object which will be returned by
|
|
5494
|
-
* the `Injector`. This provides an additional level of type safety.
|
|
5495
|
-
*
|
|
5496
|
-
* <div class="alert is-helpful">
|
|
5497
|
-
*
|
|
5498
|
-
* **Important Note**: Ensure that you use the same instance of the `InjectionToken` in both the
|
|
5499
|
-
* provider and the injection call. Creating a new instance of `InjectionToken` in different places,
|
|
5500
|
-
* even with the same description, will be treated as different tokens by Angular's DI system,
|
|
5501
|
-
* leading to a `NullInjectorError`.
|
|
5502
|
-
*
|
|
5503
|
-
* </div>
|
|
5504
|
-
*
|
|
5505
|
-
* <code-example format="typescript" language="typescript" path="injection-token/src/main.ts"
|
|
5506
|
-
* region="InjectionToken"></code-example>
|
|
5507
|
-
*
|
|
5508
|
-
* When creating an `InjectionToken`, you can optionally specify a factory function which returns
|
|
5509
|
-
* (possibly by creating) a default value of the parameterized type `T`. This sets up the
|
|
5510
|
-
* `InjectionToken` using this factory as a provider as if it was defined explicitly in the
|
|
5511
|
-
* application's root injector. If the factory function, which takes zero arguments, needs to inject
|
|
5512
|
-
* dependencies, it can do so using the [`inject`](api/core/inject) function.
|
|
5513
|
-
* As you can see in the Tree-shakable InjectionToken example below.
|
|
5514
|
-
*
|
|
5515
|
-
* Additionally, if a `factory` is specified you can also specify the `providedIn` option, which
|
|
5516
|
-
* overrides the above behavior and marks the token as belonging to a particular `@NgModule` (note:
|
|
5517
|
-
* this option is now deprecated). As mentioned above, `'root'` is the default value for
|
|
5518
|
-
* `providedIn`.
|
|
5519
|
-
*
|
|
5520
|
-
* The `providedIn: NgModule` and `providedIn: 'any'` options are deprecated.
|
|
5521
|
-
*
|
|
5522
|
-
* @usageNotes
|
|
5523
|
-
* ### Basic Examples
|
|
5524
|
-
*
|
|
5525
|
-
* ### Plain InjectionToken
|
|
5526
|
-
*
|
|
5527
|
-
* {@example core/di/ts/injector_spec.ts region='InjectionToken'}
|
|
5528
|
-
*
|
|
5529
|
-
* ### Tree-shakable InjectionToken
|
|
5530
|
-
*
|
|
5531
|
-
* {@example core/di/ts/injector_spec.ts region='ShakableInjectionToken'}
|
|
5532
|
-
*
|
|
5533
|
-
* @publicApi
|
|
5534
|
-
*/
|
|
5535
|
-
class InjectionToken {
|
|
5536
|
-
/**
|
|
5537
|
-
* @param _desc Description for the token,
|
|
5538
|
-
* used only for debugging purposes,
|
|
5539
|
-
* it should but does not need to be unique
|
|
5540
|
-
* @param options Options for the token's usage, as described above
|
|
5541
|
-
*/
|
|
5542
|
-
constructor(_desc, options) {
|
|
5543
|
-
this._desc = _desc;
|
|
5544
|
-
/** @internal */
|
|
5545
|
-
this.ngMetadataName = 'InjectionToken';
|
|
5546
|
-
this.ɵprov = undefined;
|
|
5547
|
-
if (typeof options == 'number') {
|
|
5548
|
-
(typeof ngDevMode === 'undefined' || ngDevMode) &&
|
|
5549
|
-
assertLessThan(options, 0, 'Only negative numbers are supported here');
|
|
5550
|
-
// This is a special hack to assign __NG_ELEMENT_ID__ to this instance.
|
|
5551
|
-
// See `InjectorMarkers`
|
|
5552
|
-
this.__NG_ELEMENT_ID__ = options;
|
|
5553
|
-
}
|
|
5554
|
-
else if (options !== undefined) {
|
|
5555
|
-
this.ɵprov = ɵɵdefineInjectable({
|
|
5556
|
-
token: this,
|
|
5557
|
-
providedIn: options.providedIn || 'root',
|
|
5558
|
-
factory: options.factory,
|
|
5559
|
-
});
|
|
5560
|
-
}
|
|
5561
|
-
}
|
|
5562
|
-
/**
|
|
5563
|
-
* @internal
|
|
5564
|
-
*/
|
|
5565
|
-
get multi() {
|
|
5566
|
-
return this;
|
|
5567
|
-
}
|
|
5568
|
-
toString() {
|
|
5569
|
-
return `InjectionToken ${this._desc}`;
|
|
5570
|
-
}
|
|
5571
|
-
}
|
|
5572
|
-
|
|
5573
5575
|
/**
|
|
5574
5576
|
* A multi-provider token for initialization functions that will run upon construction of an
|
|
5575
5577
|
* environment injector.
|
|
@@ -6014,6 +6016,11 @@ class R3Injector extends EnvironmentInjector {
|
|
|
6014
6016
|
if (def && this.injectableDefInScope(def)) {
|
|
6015
6017
|
// Found an injectable def and it's scoped to this injector. Pretend as if it was here
|
|
6016
6018
|
// all along.
|
|
6019
|
+
if (ngDevMode) {
|
|
6020
|
+
runInInjectorProfilerContext(this, token, () => {
|
|
6021
|
+
emitProviderConfiguredEvent(token);
|
|
6022
|
+
});
|
|
6023
|
+
}
|
|
6017
6024
|
record = makeRecord(injectableDefOrInjectorDefFactory(token), NOT_YET);
|
|
6018
6025
|
}
|
|
6019
6026
|
else {
|
|
@@ -6749,16 +6756,6 @@ const CSP_NONCE = new InjectionToken('CSP nonce', {
|
|
|
6749
6756
|
return getDocument().body?.querySelector('[ngCspNonce]')?.getAttribute('ngCspNonce') || null;
|
|
6750
6757
|
},
|
|
6751
6758
|
});
|
|
6752
|
-
/**
|
|
6753
|
-
* Internal token to collect all SSR-related features enabled for this application.
|
|
6754
|
-
*
|
|
6755
|
-
* Note: the token is in `core` to let other packages register features (the `core`
|
|
6756
|
-
* package is imported in other packages).
|
|
6757
|
-
*/
|
|
6758
|
-
const ENABLED_SSR_FEATURES = new InjectionToken((typeof ngDevMode === 'undefined' || ngDevMode) ? 'ENABLED_SSR_FEATURES' : '', {
|
|
6759
|
-
providedIn: 'root',
|
|
6760
|
-
factory: () => new Set(),
|
|
6761
|
-
});
|
|
6762
6759
|
const IMAGE_CONFIG_DEFAULTS = {
|
|
6763
6760
|
breakpoints: [16, 32, 48, 64, 96, 128, 256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840],
|
|
6764
6761
|
disableImageSizeWarning: false,
|
|
@@ -7419,11 +7416,12 @@ function matchingSchemas(schemas, tagName) {
|
|
|
7419
7416
|
* (component host node) to disable hydration for the content within that boundary.
|
|
7420
7417
|
*/
|
|
7421
7418
|
const SKIP_HYDRATION_ATTR_NAME = 'ngSkipHydration';
|
|
7419
|
+
/** Lowercase name of the `ngSkipHydration` attribute used for case-insensitive comparisons. */
|
|
7420
|
+
const SKIP_HYDRATION_ATTR_NAME_LOWER_CASE = 'ngskiphydration';
|
|
7422
7421
|
/**
|
|
7423
7422
|
* Helper function to check if a given TNode has the 'ngSkipHydration' attribute.
|
|
7424
7423
|
*/
|
|
7425
7424
|
function hasSkipHydrationAttrOnTNode(tNode) {
|
|
7426
|
-
const SKIP_HYDRATION_ATTR_NAME_LOWER_CASE = SKIP_HYDRATION_ATTR_NAME.toLowerCase();
|
|
7427
7425
|
const attrs = tNode.mergedAttrs;
|
|
7428
7426
|
if (attrs === null)
|
|
7429
7427
|
return false;
|
|
@@ -7457,15 +7455,14 @@ function hasInSkipHydrationBlockFlag(tNode) {
|
|
|
7457
7455
|
* Helper function that determines if a given node is within a skip hydration block
|
|
7458
7456
|
* by navigating up the TNode tree to see if any parent nodes have skip hydration
|
|
7459
7457
|
* attribute.
|
|
7460
|
-
*
|
|
7461
|
-
* TODO(akushnir): this function should contain the logic of `hasInSkipHydrationBlockFlag`,
|
|
7462
|
-
* there is no need to traverse parent nodes when we have a TNode flag (which would also
|
|
7463
|
-
* make this lookup O(1)).
|
|
7464
7458
|
*/
|
|
7465
7459
|
function isInSkipHydrationBlock(tNode) {
|
|
7460
|
+
if (hasInSkipHydrationBlockFlag(tNode)) {
|
|
7461
|
+
return true;
|
|
7462
|
+
}
|
|
7466
7463
|
let currentTNode = tNode.parent;
|
|
7467
7464
|
while (currentTNode) {
|
|
7468
|
-
if (hasSkipHydrationAttrOnTNode(currentTNode)) {
|
|
7465
|
+
if (hasInSkipHydrationBlockFlag(tNode) || hasSkipHydrationAttrOnTNode(currentTNode)) {
|
|
7469
7466
|
return true;
|
|
7470
7467
|
}
|
|
7471
7468
|
currentTNode = currentTNode.parent;
|
|
@@ -9997,7 +9994,7 @@ const DISCONNECTED_NODES = 'd';
|
|
|
9997
9994
|
* The name of the key used in the TransferState collection,
|
|
9998
9995
|
* where hydration information is located.
|
|
9999
9996
|
*/
|
|
10000
|
-
const TRANSFER_STATE_TOKEN_ID = '
|
|
9997
|
+
const TRANSFER_STATE_TOKEN_ID = '__nghData__';
|
|
10001
9998
|
/**
|
|
10002
9999
|
* Lookup key used to reference DOM hydration data (ngh) in `TransferState`.
|
|
10003
10000
|
*/
|
|
@@ -10429,7 +10426,7 @@ class Version {
|
|
|
10429
10426
|
/**
|
|
10430
10427
|
* @publicApi
|
|
10431
10428
|
*/
|
|
10432
|
-
const VERSION = new Version('17.0.0-
|
|
10429
|
+
const VERSION = new Version('17.0.0-rc.1');
|
|
10433
10430
|
|
|
10434
10431
|
// This default value is when checking the hierarchy for a token.
|
|
10435
10432
|
//
|
|
@@ -11410,6 +11407,34 @@ var AfterRenderPhase;
|
|
|
11410
11407
|
*/
|
|
11411
11408
|
AfterRenderPhase[AfterRenderPhase["Read"] = 3] = "Read";
|
|
11412
11409
|
})(AfterRenderPhase || (AfterRenderPhase = {}));
|
|
11410
|
+
/** `AfterRenderRef` that does nothing. */
|
|
11411
|
+
const NOOP_AFTER_RENDER_REF = {
|
|
11412
|
+
destroy() { }
|
|
11413
|
+
};
|
|
11414
|
+
/**
|
|
11415
|
+
* Register a callback to run once before any userspace `afterRender` or
|
|
11416
|
+
* `afterNextRender` callbacks.
|
|
11417
|
+
*
|
|
11418
|
+
* This function should almost always be used instead of `afterRender` or
|
|
11419
|
+
* `afterNextRender` for implementing framework functionality. Consider:
|
|
11420
|
+
*
|
|
11421
|
+
* 1.) `AfterRenderPhase.EarlyRead` is intended to be used for implementing
|
|
11422
|
+
* custom layout. If the framework itself mutates the DOM after *any*
|
|
11423
|
+
* `AfterRenderPhase.EarlyRead` callbacks are run, the phase can no
|
|
11424
|
+
* longer reliably serve its purpose.
|
|
11425
|
+
*
|
|
11426
|
+
* 2.) Importing `afterRender` in the framework can reduce the ability for it
|
|
11427
|
+
* to be tree-shaken, and the framework shouldn't need much of the behavior.
|
|
11428
|
+
*/
|
|
11429
|
+
function internalAfterNextRender(callback, options) {
|
|
11430
|
+
const injector = options?.injector ?? inject(Injector);
|
|
11431
|
+
// Similarly to the public `afterNextRender` function, an internal one
|
|
11432
|
+
// is only invoked in a browser.
|
|
11433
|
+
if (!isPlatformBrowser(injector))
|
|
11434
|
+
return;
|
|
11435
|
+
const afterRenderEventManager = injector.get(AfterRenderEventManager);
|
|
11436
|
+
afterRenderEventManager.internalCallbacks.push(callback);
|
|
11437
|
+
}
|
|
11413
11438
|
/**
|
|
11414
11439
|
* Register a callback to be invoked each time the application
|
|
11415
11440
|
* finishes rendering.
|
|
@@ -11465,22 +11490,20 @@ function afterRender(callback, options) {
|
|
|
11465
11490
|
!options && assertInInjectionContext(afterRender);
|
|
11466
11491
|
const injector = options?.injector ?? inject(Injector);
|
|
11467
11492
|
if (!isPlatformBrowser(injector)) {
|
|
11468
|
-
return
|
|
11493
|
+
return NOOP_AFTER_RENDER_REF;
|
|
11469
11494
|
}
|
|
11470
|
-
|
|
11471
|
-
const unregisterFn = injector.get(DestroyRef).onDestroy(() => destroy?.());
|
|
11495
|
+
performance.mark('mark_use_counter', { detail: { feature: 'NgAfterRender' } });
|
|
11472
11496
|
const afterRenderEventManager = injector.get(AfterRenderEventManager);
|
|
11473
11497
|
// Lazily initialize the handler implementation, if necessary. This is so that it can be
|
|
11474
11498
|
// tree-shaken if `afterRender` and `afterNextRender` aren't used.
|
|
11475
11499
|
const callbackHandler = afterRenderEventManager.handler ??= new AfterRenderCallbackHandlerImpl();
|
|
11476
|
-
const ngZone = injector.get(NgZone);
|
|
11477
|
-
const errorHandler = injector.get(ErrorHandler, null, { optional: true });
|
|
11478
11500
|
const phase = options?.phase ?? AfterRenderPhase.MixedReadWrite;
|
|
11479
|
-
const
|
|
11480
|
-
destroy = () => {
|
|
11501
|
+
const destroy = () => {
|
|
11481
11502
|
callbackHandler.unregister(instance);
|
|
11482
11503
|
unregisterFn();
|
|
11483
11504
|
};
|
|
11505
|
+
const unregisterFn = injector.get(DestroyRef).onDestroy(destroy);
|
|
11506
|
+
const instance = new AfterRenderCallback(injector, phase, callback);
|
|
11484
11507
|
callbackHandler.register(instance);
|
|
11485
11508
|
return { destroy };
|
|
11486
11509
|
}
|
|
@@ -11537,25 +11560,23 @@ function afterNextRender(callback, options) {
|
|
|
11537
11560
|
!options && assertInInjectionContext(afterNextRender);
|
|
11538
11561
|
const injector = options?.injector ?? inject(Injector);
|
|
11539
11562
|
if (!isPlatformBrowser(injector)) {
|
|
11540
|
-
return
|
|
11563
|
+
return NOOP_AFTER_RENDER_REF;
|
|
11541
11564
|
}
|
|
11542
|
-
|
|
11543
|
-
const unregisterFn = injector.get(DestroyRef).onDestroy(() => destroy?.());
|
|
11565
|
+
performance.mark('mark_use_counter', { detail: { feature: 'NgAfterNextRender' } });
|
|
11544
11566
|
const afterRenderEventManager = injector.get(AfterRenderEventManager);
|
|
11545
11567
|
// Lazily initialize the handler implementation, if necessary. This is so that it can be
|
|
11546
11568
|
// tree-shaken if `afterRender` and `afterNextRender` aren't used.
|
|
11547
11569
|
const callbackHandler = afterRenderEventManager.handler ??= new AfterRenderCallbackHandlerImpl();
|
|
11548
|
-
const ngZone = injector.get(NgZone);
|
|
11549
|
-
const errorHandler = injector.get(ErrorHandler, null, { optional: true });
|
|
11550
11570
|
const phase = options?.phase ?? AfterRenderPhase.MixedReadWrite;
|
|
11551
|
-
const
|
|
11552
|
-
destroy?.();
|
|
11553
|
-
callback();
|
|
11554
|
-
});
|
|
11555
|
-
destroy = () => {
|
|
11571
|
+
const destroy = () => {
|
|
11556
11572
|
callbackHandler.unregister(instance);
|
|
11557
11573
|
unregisterFn();
|
|
11558
11574
|
};
|
|
11575
|
+
const unregisterFn = injector.get(DestroyRef).onDestroy(destroy);
|
|
11576
|
+
const instance = new AfterRenderCallback(injector, phase, () => {
|
|
11577
|
+
destroy();
|
|
11578
|
+
callback();
|
|
11579
|
+
});
|
|
11559
11580
|
callbackHandler.register(instance);
|
|
11560
11581
|
return { destroy };
|
|
11561
11582
|
}
|
|
@@ -11563,11 +11584,11 @@ function afterNextRender(callback, options) {
|
|
|
11563
11584
|
* A wrapper around a function to be used as an after render callback.
|
|
11564
11585
|
*/
|
|
11565
11586
|
class AfterRenderCallback {
|
|
11566
|
-
constructor(
|
|
11567
|
-
this.zone = zone;
|
|
11568
|
-
this.errorHandler = errorHandler;
|
|
11587
|
+
constructor(injector, phase, callbackFn) {
|
|
11569
11588
|
this.phase = phase;
|
|
11570
11589
|
this.callbackFn = callbackFn;
|
|
11590
|
+
this.zone = injector.get(NgZone);
|
|
11591
|
+
this.errorHandler = injector.get(ErrorHandler, null, { optional: true });
|
|
11571
11592
|
}
|
|
11572
11593
|
invoke() {
|
|
11573
11594
|
try {
|
|
@@ -11640,6 +11661,8 @@ class AfterRenderEventManager {
|
|
|
11640
11661
|
this.renderDepth = 0;
|
|
11641
11662
|
/* @internal */
|
|
11642
11663
|
this.handler = null;
|
|
11664
|
+
/* @internal */
|
|
11665
|
+
this.internalCallbacks = [];
|
|
11643
11666
|
}
|
|
11644
11667
|
/**
|
|
11645
11668
|
* Mark the beginning of a render operation (i.e. CD cycle).
|
|
@@ -11657,12 +11680,20 @@ class AfterRenderEventManager {
|
|
|
11657
11680
|
ngDevMode && assertGreaterThan(this.renderDepth, 0, 'renderDepth must be greater than 0');
|
|
11658
11681
|
this.renderDepth--;
|
|
11659
11682
|
if (this.renderDepth === 0) {
|
|
11683
|
+
// Note: internal callbacks power `internalAfterNextRender`. Since internal callbacks
|
|
11684
|
+
// are fairly trivial, they are kept separate so that `AfterRenderCallbackHandlerImpl`
|
|
11685
|
+
// can still be tree-shaken unless used by the application.
|
|
11686
|
+
for (const callback of this.internalCallbacks) {
|
|
11687
|
+
callback();
|
|
11688
|
+
}
|
|
11689
|
+
this.internalCallbacks.length = 0;
|
|
11660
11690
|
this.handler?.execute();
|
|
11661
11691
|
}
|
|
11662
11692
|
}
|
|
11663
11693
|
ngOnDestroy() {
|
|
11664
11694
|
this.handler?.destroy();
|
|
11665
11695
|
this.handler = null;
|
|
11696
|
+
this.internalCallbacks.length = 0;
|
|
11666
11697
|
}
|
|
11667
11698
|
/** @nocollapse */
|
|
11668
11699
|
static { this.ɵprov = ɵɵdefineInjectable({
|
|
@@ -11840,11 +11871,6 @@ function getExpressionChangedErrorDetails(lView, bindingIndex, oldValue, newValu
|
|
|
11840
11871
|
}
|
|
11841
11872
|
|
|
11842
11873
|
let currentConsumer = null;
|
|
11843
|
-
function setLViewForConsumer(node, lView) {
|
|
11844
|
-
(typeof ngDevMode === 'undefined' || ngDevMode) &&
|
|
11845
|
-
assertEqual(node.lView, null, 'Consumer already associated with a view.');
|
|
11846
|
-
node.lView = lView;
|
|
11847
|
-
}
|
|
11848
11874
|
/**
|
|
11849
11875
|
* Create a new template consumer pointing at the specified LView.
|
|
11850
11876
|
* Sometimes, a previously created consumer may be reused, in order to save on allocations. In that
|
|
@@ -13512,6 +13538,10 @@ function collectNativeNodesInLContainer(lContainer, result) {
|
|
|
13512
13538
|
}
|
|
13513
13539
|
}
|
|
13514
13540
|
|
|
13541
|
+
/**
|
|
13542
|
+
* The maximum number of times the change detection traversal will rerun before throwing an error.
|
|
13543
|
+
*/
|
|
13544
|
+
const MAXIMUM_REFRESH_RERUNS = 100;
|
|
13515
13545
|
function detectChangesInternal(tView, lView, context, notifyErrorHandler = true) {
|
|
13516
13546
|
const environment = lView[ENVIRONMENT];
|
|
13517
13547
|
const rendererFactory = environment.rendererFactory;
|
|
@@ -13526,6 +13556,23 @@ function detectChangesInternal(tView, lView, context, notifyErrorHandler = true)
|
|
|
13526
13556
|
}
|
|
13527
13557
|
try {
|
|
13528
13558
|
refreshView(tView, lView, tView.template, context);
|
|
13559
|
+
let retries = 0;
|
|
13560
|
+
// If after running change detection, this view still needs to be refreshed or there are
|
|
13561
|
+
// descendants views that need to be refreshed due to re-dirtying during the change detection
|
|
13562
|
+
// run, detect changes on the view again. We run change detection in `Targeted` mode to only
|
|
13563
|
+
// refresh views with the `RefreshView` flag.
|
|
13564
|
+
while (lView[FLAGS] & (1024 /* LViewFlags.RefreshView */ | 8192 /* LViewFlags.HasChildViewsToRefresh */)) {
|
|
13565
|
+
if (retries === MAXIMUM_REFRESH_RERUNS) {
|
|
13566
|
+
throw new RuntimeError(103 /* RuntimeErrorCode.INFINITE_CHANGE_DETECTION */, ngDevMode &&
|
|
13567
|
+
'Infinite change detection while trying to refresh views. ' +
|
|
13568
|
+
'There may be components which each cause the other to require a refresh, ' +
|
|
13569
|
+
'causing an infinite loop.');
|
|
13570
|
+
}
|
|
13571
|
+
retries++;
|
|
13572
|
+
// Even if this view is detached, we still detect changes in targeted mode because this was
|
|
13573
|
+
// the root of the change detection run.
|
|
13574
|
+
detectChangesInView(lView, 1 /* ChangeDetectionMode.Targeted */);
|
|
13575
|
+
}
|
|
13529
13576
|
}
|
|
13530
13577
|
catch (error) {
|
|
13531
13578
|
if (notifyErrorHandler) {
|
|
@@ -13680,7 +13727,6 @@ function refreshView(tView, lView, templateFn, context) {
|
|
|
13680
13727
|
if (!isInCheckNoChangesPass) {
|
|
13681
13728
|
lView[FLAGS] &= ~(64 /* LViewFlags.Dirty */ | 8 /* LViewFlags.FirstLViewPass */);
|
|
13682
13729
|
}
|
|
13683
|
-
lView[FLAGS] &= ~1024 /* LViewFlags.RefreshView */;
|
|
13684
13730
|
}
|
|
13685
13731
|
catch (e) {
|
|
13686
13732
|
// If refreshing a view causes an error, we need to remark the ancestors as needing traversal
|
|
@@ -13763,7 +13809,7 @@ function detectChangesInView(lView, mode) {
|
|
|
13763
13809
|
const flags = lView[FLAGS];
|
|
13764
13810
|
// Flag cleared before change detection runs so that the view can be re-marked for traversal if
|
|
13765
13811
|
// necessary.
|
|
13766
|
-
lView[FLAGS] &= ~8192 /* LViewFlags.HasChildViewsToRefresh
|
|
13812
|
+
lView[FLAGS] &= ~(8192 /* LViewFlags.HasChildViewsToRefresh */ | 1024 /* LViewFlags.RefreshView */);
|
|
13767
13813
|
if ((flags & (16 /* LViewFlags.CheckAlways */ | 64 /* LViewFlags.Dirty */) &&
|
|
13768
13814
|
mode === 0 /* ChangeDetectionMode.Global */) ||
|
|
13769
13815
|
flags & 1024 /* LViewFlags.RefreshView */) {
|
|
@@ -18264,6 +18310,17 @@ class LiveCollection {
|
|
|
18264
18310
|
this.attach(newIdx, this.detach(prevIndex));
|
|
18265
18311
|
}
|
|
18266
18312
|
}
|
|
18313
|
+
function valuesMatching(liveIdx, liveValue, newIdx, newValue, trackBy) {
|
|
18314
|
+
if (liveIdx === newIdx && Object.is(liveValue, newValue)) {
|
|
18315
|
+
// matching and no value identity to update
|
|
18316
|
+
return 1;
|
|
18317
|
+
}
|
|
18318
|
+
else if (Object.is(trackBy(liveIdx, liveValue), trackBy(newIdx, newValue))) {
|
|
18319
|
+
// matching but requires value identity update
|
|
18320
|
+
return -1;
|
|
18321
|
+
}
|
|
18322
|
+
return 0;
|
|
18323
|
+
}
|
|
18267
18324
|
/**
|
|
18268
18325
|
* The live collection reconciliation algorithm that perform various in-place operations, so it
|
|
18269
18326
|
* reflects the content of the new (incoming) collection.
|
|
@@ -18296,40 +18353,47 @@ function reconcile(liveCollection, newCollection, trackByFn) {
|
|
|
18296
18353
|
let newEndIdx = newCollection.length - 1;
|
|
18297
18354
|
while (liveStartIdx <= liveEndIdx && liveStartIdx <= newEndIdx) {
|
|
18298
18355
|
// compare from the beginning
|
|
18299
|
-
const
|
|
18356
|
+
const liveStartValue = liveCollection.at(liveStartIdx);
|
|
18300
18357
|
const newStartValue = newCollection[liveStartIdx];
|
|
18301
|
-
const
|
|
18302
|
-
if (
|
|
18303
|
-
|
|
18358
|
+
const isStartMatching = valuesMatching(liveStartIdx, liveStartValue, liveStartIdx, newStartValue, trackByFn);
|
|
18359
|
+
if (isStartMatching !== 0) {
|
|
18360
|
+
if (isStartMatching < 0) {
|
|
18361
|
+
liveCollection.updateValue(liveStartIdx, newStartValue);
|
|
18362
|
+
}
|
|
18304
18363
|
liveStartIdx++;
|
|
18305
18364
|
continue;
|
|
18306
18365
|
}
|
|
18307
18366
|
// compare from the end
|
|
18308
18367
|
// TODO(perf): do _all_ the matching from the end
|
|
18309
|
-
const
|
|
18310
|
-
const
|
|
18311
|
-
const
|
|
18312
|
-
if (
|
|
18313
|
-
|
|
18368
|
+
const liveEndValue = liveCollection.at(liveEndIdx);
|
|
18369
|
+
const newEndValue = newCollection[newEndIdx];
|
|
18370
|
+
const isEndMatching = valuesMatching(liveEndIdx, liveEndValue, newEndIdx, newEndValue, trackByFn);
|
|
18371
|
+
if (isEndMatching !== 0) {
|
|
18372
|
+
if (isEndMatching < 0) {
|
|
18373
|
+
liveCollection.updateValue(liveEndIdx, newEndValue);
|
|
18374
|
+
}
|
|
18314
18375
|
liveEndIdx--;
|
|
18315
18376
|
newEndIdx--;
|
|
18316
18377
|
continue;
|
|
18317
18378
|
}
|
|
18318
|
-
// Detect swap
|
|
18319
|
-
|
|
18320
|
-
|
|
18321
|
-
|
|
18322
|
-
|
|
18323
|
-
|
|
18324
|
-
|
|
18325
|
-
|
|
18326
|
-
|
|
18327
|
-
|
|
18328
|
-
|
|
18329
|
-
|
|
18330
|
-
|
|
18331
|
-
|
|
18332
|
-
|
|
18379
|
+
// Detect swap and moves:
|
|
18380
|
+
const liveStartKey = trackByFn(liveStartIdx, liveStartValue);
|
|
18381
|
+
const liveEndKey = trackByFn(liveEndIdx, liveEndValue);
|
|
18382
|
+
const newStartKey = trackByFn(liveStartIdx, newStartValue);
|
|
18383
|
+
if (Object.is(newStartKey, liveEndKey)) {
|
|
18384
|
+
const newEndKey = trackByFn(newEndIdx, newEndValue);
|
|
18385
|
+
// detect swap on both ends;
|
|
18386
|
+
if (Object.is(newEndKey, liveStartKey)) {
|
|
18387
|
+
liveCollection.swap(liveStartIdx, liveEndIdx);
|
|
18388
|
+
liveCollection.updateValue(liveEndIdx, newEndValue);
|
|
18389
|
+
newEndIdx--;
|
|
18390
|
+
liveEndIdx--;
|
|
18391
|
+
}
|
|
18392
|
+
else {
|
|
18393
|
+
// the new item is the same as the live item with the end pointer - this is a move forward
|
|
18394
|
+
// to an earlier index;
|
|
18395
|
+
liveCollection.move(liveEndIdx, liveStartIdx);
|
|
18396
|
+
}
|
|
18333
18397
|
liveCollection.updateValue(liveStartIdx, newStartValue);
|
|
18334
18398
|
liveStartIdx++;
|
|
18335
18399
|
continue;
|
|
@@ -18337,7 +18401,8 @@ function reconcile(liveCollection, newCollection, trackByFn) {
|
|
|
18337
18401
|
// Fallback to the slow path: we need to learn more about the content of the live and new
|
|
18338
18402
|
// collections.
|
|
18339
18403
|
detachedItems ??= new MultiMap();
|
|
18340
|
-
liveKeysInTheFuture ??=
|
|
18404
|
+
liveKeysInTheFuture ??=
|
|
18405
|
+
initLiveItemsInTheFuture(liveCollection, liveStartIdx, liveEndIdx, trackByFn);
|
|
18341
18406
|
// Check if I'm inserting a previously detached item: if so, attach it here
|
|
18342
18407
|
if (attachPreviouslyDetached(liveCollection, detachedItems, liveStartIdx, newStartKey)) {
|
|
18343
18408
|
liveCollection.updateValue(liveStartIdx, newStartValue);
|
|
@@ -18371,19 +18436,23 @@ function reconcile(liveCollection, newCollection, trackByFn) {
|
|
|
18371
18436
|
const newCollectionIterator = newCollection[Symbol.iterator]();
|
|
18372
18437
|
let newIterationResult = newCollectionIterator.next();
|
|
18373
18438
|
while (!newIterationResult.done && liveStartIdx <= liveEndIdx) {
|
|
18439
|
+
const liveValue = liveCollection.at(liveStartIdx);
|
|
18374
18440
|
const newValue = newIterationResult.value;
|
|
18375
|
-
const
|
|
18376
|
-
|
|
18377
|
-
|
|
18378
|
-
|
|
18379
|
-
|
|
18441
|
+
const isStartMatching = valuesMatching(liveStartIdx, liveValue, liveStartIdx, newValue, trackByFn);
|
|
18442
|
+
if (isStartMatching !== 0) {
|
|
18443
|
+
// found a match - move on, but update value
|
|
18444
|
+
if (isStartMatching < 0) {
|
|
18445
|
+
liveCollection.updateValue(liveStartIdx, newValue);
|
|
18446
|
+
}
|
|
18380
18447
|
liveStartIdx++;
|
|
18381
18448
|
newIterationResult = newCollectionIterator.next();
|
|
18382
18449
|
}
|
|
18383
18450
|
else {
|
|
18384
18451
|
detachedItems ??= new MultiMap();
|
|
18385
|
-
liveKeysInTheFuture ??=
|
|
18452
|
+
liveKeysInTheFuture ??=
|
|
18453
|
+
initLiveItemsInTheFuture(liveCollection, liveStartIdx, liveEndIdx, trackByFn);
|
|
18386
18454
|
// Check if I'm inserting a previously detached item: if so, attach it here
|
|
18455
|
+
const newKey = trackByFn(liveStartIdx, newValue);
|
|
18387
18456
|
if (attachPreviouslyDetached(liveCollection, detachedItems, liveStartIdx, newKey)) {
|
|
18388
18457
|
liveCollection.updateValue(liveStartIdx, newValue);
|
|
18389
18458
|
liveStartIdx++;
|
|
@@ -18398,6 +18467,7 @@ function reconcile(liveCollection, newCollection, trackByFn) {
|
|
|
18398
18467
|
}
|
|
18399
18468
|
else {
|
|
18400
18469
|
// it is a move forward - detach the current item without advancing in collections
|
|
18470
|
+
const liveKey = trackByFn(liveStartIdx, liveValue);
|
|
18401
18471
|
detachedItems.set(liveKey, liveCollection.detach(liveStartIdx));
|
|
18402
18472
|
liveEndIdx--;
|
|
18403
18473
|
}
|
|
@@ -18435,10 +18505,10 @@ function createOrAttach(liveCollection, detachedItems, trackByFn, index, value)
|
|
|
18435
18505
|
liveCollection.updateValue(index, value);
|
|
18436
18506
|
}
|
|
18437
18507
|
}
|
|
18438
|
-
function initLiveItemsInTheFuture(liveCollection, start, end) {
|
|
18508
|
+
function initLiveItemsInTheFuture(liveCollection, start, end, trackByFn) {
|
|
18439
18509
|
const keys = new Set();
|
|
18440
18510
|
for (let i = start; i <= end; i++) {
|
|
18441
|
-
keys.add(liveCollection.
|
|
18511
|
+
keys.add(trackByFn(i, liveCollection.at(i)));
|
|
18442
18512
|
}
|
|
18443
18513
|
return keys;
|
|
18444
18514
|
}
|
|
@@ -18923,10 +18993,8 @@ function populateDehydratedViewsInLContainerImpl(lContainer, tNode, hostLView) {
|
|
|
18923
18993
|
}
|
|
18924
18994
|
const hydrationInfo = hostLView[HYDRATION];
|
|
18925
18995
|
const noOffsetIndex = tNode.index - HEADER_OFFSET;
|
|
18926
|
-
|
|
18927
|
-
|
|
18928
|
-
const skipHydration = isInSkipHydrationBlock(tNode) || hasInSkipHydrationBlockFlag(tNode);
|
|
18929
|
-
const isNodeCreationMode = !hydrationInfo || skipHydration || isDisconnectedNode$1(hydrationInfo, noOffsetIndex);
|
|
18996
|
+
const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock(tNode) ||
|
|
18997
|
+
isDisconnectedNode$1(hydrationInfo, noOffsetIndex);
|
|
18930
18998
|
// Regular creation mode.
|
|
18931
18999
|
if (isNodeCreationMode) {
|
|
18932
19000
|
return false;
|
|
@@ -19150,9 +19218,10 @@ function ɵɵrepeaterTrackByIdentity(_, value) {
|
|
|
19150
19218
|
return value;
|
|
19151
19219
|
}
|
|
19152
19220
|
class RepeaterMetadata {
|
|
19153
|
-
constructor(hasEmptyBlock, trackByFn) {
|
|
19221
|
+
constructor(hasEmptyBlock, trackByFn, liveCollection) {
|
|
19154
19222
|
this.hasEmptyBlock = hasEmptyBlock;
|
|
19155
19223
|
this.trackByFn = trackByFn;
|
|
19224
|
+
this.liveCollection = liveCollection;
|
|
19156
19225
|
}
|
|
19157
19226
|
}
|
|
19158
19227
|
/**
|
|
@@ -19197,12 +19266,11 @@ function ɵɵrepeaterCreate(index, templateFn, decls, vars, trackByFn, trackByUs
|
|
|
19197
19266
|
}
|
|
19198
19267
|
}
|
|
19199
19268
|
class LiveCollectionLContainerImpl extends LiveCollection {
|
|
19200
|
-
constructor(lContainer, hostLView, templateTNode
|
|
19269
|
+
constructor(lContainer, hostLView, templateTNode) {
|
|
19201
19270
|
super();
|
|
19202
19271
|
this.lContainer = lContainer;
|
|
19203
19272
|
this.hostLView = hostLView;
|
|
19204
19273
|
this.templateTNode = templateTNode;
|
|
19205
|
-
this.trackByFn = trackByFn;
|
|
19206
19274
|
/**
|
|
19207
19275
|
Property indicating if indexes in the repeater context need to be updated following the live
|
|
19208
19276
|
collection changes. Index updates are necessary if and only if views are inserted / removed in
|
|
@@ -19214,10 +19282,7 @@ class LiveCollectionLContainerImpl extends LiveCollection {
|
|
|
19214
19282
|
return this.lContainer.length - CONTAINER_HEADER_OFFSET;
|
|
19215
19283
|
}
|
|
19216
19284
|
at(index) {
|
|
19217
|
-
return
|
|
19218
|
-
}
|
|
19219
|
-
key(index) {
|
|
19220
|
-
return this.trackByFn(index, this.at(index)[CONTEXT].$implicit);
|
|
19285
|
+
return this.getLView(index)[CONTEXT].$implicit;
|
|
19221
19286
|
}
|
|
19222
19287
|
attach(index, lView) {
|
|
19223
19288
|
const dehydratedView = lView[HYDRATION];
|
|
@@ -19237,15 +19302,21 @@ class LiveCollectionLContainerImpl extends LiveCollection {
|
|
|
19237
19302
|
destroyLView(lView[TVIEW], lView);
|
|
19238
19303
|
}
|
|
19239
19304
|
updateValue(index, value) {
|
|
19240
|
-
this.
|
|
19305
|
+
this.getLView(index)[CONTEXT].$implicit = value;
|
|
19306
|
+
}
|
|
19307
|
+
reset() {
|
|
19308
|
+
this.needsIndexUpdate = false;
|
|
19241
19309
|
}
|
|
19242
19310
|
updateIndexes() {
|
|
19243
19311
|
if (this.needsIndexUpdate) {
|
|
19244
19312
|
for (let i = 0; i < this.length; i++) {
|
|
19245
|
-
this.
|
|
19313
|
+
this.getLView(i)[CONTEXT].$index = i;
|
|
19246
19314
|
}
|
|
19247
19315
|
}
|
|
19248
19316
|
}
|
|
19317
|
+
getLView(index) {
|
|
19318
|
+
return getExistingLViewFromLContainer(this.lContainer, index);
|
|
19319
|
+
}
|
|
19249
19320
|
}
|
|
19250
19321
|
/**
|
|
19251
19322
|
* The repeater instruction does update-time diffing of a provided collection (against the
|
|
@@ -19261,17 +19332,24 @@ function ɵɵrepeater(metadataSlotIdx, collection) {
|
|
|
19261
19332
|
const hostLView = getLView();
|
|
19262
19333
|
const hostTView = hostLView[TVIEW];
|
|
19263
19334
|
const metadata = hostLView[HEADER_OFFSET + metadataSlotIdx];
|
|
19264
|
-
|
|
19265
|
-
|
|
19266
|
-
|
|
19267
|
-
|
|
19335
|
+
if (metadata.liveCollection === undefined) {
|
|
19336
|
+
const containerIndex = metadataSlotIdx + 1;
|
|
19337
|
+
const lContainer = getLContainer(hostLView, HEADER_OFFSET + containerIndex);
|
|
19338
|
+
const itemTemplateTNode = getExistingTNode(hostTView, containerIndex);
|
|
19339
|
+
metadata.liveCollection =
|
|
19340
|
+
new LiveCollectionLContainerImpl(lContainer, hostLView, itemTemplateTNode);
|
|
19341
|
+
}
|
|
19342
|
+
else {
|
|
19343
|
+
metadata.liveCollection.reset();
|
|
19344
|
+
}
|
|
19345
|
+
const liveCollection = metadata.liveCollection;
|
|
19268
19346
|
reconcile(liveCollection, collection, metadata.trackByFn);
|
|
19269
19347
|
// moves in the container might caused context's index to get out of order, re-adjust if needed
|
|
19270
19348
|
liveCollection.updateIndexes();
|
|
19271
19349
|
// handle empty blocks
|
|
19272
19350
|
if (metadata.hasEmptyBlock) {
|
|
19273
19351
|
const bindingIndex = nextBindingIndex();
|
|
19274
|
-
const isCollectionEmpty =
|
|
19352
|
+
const isCollectionEmpty = liveCollection.length === 0;
|
|
19275
19353
|
if (bindingUpdated(hostLView, bindingIndex, isCollectionEmpty)) {
|
|
19276
19354
|
const emptyTemplateIndex = metadataSlotIdx + 2;
|
|
19277
19355
|
const lContainerForEmpty = getLContainer(hostLView, HEADER_OFFSET + emptyTemplateIndex);
|
|
@@ -19362,6 +19440,8 @@ const NEXT_DEFER_BLOCK_STATE = 0;
|
|
|
19362
19440
|
const DEFER_BLOCK_STATE = 1;
|
|
19363
19441
|
const STATE_IS_FROZEN_UNTIL = 2;
|
|
19364
19442
|
const LOADING_AFTER_CLEANUP_FN = 3;
|
|
19443
|
+
const TRIGGER_CLEANUP_FNS = 4;
|
|
19444
|
+
const PREFETCH_TRIGGER_CLEANUP_FNS = 5;
|
|
19365
19445
|
/**
|
|
19366
19446
|
* Options for configuring defer blocks behavior.
|
|
19367
19447
|
* @publicApi
|
|
@@ -19380,6 +19460,155 @@ var DeferBlockBehavior;
|
|
|
19380
19460
|
DeferBlockBehavior[DeferBlockBehavior["Playthrough"] = 1] = "Playthrough";
|
|
19381
19461
|
})(DeferBlockBehavior || (DeferBlockBehavior = {}));
|
|
19382
19462
|
|
|
19463
|
+
/*!
|
|
19464
|
+
* @license
|
|
19465
|
+
* Copyright Google LLC All Rights Reserved.
|
|
19466
|
+
*
|
|
19467
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
19468
|
+
* found in the LICENSE file at https://angular.io/license
|
|
19469
|
+
*/
|
|
19470
|
+
/**
|
|
19471
|
+
* Registers a cleanup function associated with a prefetching trigger
|
|
19472
|
+
* or a regular trigger of a defer block.
|
|
19473
|
+
*/
|
|
19474
|
+
function storeTriggerCleanupFn(type, lDetails, cleanupFn) {
|
|
19475
|
+
const key = type === 1 /* TriggerType.Prefetch */ ? PREFETCH_TRIGGER_CLEANUP_FNS : TRIGGER_CLEANUP_FNS;
|
|
19476
|
+
if (lDetails[key] === null) {
|
|
19477
|
+
lDetails[key] = [];
|
|
19478
|
+
}
|
|
19479
|
+
lDetails[key].push(cleanupFn);
|
|
19480
|
+
}
|
|
19481
|
+
/**
|
|
19482
|
+
* Invokes registered cleanup functions either for prefetch or for regular triggers.
|
|
19483
|
+
*/
|
|
19484
|
+
function invokeTriggerCleanupFns(type, lDetails) {
|
|
19485
|
+
const key = type === 1 /* TriggerType.Prefetch */ ? PREFETCH_TRIGGER_CLEANUP_FNS : TRIGGER_CLEANUP_FNS;
|
|
19486
|
+
const cleanupFns = lDetails[key];
|
|
19487
|
+
if (cleanupFns !== null) {
|
|
19488
|
+
for (const cleanupFn of cleanupFns) {
|
|
19489
|
+
cleanupFn();
|
|
19490
|
+
}
|
|
19491
|
+
lDetails[key] = null;
|
|
19492
|
+
}
|
|
19493
|
+
}
|
|
19494
|
+
/**
|
|
19495
|
+
* Invokes registered cleanup functions for both prefetch and regular triggers.
|
|
19496
|
+
*/
|
|
19497
|
+
function invokeAllTriggerCleanupFns(lDetails) {
|
|
19498
|
+
invokeTriggerCleanupFns(1 /* TriggerType.Prefetch */, lDetails);
|
|
19499
|
+
invokeTriggerCleanupFns(0 /* TriggerType.Regular */, lDetails);
|
|
19500
|
+
}
|
|
19501
|
+
|
|
19502
|
+
/**
|
|
19503
|
+
* Calculates a data slot index for defer block info (either static or
|
|
19504
|
+
* instance-specific), given an index of a defer instruction.
|
|
19505
|
+
*/
|
|
19506
|
+
function getDeferBlockDataIndex(deferBlockIndex) {
|
|
19507
|
+
// Instance state is located at the *next* position
|
|
19508
|
+
// after the defer block slot in an LView or TView.data.
|
|
19509
|
+
return deferBlockIndex + 1;
|
|
19510
|
+
}
|
|
19511
|
+
/** Retrieves a defer block state from an LView, given a TNode that represents a block. */
|
|
19512
|
+
function getLDeferBlockDetails(lView, tNode) {
|
|
19513
|
+
const tView = lView[TVIEW];
|
|
19514
|
+
const slotIndex = getDeferBlockDataIndex(tNode.index);
|
|
19515
|
+
ngDevMode && assertIndexInDeclRange(tView, slotIndex);
|
|
19516
|
+
return lView[slotIndex];
|
|
19517
|
+
}
|
|
19518
|
+
/** Stores a defer block instance state in LView. */
|
|
19519
|
+
function setLDeferBlockDetails(lView, deferBlockIndex, lDetails) {
|
|
19520
|
+
const tView = lView[TVIEW];
|
|
19521
|
+
const slotIndex = getDeferBlockDataIndex(deferBlockIndex);
|
|
19522
|
+
ngDevMode && assertIndexInDeclRange(tView, slotIndex);
|
|
19523
|
+
lView[slotIndex] = lDetails;
|
|
19524
|
+
}
|
|
19525
|
+
/** Retrieves static info about a defer block, given a TView and a TNode that represents a block. */
|
|
19526
|
+
function getTDeferBlockDetails(tView, tNode) {
|
|
19527
|
+
const slotIndex = getDeferBlockDataIndex(tNode.index);
|
|
19528
|
+
ngDevMode && assertIndexInDeclRange(tView, slotIndex);
|
|
19529
|
+
return tView.data[slotIndex];
|
|
19530
|
+
}
|
|
19531
|
+
/** Stores a defer block static info in `TView.data`. */
|
|
19532
|
+
function setTDeferBlockDetails(tView, deferBlockIndex, deferBlockConfig) {
|
|
19533
|
+
const slotIndex = getDeferBlockDataIndex(deferBlockIndex);
|
|
19534
|
+
ngDevMode && assertIndexInDeclRange(tView, slotIndex);
|
|
19535
|
+
tView.data[slotIndex] = deferBlockConfig;
|
|
19536
|
+
}
|
|
19537
|
+
function getTemplateIndexForState(newState, hostLView, tNode) {
|
|
19538
|
+
const tView = hostLView[TVIEW];
|
|
19539
|
+
const tDetails = getTDeferBlockDetails(tView, tNode);
|
|
19540
|
+
switch (newState) {
|
|
19541
|
+
case DeferBlockState.Complete:
|
|
19542
|
+
return tDetails.primaryTmplIndex;
|
|
19543
|
+
case DeferBlockState.Loading:
|
|
19544
|
+
return tDetails.loadingTmplIndex;
|
|
19545
|
+
case DeferBlockState.Error:
|
|
19546
|
+
return tDetails.errorTmplIndex;
|
|
19547
|
+
case DeferBlockState.Placeholder:
|
|
19548
|
+
return tDetails.placeholderTmplIndex;
|
|
19549
|
+
default:
|
|
19550
|
+
ngDevMode && throwError(`Unexpected defer block state: ${newState}`);
|
|
19551
|
+
return null;
|
|
19552
|
+
}
|
|
19553
|
+
}
|
|
19554
|
+
/**
|
|
19555
|
+
* Returns a minimum amount of time that a given state should be rendered for,
|
|
19556
|
+
* taking into account `minimum` parameter value. If the `minimum` value is
|
|
19557
|
+
* not specified - returns `null`.
|
|
19558
|
+
*/
|
|
19559
|
+
function getMinimumDurationForState(tDetails, currentState) {
|
|
19560
|
+
if (currentState === DeferBlockState.Placeholder) {
|
|
19561
|
+
return tDetails.placeholderBlockConfig?.[MINIMUM_SLOT] ?? null;
|
|
19562
|
+
}
|
|
19563
|
+
else if (currentState === DeferBlockState.Loading) {
|
|
19564
|
+
return tDetails.loadingBlockConfig?.[MINIMUM_SLOT] ?? null;
|
|
19565
|
+
}
|
|
19566
|
+
return null;
|
|
19567
|
+
}
|
|
19568
|
+
/** Retrieves the value of the `after` parameter on the @loading block. */
|
|
19569
|
+
function getLoadingBlockAfter(tDetails) {
|
|
19570
|
+
return tDetails.loadingBlockConfig?.[LOADING_AFTER_SLOT] ?? null;
|
|
19571
|
+
}
|
|
19572
|
+
/**
|
|
19573
|
+
* Adds downloaded dependencies into a directive or a pipe registry,
|
|
19574
|
+
* making sure that a dependency doesn't yet exist in the registry.
|
|
19575
|
+
*/
|
|
19576
|
+
function addDepsToRegistry(currentDeps, newDeps) {
|
|
19577
|
+
if (!currentDeps || currentDeps.length === 0) {
|
|
19578
|
+
return newDeps;
|
|
19579
|
+
}
|
|
19580
|
+
const currentDepSet = new Set(currentDeps);
|
|
19581
|
+
for (const dep of newDeps) {
|
|
19582
|
+
currentDepSet.add(dep);
|
|
19583
|
+
}
|
|
19584
|
+
// If `currentDeps` is the same length, there were no new deps and can
|
|
19585
|
+
// return the original array.
|
|
19586
|
+
return (currentDeps.length === currentDepSet.size) ? currentDeps : Array.from(currentDepSet);
|
|
19587
|
+
}
|
|
19588
|
+
/** Retrieves a TNode that represents main content of a defer block. */
|
|
19589
|
+
function getPrimaryBlockTNode(tView, tDetails) {
|
|
19590
|
+
const adjustedIndex = tDetails.primaryTmplIndex + HEADER_OFFSET;
|
|
19591
|
+
return getTNode(tView, adjustedIndex);
|
|
19592
|
+
}
|
|
19593
|
+
/**
|
|
19594
|
+
* Asserts whether all dependencies for a defer block are loaded.
|
|
19595
|
+
* Always run this function (in dev mode) before rendering a defer
|
|
19596
|
+
* block in completed state.
|
|
19597
|
+
*/
|
|
19598
|
+
function assertDeferredDependenciesLoaded(tDetails) {
|
|
19599
|
+
assertEqual(tDetails.loadingState, DeferDependenciesLoadingState.COMPLETE, 'Expecting all deferred dependencies to be loaded.');
|
|
19600
|
+
}
|
|
19601
|
+
/**
|
|
19602
|
+
* Determines if a given value matches the expected structure of a defer block
|
|
19603
|
+
*
|
|
19604
|
+
* We can safely rely on the primaryTmplIndex because every defer block requires
|
|
19605
|
+
* that a primary template exists. All the other template options are optional.
|
|
19606
|
+
*/
|
|
19607
|
+
function isTDeferBlockDetails(value) {
|
|
19608
|
+
return (typeof value === 'object') &&
|
|
19609
|
+
(typeof value.primaryTmplIndex === 'number');
|
|
19610
|
+
}
|
|
19611
|
+
|
|
19383
19612
|
/*!
|
|
19384
19613
|
* @license
|
|
19385
19614
|
* Copyright Google LLC All Rights Reserved.
|
|
@@ -19396,10 +19625,16 @@ const eventListenerOptions = {
|
|
|
19396
19625
|
const hoverTriggers = new WeakMap();
|
|
19397
19626
|
/** Keeps track of the currently-registered `on interaction` triggers. */
|
|
19398
19627
|
const interactionTriggers = new WeakMap();
|
|
19628
|
+
/** Currently-registered `viewport` triggers. */
|
|
19629
|
+
const viewportTriggers = new WeakMap();
|
|
19399
19630
|
/** Names of the events considered as interaction events. */
|
|
19400
19631
|
const interactionEventNames = ['click', 'keydown'];
|
|
19401
19632
|
/** Names of the events considered as hover events. */
|
|
19402
19633
|
const hoverEventNames = ['mouseenter', 'focusin'];
|
|
19634
|
+
/** `IntersectionObserver` used to observe `viewport` triggers. */
|
|
19635
|
+
let intersectionObserver = null;
|
|
19636
|
+
/** Number of elements currently observed with `viewport` triggers. */
|
|
19637
|
+
let observedViewportElements = 0;
|
|
19403
19638
|
/** Object keeping track of registered callbacks for a deferred block trigger. */
|
|
19404
19639
|
class DeferEventEntry {
|
|
19405
19640
|
constructor() {
|
|
@@ -19415,13 +19650,12 @@ class DeferEventEntry {
|
|
|
19415
19650
|
* Registers an interaction trigger.
|
|
19416
19651
|
* @param trigger Element that is the trigger.
|
|
19417
19652
|
* @param callback Callback to be invoked when the trigger is interacted with.
|
|
19418
|
-
* @param injector Injector that can be used by the trigger to resolve DI tokens.
|
|
19419
19653
|
*/
|
|
19420
|
-
function onInteraction(trigger, callback
|
|
19654
|
+
function onInteraction(trigger, callback) {
|
|
19421
19655
|
let entry = interactionTriggers.get(trigger);
|
|
19422
19656
|
// If this is the first entry for this element, add the listeners.
|
|
19423
19657
|
if (!entry) {
|
|
19424
|
-
// Note that
|
|
19658
|
+
// Note that managing events centrally like this lends itself well to using global
|
|
19425
19659
|
// event delegation. It currently does delegation at the element level, rather than the
|
|
19426
19660
|
// document level, because:
|
|
19427
19661
|
// 1. Global delegation is the most effective when there are a lot of events being registered
|
|
@@ -19434,13 +19668,11 @@ function onInteraction(trigger, callback, injector) {
|
|
|
19434
19668
|
// are referencing it.
|
|
19435
19669
|
entry = new DeferEventEntry();
|
|
19436
19670
|
interactionTriggers.set(trigger, entry);
|
|
19437
|
-
// Ensure that the handler runs in the NgZone
|
|
19438
|
-
|
|
19439
|
-
|
|
19440
|
-
|
|
19441
|
-
|
|
19442
|
-
}
|
|
19443
|
-
});
|
|
19671
|
+
// Ensure that the handler runs in the NgZone
|
|
19672
|
+
ngDevMode && NgZone.assertInAngularZone();
|
|
19673
|
+
for (const name of interactionEventNames) {
|
|
19674
|
+
trigger.addEventListener(name, entry.listener, eventListenerOptions);
|
|
19675
|
+
}
|
|
19444
19676
|
}
|
|
19445
19677
|
entry.callbacks.add(callback);
|
|
19446
19678
|
return () => {
|
|
@@ -19458,21 +19690,18 @@ function onInteraction(trigger, callback, injector) {
|
|
|
19458
19690
|
* Registers a hover trigger.
|
|
19459
19691
|
* @param trigger Element that is the trigger.
|
|
19460
19692
|
* @param callback Callback to be invoked when the trigger is hovered over.
|
|
19461
|
-
* @param injector Injector that can be used by the trigger to resolve DI tokens.
|
|
19462
19693
|
*/
|
|
19463
|
-
function onHover(trigger, callback
|
|
19694
|
+
function onHover(trigger, callback) {
|
|
19464
19695
|
let entry = hoverTriggers.get(trigger);
|
|
19465
19696
|
// If this is the first entry for this element, add the listener.
|
|
19466
19697
|
if (!entry) {
|
|
19467
19698
|
entry = new DeferEventEntry();
|
|
19468
19699
|
hoverTriggers.set(trigger, entry);
|
|
19469
|
-
// Ensure that the handler runs in the NgZone
|
|
19470
|
-
|
|
19471
|
-
|
|
19472
|
-
|
|
19473
|
-
|
|
19474
|
-
}
|
|
19475
|
-
});
|
|
19700
|
+
// Ensure that the handler runs in the NgZone
|
|
19701
|
+
ngDevMode && NgZone.assertInAngularZone();
|
|
19702
|
+
for (const name of hoverEventNames) {
|
|
19703
|
+
trigger.addEventListener(name, entry.listener, eventListenerOptions);
|
|
19704
|
+
}
|
|
19476
19705
|
}
|
|
19477
19706
|
entry.callbacks.add(callback);
|
|
19478
19707
|
return () => {
|
|
@@ -19493,65 +19722,442 @@ function onHover(trigger, callback, injector) {
|
|
|
19493
19722
|
* @param injector Injector that can be used by the trigger to resolve DI tokens.
|
|
19494
19723
|
*/
|
|
19495
19724
|
function onViewport(trigger, callback, injector) {
|
|
19496
|
-
|
|
19725
|
+
const ngZone = injector.get(NgZone);
|
|
19726
|
+
let entry = viewportTriggers.get(trigger);
|
|
19727
|
+
intersectionObserver = intersectionObserver || ngZone.runOutsideAngular(() => {
|
|
19728
|
+
return new IntersectionObserver(entries => {
|
|
19729
|
+
for (const current of entries) {
|
|
19730
|
+
// Only invoke the callbacks if the specific element is intersecting.
|
|
19731
|
+
if (current.isIntersecting && viewportTriggers.has(current.target)) {
|
|
19732
|
+
ngZone.run(viewportTriggers.get(current.target).listener);
|
|
19733
|
+
}
|
|
19734
|
+
}
|
|
19735
|
+
});
|
|
19736
|
+
});
|
|
19737
|
+
if (!entry) {
|
|
19738
|
+
entry = new DeferEventEntry();
|
|
19739
|
+
ngZone.runOutsideAngular(() => intersectionObserver.observe(trigger));
|
|
19740
|
+
viewportTriggers.set(trigger, entry);
|
|
19741
|
+
observedViewportElements++;
|
|
19742
|
+
}
|
|
19743
|
+
entry.callbacks.add(callback);
|
|
19744
|
+
return () => {
|
|
19745
|
+
// It's possible that a different cleanup callback fully removed this element already.
|
|
19746
|
+
if (!viewportTriggers.has(trigger)) {
|
|
19747
|
+
return;
|
|
19748
|
+
}
|
|
19749
|
+
entry.callbacks.delete(callback);
|
|
19750
|
+
if (entry.callbacks.size === 0) {
|
|
19751
|
+
intersectionObserver?.unobserve(trigger);
|
|
19752
|
+
viewportTriggers.delete(trigger);
|
|
19753
|
+
observedViewportElements--;
|
|
19754
|
+
}
|
|
19755
|
+
if (observedViewportElements === 0) {
|
|
19756
|
+
intersectionObserver?.disconnect();
|
|
19757
|
+
intersectionObserver = null;
|
|
19758
|
+
}
|
|
19759
|
+
};
|
|
19760
|
+
}
|
|
19761
|
+
/**
|
|
19762
|
+
* Helper function to get the LView in which a deferred block's trigger is rendered.
|
|
19763
|
+
* @param deferredHostLView LView in which the deferred block is defined.
|
|
19764
|
+
* @param deferredTNode TNode defining the deferred block.
|
|
19765
|
+
* @param walkUpTimes Number of times to go up in the view hierarchy to find the trigger's view.
|
|
19766
|
+
* A negative value means that the trigger is inside the block's placeholder, while an undefined
|
|
19767
|
+
* value means that the trigger is in the same LView as the deferred block.
|
|
19768
|
+
*/
|
|
19769
|
+
function getTriggerLView(deferredHostLView, deferredTNode, walkUpTimes) {
|
|
19770
|
+
// The trigger is in the same view, we don't need to traverse.
|
|
19771
|
+
if (walkUpTimes == null) {
|
|
19772
|
+
return deferredHostLView;
|
|
19773
|
+
}
|
|
19774
|
+
// A positive value or zero means that the trigger is in a parent view.
|
|
19775
|
+
if (walkUpTimes >= 0) {
|
|
19776
|
+
return walkUpViews(walkUpTimes, deferredHostLView);
|
|
19777
|
+
}
|
|
19778
|
+
// If the value is negative, it means that the trigger is inside the placeholder.
|
|
19779
|
+
const deferredContainer = deferredHostLView[deferredTNode.index];
|
|
19780
|
+
ngDevMode && assertLContainer(deferredContainer);
|
|
19781
|
+
const triggerLView = deferredContainer[CONTAINER_HEADER_OFFSET] ?? null;
|
|
19782
|
+
// We need to null check, because the placeholder might not have been rendered yet.
|
|
19783
|
+
if (ngDevMode && triggerLView !== null) {
|
|
19784
|
+
const lDetails = getLDeferBlockDetails(deferredHostLView, deferredTNode);
|
|
19785
|
+
const renderedState = lDetails[DEFER_BLOCK_STATE];
|
|
19786
|
+
assertEqual(renderedState, DeferBlockState.Placeholder, 'Expected a placeholder to be rendered in this defer block.');
|
|
19787
|
+
assertLView(triggerLView);
|
|
19788
|
+
}
|
|
19789
|
+
return triggerLView;
|
|
19790
|
+
}
|
|
19791
|
+
/**
|
|
19792
|
+
* Gets the element that a deferred block's trigger is pointing to.
|
|
19793
|
+
* @param triggerLView LView in which the trigger is defined.
|
|
19794
|
+
* @param triggerIndex Index at which the trigger element should've been rendered.
|
|
19795
|
+
*/
|
|
19796
|
+
function getTriggerElement(triggerLView, triggerIndex) {
|
|
19797
|
+
const element = getNativeByIndex(HEADER_OFFSET + triggerIndex, triggerLView);
|
|
19798
|
+
ngDevMode && assertElement(element);
|
|
19799
|
+
return element;
|
|
19800
|
+
}
|
|
19801
|
+
/**
|
|
19802
|
+
* Registers a DOM-node based trigger.
|
|
19803
|
+
* @param initialLView LView in which the defer block is rendered.
|
|
19804
|
+
* @param tNode TNode representing the defer block.
|
|
19805
|
+
* @param triggerIndex Index at which to find the trigger element.
|
|
19806
|
+
* @param walkUpTimes Number of times to go up/down in the view hierarchy to find the trigger.
|
|
19807
|
+
* @param registerFn Function that will register the DOM events.
|
|
19808
|
+
* @param callback Callback to be invoked when the trigger receives the event that should render
|
|
19809
|
+
* the deferred block.
|
|
19810
|
+
* @param type Trigger type to distinguish between regular and prefetch triggers.
|
|
19811
|
+
*/
|
|
19812
|
+
function registerDomTrigger(initialLView, tNode, triggerIndex, walkUpTimes, registerFn, callback, type) {
|
|
19813
|
+
const injector = initialLView[INJECTOR$1];
|
|
19814
|
+
function pollDomTrigger() {
|
|
19815
|
+
// If the initial view was destroyed, we don't need to do anything.
|
|
19816
|
+
if (isDestroyed(initialLView)) {
|
|
19817
|
+
return;
|
|
19818
|
+
}
|
|
19819
|
+
const lDetails = getLDeferBlockDetails(initialLView, tNode);
|
|
19820
|
+
const renderedState = lDetails[DEFER_BLOCK_STATE];
|
|
19821
|
+
// If the block was loaded before the trigger was resolved, we don't need to do anything.
|
|
19822
|
+
if (renderedState !== DeferBlockInternalState.Initial &&
|
|
19823
|
+
renderedState !== DeferBlockState.Placeholder) {
|
|
19824
|
+
return;
|
|
19825
|
+
}
|
|
19826
|
+
const triggerLView = getTriggerLView(initialLView, tNode, walkUpTimes);
|
|
19827
|
+
// Keep polling until we resolve the trigger's LView.
|
|
19828
|
+
if (!triggerLView) {
|
|
19829
|
+
internalAfterNextRender(pollDomTrigger, { injector });
|
|
19830
|
+
return;
|
|
19831
|
+
}
|
|
19832
|
+
// It's possible that the trigger's view was destroyed before we resolved the trigger element.
|
|
19833
|
+
if (isDestroyed(triggerLView)) {
|
|
19834
|
+
return;
|
|
19835
|
+
}
|
|
19836
|
+
const element = getTriggerElement(triggerLView, triggerIndex);
|
|
19837
|
+
const cleanup = registerFn(element, () => {
|
|
19838
|
+
if (initialLView !== triggerLView) {
|
|
19839
|
+
removeLViewOnDestroy(triggerLView, cleanup);
|
|
19840
|
+
}
|
|
19841
|
+
callback();
|
|
19842
|
+
}, injector);
|
|
19843
|
+
// The trigger and deferred block might be in different LViews.
|
|
19844
|
+
// For the main LView the cleanup would happen as a part of
|
|
19845
|
+
// `storeTriggerCleanupFn` logic. For trigger LView we register
|
|
19846
|
+
// a cleanup function there to remove event handlers in case an
|
|
19847
|
+
// LView gets destroyed before a trigger is invoked.
|
|
19848
|
+
if (initialLView !== triggerLView) {
|
|
19849
|
+
storeLViewOnDestroy(triggerLView, cleanup);
|
|
19850
|
+
}
|
|
19851
|
+
storeTriggerCleanupFn(type, lDetails, cleanup);
|
|
19852
|
+
}
|
|
19853
|
+
// Begin polling for the trigger.
|
|
19854
|
+
internalAfterNextRender(pollDomTrigger, { injector });
|
|
19497
19855
|
}
|
|
19498
|
-
|
|
19499
|
-
|
|
19856
|
+
|
|
19857
|
+
/**
|
|
19858
|
+
* Helper function to schedule a callback to be invoked when a browser becomes idle.
|
|
19859
|
+
*
|
|
19860
|
+
* @param callback A function to be invoked when a browser becomes idle.
|
|
19861
|
+
* @param lView LView that hosts an instance of a defer block.
|
|
19862
|
+
*/
|
|
19863
|
+
function onIdle(callback, lView) {
|
|
19864
|
+
const injector = lView[INJECTOR$1];
|
|
19865
|
+
const scheduler = injector.get(IdleScheduler);
|
|
19866
|
+
const cleanupFn = () => scheduler.remove(callback);
|
|
19867
|
+
scheduler.add(callback);
|
|
19868
|
+
return cleanupFn;
|
|
19869
|
+
}
|
|
19870
|
+
/**
|
|
19871
|
+
* Use shims for the `requestIdleCallback` and `cancelIdleCallback` functions for
|
|
19872
|
+
* environments where those functions are not available (e.g. Node.js and Safari).
|
|
19873
|
+
*
|
|
19874
|
+
* Note: we wrap the `requestIdleCallback` call into a function, so that it can be
|
|
19875
|
+
* overridden/mocked in test environment and picked up by the runtime code.
|
|
19876
|
+
*/
|
|
19877
|
+
const _requestIdleCallback = () => typeof requestIdleCallback !== 'undefined' ? requestIdleCallback : setTimeout;
|
|
19878
|
+
const _cancelIdleCallback = () => typeof requestIdleCallback !== 'undefined' ? cancelIdleCallback : clearTimeout;
|
|
19879
|
+
/**
|
|
19880
|
+
* Helper service to schedule `requestIdleCallback`s for batches of defer blocks,
|
|
19881
|
+
* to avoid calling `requestIdleCallback` for each defer block (e.g. if
|
|
19882
|
+
* defer blocks are defined inside a for loop).
|
|
19883
|
+
*/
|
|
19884
|
+
class IdleScheduler {
|
|
19885
|
+
constructor() {
|
|
19886
|
+
// Indicates whether current callbacks are being invoked.
|
|
19887
|
+
this.executingCallbacks = false;
|
|
19888
|
+
// Currently scheduled idle callback id.
|
|
19889
|
+
this.idleId = null;
|
|
19890
|
+
// Set of callbacks to be invoked next.
|
|
19891
|
+
this.current = new Set();
|
|
19892
|
+
// Set of callbacks collected while invoking current set of callbacks.
|
|
19893
|
+
// Those callbacks are scheduled for the next idle period.
|
|
19894
|
+
this.deferred = new Set();
|
|
19895
|
+
this.ngZone = inject(NgZone);
|
|
19896
|
+
this.requestIdleCallbackFn = _requestIdleCallback().bind(globalThis);
|
|
19897
|
+
this.cancelIdleCallbackFn = _cancelIdleCallback().bind(globalThis);
|
|
19898
|
+
}
|
|
19899
|
+
add(callback) {
|
|
19900
|
+
const target = this.executingCallbacks ? this.deferred : this.current;
|
|
19901
|
+
target.add(callback);
|
|
19902
|
+
if (this.idleId === null) {
|
|
19903
|
+
this.scheduleIdleCallback();
|
|
19904
|
+
}
|
|
19905
|
+
}
|
|
19906
|
+
remove(callback) {
|
|
19907
|
+
const { current, deferred } = this;
|
|
19908
|
+
current.delete(callback);
|
|
19909
|
+
deferred.delete(callback);
|
|
19910
|
+
// If the last callback was removed and there is a pending
|
|
19911
|
+
// idle callback - cancel it.
|
|
19912
|
+
if (current.size === 0 && deferred.size === 0) {
|
|
19913
|
+
this.cancelIdleCallback();
|
|
19914
|
+
}
|
|
19915
|
+
}
|
|
19916
|
+
scheduleIdleCallback() {
|
|
19917
|
+
const callback = () => {
|
|
19918
|
+
this.cancelIdleCallback();
|
|
19919
|
+
this.executingCallbacks = true;
|
|
19920
|
+
for (const callback of this.current) {
|
|
19921
|
+
callback();
|
|
19922
|
+
}
|
|
19923
|
+
this.current.clear();
|
|
19924
|
+
this.executingCallbacks = false;
|
|
19925
|
+
// If there are any callbacks added during an invocation
|
|
19926
|
+
// of the current ones - make them "current" and schedule
|
|
19927
|
+
// a new idle callback.
|
|
19928
|
+
if (this.deferred.size > 0) {
|
|
19929
|
+
for (const callback of this.deferred) {
|
|
19930
|
+
this.current.add(callback);
|
|
19931
|
+
}
|
|
19932
|
+
this.deferred.clear();
|
|
19933
|
+
this.scheduleIdleCallback();
|
|
19934
|
+
}
|
|
19935
|
+
};
|
|
19936
|
+
// Ensure that the callback runs in the NgZone since
|
|
19937
|
+
// the `requestIdleCallback` is not currently patched by Zone.js.
|
|
19938
|
+
this.idleId = this.requestIdleCallbackFn(() => this.ngZone.run(callback));
|
|
19939
|
+
}
|
|
19940
|
+
cancelIdleCallback() {
|
|
19941
|
+
if (this.idleId !== null) {
|
|
19942
|
+
this.cancelIdleCallbackFn(this.idleId);
|
|
19943
|
+
this.idleId = null;
|
|
19944
|
+
}
|
|
19945
|
+
}
|
|
19946
|
+
ngOnDestroy() {
|
|
19947
|
+
this.cancelIdleCallback();
|
|
19948
|
+
this.current.clear();
|
|
19949
|
+
this.deferred.clear();
|
|
19950
|
+
}
|
|
19500
19951
|
/** @nocollapse */
|
|
19501
19952
|
static { this.ɵprov = ɵɵdefineInjectable({
|
|
19502
|
-
token:
|
|
19953
|
+
token: IdleScheduler,
|
|
19503
19954
|
providedIn: 'root',
|
|
19504
|
-
factory: () => new
|
|
19955
|
+
factory: () => new IdleScheduler(),
|
|
19505
19956
|
}); }
|
|
19506
|
-
|
|
19507
|
-
|
|
19508
|
-
|
|
19509
|
-
|
|
19510
|
-
|
|
19511
|
-
|
|
19512
|
-
|
|
19513
|
-
|
|
19514
|
-
|
|
19515
|
-
|
|
19516
|
-
|
|
19517
|
-
|
|
19518
|
-
|
|
19519
|
-
|
|
19957
|
+
}
|
|
19958
|
+
|
|
19959
|
+
/**
|
|
19960
|
+
* Returns a function that captures a provided delay.
|
|
19961
|
+
* Invoking the returned function schedules a trigger.
|
|
19962
|
+
*/
|
|
19963
|
+
function onTimer(delay) {
|
|
19964
|
+
return (callback, lView) => scheduleTimerTrigger(delay, callback, lView);
|
|
19965
|
+
}
|
|
19966
|
+
/**
|
|
19967
|
+
* Schedules a callback to be invoked after a given timeout.
|
|
19968
|
+
*
|
|
19969
|
+
* @param delay A number of ms to wait until firing a callback.
|
|
19970
|
+
* @param callback A function to be invoked after a timeout.
|
|
19971
|
+
* @param lView LView that hosts an instance of a defer block.
|
|
19972
|
+
*/
|
|
19973
|
+
function scheduleTimerTrigger(delay, callback, lView) {
|
|
19974
|
+
const injector = lView[INJECTOR$1];
|
|
19975
|
+
const scheduler = injector.get(TimerScheduler);
|
|
19976
|
+
const cleanupFn = () => scheduler.remove(callback);
|
|
19977
|
+
scheduler.add(delay, callback);
|
|
19978
|
+
return cleanupFn;
|
|
19979
|
+
}
|
|
19980
|
+
/**
|
|
19981
|
+
* Helper service to schedule `setTimeout`s for batches of defer blocks,
|
|
19982
|
+
* to avoid calling `setTimeout` for each defer block (e.g. if defer blocks
|
|
19983
|
+
* are created inside a for loop).
|
|
19984
|
+
*/
|
|
19985
|
+
class TimerScheduler {
|
|
19986
|
+
constructor() {
|
|
19987
|
+
// Indicates whether current callbacks are being invoked.
|
|
19988
|
+
this.executingCallbacks = false;
|
|
19989
|
+
// Currently scheduled `setTimeout` id.
|
|
19990
|
+
this.timeoutId = null;
|
|
19991
|
+
// When currently scheduled timer would fire.
|
|
19992
|
+
this.invokeTimerAt = null;
|
|
19993
|
+
// List of callbacks to be invoked.
|
|
19994
|
+
// For each callback we also store a timestamp on when the callback
|
|
19995
|
+
// should be invoked. We store timestamps and callback functions
|
|
19996
|
+
// in a flat array to avoid creating new objects for each entry.
|
|
19997
|
+
// [timestamp1, callback1, timestamp2, callback2, ...]
|
|
19998
|
+
this.current = [];
|
|
19999
|
+
// List of callbacks collected while invoking current set of callbacks.
|
|
20000
|
+
// Those callbacks are added to the "current" queue at the end of
|
|
20001
|
+
// the current callback invocation. The shape of this list is the same
|
|
20002
|
+
// as the shape of the `current` list.
|
|
20003
|
+
this.deferred = [];
|
|
20004
|
+
}
|
|
20005
|
+
add(delay, callback) {
|
|
20006
|
+
const target = this.executingCallbacks ? this.deferred : this.current;
|
|
20007
|
+
this.addToQueue(target, Date.now() + delay, callback);
|
|
20008
|
+
this.scheduleTimer();
|
|
20009
|
+
}
|
|
20010
|
+
remove(callback) {
|
|
20011
|
+
const { current, deferred } = this;
|
|
20012
|
+
const callbackIndex = this.removeFromQueue(current, callback);
|
|
20013
|
+
if (callbackIndex === -1) {
|
|
20014
|
+
// Try cleaning up deferred queue only in case
|
|
20015
|
+
// we didn't find a callback in the "current" queue.
|
|
20016
|
+
this.removeFromQueue(deferred, callback);
|
|
20017
|
+
}
|
|
20018
|
+
// If the last callback was removed and there is a pending timeout - cancel it.
|
|
20019
|
+
if (current.length === 0 && deferred.length === 0) {
|
|
20020
|
+
this.clearTimeout();
|
|
20021
|
+
}
|
|
20022
|
+
}
|
|
20023
|
+
addToQueue(target, invokeAt, callback) {
|
|
20024
|
+
let insertAtIndex = target.length;
|
|
20025
|
+
for (let i = 0; i < target.length; i += 2) {
|
|
20026
|
+
const invokeQueuedCallbackAt = target[i];
|
|
20027
|
+
if (invokeQueuedCallbackAt > invokeAt) {
|
|
20028
|
+
// We've reached a first timer that is scheduled
|
|
20029
|
+
// for a later time than what we are trying to insert.
|
|
20030
|
+
// This is the location at which we need to insert,
|
|
20031
|
+
// no need to iterate further.
|
|
20032
|
+
insertAtIndex = i;
|
|
20033
|
+
break;
|
|
19520
20034
|
}
|
|
19521
|
-
}
|
|
20035
|
+
}
|
|
20036
|
+
arrayInsert2(target, insertAtIndex, invokeAt, callback);
|
|
19522
20037
|
}
|
|
19523
|
-
|
|
19524
|
-
let
|
|
19525
|
-
|
|
19526
|
-
|
|
19527
|
-
|
|
20038
|
+
removeFromQueue(target, callback) {
|
|
20039
|
+
let index = -1;
|
|
20040
|
+
for (let i = 0; i < target.length; i += 2) {
|
|
20041
|
+
const queuedCallback = target[i + 1];
|
|
20042
|
+
if (queuedCallback === callback) {
|
|
20043
|
+
index = i;
|
|
20044
|
+
break;
|
|
20045
|
+
}
|
|
19528
20046
|
}
|
|
19529
|
-
if (
|
|
19530
|
-
|
|
19531
|
-
|
|
19532
|
-
|
|
19533
|
-
this.observedViewportElements++;
|
|
20047
|
+
if (index > -1) {
|
|
20048
|
+
// Remove 2 elements: a timestamp slot and
|
|
20049
|
+
// the following slot with a callback function.
|
|
20050
|
+
arraySplice(target, index, 2);
|
|
19534
20051
|
}
|
|
19535
|
-
|
|
19536
|
-
|
|
19537
|
-
|
|
19538
|
-
|
|
19539
|
-
|
|
20052
|
+
return index;
|
|
20053
|
+
}
|
|
20054
|
+
scheduleTimer() {
|
|
20055
|
+
const callback = () => {
|
|
20056
|
+
this.clearTimeout();
|
|
20057
|
+
this.executingCallbacks = true;
|
|
20058
|
+
// Clone the current state of the queue, since it might be altered
|
|
20059
|
+
// as we invoke callbacks.
|
|
20060
|
+
const current = [...this.current];
|
|
20061
|
+
// Invoke callbacks that were scheduled to run before the current time.
|
|
20062
|
+
const now = Date.now();
|
|
20063
|
+
for (let i = 0; i < current.length; i += 2) {
|
|
20064
|
+
const invokeAt = current[i];
|
|
20065
|
+
const callback = current[i + 1];
|
|
20066
|
+
if (invokeAt <= now) {
|
|
20067
|
+
callback();
|
|
20068
|
+
}
|
|
20069
|
+
else {
|
|
20070
|
+
// We've reached a timer that should not be invoked yet.
|
|
20071
|
+
break;
|
|
20072
|
+
}
|
|
19540
20073
|
}
|
|
19541
|
-
|
|
19542
|
-
|
|
19543
|
-
|
|
19544
|
-
|
|
19545
|
-
this.
|
|
20074
|
+
// The state of the queue might've changed after callbacks invocation,
|
|
20075
|
+
// run the cleanup logic based on the *current* state of the queue.
|
|
20076
|
+
let lastCallbackIndex = -1;
|
|
20077
|
+
for (let i = 0; i < this.current.length; i += 2) {
|
|
20078
|
+
const invokeAt = this.current[i];
|
|
20079
|
+
if (invokeAt <= now) {
|
|
20080
|
+
// Add +1 to account for a callback function that
|
|
20081
|
+
// goes after the timestamp in events array.
|
|
20082
|
+
lastCallbackIndex = i + 1;
|
|
20083
|
+
}
|
|
20084
|
+
else {
|
|
20085
|
+
// We've reached a timer that should not be invoked yet.
|
|
20086
|
+
break;
|
|
20087
|
+
}
|
|
19546
20088
|
}
|
|
19547
|
-
if (
|
|
19548
|
-
this.
|
|
19549
|
-
this.intersectionObserver = null;
|
|
20089
|
+
if (lastCallbackIndex >= 0) {
|
|
20090
|
+
arraySplice(this.current, 0, lastCallbackIndex + 1);
|
|
19550
20091
|
}
|
|
20092
|
+
this.executingCallbacks = false;
|
|
20093
|
+
// If there are any callbacks added during an invocation
|
|
20094
|
+
// of the current ones - move them over to the "current"
|
|
20095
|
+
// queue.
|
|
20096
|
+
if (this.deferred.length > 0) {
|
|
20097
|
+
for (let i = 0; i < this.deferred.length; i += 2) {
|
|
20098
|
+
const invokeAt = this.deferred[i];
|
|
20099
|
+
const callback = this.deferred[i + 1];
|
|
20100
|
+
this.addToQueue(this.current, invokeAt, callback);
|
|
20101
|
+
}
|
|
20102
|
+
this.deferred.length = 0;
|
|
20103
|
+
}
|
|
20104
|
+
this.scheduleTimer();
|
|
19551
20105
|
};
|
|
20106
|
+
// Avoid running timer callbacks more than once per
|
|
20107
|
+
// average frame duration. This is needed for better
|
|
20108
|
+
// batching and to avoid kicking off excessive change
|
|
20109
|
+
// detection cycles.
|
|
20110
|
+
const FRAME_DURATION_MS = 16; // 1000ms / 60fps
|
|
20111
|
+
if (this.current.length > 0) {
|
|
20112
|
+
const now = Date.now();
|
|
20113
|
+
// First element in the queue points at the timestamp
|
|
20114
|
+
// of the first (earliest) event.
|
|
20115
|
+
const invokeAt = this.current[0];
|
|
20116
|
+
if (this.timeoutId === null ||
|
|
20117
|
+
// Reschedule a timer in case a queue contains an item with
|
|
20118
|
+
// an earlier timestamp and the delta is more than an average
|
|
20119
|
+
// frame duration.
|
|
20120
|
+
(this.invokeTimerAt && (this.invokeTimerAt - invokeAt > FRAME_DURATION_MS))) {
|
|
20121
|
+
// There was a timeout already, but an earlier event was added
|
|
20122
|
+
// into the queue. In this case we drop an old timer and setup
|
|
20123
|
+
// a new one with an updated (smaller) timeout.
|
|
20124
|
+
this.clearTimeout();
|
|
20125
|
+
const timeout = Math.max(invokeAt - now, FRAME_DURATION_MS);
|
|
20126
|
+
this.invokeTimerAt = invokeAt;
|
|
20127
|
+
this.timeoutId = setTimeout(callback, timeout);
|
|
20128
|
+
}
|
|
20129
|
+
}
|
|
19552
20130
|
}
|
|
20131
|
+
clearTimeout() {
|
|
20132
|
+
if (this.timeoutId !== null) {
|
|
20133
|
+
clearTimeout(this.timeoutId);
|
|
20134
|
+
this.timeoutId = null;
|
|
20135
|
+
}
|
|
20136
|
+
}
|
|
20137
|
+
ngOnDestroy() {
|
|
20138
|
+
this.clearTimeout();
|
|
20139
|
+
this.current.length = 0;
|
|
20140
|
+
this.deferred.length = 0;
|
|
20141
|
+
}
|
|
20142
|
+
/** @nocollapse */
|
|
20143
|
+
static { this.ɵprov = ɵɵdefineInjectable({
|
|
20144
|
+
token: TimerScheduler,
|
|
20145
|
+
providedIn: 'root',
|
|
20146
|
+
factory: () => new TimerScheduler(),
|
|
20147
|
+
}); }
|
|
19553
20148
|
}
|
|
19554
20149
|
|
|
20150
|
+
/**
|
|
20151
|
+
* **INTERNAL**, avoid referencing it in application code.
|
|
20152
|
+
*
|
|
20153
|
+
* Injector token that allows to provide `DeferBlockDependencyInterceptor` class
|
|
20154
|
+
* implementation.
|
|
20155
|
+
*/
|
|
20156
|
+
const DEFER_BLOCK_DEPENDENCY_INTERCEPTOR = new InjectionToken('DEFER_BLOCK_DEPENDENCY_INTERCEPTOR');
|
|
20157
|
+
/**
|
|
20158
|
+
* **INTERNAL**, token used for configuring defer block behavior.
|
|
20159
|
+
*/
|
|
20160
|
+
const DEFER_BLOCK_CONFIG = new InjectionToken(ngDevMode ? 'DEFER_BLOCK_CONFIG' : '');
|
|
19555
20161
|
/**
|
|
19556
20162
|
* Returns whether defer blocks should be triggered.
|
|
19557
20163
|
*
|
|
@@ -19616,6 +20222,7 @@ function ɵɵdefer(index, primaryTmplIndex, dependencyResolverFn, loadingTmplInd
|
|
|
19616
20222
|
const adjustedIndex = index + HEADER_OFFSET;
|
|
19617
20223
|
ɵɵtemplate(index, null, 0, 0);
|
|
19618
20224
|
if (tView.firstCreatePass) {
|
|
20225
|
+
performance.mark('mark_use_counter', { detail: { feature: 'NgDefer' } });
|
|
19619
20226
|
const tDetails = {
|
|
19620
20227
|
primaryTmplIndex,
|
|
19621
20228
|
loadingTmplIndex: loadingTmplIndex ?? null,
|
|
@@ -19641,9 +20248,15 @@ function ɵɵdefer(index, primaryTmplIndex, dependencyResolverFn, loadingTmplInd
|
|
|
19641
20248
|
null,
|
|
19642
20249
|
DeferBlockInternalState.Initial,
|
|
19643
20250
|
null,
|
|
19644
|
-
null
|
|
20251
|
+
null,
|
|
20252
|
+
null,
|
|
20253
|
+
null // PREFETCH_TRIGGER_CLEANUP_FNS
|
|
19645
20254
|
];
|
|
19646
20255
|
setLDeferBlockDetails(lView, adjustedIndex, lDetails);
|
|
20256
|
+
const cleanupTriggersFn = () => invokeAllTriggerCleanupFns(lDetails);
|
|
20257
|
+
// When defer block is triggered - unsubscribe from LView destroy cleanup.
|
|
20258
|
+
storeTriggerCleanupFn(0 /* TriggerType.Regular */, lDetails, () => removeLViewOnDestroy(lView, cleanupTriggersFn));
|
|
20259
|
+
storeLViewOnDestroy(lView, cleanupTriggersFn);
|
|
19647
20260
|
}
|
|
19648
20261
|
/**
|
|
19649
20262
|
* Loads defer block dependencies when a trigger value becomes truthy.
|
|
@@ -19685,7 +20298,7 @@ function ɵɵdeferPrefetchWhen(rawValue) {
|
|
|
19685
20298
|
const tDetails = getTDeferBlockDetails(tView, tNode);
|
|
19686
20299
|
if (value === true && tDetails.loadingState === DeferDependenciesLoadingState.NOT_STARTED) {
|
|
19687
20300
|
// If loading has not been started yet, trigger it now.
|
|
19688
|
-
triggerPrefetching(tDetails, lView);
|
|
20301
|
+
triggerPrefetching(tDetails, lView, tNode);
|
|
19689
20302
|
}
|
|
19690
20303
|
}
|
|
19691
20304
|
}
|
|
@@ -19701,7 +20314,7 @@ function ɵɵdeferOnIdle() {
|
|
|
19701
20314
|
* @codeGenApi
|
|
19702
20315
|
*/
|
|
19703
20316
|
function ɵɵdeferPrefetchOnIdle() {
|
|
19704
|
-
scheduleDelayedPrefetching(onIdle
|
|
20317
|
+
scheduleDelayedPrefetching(onIdle);
|
|
19705
20318
|
}
|
|
19706
20319
|
/**
|
|
19707
20320
|
* Sets up logic to handle the `on immediate` deferred trigger.
|
|
@@ -19730,7 +20343,7 @@ function ɵɵdeferPrefetchOnImmediate() {
|
|
|
19730
20343
|
const tView = lView[TVIEW];
|
|
19731
20344
|
const tDetails = getTDeferBlockDetails(tView, tNode);
|
|
19732
20345
|
if (tDetails.loadingState === DeferDependenciesLoadingState.NOT_STARTED) {
|
|
19733
|
-
triggerResourceLoading(tDetails, lView);
|
|
20346
|
+
triggerResourceLoading(tDetails, lView, tNode);
|
|
19734
20347
|
}
|
|
19735
20348
|
}
|
|
19736
20349
|
/**
|
|
@@ -19747,7 +20360,7 @@ function ɵɵdeferOnTimer(delay) {
|
|
|
19747
20360
|
* @codeGenApi
|
|
19748
20361
|
*/
|
|
19749
20362
|
function ɵɵdeferPrefetchOnTimer(delay) {
|
|
19750
|
-
scheduleDelayedPrefetching(onTimer(delay)
|
|
20363
|
+
scheduleDelayedPrefetching(onTimer(delay));
|
|
19751
20364
|
}
|
|
19752
20365
|
/**
|
|
19753
20366
|
* Creates runtime data structures for the `on hover` deferred trigger.
|
|
@@ -19759,7 +20372,7 @@ function ɵɵdeferOnHover(triggerIndex, walkUpTimes) {
|
|
|
19759
20372
|
const lView = getLView();
|
|
19760
20373
|
const tNode = getCurrentTNode();
|
|
19761
20374
|
renderPlaceholder(lView, tNode);
|
|
19762
|
-
registerDomTrigger(lView, tNode, triggerIndex, walkUpTimes, onHover, () => triggerDeferBlock(lView, tNode));
|
|
20375
|
+
registerDomTrigger(lView, tNode, triggerIndex, walkUpTimes, onHover, () => triggerDeferBlock(lView, tNode), 0 /* TriggerType.Regular */);
|
|
19763
20376
|
}
|
|
19764
20377
|
/**
|
|
19765
20378
|
* Creates runtime data structures for the `prefetch on hover` deferred trigger.
|
|
@@ -19773,7 +20386,7 @@ function ɵɵdeferPrefetchOnHover(triggerIndex, walkUpTimes) {
|
|
|
19773
20386
|
const tView = lView[TVIEW];
|
|
19774
20387
|
const tDetails = getTDeferBlockDetails(tView, tNode);
|
|
19775
20388
|
if (tDetails.loadingState === DeferDependenciesLoadingState.NOT_STARTED) {
|
|
19776
|
-
registerDomTrigger(lView, tNode, triggerIndex, walkUpTimes, onHover, () => triggerPrefetching(tDetails, lView));
|
|
20389
|
+
registerDomTrigger(lView, tNode, triggerIndex, walkUpTimes, onHover, () => triggerPrefetching(tDetails, lView, tNode), 1 /* TriggerType.Prefetch */);
|
|
19777
20390
|
}
|
|
19778
20391
|
}
|
|
19779
20392
|
/**
|
|
@@ -19786,7 +20399,7 @@ function ɵɵdeferOnInteraction(triggerIndex, walkUpTimes) {
|
|
|
19786
20399
|
const lView = getLView();
|
|
19787
20400
|
const tNode = getCurrentTNode();
|
|
19788
20401
|
renderPlaceholder(lView, tNode);
|
|
19789
|
-
registerDomTrigger(lView, tNode, triggerIndex, walkUpTimes, onInteraction, () => triggerDeferBlock(lView, tNode));
|
|
20402
|
+
registerDomTrigger(lView, tNode, triggerIndex, walkUpTimes, onInteraction, () => triggerDeferBlock(lView, tNode), 0 /* TriggerType.Regular */);
|
|
19790
20403
|
}
|
|
19791
20404
|
/**
|
|
19792
20405
|
* Creates runtime data structures for the `prefetch on interaction` deferred trigger.
|
|
@@ -19800,7 +20413,7 @@ function ɵɵdeferPrefetchOnInteraction(triggerIndex, walkUpTimes) {
|
|
|
19800
20413
|
const tView = lView[TVIEW];
|
|
19801
20414
|
const tDetails = getTDeferBlockDetails(tView, tNode);
|
|
19802
20415
|
if (tDetails.loadingState === DeferDependenciesLoadingState.NOT_STARTED) {
|
|
19803
|
-
registerDomTrigger(lView, tNode, triggerIndex, walkUpTimes, onInteraction, () => triggerPrefetching(tDetails, lView));
|
|
20416
|
+
registerDomTrigger(lView, tNode, triggerIndex, walkUpTimes, onInteraction, () => triggerPrefetching(tDetails, lView, tNode), 1 /* TriggerType.Prefetch */);
|
|
19804
20417
|
}
|
|
19805
20418
|
}
|
|
19806
20419
|
/**
|
|
@@ -19813,7 +20426,7 @@ function ɵɵdeferOnViewport(triggerIndex, walkUpTimes) {
|
|
|
19813
20426
|
const lView = getLView();
|
|
19814
20427
|
const tNode = getCurrentTNode();
|
|
19815
20428
|
renderPlaceholder(lView, tNode);
|
|
19816
|
-
registerDomTrigger(lView, tNode, triggerIndex, walkUpTimes, onViewport, () => triggerDeferBlock(lView, tNode));
|
|
20429
|
+
registerDomTrigger(lView, tNode, triggerIndex, walkUpTimes, onViewport, () => triggerDeferBlock(lView, tNode), 0 /* TriggerType.Regular */);
|
|
19817
20430
|
}
|
|
19818
20431
|
/**
|
|
19819
20432
|
* Creates runtime data structures for the `prefetch on viewport` deferred trigger.
|
|
@@ -19827,7 +20440,7 @@ function ɵɵdeferPrefetchOnViewport(triggerIndex, walkUpTimes) {
|
|
|
19827
20440
|
const tView = lView[TVIEW];
|
|
19828
20441
|
const tDetails = getTDeferBlockDetails(tView, tNode);
|
|
19829
20442
|
if (tDetails.loadingState === DeferDependenciesLoadingState.NOT_STARTED) {
|
|
19830
|
-
registerDomTrigger(lView, tNode, triggerIndex, walkUpTimes, onViewport, () => triggerPrefetching(tDetails, lView));
|
|
20443
|
+
registerDomTrigger(lView, tNode, triggerIndex, walkUpTimes, onViewport, () => triggerPrefetching(tDetails, lView, tNode), 1 /* TriggerType.Prefetch */);
|
|
19831
20444
|
}
|
|
19832
20445
|
}
|
|
19833
20446
|
/********** Helper functions **********/
|
|
@@ -19838,253 +20451,26 @@ function scheduleDelayedTrigger(scheduleFn) {
|
|
|
19838
20451
|
const lView = getLView();
|
|
19839
20452
|
const tNode = getCurrentTNode();
|
|
19840
20453
|
renderPlaceholder(lView, tNode);
|
|
19841
|
-
scheduleFn(() => triggerDeferBlock(lView, tNode), lView
|
|
20454
|
+
const cleanupFn = scheduleFn(() => triggerDeferBlock(lView, tNode), lView);
|
|
20455
|
+
const lDetails = getLDeferBlockDetails(lView, tNode);
|
|
20456
|
+
storeTriggerCleanupFn(0 /* TriggerType.Regular */, lDetails, cleanupFn);
|
|
19842
20457
|
}
|
|
19843
20458
|
/**
|
|
19844
20459
|
* Schedules prefetching for `on idle` and `on timer` triggers.
|
|
19845
20460
|
*
|
|
19846
20461
|
* @param scheduleFn A function that does the scheduling.
|
|
19847
|
-
* @param trigger A trigger that initiated scheduling.
|
|
19848
20462
|
*/
|
|
19849
|
-
function scheduleDelayedPrefetching(scheduleFn
|
|
20463
|
+
function scheduleDelayedPrefetching(scheduleFn) {
|
|
19850
20464
|
const lView = getLView();
|
|
19851
20465
|
const tNode = getCurrentTNode();
|
|
19852
20466
|
const tView = lView[TVIEW];
|
|
19853
20467
|
const tDetails = getTDeferBlockDetails(tView, tNode);
|
|
19854
20468
|
if (tDetails.loadingState === DeferDependenciesLoadingState.NOT_STARTED) {
|
|
19855
|
-
|
|
19856
|
-
|
|
19857
|
-
|
|
19858
|
-
|
|
19859
|
-
const injector = lView[INJECTOR$1];
|
|
19860
|
-
const manager = injector.get(DeferBlockCleanupManager);
|
|
19861
|
-
if (!manager.has(tDetails, key)) {
|
|
19862
|
-
// In case of prefetching, we intentionally avoid cancelling resource loading if
|
|
19863
|
-
// an underlying LView get destroyed (thus passing `null` as a second argument),
|
|
19864
|
-
// because there might be other LViews (that represent embedded views) that
|
|
19865
|
-
// depend on resource loading.
|
|
19866
|
-
const prefetch = () => triggerPrefetching(tDetails, lView);
|
|
19867
|
-
const cleanupFn = scheduleFn(prefetch, lView, false /* withLViewCleanup */);
|
|
19868
|
-
registerTDetailsCleanup(injector, tDetails, key, cleanupFn);
|
|
19869
|
-
}
|
|
19870
|
-
}
|
|
19871
|
-
}
|
|
19872
|
-
/**
|
|
19873
|
-
* Helper function to get the LView in which a deferred block's trigger is rendered.
|
|
19874
|
-
* @param deferredHostLView LView in which the deferred block is defined.
|
|
19875
|
-
* @param deferredTNode TNode defining the deferred block.
|
|
19876
|
-
* @param walkUpTimes Number of times to go up in the view hierarchy to find the trigger's view.
|
|
19877
|
-
* A negative value means that the trigger is inside the block's placeholder, while an undefined
|
|
19878
|
-
* value means that the trigger is in the same LView as the deferred block.
|
|
19879
|
-
*/
|
|
19880
|
-
function getTriggerLView(deferredHostLView, deferredTNode, walkUpTimes) {
|
|
19881
|
-
// The trigger is in the same view, we don't need to traverse.
|
|
19882
|
-
if (walkUpTimes == null) {
|
|
19883
|
-
return deferredHostLView;
|
|
19884
|
-
}
|
|
19885
|
-
// A positive value or zero means that the trigger is in a parent view.
|
|
19886
|
-
if (walkUpTimes >= 0) {
|
|
19887
|
-
return walkUpViews(walkUpTimes, deferredHostLView);
|
|
19888
|
-
}
|
|
19889
|
-
// If the value is negative, it means that the trigger is inside the placeholder.
|
|
19890
|
-
const deferredContainer = deferredHostLView[deferredTNode.index];
|
|
19891
|
-
ngDevMode && assertLContainer(deferredContainer);
|
|
19892
|
-
const triggerLView = deferredContainer[CONTAINER_HEADER_OFFSET] ?? null;
|
|
19893
|
-
// We need to null check, because the placeholder might not have been rendered yet.
|
|
19894
|
-
if (ngDevMode && triggerLView !== null) {
|
|
19895
|
-
const lDetails = getLDeferBlockDetails(deferredHostLView, deferredTNode);
|
|
19896
|
-
const renderedState = lDetails[DEFER_BLOCK_STATE];
|
|
19897
|
-
assertEqual(renderedState, DeferBlockState.Placeholder, 'Expected a placeholder to be rendered in this defer block.');
|
|
19898
|
-
assertLView(triggerLView);
|
|
19899
|
-
}
|
|
19900
|
-
return triggerLView;
|
|
19901
|
-
}
|
|
19902
|
-
/**
|
|
19903
|
-
* Gets the element that a deferred block's trigger is pointing to.
|
|
19904
|
-
* @param triggerLView LView in which the trigger is defined.
|
|
19905
|
-
* @param triggerIndex Index at which the trigger element should've been rendered.
|
|
19906
|
-
*/
|
|
19907
|
-
function getTriggerElement(triggerLView, triggerIndex) {
|
|
19908
|
-
const element = getNativeByIndex(HEADER_OFFSET + triggerIndex, triggerLView);
|
|
19909
|
-
ngDevMode && assertElement(element);
|
|
19910
|
-
return element;
|
|
19911
|
-
}
|
|
19912
|
-
/**
|
|
19913
|
-
* Registers a DOM-node based trigger.
|
|
19914
|
-
* @param initialLView LView in which the defer block is rendered.
|
|
19915
|
-
* @param tNode TNode representing the defer block.
|
|
19916
|
-
* @param triggerIndex Index at which to find the trigger element.
|
|
19917
|
-
* @param walkUpTimes Number of times to go up/down in the view hierarchy to find the trigger.
|
|
19918
|
-
* @param registerFn Function that will register the DOM events.
|
|
19919
|
-
* @param callback Callback to be invoked when the trigger receives the event that should render
|
|
19920
|
-
* the deferred block.
|
|
19921
|
-
*/
|
|
19922
|
-
function registerDomTrigger(initialLView, tNode, triggerIndex, walkUpTimes, registerFn, callback) {
|
|
19923
|
-
const injector = initialLView[INJECTOR$1];
|
|
19924
|
-
// Assumption: the `afterRender` reference should be destroyed
|
|
19925
|
-
// automatically so we don't need to keep track of it.
|
|
19926
|
-
const afterRenderRef = afterRender(() => {
|
|
19927
|
-
const lDetails = getLDeferBlockDetails(initialLView, tNode);
|
|
19928
|
-
const renderedState = lDetails[DEFER_BLOCK_STATE];
|
|
19929
|
-
// If the block was loaded before the trigger was resolved, we don't need to do anything.
|
|
19930
|
-
if (renderedState !== DeferBlockInternalState.Initial &&
|
|
19931
|
-
renderedState !== DeferBlockState.Placeholder) {
|
|
19932
|
-
afterRenderRef.destroy();
|
|
19933
|
-
return;
|
|
19934
|
-
}
|
|
19935
|
-
const triggerLView = getTriggerLView(initialLView, tNode, walkUpTimes);
|
|
19936
|
-
// Keep polling until we resolve the trigger's LView.
|
|
19937
|
-
// `afterRender` should stop automatically if the view is destroyed.
|
|
19938
|
-
if (!triggerLView) {
|
|
19939
|
-
return;
|
|
19940
|
-
}
|
|
19941
|
-
// It's possible that the trigger's view was destroyed before we resolved the trigger element.
|
|
19942
|
-
if (triggerLView[FLAGS] & 256 /* LViewFlags.Destroyed */) {
|
|
19943
|
-
afterRenderRef.destroy();
|
|
19944
|
-
return;
|
|
19945
|
-
}
|
|
19946
|
-
// TODO: add integration with `DeferBlockCleanupManager`.
|
|
19947
|
-
const element = getTriggerElement(triggerLView, triggerIndex);
|
|
19948
|
-
const cleanup = registerFn(element, () => {
|
|
19949
|
-
callback();
|
|
19950
|
-
removeLViewOnDestroy(triggerLView, cleanup);
|
|
19951
|
-
if (initialLView !== triggerLView) {
|
|
19952
|
-
removeLViewOnDestroy(initialLView, cleanup);
|
|
19953
|
-
}
|
|
19954
|
-
cleanup();
|
|
19955
|
-
}, injector);
|
|
19956
|
-
afterRenderRef.destroy();
|
|
19957
|
-
storeLViewOnDestroy(triggerLView, cleanup);
|
|
19958
|
-
// Since the trigger and deferred block might be in different
|
|
19959
|
-
// views, we have to register the callback in both locations.
|
|
19960
|
-
if (initialLView !== triggerLView) {
|
|
19961
|
-
storeLViewOnDestroy(initialLView, cleanup);
|
|
19962
|
-
}
|
|
19963
|
-
}, { injector });
|
|
19964
|
-
}
|
|
19965
|
-
/**
|
|
19966
|
-
* Helper function to schedule a callback to be invoked when a browser becomes idle.
|
|
19967
|
-
*
|
|
19968
|
-
* @param callback A function to be invoked when a browser becomes idle.
|
|
19969
|
-
* @param lView LView that hosts an instance of a defer block.
|
|
19970
|
-
* @param withLViewCleanup A flag that indicates whether a scheduled callback
|
|
19971
|
-
* should be cancelled in case an LView is destroyed before a callback
|
|
19972
|
-
* was invoked.
|
|
19973
|
-
*/
|
|
19974
|
-
function onIdle(callback, lView, withLViewCleanup) {
|
|
19975
|
-
const injector = lView[INJECTOR$1];
|
|
19976
|
-
const scheduler = injector.get(OnIdleScheduler);
|
|
19977
|
-
const cleanupFn = () => scheduler.remove(callback);
|
|
19978
|
-
const wrappedCallback = withLViewCleanup ? wrapWithLViewCleanup(callback, lView, cleanupFn) : callback;
|
|
19979
|
-
scheduler.add(wrappedCallback);
|
|
19980
|
-
return cleanupFn;
|
|
19981
|
-
}
|
|
19982
|
-
/**
|
|
19983
|
-
* Returns a function that captures a provided delay.
|
|
19984
|
-
* Invoking the returned function schedules a trigger.
|
|
19985
|
-
*/
|
|
19986
|
-
function onTimer(delay) {
|
|
19987
|
-
return (callback, lView, withLViewCleanup) => scheduleTimerTrigger(delay, callback, lView, withLViewCleanup);
|
|
19988
|
-
}
|
|
19989
|
-
/**
|
|
19990
|
-
* Schedules a callback to be invoked after a given timeout.
|
|
19991
|
-
*
|
|
19992
|
-
* @param delay A number of ms to wait until firing a callback.
|
|
19993
|
-
* @param callback A function to be invoked after a timeout.
|
|
19994
|
-
* @param lView LView that hosts an instance of a defer block.
|
|
19995
|
-
* @param withLViewCleanup A flag that indicates whether a scheduled callback
|
|
19996
|
-
* should be cancelled in case an LView is destroyed before a callback
|
|
19997
|
-
* was invoked.
|
|
19998
|
-
*/
|
|
19999
|
-
function scheduleTimerTrigger(delay, callback, lView, withLViewCleanup) {
|
|
20000
|
-
const injector = lView[INJECTOR$1];
|
|
20001
|
-
const scheduler = injector.get(TimerScheduler);
|
|
20002
|
-
const cleanupFn = () => scheduler.remove(callback);
|
|
20003
|
-
const wrappedCallback = withLViewCleanup ? wrapWithLViewCleanup(callback, lView, cleanupFn) : callback;
|
|
20004
|
-
scheduler.add(delay, wrappedCallback);
|
|
20005
|
-
return cleanupFn;
|
|
20006
|
-
}
|
|
20007
|
-
/**
|
|
20008
|
-
* Wraps a given callback into a logic that registers a cleanup function
|
|
20009
|
-
* in the LView cleanup slot, to be invoked when an LView is destroyed.
|
|
20010
|
-
*/
|
|
20011
|
-
function wrapWithLViewCleanup(callback, lView, cleanup) {
|
|
20012
|
-
const wrappedCallback = () => {
|
|
20013
|
-
callback();
|
|
20014
|
-
removeLViewOnDestroy(lView, cleanup);
|
|
20015
|
-
};
|
|
20016
|
-
storeLViewOnDestroy(lView, cleanup);
|
|
20017
|
-
return wrappedCallback;
|
|
20018
|
-
}
|
|
20019
|
-
/**
|
|
20020
|
-
* Calculates a data slot index for defer block info (either static or
|
|
20021
|
-
* instance-specific), given an index of a defer instruction.
|
|
20022
|
-
*/
|
|
20023
|
-
function getDeferBlockDataIndex(deferBlockIndex) {
|
|
20024
|
-
// Instance state is located at the *next* position
|
|
20025
|
-
// after the defer block slot in an LView or TView.data.
|
|
20026
|
-
return deferBlockIndex + 1;
|
|
20027
|
-
}
|
|
20028
|
-
/** Retrieves a defer block state from an LView, given a TNode that represents a block. */
|
|
20029
|
-
function getLDeferBlockDetails(lView, tNode) {
|
|
20030
|
-
const tView = lView[TVIEW];
|
|
20031
|
-
const slotIndex = getDeferBlockDataIndex(tNode.index);
|
|
20032
|
-
ngDevMode && assertIndexInDeclRange(tView, slotIndex);
|
|
20033
|
-
return lView[slotIndex];
|
|
20034
|
-
}
|
|
20035
|
-
/** Stores a defer block instance state in LView. */
|
|
20036
|
-
function setLDeferBlockDetails(lView, deferBlockIndex, lDetails) {
|
|
20037
|
-
const tView = lView[TVIEW];
|
|
20038
|
-
const slotIndex = getDeferBlockDataIndex(deferBlockIndex);
|
|
20039
|
-
ngDevMode && assertIndexInDeclRange(tView, slotIndex);
|
|
20040
|
-
lView[slotIndex] = lDetails;
|
|
20041
|
-
}
|
|
20042
|
-
/** Retrieves static info about a defer block, given a TView and a TNode that represents a block. */
|
|
20043
|
-
function getTDeferBlockDetails(tView, tNode) {
|
|
20044
|
-
const slotIndex = getDeferBlockDataIndex(tNode.index);
|
|
20045
|
-
ngDevMode && assertIndexInDeclRange(tView, slotIndex);
|
|
20046
|
-
return tView.data[slotIndex];
|
|
20047
|
-
}
|
|
20048
|
-
/** Stores a defer block static info in `TView.data`. */
|
|
20049
|
-
function setTDeferBlockDetails(tView, deferBlockIndex, deferBlockConfig) {
|
|
20050
|
-
const slotIndex = getDeferBlockDataIndex(deferBlockIndex);
|
|
20051
|
-
ngDevMode && assertIndexInDeclRange(tView, slotIndex);
|
|
20052
|
-
tView.data[slotIndex] = deferBlockConfig;
|
|
20053
|
-
}
|
|
20054
|
-
function getTemplateIndexForState(newState, hostLView, tNode) {
|
|
20055
|
-
const tView = hostLView[TVIEW];
|
|
20056
|
-
const tDetails = getTDeferBlockDetails(tView, tNode);
|
|
20057
|
-
switch (newState) {
|
|
20058
|
-
case DeferBlockState.Complete:
|
|
20059
|
-
return tDetails.primaryTmplIndex;
|
|
20060
|
-
case DeferBlockState.Loading:
|
|
20061
|
-
return tDetails.loadingTmplIndex;
|
|
20062
|
-
case DeferBlockState.Error:
|
|
20063
|
-
return tDetails.errorTmplIndex;
|
|
20064
|
-
case DeferBlockState.Placeholder:
|
|
20065
|
-
return tDetails.placeholderTmplIndex;
|
|
20066
|
-
default:
|
|
20067
|
-
ngDevMode && throwError(`Unexpected defer block state: ${newState}`);
|
|
20068
|
-
return null;
|
|
20069
|
-
}
|
|
20070
|
-
}
|
|
20071
|
-
/**
|
|
20072
|
-
* Returns a minimum amount of time that a given state should be rendered for,
|
|
20073
|
-
* taking into account `minimum` parameter value. If the `minimum` value is
|
|
20074
|
-
* not specified - returns `null`.
|
|
20075
|
-
*/
|
|
20076
|
-
function getMinimumDurationForState(tDetails, currentState) {
|
|
20077
|
-
if (currentState === DeferBlockState.Placeholder) {
|
|
20078
|
-
return tDetails.placeholderBlockConfig?.[MINIMUM_SLOT] ?? null;
|
|
20079
|
-
}
|
|
20080
|
-
else if (currentState === DeferBlockState.Loading) {
|
|
20081
|
-
return tDetails.loadingBlockConfig?.[MINIMUM_SLOT] ?? null;
|
|
20469
|
+
const lDetails = getLDeferBlockDetails(lView, tNode);
|
|
20470
|
+
const prefetch = () => triggerPrefetching(tDetails, lView, tNode);
|
|
20471
|
+
const cleanupFn = scheduleFn(prefetch, lView);
|
|
20472
|
+
storeTriggerCleanupFn(1 /* TriggerType.Prefetch */, lDetails, cleanupFn);
|
|
20082
20473
|
}
|
|
20083
|
-
return null;
|
|
20084
|
-
}
|
|
20085
|
-
/** Retrieves the value of the `after` parameter on the @loading block. */
|
|
20086
|
-
function getLoadingBlockAfter(tDetails) {
|
|
20087
|
-
return tDetails.loadingBlockConfig?.[LOADING_AFTER_SLOT] ?? null;
|
|
20088
20474
|
}
|
|
20089
20475
|
/**
|
|
20090
20476
|
* Transitions a defer block to the new state. Updates the necessary
|
|
@@ -20093,8 +20479,12 @@ function getLoadingBlockAfter(tDetails) {
|
|
|
20093
20479
|
* @param newState New state that should be applied to the defer block.
|
|
20094
20480
|
* @param tNode TNode that represents a defer block.
|
|
20095
20481
|
* @param lContainer Represents an instance of a defer block.
|
|
20482
|
+
* @param skipTimerScheduling Indicates that `@loading` and `@placeholder` block
|
|
20483
|
+
* should be rendered immediately, even if they have `after` or `minimum` config
|
|
20484
|
+
* options setup. This flag to needed for testing APIs to transition defer block
|
|
20485
|
+
* between states via `DeferFixture.render` method.
|
|
20096
20486
|
*/
|
|
20097
|
-
function renderDeferBlockState(newState, tNode, lContainer) {
|
|
20487
|
+
function renderDeferBlockState(newState, tNode, lContainer, skipTimerScheduling = false) {
|
|
20098
20488
|
const hostLView = lContainer[PARENT];
|
|
20099
20489
|
const hostTView = hostLView[TVIEW];
|
|
20100
20490
|
// Check if this view is not destroyed. Since the loading process was async,
|
|
@@ -20109,14 +20499,20 @@ function renderDeferBlockState(newState, tNode, lContainer) {
|
|
|
20109
20499
|
if (isValidStateChange(currentState, newState) &&
|
|
20110
20500
|
isValidStateChange(lDetails[NEXT_DEFER_BLOCK_STATE] ?? -1, newState)) {
|
|
20111
20501
|
const tDetails = getTDeferBlockDetails(hostTView, tNode);
|
|
20112
|
-
const needsScheduling =
|
|
20113
|
-
|
|
20114
|
-
|
|
20502
|
+
const needsScheduling = !skipTimerScheduling &&
|
|
20503
|
+
(getLoadingBlockAfter(tDetails) !== null ||
|
|
20504
|
+
getMinimumDurationForState(tDetails, DeferBlockState.Loading) !== null ||
|
|
20505
|
+
getMinimumDurationForState(tDetails, DeferBlockState.Placeholder));
|
|
20115
20506
|
if (ngDevMode && needsScheduling) {
|
|
20116
20507
|
assertDefined(applyDeferBlockStateWithSchedulingImpl, 'Expected scheduling function to be defined');
|
|
20117
20508
|
}
|
|
20118
20509
|
const applyStateFn = needsScheduling ? applyDeferBlockStateWithSchedulingImpl : applyDeferBlockState;
|
|
20119
|
-
|
|
20510
|
+
try {
|
|
20511
|
+
applyStateFn(newState, lDetails, lContainer, tNode, hostLView);
|
|
20512
|
+
}
|
|
20513
|
+
catch (error) {
|
|
20514
|
+
handleError(hostLView, error);
|
|
20515
|
+
}
|
|
20120
20516
|
}
|
|
20121
20517
|
}
|
|
20122
20518
|
/**
|
|
@@ -20196,7 +20592,7 @@ function scheduleDeferBlockUpdate(timeout, lDetails, tNode, lContainer, hostLVie
|
|
|
20196
20592
|
renderDeferBlockState(nextState, tNode, lContainer);
|
|
20197
20593
|
}
|
|
20198
20594
|
};
|
|
20199
|
-
return scheduleTimerTrigger(timeout, callback, hostLView
|
|
20595
|
+
return scheduleTimerTrigger(timeout, callback, hostLView);
|
|
20200
20596
|
}
|
|
20201
20597
|
/**
|
|
20202
20598
|
* Checks whether we can transition to the next state.
|
|
@@ -20216,9 +20612,9 @@ function isValidStateChange(currentState, newState) {
|
|
|
20216
20612
|
* @param tDetails Static information about this defer block.
|
|
20217
20613
|
* @param lView LView of a host view.
|
|
20218
20614
|
*/
|
|
20219
|
-
function triggerPrefetching(tDetails, lView) {
|
|
20615
|
+
function triggerPrefetching(tDetails, lView, tNode) {
|
|
20220
20616
|
if (lView[INJECTOR$1] && shouldTriggerDeferBlock(lView[INJECTOR$1])) {
|
|
20221
|
-
triggerResourceLoading(tDetails, lView);
|
|
20617
|
+
triggerResourceLoading(tDetails, lView, tNode);
|
|
20222
20618
|
}
|
|
20223
20619
|
}
|
|
20224
20620
|
/**
|
|
@@ -20227,7 +20623,7 @@ function triggerPrefetching(tDetails, lView) {
|
|
|
20227
20623
|
* @param tDetails Static information about this defer block.
|
|
20228
20624
|
* @param lView LView of a host view.
|
|
20229
20625
|
*/
|
|
20230
|
-
function triggerResourceLoading(tDetails, lView) {
|
|
20626
|
+
function triggerResourceLoading(tDetails, lView, tNode) {
|
|
20231
20627
|
const injector = lView[INJECTOR$1];
|
|
20232
20628
|
const tView = lView[TVIEW];
|
|
20233
20629
|
if (tDetails.loadingState !== DeferDependenciesLoadingState.NOT_STARTED) {
|
|
@@ -20236,14 +20632,20 @@ function triggerResourceLoading(tDetails, lView) {
|
|
|
20236
20632
|
// in this function. All details can be obtained from the `tDetails` object.
|
|
20237
20633
|
return;
|
|
20238
20634
|
}
|
|
20635
|
+
const lDetails = getLDeferBlockDetails(lView, tNode);
|
|
20239
20636
|
const primaryBlockTNode = getPrimaryBlockTNode(tView, tDetails);
|
|
20240
20637
|
// Switch from NOT_STARTED -> IN_PROGRESS state.
|
|
20241
20638
|
tDetails.loadingState = DeferDependenciesLoadingState.IN_PROGRESS;
|
|
20242
|
-
//
|
|
20243
|
-
|
|
20244
|
-
|
|
20245
|
-
|
|
20246
|
-
|
|
20639
|
+
// Prefetching is triggered, cleanup all registered prefetch triggers.
|
|
20640
|
+
invokeTriggerCleanupFns(1 /* TriggerType.Prefetch */, lDetails);
|
|
20641
|
+
let dependenciesFn = tDetails.dependencyResolverFn;
|
|
20642
|
+
if (ngDevMode) {
|
|
20643
|
+
// Check if dependency function interceptor is configured.
|
|
20644
|
+
const deferDependencyInterceptor = injector.get(DEFER_BLOCK_DEPENDENCY_INTERCEPTOR, null, { optional: true });
|
|
20645
|
+
if (deferDependencyInterceptor) {
|
|
20646
|
+
dependenciesFn = deferDependencyInterceptor.intercept(dependenciesFn);
|
|
20647
|
+
}
|
|
20648
|
+
}
|
|
20247
20649
|
// The `dependenciesFn` might be `null` when all dependencies within
|
|
20248
20650
|
// a given defer block were eagerly references elsewhere in a file,
|
|
20249
20651
|
// thus no dynamic `import()`s were produced.
|
|
@@ -20253,9 +20655,6 @@ function triggerResourceLoading(tDetails, lView) {
|
|
|
20253
20655
|
});
|
|
20254
20656
|
return;
|
|
20255
20657
|
}
|
|
20256
|
-
// Defer block may have multiple prefetch triggers. Once the loading
|
|
20257
|
-
// starts, invoke all clean functions, since they are no longer needed.
|
|
20258
|
-
invokeTDetailsCleanup(injector, tDetails);
|
|
20259
20658
|
// Start downloading of defer block dependencies.
|
|
20260
20659
|
tDetails.loadingPromise = Promise.allSettled(dependenciesFn()).then(results => {
|
|
20261
20660
|
let failed = false;
|
|
@@ -20284,6 +20683,14 @@ function triggerResourceLoading(tDetails, lView) {
|
|
|
20284
20683
|
tDetails.loadingPromise = null;
|
|
20285
20684
|
if (failed) {
|
|
20286
20685
|
tDetails.loadingState = DeferDependenciesLoadingState.FAILED;
|
|
20686
|
+
if (tDetails.errorTmplIndex === null) {
|
|
20687
|
+
const templateLocation = getTemplateLocationDetails(lView);
|
|
20688
|
+
const error = new RuntimeError(750 /* RuntimeErrorCode.DEFER_LOADING_FAILED */, ngDevMode &&
|
|
20689
|
+
'Loading dependencies for `@defer` block failed, ' +
|
|
20690
|
+
`but no \`@error\` block was configured${templateLocation}. ` +
|
|
20691
|
+
'Consider using the `@error` block to render an error state.');
|
|
20692
|
+
handleError(lView, error);
|
|
20693
|
+
}
|
|
20287
20694
|
}
|
|
20288
20695
|
else {
|
|
20289
20696
|
tDetails.loadingState = DeferDependenciesLoadingState.COMPLETE;
|
|
@@ -20300,22 +20707,6 @@ function triggerResourceLoading(tDetails, lView) {
|
|
|
20300
20707
|
}
|
|
20301
20708
|
});
|
|
20302
20709
|
}
|
|
20303
|
-
/**
|
|
20304
|
-
* Adds downloaded dependencies into a directive or a pipe registry,
|
|
20305
|
-
* making sure that a dependency doesn't yet exist in the registry.
|
|
20306
|
-
*/
|
|
20307
|
-
function addDepsToRegistry(currentDeps, newDeps) {
|
|
20308
|
-
if (!currentDeps || currentDeps.length === 0) {
|
|
20309
|
-
return newDeps;
|
|
20310
|
-
}
|
|
20311
|
-
const currentDepSet = new Set(currentDeps);
|
|
20312
|
-
for (const dep of newDeps) {
|
|
20313
|
-
currentDepSet.add(dep);
|
|
20314
|
-
}
|
|
20315
|
-
// If `currentDeps` is the same length, there were no new deps and can
|
|
20316
|
-
// return the original array.
|
|
20317
|
-
return (currentDeps.length === currentDepSet.size) ? currentDeps : Array.from(currentDepSet);
|
|
20318
|
-
}
|
|
20319
20710
|
/** Utility function to render placeholder content (if present) */
|
|
20320
20711
|
function renderPlaceholder(lView, tNode) {
|
|
20321
20712
|
const lContainer = lView[tNode.index];
|
|
@@ -20343,11 +20734,6 @@ function renderDeferStateAfterResourceLoading(tDetails, tNode, lContainer) {
|
|
|
20343
20734
|
}
|
|
20344
20735
|
});
|
|
20345
20736
|
}
|
|
20346
|
-
/** Retrieves a TNode that represents main content of a defer block. */
|
|
20347
|
-
function getPrimaryBlockTNode(tView, tDetails) {
|
|
20348
|
-
const adjustedIndex = tDetails.primaryTmplIndex + HEADER_OFFSET;
|
|
20349
|
-
return getTNode(tView, adjustedIndex);
|
|
20350
|
-
}
|
|
20351
20737
|
/**
|
|
20352
20738
|
* Attempts to trigger loading of defer block dependencies.
|
|
20353
20739
|
* If the block is already in a loading, completed or an error state -
|
|
@@ -20360,11 +20746,14 @@ function triggerDeferBlock(lView, tNode) {
|
|
|
20360
20746
|
ngDevMode && assertLContainer(lContainer);
|
|
20361
20747
|
if (!shouldTriggerDeferBlock(injector))
|
|
20362
20748
|
return;
|
|
20749
|
+
const lDetails = getLDeferBlockDetails(lView, tNode);
|
|
20363
20750
|
const tDetails = getTDeferBlockDetails(tView, tNode);
|
|
20751
|
+
// Defer block is triggered, cleanup all registered trigger functions.
|
|
20752
|
+
invokeAllTriggerCleanupFns(lDetails);
|
|
20364
20753
|
switch (tDetails.loadingState) {
|
|
20365
20754
|
case DeferDependenciesLoadingState.NOT_STARTED:
|
|
20366
20755
|
renderDeferBlockState(DeferBlockState.Loading, tNode, lContainer);
|
|
20367
|
-
triggerResourceLoading(tDetails, lView);
|
|
20756
|
+
triggerResourceLoading(tDetails, lView, tNode);
|
|
20368
20757
|
// The `loadingState` might have changed to "loading".
|
|
20369
20758
|
if (tDetails.loadingState ===
|
|
20370
20759
|
DeferDependenciesLoadingState.IN_PROGRESS) {
|
|
@@ -20388,366 +20777,6 @@ function triggerDeferBlock(lView, tNode) {
|
|
|
20388
20777
|
}
|
|
20389
20778
|
}
|
|
20390
20779
|
}
|
|
20391
|
-
/**
|
|
20392
|
-
* Asserts whether all dependencies for a defer block are loaded.
|
|
20393
|
-
* Always run this function (in dev mode) before rendering a defer
|
|
20394
|
-
* block in completed state.
|
|
20395
|
-
*/
|
|
20396
|
-
function assertDeferredDependenciesLoaded(tDetails) {
|
|
20397
|
-
assertEqual(tDetails.loadingState, DeferDependenciesLoadingState.COMPLETE, 'Expecting all deferred dependencies to be loaded.');
|
|
20398
|
-
}
|
|
20399
|
-
/**
|
|
20400
|
-
* **INTERNAL**, avoid referencing it in application code.
|
|
20401
|
-
*
|
|
20402
|
-
* Injector token that allows to provide `DeferBlockDependencyInterceptor` class
|
|
20403
|
-
* implementation.
|
|
20404
|
-
*/
|
|
20405
|
-
const DEFER_BLOCK_DEPENDENCY_INTERCEPTOR = new InjectionToken(ngDevMode ? 'DEFER_BLOCK_DEPENDENCY_INTERCEPTOR' : '');
|
|
20406
|
-
/**
|
|
20407
|
-
* Determines if a given value matches the expected structure of a defer block
|
|
20408
|
-
*
|
|
20409
|
-
* We can safely rely on the primaryTmplIndex because every defer block requires
|
|
20410
|
-
* that a primary template exists. All the other template options are optional.
|
|
20411
|
-
*/
|
|
20412
|
-
function isTDeferBlockDetails(value) {
|
|
20413
|
-
return (typeof value === 'object') &&
|
|
20414
|
-
(typeof value.primaryTmplIndex === 'number');
|
|
20415
|
-
}
|
|
20416
|
-
/**
|
|
20417
|
-
* Internal token used for configuring defer block behavior.
|
|
20418
|
-
*/
|
|
20419
|
-
const DEFER_BLOCK_CONFIG = new InjectionToken(ngDevMode ? 'DEFER_BLOCK_CONFIG' : '');
|
|
20420
|
-
/**
|
|
20421
|
-
* Retrieves all defer blocks in a given LView.
|
|
20422
|
-
*
|
|
20423
|
-
* @param lView lView with defer blocks
|
|
20424
|
-
* @param deferBlocks defer block aggregator array
|
|
20425
|
-
*/
|
|
20426
|
-
function getDeferBlocks(lView, deferBlocks) {
|
|
20427
|
-
const tView = lView[TVIEW];
|
|
20428
|
-
for (let i = HEADER_OFFSET; i < tView.bindingStartIndex; i++) {
|
|
20429
|
-
if (isLContainer(lView[i])) {
|
|
20430
|
-
const lContainer = lView[i];
|
|
20431
|
-
// An LContainer may represent an instance of a defer block, in which case
|
|
20432
|
-
// we store it as a result. Otherwise, keep iterating over LContainer views and
|
|
20433
|
-
// look for defer blocks.
|
|
20434
|
-
const isLast = i === tView.bindingStartIndex - 1;
|
|
20435
|
-
if (!isLast) {
|
|
20436
|
-
const tNode = tView.data[i];
|
|
20437
|
-
const tDetails = getTDeferBlockDetails(tView, tNode);
|
|
20438
|
-
if (isTDeferBlockDetails(tDetails)) {
|
|
20439
|
-
deferBlocks.push({ lContainer, lView, tNode, tDetails });
|
|
20440
|
-
// This LContainer represents a defer block, so we exit
|
|
20441
|
-
// this iteration and don't inspect views in this LContainer.
|
|
20442
|
-
continue;
|
|
20443
|
-
}
|
|
20444
|
-
}
|
|
20445
|
-
for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
|
|
20446
|
-
getDeferBlocks(lContainer[i], deferBlocks);
|
|
20447
|
-
}
|
|
20448
|
-
}
|
|
20449
|
-
else if (isLView(lView[i])) {
|
|
20450
|
-
// This is a component, enter the `getDeferBlocks` recursively.
|
|
20451
|
-
getDeferBlocks(lView[i], deferBlocks);
|
|
20452
|
-
}
|
|
20453
|
-
}
|
|
20454
|
-
}
|
|
20455
|
-
/**
|
|
20456
|
-
* Registers a cleanup function associated with a prefetching trigger
|
|
20457
|
-
* of a given defer block.
|
|
20458
|
-
*/
|
|
20459
|
-
function registerTDetailsCleanup(injector, tDetails, key, cleanupFn) {
|
|
20460
|
-
injector.get(DeferBlockCleanupManager).add(tDetails, key, cleanupFn);
|
|
20461
|
-
}
|
|
20462
|
-
/**
|
|
20463
|
-
* Invokes all registered prefetch cleanup triggers
|
|
20464
|
-
* and removes all cleanup functions afterwards.
|
|
20465
|
-
*/
|
|
20466
|
-
function invokeTDetailsCleanup(injector, tDetails) {
|
|
20467
|
-
injector.get(DeferBlockCleanupManager).cleanup(tDetails);
|
|
20468
|
-
}
|
|
20469
|
-
/**
|
|
20470
|
-
* Internal service to keep track of cleanup functions associated
|
|
20471
|
-
* with defer blocks. This class is used to manage cleanup functions
|
|
20472
|
-
* created for prefetching triggers.
|
|
20473
|
-
*/
|
|
20474
|
-
class DeferBlockCleanupManager {
|
|
20475
|
-
constructor() {
|
|
20476
|
-
this.blocks = new Map();
|
|
20477
|
-
}
|
|
20478
|
-
add(tDetails, key, callback) {
|
|
20479
|
-
if (!this.blocks.has(tDetails)) {
|
|
20480
|
-
this.blocks.set(tDetails, new Map());
|
|
20481
|
-
}
|
|
20482
|
-
const block = this.blocks.get(tDetails);
|
|
20483
|
-
if (!block.has(key)) {
|
|
20484
|
-
block.set(key, []);
|
|
20485
|
-
}
|
|
20486
|
-
const callbacks = block.get(key);
|
|
20487
|
-
callbacks.push(callback);
|
|
20488
|
-
}
|
|
20489
|
-
has(tDetails, key) {
|
|
20490
|
-
return !!this.blocks.get(tDetails)?.has(key);
|
|
20491
|
-
}
|
|
20492
|
-
cleanup(tDetails) {
|
|
20493
|
-
const block = this.blocks.get(tDetails);
|
|
20494
|
-
if (block) {
|
|
20495
|
-
for (const callbacks of Object.values(block)) {
|
|
20496
|
-
for (const callback of callbacks) {
|
|
20497
|
-
callback();
|
|
20498
|
-
}
|
|
20499
|
-
}
|
|
20500
|
-
this.blocks.delete(tDetails);
|
|
20501
|
-
}
|
|
20502
|
-
}
|
|
20503
|
-
ngOnDestroy() {
|
|
20504
|
-
for (const [block] of this.blocks) {
|
|
20505
|
-
this.cleanup(block);
|
|
20506
|
-
}
|
|
20507
|
-
this.blocks.clear();
|
|
20508
|
-
}
|
|
20509
|
-
/** @nocollapse */
|
|
20510
|
-
static { this.ɵprov = ɵɵdefineInjectable({
|
|
20511
|
-
token: DeferBlockCleanupManager,
|
|
20512
|
-
providedIn: 'root',
|
|
20513
|
-
factory: () => new DeferBlockCleanupManager(),
|
|
20514
|
-
}); }
|
|
20515
|
-
}
|
|
20516
|
-
/**
|
|
20517
|
-
* Use shims for the `requestIdleCallback` and `cancelIdleCallback` functions for
|
|
20518
|
-
* environments where those functions are not available (e.g. Node.js and Safari).
|
|
20519
|
-
*
|
|
20520
|
-
* Note: we wrap the `requestIdleCallback` call into a function, so that it can be
|
|
20521
|
-
* overridden/mocked in test environment and picked up by the runtime code.
|
|
20522
|
-
*/
|
|
20523
|
-
const _requestIdleCallback = () => typeof requestIdleCallback !== 'undefined' ? requestIdleCallback : setTimeout;
|
|
20524
|
-
const _cancelIdleCallback = () => typeof requestIdleCallback !== 'undefined' ? cancelIdleCallback : clearTimeout;
|
|
20525
|
-
/**
|
|
20526
|
-
* Helper service to schedule `requestIdleCallback`s for batches of defer blocks,
|
|
20527
|
-
* to avoid calling `requestIdleCallback` for each defer block (e.g. if
|
|
20528
|
-
* defer blocks are defined inside a for loop).
|
|
20529
|
-
*/
|
|
20530
|
-
class OnIdleScheduler {
|
|
20531
|
-
constructor() {
|
|
20532
|
-
// Indicates whether current callbacks are being invoked.
|
|
20533
|
-
this.executingCallbacks = false;
|
|
20534
|
-
// Currently scheduled idle callback id.
|
|
20535
|
-
this.idleId = null;
|
|
20536
|
-
// Set of callbacks to be invoked next.
|
|
20537
|
-
this.current = new Set();
|
|
20538
|
-
// Set of callbacks collected while invoking current set of callbacks.
|
|
20539
|
-
// Those callbacks are scheduled for the next idle period.
|
|
20540
|
-
this.deferred = new Set();
|
|
20541
|
-
this.ngZone = inject(NgZone);
|
|
20542
|
-
this.requestIdleCallback = _requestIdleCallback().bind(globalThis);
|
|
20543
|
-
this.cancelIdleCallback = _cancelIdleCallback().bind(globalThis);
|
|
20544
|
-
}
|
|
20545
|
-
add(callback) {
|
|
20546
|
-
const target = this.executingCallbacks ? this.deferred : this.current;
|
|
20547
|
-
target.add(callback);
|
|
20548
|
-
if (this.idleId === null) {
|
|
20549
|
-
this.scheduleIdleCallback();
|
|
20550
|
-
}
|
|
20551
|
-
}
|
|
20552
|
-
remove(callback) {
|
|
20553
|
-
this.current.delete(callback);
|
|
20554
|
-
this.deferred.delete(callback);
|
|
20555
|
-
}
|
|
20556
|
-
scheduleIdleCallback() {
|
|
20557
|
-
const callback = () => {
|
|
20558
|
-
this.cancelIdleCallback(this.idleId);
|
|
20559
|
-
this.idleId = null;
|
|
20560
|
-
this.executingCallbacks = true;
|
|
20561
|
-
for (const callback of this.current) {
|
|
20562
|
-
callback();
|
|
20563
|
-
}
|
|
20564
|
-
this.current.clear();
|
|
20565
|
-
this.executingCallbacks = false;
|
|
20566
|
-
// If there are any callbacks added during an invocation
|
|
20567
|
-
// of the current ones - make them "current" and schedule
|
|
20568
|
-
// a new idle callback.
|
|
20569
|
-
if (this.deferred.size > 0) {
|
|
20570
|
-
for (const callback of this.deferred) {
|
|
20571
|
-
this.current.add(callback);
|
|
20572
|
-
}
|
|
20573
|
-
this.deferred.clear();
|
|
20574
|
-
this.scheduleIdleCallback();
|
|
20575
|
-
}
|
|
20576
|
-
};
|
|
20577
|
-
// Ensure that the callback runs in the NgZone since
|
|
20578
|
-
// the `requestIdleCallback` is not currently patched by Zone.js.
|
|
20579
|
-
this.idleId = this.requestIdleCallback(() => this.ngZone.run(callback));
|
|
20580
|
-
}
|
|
20581
|
-
ngOnDestroy() {
|
|
20582
|
-
if (this.idleId !== null) {
|
|
20583
|
-
this.cancelIdleCallback(this.idleId);
|
|
20584
|
-
this.idleId = null;
|
|
20585
|
-
}
|
|
20586
|
-
this.current.clear();
|
|
20587
|
-
this.deferred.clear();
|
|
20588
|
-
}
|
|
20589
|
-
/** @nocollapse */
|
|
20590
|
-
static { this.ɵprov = ɵɵdefineInjectable({
|
|
20591
|
-
token: OnIdleScheduler,
|
|
20592
|
-
providedIn: 'root',
|
|
20593
|
-
factory: () => new OnIdleScheduler(),
|
|
20594
|
-
}); }
|
|
20595
|
-
}
|
|
20596
|
-
/**
|
|
20597
|
-
* Helper service to schedule `setTimeout`s for batches of defer blocks,
|
|
20598
|
-
* to avoid calling `setTimeout` for each defer block (e.g. if defer blocks
|
|
20599
|
-
* are created inside a for loop).
|
|
20600
|
-
*/
|
|
20601
|
-
class TimerScheduler {
|
|
20602
|
-
constructor() {
|
|
20603
|
-
// Indicates whether current callbacks are being invoked.
|
|
20604
|
-
this.executingCallbacks = false;
|
|
20605
|
-
// Currently scheduled `setTimeout` id.
|
|
20606
|
-
this.timeoutId = null;
|
|
20607
|
-
// When currently scheduled timer would fire.
|
|
20608
|
-
this.invokeTimerAt = null;
|
|
20609
|
-
// List of callbacks to be invoked.
|
|
20610
|
-
// For each callback we also store a timestamp on when the callback
|
|
20611
|
-
// should be invoked. We store timestamps and callback functions
|
|
20612
|
-
// in a flat array to avoid creating new objects for each entry.
|
|
20613
|
-
// [timestamp1, callback1, timestamp2, callback2, ...]
|
|
20614
|
-
this.current = [];
|
|
20615
|
-
// List of callbacks collected while invoking current set of callbacks.
|
|
20616
|
-
// Those callbacks are added to the "current" queue at the end of
|
|
20617
|
-
// the current callback invocation. The shape of this list is the same
|
|
20618
|
-
// as the shape of the `current` list.
|
|
20619
|
-
this.deferred = [];
|
|
20620
|
-
}
|
|
20621
|
-
add(delay, callback) {
|
|
20622
|
-
const target = this.executingCallbacks ? this.deferred : this.current;
|
|
20623
|
-
this.addToQueue(target, Date.now() + delay, callback);
|
|
20624
|
-
this.scheduleTimer();
|
|
20625
|
-
}
|
|
20626
|
-
remove(callback) {
|
|
20627
|
-
const callbackIndex = this.removeFromQueue(this.current, callback);
|
|
20628
|
-
if (callbackIndex === -1) {
|
|
20629
|
-
// Try cleaning up deferred queue only in case
|
|
20630
|
-
// we didn't find a callback in the "current" queue.
|
|
20631
|
-
this.removeFromQueue(this.deferred, callback);
|
|
20632
|
-
}
|
|
20633
|
-
}
|
|
20634
|
-
addToQueue(target, invokeAt, callback) {
|
|
20635
|
-
let insertAtIndex = target.length;
|
|
20636
|
-
for (let i = 0; i < target.length; i += 2) {
|
|
20637
|
-
const invokeQueuedCallbackAt = target[i];
|
|
20638
|
-
if (invokeQueuedCallbackAt > invokeAt) {
|
|
20639
|
-
// We've reached a first timer that is scheduled
|
|
20640
|
-
// for a later time than what we are trying to insert.
|
|
20641
|
-
// This is the location at which we need to insert,
|
|
20642
|
-
// no need to iterate further.
|
|
20643
|
-
insertAtIndex = i;
|
|
20644
|
-
break;
|
|
20645
|
-
}
|
|
20646
|
-
}
|
|
20647
|
-
arrayInsert2(target, insertAtIndex, invokeAt, callback);
|
|
20648
|
-
}
|
|
20649
|
-
removeFromQueue(target, callback) {
|
|
20650
|
-
let index = -1;
|
|
20651
|
-
for (let i = 0; i < target.length; i += 2) {
|
|
20652
|
-
const queuedCallback = target[i + 1];
|
|
20653
|
-
if (queuedCallback === callback) {
|
|
20654
|
-
index = i;
|
|
20655
|
-
break;
|
|
20656
|
-
}
|
|
20657
|
-
}
|
|
20658
|
-
if (index > -1) {
|
|
20659
|
-
// Remove 2 elements: a timestamp slot and
|
|
20660
|
-
// the following slot with a callback function.
|
|
20661
|
-
arraySplice(target, index, 2);
|
|
20662
|
-
}
|
|
20663
|
-
return index;
|
|
20664
|
-
}
|
|
20665
|
-
scheduleTimer() {
|
|
20666
|
-
const callback = () => {
|
|
20667
|
-
clearTimeout(this.timeoutId);
|
|
20668
|
-
this.timeoutId = null;
|
|
20669
|
-
this.executingCallbacks = true;
|
|
20670
|
-
// Invoke callbacks that were scheduled to run
|
|
20671
|
-
// before the current time.
|
|
20672
|
-
let now = Date.now();
|
|
20673
|
-
let lastCallbackIndex = null;
|
|
20674
|
-
for (let i = 0; i < this.current.length; i += 2) {
|
|
20675
|
-
const invokeAt = this.current[i];
|
|
20676
|
-
const callback = this.current[i + 1];
|
|
20677
|
-
if (invokeAt <= now) {
|
|
20678
|
-
callback();
|
|
20679
|
-
// Point at the invoked callback function, which is located
|
|
20680
|
-
// after the timestamp.
|
|
20681
|
-
lastCallbackIndex = i + 1;
|
|
20682
|
-
}
|
|
20683
|
-
else {
|
|
20684
|
-
// We've reached a timer that should not be invoked yet.
|
|
20685
|
-
break;
|
|
20686
|
-
}
|
|
20687
|
-
}
|
|
20688
|
-
if (lastCallbackIndex !== null) {
|
|
20689
|
-
// If last callback index is `null` - no callbacks were invoked,
|
|
20690
|
-
// so no cleanup is needed. Otherwise, remove invoked callbacks
|
|
20691
|
-
// from the queue.
|
|
20692
|
-
arraySplice(this.current, 0, lastCallbackIndex + 1);
|
|
20693
|
-
}
|
|
20694
|
-
this.executingCallbacks = false;
|
|
20695
|
-
// If there are any callbacks added during an invocation
|
|
20696
|
-
// of the current ones - move them over to the "current"
|
|
20697
|
-
// queue.
|
|
20698
|
-
if (this.deferred.length > 0) {
|
|
20699
|
-
for (let i = 0; i < this.deferred.length; i += 2) {
|
|
20700
|
-
const invokeAt = this.deferred[i];
|
|
20701
|
-
const callback = this.deferred[i + 1];
|
|
20702
|
-
this.addToQueue(this.current, invokeAt, callback);
|
|
20703
|
-
}
|
|
20704
|
-
this.deferred.length = 0;
|
|
20705
|
-
}
|
|
20706
|
-
this.scheduleTimer();
|
|
20707
|
-
};
|
|
20708
|
-
// Avoid running timer callbacks more than once per
|
|
20709
|
-
// average frame duration. This is needed for better
|
|
20710
|
-
// batching and to avoid kicking off excessive change
|
|
20711
|
-
// detection cycles.
|
|
20712
|
-
const FRAME_DURATION_MS = 16; // 1000ms / 60fps
|
|
20713
|
-
if (this.current.length > 0) {
|
|
20714
|
-
const now = Date.now();
|
|
20715
|
-
// First element in the queue points at the timestamp
|
|
20716
|
-
// of the first (earliest) event.
|
|
20717
|
-
const invokeAt = this.current[0];
|
|
20718
|
-
if (!this.timeoutId ||
|
|
20719
|
-
// Reschedule a timer in case a queue contains an item with
|
|
20720
|
-
// an earlier timestamp and the delta is more than an average
|
|
20721
|
-
// frame duration.
|
|
20722
|
-
(this.invokeTimerAt && (this.invokeTimerAt - invokeAt > FRAME_DURATION_MS))) {
|
|
20723
|
-
if (this.timeoutId !== null) {
|
|
20724
|
-
// There was a timeout already, but an earlier event was added
|
|
20725
|
-
// into the queue. In this case we drop an old timer and setup
|
|
20726
|
-
// a new one with an updated (smaller) timeout.
|
|
20727
|
-
clearTimeout(this.timeoutId);
|
|
20728
|
-
this.timeoutId = null;
|
|
20729
|
-
}
|
|
20730
|
-
const timeout = Math.max(invokeAt - now, FRAME_DURATION_MS);
|
|
20731
|
-
this.invokeTimerAt = invokeAt;
|
|
20732
|
-
this.timeoutId = setTimeout(callback, timeout);
|
|
20733
|
-
}
|
|
20734
|
-
}
|
|
20735
|
-
}
|
|
20736
|
-
ngOnDestroy() {
|
|
20737
|
-
if (this.timeoutId !== null) {
|
|
20738
|
-
clearTimeout(this.timeoutId);
|
|
20739
|
-
this.timeoutId = null;
|
|
20740
|
-
}
|
|
20741
|
-
this.current.length = 0;
|
|
20742
|
-
this.deferred.length = 0;
|
|
20743
|
-
}
|
|
20744
|
-
/** @nocollapse */
|
|
20745
|
-
static { this.ɵprov = ɵɵdefineInjectable({
|
|
20746
|
-
token: TimerScheduler,
|
|
20747
|
-
providedIn: 'root',
|
|
20748
|
-
factory: () => new TimerScheduler(),
|
|
20749
|
-
}); }
|
|
20750
|
-
}
|
|
20751
20780
|
|
|
20752
20781
|
function elementStartFirstCreatePass(index, tView, lView, name, attrsIndex, localRefsIndex) {
|
|
20753
20782
|
ngDevMode && assertFirstCreatePass(tView);
|
|
@@ -21346,9 +21375,6 @@ var I18nCreateOpCode;
|
|
|
21346
21375
|
*/
|
|
21347
21376
|
I18nCreateOpCode[I18nCreateOpCode["COMMENT"] = 2] = "COMMENT";
|
|
21348
21377
|
})(I18nCreateOpCode || (I18nCreateOpCode = {}));
|
|
21349
|
-
// Note: This hack is necessary so we don't erroneously get a circular dependency
|
|
21350
|
-
// failure based on types.
|
|
21351
|
-
const unusedValueExportToPlacateAjd = 1;
|
|
21352
21378
|
|
|
21353
21379
|
/**
|
|
21354
21380
|
* The locale id that the application is currently using (for translations and ICU expressions).
|
|
@@ -28775,7 +28801,7 @@ const ITS_JUST_ANGULAR = true;
|
|
|
28775
28801
|
* ```
|
|
28776
28802
|
*
|
|
28777
28803
|
* ### Example with standalone application
|
|
28778
|
-
*
|
|
28804
|
+
* ```
|
|
28779
28805
|
* function initializeAppFactory(httpClient: HttpClient): () => Observable<any> {
|
|
28780
28806
|
* return () => httpClient.get("https://someUrl.com/api/user")
|
|
28781
28807
|
* .pipe(
|
|
@@ -28794,6 +28820,7 @@ const ITS_JUST_ANGULAR = true;
|
|
|
28794
28820
|
* },
|
|
28795
28821
|
* ],
|
|
28796
28822
|
* });
|
|
28823
|
+
* ```
|
|
28797
28824
|
*
|
|
28798
28825
|
* @publicApi
|
|
28799
28826
|
*/
|
|
@@ -29708,6 +29735,11 @@ function getProviderImportsContainer(injector) {
|
|
|
29708
29735
|
if (defTypeRef === null) {
|
|
29709
29736
|
return null;
|
|
29710
29737
|
}
|
|
29738
|
+
// In standalone applications, the root environment injector created by bootstrapApplication
|
|
29739
|
+
// may have no associated "instance".
|
|
29740
|
+
if (defTypeRef.instance === null) {
|
|
29741
|
+
return null;
|
|
29742
|
+
}
|
|
29711
29743
|
return defTypeRef.instance.constructor;
|
|
29712
29744
|
}
|
|
29713
29745
|
/**
|
|
@@ -29889,12 +29921,25 @@ function walkProviderTreeToDiscoverImportPaths(providerToPath, visitedContainers
|
|
|
29889
29921
|
* @returns an array of objects representing the providers of the given injector
|
|
29890
29922
|
*/
|
|
29891
29923
|
function getEnvironmentInjectorProviders(injector) {
|
|
29924
|
+
const providerRecords = getFrameworkDIDebugData().resolverToProviders.get(injector) ?? [];
|
|
29925
|
+
// platform injector has no provider imports container so can we skip trying to
|
|
29926
|
+
// find import paths
|
|
29927
|
+
if (isPlatformInjector(injector)) {
|
|
29928
|
+
return providerRecords;
|
|
29929
|
+
}
|
|
29892
29930
|
const providerImportsContainer = getProviderImportsContainer(injector);
|
|
29893
29931
|
if (providerImportsContainer === null) {
|
|
29932
|
+
// There is a special case where the bootstrapped component does not
|
|
29933
|
+
// import any NgModules. In this case the environment injector connected to
|
|
29934
|
+
// that component is the root injector, which does not have a provider imports
|
|
29935
|
+
// container (and thus no concept of module import paths). Therefore we simply
|
|
29936
|
+
// return the provider records as is.
|
|
29937
|
+
if (isRootInjector(injector)) {
|
|
29938
|
+
return providerRecords;
|
|
29939
|
+
}
|
|
29894
29940
|
throwError('Could not determine where injector providers were configured.');
|
|
29895
29941
|
}
|
|
29896
29942
|
const providerToPath = getProviderImportPaths(providerImportsContainer);
|
|
29897
|
-
const providerRecords = getFrameworkDIDebugData().resolverToProviders.get(injector) ?? [];
|
|
29898
29943
|
return providerRecords.map(providerRecord => {
|
|
29899
29944
|
let importPath = providerToPath.get(providerRecord.provider) ?? [providerImportsContainer];
|
|
29900
29945
|
const def = getComponentDef(providerImportsContainer);
|
|
@@ -29907,6 +29952,12 @@ function getEnvironmentInjectorProviders(injector) {
|
|
|
29907
29952
|
return { ...providerRecord, importPath };
|
|
29908
29953
|
});
|
|
29909
29954
|
}
|
|
29955
|
+
function isPlatformInjector(injector) {
|
|
29956
|
+
return injector instanceof R3Injector && injector.scopes.has('platform');
|
|
29957
|
+
}
|
|
29958
|
+
function isRootInjector(injector) {
|
|
29959
|
+
return injector instanceof R3Injector && injector.scopes.has('root');
|
|
29960
|
+
}
|
|
29910
29961
|
/**
|
|
29911
29962
|
* Gets the providers configured on an injector.
|
|
29912
29963
|
*
|
|
@@ -30528,6 +30579,7 @@ function isBoundToModule(cf) {
|
|
|
30528
30579
|
/**
|
|
30529
30580
|
* A token for third-party components that can register themselves with NgProbe.
|
|
30530
30581
|
*
|
|
30582
|
+
* @deprecated
|
|
30531
30583
|
* @publicApi
|
|
30532
30584
|
*/
|
|
30533
30585
|
class NgProbeToken {
|
|
@@ -30564,10 +30616,10 @@ function createOrReusePlatformInjector(providers = []) {
|
|
|
30564
30616
|
// is already bootstrapped and no additional actions are required.
|
|
30565
30617
|
if (_platformInjector)
|
|
30566
30618
|
return _platformInjector;
|
|
30619
|
+
publishDefaultGlobalUtils();
|
|
30567
30620
|
// Otherwise, setup a new platform injector and run platform initializers.
|
|
30568
30621
|
const injector = createPlatformInjector(providers);
|
|
30569
30622
|
_platformInjector = injector;
|
|
30570
|
-
publishDefaultGlobalUtils();
|
|
30571
30623
|
publishSignalConfiguration();
|
|
30572
30624
|
runPlatformInitializers(injector);
|
|
30573
30625
|
return injector;
|
|
@@ -31362,7 +31414,7 @@ function internalProvideZoneChangeDetection(ngZoneFactory) {
|
|
|
31362
31414
|
* `BootstrapOptions` instead.
|
|
31363
31415
|
*
|
|
31364
31416
|
* @usageNotes
|
|
31365
|
-
* ```typescript
|
|
31417
|
+
* ```typescript
|
|
31366
31418
|
* bootstrapApplication(MyApp, {providers: [
|
|
31367
31419
|
* provideZoneChangeDetection({eventCoalescing: true}),
|
|
31368
31420
|
* ]});
|
|
@@ -31753,6 +31805,7 @@ class DebugElement extends DebugNode {
|
|
|
31753
31805
|
/**
|
|
31754
31806
|
* A map of attribute names to attribute values for an element.
|
|
31755
31807
|
*/
|
|
31808
|
+
// TODO: replace null by undefined in the return type
|
|
31756
31809
|
get attributes() {
|
|
31757
31810
|
const attributes = {};
|
|
31758
31811
|
const element = this.nativeElement;
|
|
@@ -31798,16 +31851,11 @@ class DebugElement extends DebugNode {
|
|
|
31798
31851
|
}
|
|
31799
31852
|
/**
|
|
31800
31853
|
* The inline styles of the DOM element.
|
|
31801
|
-
*
|
|
31802
|
-
* Will be `null` if there is no `style` property on the underlying DOM element.
|
|
31803
|
-
*
|
|
31804
|
-
* @see [ElementCSSInlineStyle](https://developer.mozilla.org/en-US/docs/Web/API/ElementCSSInlineStyle/style)
|
|
31805
31854
|
*/
|
|
31855
|
+
// TODO: replace null by undefined in the return type
|
|
31806
31856
|
get styles() {
|
|
31807
|
-
|
|
31808
|
-
|
|
31809
|
-
}
|
|
31810
|
-
return {};
|
|
31857
|
+
const element = this.nativeElement;
|
|
31858
|
+
return (element?.style ?? {});
|
|
31811
31859
|
}
|
|
31812
31860
|
/**
|
|
31813
31861
|
* A map containing the class names on the element as keys.
|
|
@@ -33783,6 +33831,42 @@ function setAlternateWeakRefImpl(impl) {
|
|
|
33783
33831
|
// TODO: remove this function
|
|
33784
33832
|
}
|
|
33785
33833
|
|
|
33834
|
+
/**
|
|
33835
|
+
* Retrieves all defer blocks in a given LView.
|
|
33836
|
+
*
|
|
33837
|
+
* @param lView lView with defer blocks
|
|
33838
|
+
* @param deferBlocks defer block aggregator array
|
|
33839
|
+
*/
|
|
33840
|
+
function getDeferBlocks(lView, deferBlocks) {
|
|
33841
|
+
const tView = lView[TVIEW];
|
|
33842
|
+
for (let i = HEADER_OFFSET; i < tView.bindingStartIndex; i++) {
|
|
33843
|
+
if (isLContainer(lView[i])) {
|
|
33844
|
+
const lContainer = lView[i];
|
|
33845
|
+
// An LContainer may represent an instance of a defer block, in which case
|
|
33846
|
+
// we store it as a result. Otherwise, keep iterating over LContainer views and
|
|
33847
|
+
// look for defer blocks.
|
|
33848
|
+
const isLast = i === tView.bindingStartIndex - 1;
|
|
33849
|
+
if (!isLast) {
|
|
33850
|
+
const tNode = tView.data[i];
|
|
33851
|
+
const tDetails = getTDeferBlockDetails(tView, tNode);
|
|
33852
|
+
if (isTDeferBlockDetails(tDetails)) {
|
|
33853
|
+
deferBlocks.push({ lContainer, lView, tNode, tDetails });
|
|
33854
|
+
// This LContainer represents a defer block, so we exit
|
|
33855
|
+
// this iteration and don't inspect views in this LContainer.
|
|
33856
|
+
continue;
|
|
33857
|
+
}
|
|
33858
|
+
}
|
|
33859
|
+
for (let i = CONTAINER_HEADER_OFFSET; i < lContainer.length; i++) {
|
|
33860
|
+
getDeferBlocks(lContainer[i], deferBlocks);
|
|
33861
|
+
}
|
|
33862
|
+
}
|
|
33863
|
+
else if (isLView(lView[i])) {
|
|
33864
|
+
// This is a component, enter the `getDeferBlocks` recursively.
|
|
33865
|
+
getDeferBlocks(lView[i], deferBlocks);
|
|
33866
|
+
}
|
|
33867
|
+
}
|
|
33868
|
+
}
|
|
33869
|
+
|
|
33786
33870
|
/**
|
|
33787
33871
|
* A collection that tracks all serialized views (`ngh` DOM annotations)
|
|
33788
33872
|
* to avoid duplication. An attempt to add a duplicate view results in the
|
|
@@ -34319,7 +34403,6 @@ function printHydrationStats(injector) {
|
|
|
34319
34403
|
const message = `Angular hydrated ${ngDevMode.hydratedComponents} component(s) ` +
|
|
34320
34404
|
`and ${ngDevMode.hydratedNodes} node(s), ` +
|
|
34321
34405
|
`${ngDevMode.componentsSkippedHydration} component(s) were skipped. ` +
|
|
34322
|
-
`Note: this feature is in Developer Preview mode. ` +
|
|
34323
34406
|
`Learn more at https://angular.io/guide/hydration.`;
|
|
34324
34407
|
// tslint:disable-next-line:no-console
|
|
34325
34408
|
console.log(message);
|
|
@@ -34376,7 +34459,7 @@ function withDomHydration() {
|
|
|
34376
34459
|
}
|
|
34377
34460
|
}
|
|
34378
34461
|
if (isEnabled) {
|
|
34379
|
-
|
|
34462
|
+
performance.mark('mark_use_counter', { detail: { feature: 'NgHydration' } });
|
|
34380
34463
|
}
|
|
34381
34464
|
return isEnabled;
|
|
34382
34465
|
},
|
|
@@ -34764,7 +34847,7 @@ if (typeof ngDevMode !== 'undefined' && ngDevMode) {
|
|
|
34764
34847
|
// This helper is to give a reasonable error message to people upgrading to v9 that have not yet
|
|
34765
34848
|
// installed `@angular/localize` in their app.
|
|
34766
34849
|
// tslint:disable-next-line: no-toplevel-property-access
|
|
34767
|
-
_global.$localize
|
|
34850
|
+
_global.$localize ??= function () {
|
|
34768
34851
|
throw new Error('It looks like your application or one of its dependencies is using i18n.\n' +
|
|
34769
34852
|
'Angular 9 introduced a global `$localize()` function that needs to be loaded.\n' +
|
|
34770
34853
|
'Please run `ng add @angular/localize` from the Angular CLI.\n' +
|
|
@@ -34790,5 +34873,5 @@ if (typeof ngDevMode !== 'undefined' && ngDevMode) {
|
|
|
34790
34873
|
* Generated bundle index. Do not edit.
|
|
34791
34874
|
*/
|
|
34792
34875
|
|
|
34793
|
-
export { ANIMATION_MODULE_TYPE, APP_BOOTSTRAP_LISTENER, APP_ID, APP_INITIALIZER, AfterRenderPhase, ApplicationInitStatus, ApplicationModule, ApplicationRef, Attribute, COMPILER_OPTIONS, CSP_NONCE, CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, ChangeDetectorRef, Compiler, CompilerFactory, Component, ComponentFactory$1 as ComponentFactory, ComponentFactoryResolver$1 as ComponentFactoryResolver, ComponentRef$1 as ComponentRef, ContentChild, ContentChildren, DEFAULT_CURRENCY_CODE, DebugElement, DebugEventListener, DebugNode, DefaultIterableDiffer, DestroyRef, Directive, ENVIRONMENT_INITIALIZER, ElementRef, EmbeddedViewRef, EnvironmentInjector, ErrorHandler, EventEmitter, Host, HostBinding, HostListener, INJECTOR, Inject, InjectFlags, Injectable, InjectionToken, Injector, Input, IterableDiffers, KeyValueDiffers, LOCALE_ID, MissingTranslationStrategy, ModuleWithComponentFactories, NO_ERRORS_SCHEMA, NgModule, NgModuleFactory$1 as NgModuleFactory, NgModuleRef$1 as NgModuleRef, NgProbeToken, NgZone, Optional, Output, PACKAGE_ROOT_URL, PLATFORM_ID, PLATFORM_INITIALIZER, Pipe, PlatformRef, Query, QueryList, Renderer2, RendererFactory2, RendererStyleFlags2, Sanitizer, SecurityContext, Self, SimpleChange, SkipSelf, TRANSLATIONS, TRANSLATIONS_FORMAT, TemplateRef, Testability, TestabilityRegistry, TransferState, Type, VERSION, Version, ViewChild, ViewChildren, ViewContainerRef, ViewEncapsulation$1 as ViewEncapsulation, ViewRef, afterNextRender, afterRender, asNativeElements, assertInInjectionContext, assertNotInReactiveContext, assertPlatform, booleanAttribute, computed, createComponent, createEnvironmentInjector, createNgModule, createNgModuleRef, createPlatform, createPlatformFactory, defineInjectable, destroyPlatform, effect, enableProdMode, forwardRef, getDebugNode, getModuleFactory, getNgModuleById, getPlatform, importProvidersFrom, inject, isDevMode, isSignal, isStandalone, makeEnvironmentProviders, makeStateKey, mergeApplicationConfig, numberAttribute, platformCore, provideZoneChangeDetection, reflectComponentType, resolveForwardRef, runInInjectionContext, setTestabilityGetter, signal, untracked, ALLOW_MULTIPLE_PLATFORMS as ɵALLOW_MULTIPLE_PLATFORMS, AfterRenderEventManager as ɵAfterRenderEventManager, CONTAINER_HEADER_OFFSET as ɵCONTAINER_HEADER_OFFSET, ComponentFactory$1 as ɵComponentFactory, Console as ɵConsole, DEFAULT_LOCALE_ID as ɵDEFAULT_LOCALE_ID, DEFER_BLOCK_CONFIG as ɵDEFER_BLOCK_CONFIG, DEFER_BLOCK_DEPENDENCY_INTERCEPTOR as ɵDEFER_BLOCK_DEPENDENCY_INTERCEPTOR, DeferBlockBehavior as ɵDeferBlockBehavior, DeferBlockState as ɵDeferBlockState, ENABLED_SSR_FEATURES as ɵENABLED_SSR_FEATURES, EffectScheduler as ɵEffectScheduler, IMAGE_CONFIG as ɵIMAGE_CONFIG, IMAGE_CONFIG_DEFAULTS as ɵIMAGE_CONFIG_DEFAULTS, INJECTOR_SCOPE as ɵINJECTOR_SCOPE, IS_HYDRATION_DOM_REUSE_ENABLED as ɵIS_HYDRATION_DOM_REUSE_ENABLED, InitialRenderPendingTasks as ɵInitialRenderPendingTasks, LContext as ɵLContext, LifecycleHooksFeature as ɵLifecycleHooksFeature, LocaleDataIndex as ɵLocaleDataIndex, NG_COMP_DEF as ɵNG_COMP_DEF, NG_DIR_DEF as ɵNG_DIR_DEF, NG_ELEMENT_ID as ɵNG_ELEMENT_ID, NG_INJ_DEF as ɵNG_INJ_DEF, NG_MOD_DEF as ɵNG_MOD_DEF, NG_PIPE_DEF as ɵNG_PIPE_DEF, NG_PROV_DEF as ɵNG_PROV_DEF, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR as ɵNOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR, NO_CHANGE as ɵNO_CHANGE, NgModuleFactory as ɵNgModuleFactory, NoopNgZone as ɵNoopNgZone, ReflectionCapabilities as ɵReflectionCapabilities, ComponentFactory as ɵRender3ComponentFactory, ComponentRef as ɵRender3ComponentRef, NgModuleRef as ɵRender3NgModuleRef, RuntimeError as ɵRuntimeError, SSR_CONTENT_INTEGRITY_MARKER as ɵSSR_CONTENT_INTEGRITY_MARKER, TESTABILITY as ɵTESTABILITY, TESTABILITY_GETTER as ɵTESTABILITY_GETTER, USE_RUNTIME_DEPS_TRACKER_FOR_JIT as ɵUSE_RUNTIME_DEPS_TRACKER_FOR_JIT, ViewRef$1 as ɵViewRef, XSS_SECURITY_URL as ɵXSS_SECURITY_URL, ZoneAwareQueueingScheduler as ɵZoneAwareQueueingScheduler, _sanitizeHtml as ɵ_sanitizeHtml, _sanitizeUrl as ɵ_sanitizeUrl, allowSanitizationBypassAndThrow as ɵallowSanitizationBypassAndThrow, annotateForHydration as ɵannotateForHydration, bypassSanitizationTrustHtml as ɵbypassSanitizationTrustHtml, bypassSanitizationTrustResourceUrl as ɵbypassSanitizationTrustResourceUrl, bypassSanitizationTrustScript as ɵbypassSanitizationTrustScript, bypassSanitizationTrustStyle as ɵbypassSanitizationTrustStyle, bypassSanitizationTrustUrl as ɵbypassSanitizationTrustUrl, clearResolutionOfComponentResourcesQueue as ɵclearResolutionOfComponentResourcesQueue, compileComponent as ɵcompileComponent, compileDirective as ɵcompileDirective, compileNgModule as ɵcompileNgModule, compileNgModuleDefs as ɵcompileNgModuleDefs, compileNgModuleFactory as ɵcompileNgModuleFactory, compilePipe as ɵcompilePipe, convertToBitFlags as ɵconvertToBitFlags, createInjector as ɵcreateInjector, defaultIterableDiffers as ɵdefaultIterableDiffers, defaultKeyValueDiffers as ɵdefaultKeyValueDiffers, depsTracker as ɵdepsTracker, detectChanges as ɵdetectChanges, devModeEqual as ɵdevModeEqual, findLocaleData as ɵfindLocaleData, flushModuleScopingQueueAsMuchAsPossible as ɵflushModuleScopingQueueAsMuchAsPossible, formatRuntimeError as ɵformatRuntimeError, generateStandaloneInDeclarationsError as ɵgenerateStandaloneInDeclarationsError, getAsyncClassMetadata as ɵgetAsyncClassMetadata, getDebugNode as ɵgetDebugNode, getDeferBlocks as ɵgetDeferBlocks, getDirectives as ɵgetDirectives, getHostElement as ɵgetHostElement, getInjectableDef as ɵgetInjectableDef, getLContext as ɵgetLContext, getLocaleCurrencyCode as ɵgetLocaleCurrencyCode, getLocalePluralCase as ɵgetLocalePluralCase, getSanitizationBypassType as ɵgetSanitizationBypassType, ɵgetUnknownElementStrictMode, ɵgetUnknownPropertyStrictMode, _global as ɵglobal, injectChangeDetectorRef as ɵinjectChangeDetectorRef, internalCreateApplication as ɵinternalCreateApplication, isBoundToModule as ɵisBoundToModule, isComponentDefPendingResolution as ɵisComponentDefPendingResolution, isEnvironmentProviders as ɵisEnvironmentProviders, isInjectable as ɵisInjectable, isNgModule as ɵisNgModule, isPromise as ɵisPromise, isSubscribable as ɵisSubscribable, noSideEffects as ɵnoSideEffects, patchComponentDefWithScope as ɵpatchComponentDefWithScope, publishDefaultGlobalUtils$1 as ɵpublishDefaultGlobalUtils, publishGlobalUtil as ɵpublishGlobalUtil, registerLocaleData as ɵregisterLocaleData, renderDeferBlockState as ɵrenderDeferBlockState, resetCompiledComponents as ɵresetCompiledComponents, resetJitOptions as ɵresetJitOptions, resolveComponentResources as ɵresolveComponentResources, restoreComponentResolutionQueue as ɵrestoreComponentResolutionQueue, setAllowDuplicateNgModuleIdsForTest as ɵsetAllowDuplicateNgModuleIdsForTest, setAlternateWeakRefImpl as ɵsetAlternateWeakRefImpl, ɵsetClassDebugInfo, setClassMetadata as ɵsetClassMetadata, setClassMetadataAsync as ɵsetClassMetadataAsync, setCurrentInjector as ɵsetCurrentInjector, setDocument as ɵsetDocument, setInjectorProfilerContext as ɵsetInjectorProfilerContext, setLocaleId as ɵsetLocaleId, ɵsetUnknownElementStrictMode, ɵsetUnknownPropertyStrictMode, store as ɵstore, stringify as ɵstringify, transitiveScopesFor as ɵtransitiveScopesFor, triggerResourceLoading as ɵtriggerResourceLoading, truncateMiddle as ɵtruncateMiddle, unregisterAllLocaleData as ɵunregisterLocaleData, unwrapSafeValue as ɵunwrapSafeValue, whenStable as ɵwhenStable, withDomHydration as ɵwithDomHydration, ɵɵCopyDefinitionFeature, FactoryTarget as ɵɵFactoryTarget, ɵɵHostDirectivesFeature, ɵɵInheritDefinitionFeature, ɵɵInputTransformsFeature, ɵɵNgOnChangesFeature, ɵɵProvidersFeature, ɵɵStandaloneFeature, ɵɵadvance, ɵɵattribute, ɵɵattributeInterpolate1, ɵɵattributeInterpolate2, ɵɵattributeInterpolate3, ɵɵattributeInterpolate4, ɵɵattributeInterpolate5, ɵɵattributeInterpolate6, ɵɵattributeInterpolate7, ɵɵattributeInterpolate8, ɵɵattributeInterpolateV, ɵɵclassMap, ɵɵclassMapInterpolate1, ɵɵclassMapInterpolate2, ɵɵclassMapInterpolate3, ɵɵclassMapInterpolate4, ɵɵclassMapInterpolate5, ɵɵclassMapInterpolate6, ɵɵclassMapInterpolate7, ɵɵclassMapInterpolate8, ɵɵclassMapInterpolateV, ɵɵclassProp, ɵɵcomponentInstance, ɵɵconditional, ɵɵcontentQuery, ɵɵdefer, ɵɵdeferEnableTimerScheduling, ɵɵdeferOnHover, ɵɵdeferOnIdle, ɵɵdeferOnImmediate, ɵɵdeferOnInteraction, ɵɵdeferOnTimer, ɵɵdeferOnViewport, ɵɵdeferPrefetchOnHover, ɵɵdeferPrefetchOnIdle, ɵɵdeferPrefetchOnImmediate, ɵɵdeferPrefetchOnInteraction, ɵɵdeferPrefetchOnTimer, ɵɵdeferPrefetchOnViewport, ɵɵdeferPrefetchWhen, ɵɵdeferWhen, ɵɵdefineComponent, ɵɵdefineDirective, ɵɵdefineInjectable, ɵɵdefineInjector, ɵɵdefineNgModule, ɵɵdefinePipe, ɵɵdirectiveInject, ɵɵdisableBindings, ɵɵelement, ɵɵelementContainer, ɵɵelementContainerEnd, ɵɵelementContainerStart, ɵɵelementEnd, ɵɵelementStart, ɵɵenableBindings, ɵɵgetComponentDepsFactory, ɵɵgetCurrentView, ɵɵgetInheritedFactory, ɵɵhostProperty, ɵɵi18n, ɵɵi18nApply, ɵɵi18nAttributes, ɵɵi18nEnd, ɵɵi18nExp, ɵɵi18nPostprocess, ɵɵi18nStart, ɵɵinject, ɵɵinjectAttribute, ɵɵinvalidFactory, ɵɵinvalidFactoryDep, ɵɵlistener, ɵɵloadQuery, ɵɵnamespaceHTML, ɵɵnamespaceMathML, ɵɵnamespaceSVG, ɵɵnextContext, ɵɵngDeclareClassMetadata, ɵɵngDeclareComponent, ɵɵngDeclareDirective, ɵɵngDeclareFactory, ɵɵngDeclareInjectable, ɵɵngDeclareInjector, ɵɵngDeclareNgModule, ɵɵngDeclarePipe, ɵɵpipe, ɵɵpipeBind1, ɵɵpipeBind2, ɵɵpipeBind3, ɵɵpipeBind4, ɵɵpipeBindV, ɵɵprojection, ɵɵprojectionDef, ɵɵproperty, ɵɵpropertyInterpolate, ɵɵpropertyInterpolate1, ɵɵpropertyInterpolate2, ɵɵpropertyInterpolate3, ɵɵpropertyInterpolate4, ɵɵpropertyInterpolate5, ɵɵpropertyInterpolate6, ɵɵpropertyInterpolate7, ɵɵpropertyInterpolate8, ɵɵpropertyInterpolateV, ɵɵpureFunction0, ɵɵpureFunction1, ɵɵpureFunction2, ɵɵpureFunction3, ɵɵpureFunction4, ɵɵpureFunction5, ɵɵpureFunction6, ɵɵpureFunction7, ɵɵpureFunction8, ɵɵpureFunctionV, ɵɵqueryRefresh, ɵɵreference, registerNgModuleType as ɵɵregisterNgModuleType, ɵɵrepeater, ɵɵrepeaterCreate, ɵɵrepeaterTrackByIdentity, ɵɵrepeaterTrackByIndex, ɵɵresetView, ɵɵresolveBody, ɵɵresolveDocument, ɵɵresolveWindow, ɵɵrestoreView, ɵɵsanitizeHtml, ɵɵsanitizeResourceUrl, ɵɵsanitizeScript, ɵɵsanitizeStyle, ɵɵsanitizeUrl, ɵɵsanitizeUrlOrResourceUrl, ɵɵsetComponentScope, ɵɵsetNgModuleScope, ɵɵstyleMap, ɵɵstyleMapInterpolate1, ɵɵstyleMapInterpolate2, ɵɵstyleMapInterpolate3, ɵɵstyleMapInterpolate4, ɵɵstyleMapInterpolate5, ɵɵstyleMapInterpolate6, ɵɵstyleMapInterpolate7, ɵɵstyleMapInterpolate8, ɵɵstyleMapInterpolateV, ɵɵstyleProp, ɵɵstylePropInterpolate1, ɵɵstylePropInterpolate2, ɵɵstylePropInterpolate3, ɵɵstylePropInterpolate4, ɵɵstylePropInterpolate5, ɵɵstylePropInterpolate6, ɵɵstylePropInterpolate7, ɵɵstylePropInterpolate8, ɵɵstylePropInterpolateV, ɵɵsyntheticHostListener, ɵɵsyntheticHostProperty, ɵɵtemplate, ɵɵtemplateRefExtractor, ɵɵtext, ɵɵtextInterpolate, ɵɵtextInterpolate1, ɵɵtextInterpolate2, ɵɵtextInterpolate3, ɵɵtextInterpolate4, ɵɵtextInterpolate5, ɵɵtextInterpolate6, ɵɵtextInterpolate7, ɵɵtextInterpolate8, ɵɵtextInterpolateV, ɵɵtrustConstantHtml, ɵɵtrustConstantResourceUrl, ɵɵvalidateIframeAttribute, ɵɵviewQuery };
|
|
34876
|
+
export { ANIMATION_MODULE_TYPE, APP_BOOTSTRAP_LISTENER, APP_ID, APP_INITIALIZER, AfterRenderPhase, ApplicationInitStatus, ApplicationModule, ApplicationRef, Attribute, COMPILER_OPTIONS, CSP_NONCE, CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, ChangeDetectorRef, Compiler, CompilerFactory, Component, ComponentFactory$1 as ComponentFactory, ComponentFactoryResolver$1 as ComponentFactoryResolver, ComponentRef$1 as ComponentRef, ContentChild, ContentChildren, DEFAULT_CURRENCY_CODE, DebugElement, DebugEventListener, DebugNode, DefaultIterableDiffer, DestroyRef, Directive, ENVIRONMENT_INITIALIZER, ElementRef, EmbeddedViewRef, EnvironmentInjector, ErrorHandler, EventEmitter, Host, HostBinding, HostListener, INJECTOR, Inject, InjectFlags, Injectable, InjectionToken, Injector, Input, IterableDiffers, KeyValueDiffers, LOCALE_ID, MissingTranslationStrategy, ModuleWithComponentFactories, NO_ERRORS_SCHEMA, NgModule, NgModuleFactory$1 as NgModuleFactory, NgModuleRef$1 as NgModuleRef, NgProbeToken, NgZone, Optional, Output, PACKAGE_ROOT_URL, PLATFORM_ID, PLATFORM_INITIALIZER, Pipe, PlatformRef, Query, QueryList, Renderer2, RendererFactory2, RendererStyleFlags2, Sanitizer, SecurityContext, Self, SimpleChange, SkipSelf, TRANSLATIONS, TRANSLATIONS_FORMAT, TemplateRef, Testability, TestabilityRegistry, TransferState, Type, VERSION, Version, ViewChild, ViewChildren, ViewContainerRef, ViewEncapsulation$1 as ViewEncapsulation, ViewRef, afterNextRender, afterRender, asNativeElements, assertInInjectionContext, assertNotInReactiveContext, assertPlatform, booleanAttribute, computed, createComponent, createEnvironmentInjector, createNgModule, createNgModuleRef, createPlatform, createPlatformFactory, defineInjectable, destroyPlatform, effect, enableProdMode, forwardRef, getDebugNode, getModuleFactory, getNgModuleById, getPlatform, importProvidersFrom, inject, isDevMode, isSignal, isStandalone, makeEnvironmentProviders, makeStateKey, mergeApplicationConfig, numberAttribute, platformCore, provideZoneChangeDetection, reflectComponentType, resolveForwardRef, runInInjectionContext, setTestabilityGetter, signal, untracked, ALLOW_MULTIPLE_PLATFORMS as ɵALLOW_MULTIPLE_PLATFORMS, AfterRenderEventManager as ɵAfterRenderEventManager, CONTAINER_HEADER_OFFSET as ɵCONTAINER_HEADER_OFFSET, ComponentFactory$1 as ɵComponentFactory, Console as ɵConsole, DEFAULT_LOCALE_ID as ɵDEFAULT_LOCALE_ID, DEFER_BLOCK_CONFIG as ɵDEFER_BLOCK_CONFIG, DEFER_BLOCK_DEPENDENCY_INTERCEPTOR as ɵDEFER_BLOCK_DEPENDENCY_INTERCEPTOR, DeferBlockBehavior as ɵDeferBlockBehavior, DeferBlockState as ɵDeferBlockState, EffectScheduler as ɵEffectScheduler, IMAGE_CONFIG as ɵIMAGE_CONFIG, IMAGE_CONFIG_DEFAULTS as ɵIMAGE_CONFIG_DEFAULTS, INJECTOR_SCOPE as ɵINJECTOR_SCOPE, IS_HYDRATION_DOM_REUSE_ENABLED as ɵIS_HYDRATION_DOM_REUSE_ENABLED, InitialRenderPendingTasks as ɵInitialRenderPendingTasks, LContext as ɵLContext, LifecycleHooksFeature as ɵLifecycleHooksFeature, LocaleDataIndex as ɵLocaleDataIndex, NG_COMP_DEF as ɵNG_COMP_DEF, NG_DIR_DEF as ɵNG_DIR_DEF, NG_ELEMENT_ID as ɵNG_ELEMENT_ID, NG_INJ_DEF as ɵNG_INJ_DEF, NG_MOD_DEF as ɵNG_MOD_DEF, NG_PIPE_DEF as ɵNG_PIPE_DEF, NG_PROV_DEF as ɵNG_PROV_DEF, NOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR as ɵNOT_FOUND_CHECK_ONLY_ELEMENT_INJECTOR, NO_CHANGE as ɵNO_CHANGE, NgModuleFactory as ɵNgModuleFactory, NoopNgZone as ɵNoopNgZone, ReflectionCapabilities as ɵReflectionCapabilities, ComponentFactory as ɵRender3ComponentFactory, ComponentRef as ɵRender3ComponentRef, NgModuleRef as ɵRender3NgModuleRef, RuntimeError as ɵRuntimeError, SSR_CONTENT_INTEGRITY_MARKER as ɵSSR_CONTENT_INTEGRITY_MARKER, TESTABILITY as ɵTESTABILITY, TESTABILITY_GETTER as ɵTESTABILITY_GETTER, USE_RUNTIME_DEPS_TRACKER_FOR_JIT as ɵUSE_RUNTIME_DEPS_TRACKER_FOR_JIT, ViewRef$1 as ɵViewRef, XSS_SECURITY_URL as ɵXSS_SECURITY_URL, ZoneAwareQueueingScheduler as ɵZoneAwareQueueingScheduler, _sanitizeHtml as ɵ_sanitizeHtml, _sanitizeUrl as ɵ_sanitizeUrl, allowSanitizationBypassAndThrow as ɵallowSanitizationBypassAndThrow, annotateForHydration as ɵannotateForHydration, bypassSanitizationTrustHtml as ɵbypassSanitizationTrustHtml, bypassSanitizationTrustResourceUrl as ɵbypassSanitizationTrustResourceUrl, bypassSanitizationTrustScript as ɵbypassSanitizationTrustScript, bypassSanitizationTrustStyle as ɵbypassSanitizationTrustStyle, bypassSanitizationTrustUrl as ɵbypassSanitizationTrustUrl, clearResolutionOfComponentResourcesQueue as ɵclearResolutionOfComponentResourcesQueue, compileComponent as ɵcompileComponent, compileDirective as ɵcompileDirective, compileNgModule as ɵcompileNgModule, compileNgModuleDefs as ɵcompileNgModuleDefs, compileNgModuleFactory as ɵcompileNgModuleFactory, compilePipe as ɵcompilePipe, convertToBitFlags as ɵconvertToBitFlags, createInjector as ɵcreateInjector, defaultIterableDiffers as ɵdefaultIterableDiffers, defaultKeyValueDiffers as ɵdefaultKeyValueDiffers, depsTracker as ɵdepsTracker, detectChanges as ɵdetectChanges, devModeEqual as ɵdevModeEqual, findLocaleData as ɵfindLocaleData, flushModuleScopingQueueAsMuchAsPossible as ɵflushModuleScopingQueueAsMuchAsPossible, formatRuntimeError as ɵformatRuntimeError, generateStandaloneInDeclarationsError as ɵgenerateStandaloneInDeclarationsError, getAsyncClassMetadata as ɵgetAsyncClassMetadata, getDebugNode as ɵgetDebugNode, getDeferBlocks as ɵgetDeferBlocks, getDirectives as ɵgetDirectives, getHostElement as ɵgetHostElement, getInjectableDef as ɵgetInjectableDef, getLContext as ɵgetLContext, getLocaleCurrencyCode as ɵgetLocaleCurrencyCode, getLocalePluralCase as ɵgetLocalePluralCase, getSanitizationBypassType as ɵgetSanitizationBypassType, ɵgetUnknownElementStrictMode, ɵgetUnknownPropertyStrictMode, _global as ɵglobal, injectChangeDetectorRef as ɵinjectChangeDetectorRef, internalAfterNextRender as ɵinternalAfterNextRender, internalCreateApplication as ɵinternalCreateApplication, isBoundToModule as ɵisBoundToModule, isComponentDefPendingResolution as ɵisComponentDefPendingResolution, isEnvironmentProviders as ɵisEnvironmentProviders, isInjectable as ɵisInjectable, isNgModule as ɵisNgModule, isPromise as ɵisPromise, isSubscribable as ɵisSubscribable, noSideEffects as ɵnoSideEffects, patchComponentDefWithScope as ɵpatchComponentDefWithScope, publishDefaultGlobalUtils$1 as ɵpublishDefaultGlobalUtils, publishGlobalUtil as ɵpublishGlobalUtil, registerLocaleData as ɵregisterLocaleData, renderDeferBlockState as ɵrenderDeferBlockState, resetCompiledComponents as ɵresetCompiledComponents, resetJitOptions as ɵresetJitOptions, resolveComponentResources as ɵresolveComponentResources, restoreComponentResolutionQueue as ɵrestoreComponentResolutionQueue, setAllowDuplicateNgModuleIdsForTest as ɵsetAllowDuplicateNgModuleIdsForTest, setAlternateWeakRefImpl as ɵsetAlternateWeakRefImpl, ɵsetClassDebugInfo, setClassMetadata as ɵsetClassMetadata, setClassMetadataAsync as ɵsetClassMetadataAsync, setCurrentInjector as ɵsetCurrentInjector, setDocument as ɵsetDocument, setInjectorProfilerContext as ɵsetInjectorProfilerContext, setLocaleId as ɵsetLocaleId, ɵsetUnknownElementStrictMode, ɵsetUnknownPropertyStrictMode, store as ɵstore, stringify as ɵstringify, transitiveScopesFor as ɵtransitiveScopesFor, triggerResourceLoading as ɵtriggerResourceLoading, truncateMiddle as ɵtruncateMiddle, unregisterAllLocaleData as ɵunregisterLocaleData, unwrapSafeValue as ɵunwrapSafeValue, whenStable as ɵwhenStable, withDomHydration as ɵwithDomHydration, ɵɵCopyDefinitionFeature, FactoryTarget as ɵɵFactoryTarget, ɵɵHostDirectivesFeature, ɵɵInheritDefinitionFeature, ɵɵInputTransformsFeature, ɵɵNgOnChangesFeature, ɵɵProvidersFeature, ɵɵStandaloneFeature, ɵɵadvance, ɵɵattribute, ɵɵattributeInterpolate1, ɵɵattributeInterpolate2, ɵɵattributeInterpolate3, ɵɵattributeInterpolate4, ɵɵattributeInterpolate5, ɵɵattributeInterpolate6, ɵɵattributeInterpolate7, ɵɵattributeInterpolate8, ɵɵattributeInterpolateV, ɵɵclassMap, ɵɵclassMapInterpolate1, ɵɵclassMapInterpolate2, ɵɵclassMapInterpolate3, ɵɵclassMapInterpolate4, ɵɵclassMapInterpolate5, ɵɵclassMapInterpolate6, ɵɵclassMapInterpolate7, ɵɵclassMapInterpolate8, ɵɵclassMapInterpolateV, ɵɵclassProp, ɵɵcomponentInstance, ɵɵconditional, ɵɵcontentQuery, ɵɵdefer, ɵɵdeferEnableTimerScheduling, ɵɵdeferOnHover, ɵɵdeferOnIdle, ɵɵdeferOnImmediate, ɵɵdeferOnInteraction, ɵɵdeferOnTimer, ɵɵdeferOnViewport, ɵɵdeferPrefetchOnHover, ɵɵdeferPrefetchOnIdle, ɵɵdeferPrefetchOnImmediate, ɵɵdeferPrefetchOnInteraction, ɵɵdeferPrefetchOnTimer, ɵɵdeferPrefetchOnViewport, ɵɵdeferPrefetchWhen, ɵɵdeferWhen, ɵɵdefineComponent, ɵɵdefineDirective, ɵɵdefineInjectable, ɵɵdefineInjector, ɵɵdefineNgModule, ɵɵdefinePipe, ɵɵdirectiveInject, ɵɵdisableBindings, ɵɵelement, ɵɵelementContainer, ɵɵelementContainerEnd, ɵɵelementContainerStart, ɵɵelementEnd, ɵɵelementStart, ɵɵenableBindings, ɵɵgetComponentDepsFactory, ɵɵgetCurrentView, ɵɵgetInheritedFactory, ɵɵhostProperty, ɵɵi18n, ɵɵi18nApply, ɵɵi18nAttributes, ɵɵi18nEnd, ɵɵi18nExp, ɵɵi18nPostprocess, ɵɵi18nStart, ɵɵinject, ɵɵinjectAttribute, ɵɵinvalidFactory, ɵɵinvalidFactoryDep, ɵɵlistener, ɵɵloadQuery, ɵɵnamespaceHTML, ɵɵnamespaceMathML, ɵɵnamespaceSVG, ɵɵnextContext, ɵɵngDeclareClassMetadata, ɵɵngDeclareComponent, ɵɵngDeclareDirective, ɵɵngDeclareFactory, ɵɵngDeclareInjectable, ɵɵngDeclareInjector, ɵɵngDeclareNgModule, ɵɵngDeclarePipe, ɵɵpipe, ɵɵpipeBind1, ɵɵpipeBind2, ɵɵpipeBind3, ɵɵpipeBind4, ɵɵpipeBindV, ɵɵprojection, ɵɵprojectionDef, ɵɵproperty, ɵɵpropertyInterpolate, ɵɵpropertyInterpolate1, ɵɵpropertyInterpolate2, ɵɵpropertyInterpolate3, ɵɵpropertyInterpolate4, ɵɵpropertyInterpolate5, ɵɵpropertyInterpolate6, ɵɵpropertyInterpolate7, ɵɵpropertyInterpolate8, ɵɵpropertyInterpolateV, ɵɵpureFunction0, ɵɵpureFunction1, ɵɵpureFunction2, ɵɵpureFunction3, ɵɵpureFunction4, ɵɵpureFunction5, ɵɵpureFunction6, ɵɵpureFunction7, ɵɵpureFunction8, ɵɵpureFunctionV, ɵɵqueryRefresh, ɵɵreference, registerNgModuleType as ɵɵregisterNgModuleType, ɵɵrepeater, ɵɵrepeaterCreate, ɵɵrepeaterTrackByIdentity, ɵɵrepeaterTrackByIndex, ɵɵresetView, ɵɵresolveBody, ɵɵresolveDocument, ɵɵresolveWindow, ɵɵrestoreView, ɵɵsanitizeHtml, ɵɵsanitizeResourceUrl, ɵɵsanitizeScript, ɵɵsanitizeStyle, ɵɵsanitizeUrl, ɵɵsanitizeUrlOrResourceUrl, ɵɵsetComponentScope, ɵɵsetNgModuleScope, ɵɵstyleMap, ɵɵstyleMapInterpolate1, ɵɵstyleMapInterpolate2, ɵɵstyleMapInterpolate3, ɵɵstyleMapInterpolate4, ɵɵstyleMapInterpolate5, ɵɵstyleMapInterpolate6, ɵɵstyleMapInterpolate7, ɵɵstyleMapInterpolate8, ɵɵstyleMapInterpolateV, ɵɵstyleProp, ɵɵstylePropInterpolate1, ɵɵstylePropInterpolate2, ɵɵstylePropInterpolate3, ɵɵstylePropInterpolate4, ɵɵstylePropInterpolate5, ɵɵstylePropInterpolate6, ɵɵstylePropInterpolate7, ɵɵstylePropInterpolate8, ɵɵstylePropInterpolateV, ɵɵsyntheticHostListener, ɵɵsyntheticHostProperty, ɵɵtemplate, ɵɵtemplateRefExtractor, ɵɵtext, ɵɵtextInterpolate, ɵɵtextInterpolate1, ɵɵtextInterpolate2, ɵɵtextInterpolate3, ɵɵtextInterpolate4, ɵɵtextInterpolate5, ɵɵtextInterpolate6, ɵɵtextInterpolate7, ɵɵtextInterpolate8, ɵɵtextInterpolateV, ɵɵtrustConstantHtml, ɵɵtrustConstantResourceUrl, ɵɵvalidateIframeAttribute, ɵɵviewQuery };
|
|
34794
34877
|
//# sourceMappingURL=core.mjs.map
|