@angular/core 17.3.6 → 17.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/src/change_detection/constants.mjs +2 -2
- package/esm2022/src/render3/after_render_hooks.mjs +2 -4
- package/esm2022/src/render3/component_ref.mjs +1 -1
- package/esm2022/src/render3/util/global_utils.mjs +5 -2
- package/esm2022/src/version.mjs +1 -1
- package/esm2022/testing/src/logger.mjs +3 -3
- package/fesm2022/core.mjs +1634 -1632
- 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 +1 -1
- package/index.d.ts +2 -2
- 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 +1 -1
- package/schematics/migrations/block-template-entities/bundle.js.map +1 -1
- package/schematics/migrations/invalid-two-way-bindings/bundle.js +1 -1
- package/schematics/migrations/invalid-two-way-bindings/bundle.js.map +1 -1
- package/schematics/ng-generate/control-flow-migration/bundle.js +1 -1
- package/schematics/ng-generate/control-flow-migration/bundle.js.map +1 -1
- package/schematics/ng-generate/standalone-migration/bundle.js +22 -15
- package/schematics/ng-generate/standalone-migration/bundle.js.map +2 -2
- package/testing/index.d.ts +1 -1
package/fesm2022/core.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v17.3.
|
|
2
|
+
* @license Angular v17.3.7
|
|
3
3
|
* (c) 2010-2024 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
@@ -1663,7 +1663,7 @@ class NullInjector {
|
|
|
1663
1663
|
* The strategy that the default change detector uses to detect changes.
|
|
1664
1664
|
* When set, takes effect the next time change detection is triggered.
|
|
1665
1665
|
*
|
|
1666
|
-
* @see
|
|
1666
|
+
* @see [Change detection usage](/api/core/ChangeDetectorRef?tab=usage-notes)
|
|
1667
1667
|
*
|
|
1668
1668
|
* @publicApi
|
|
1669
1669
|
*/
|
|
@@ -14504,617 +14504,141 @@ function performanceMarkFeature(feature) {
|
|
|
14504
14504
|
performance?.mark?.('mark_feature_usage', { detail: { feature } });
|
|
14505
14505
|
}
|
|
14506
14506
|
|
|
14507
|
-
|
|
14508
|
-
|
|
14509
|
-
|
|
14510
|
-
|
|
14511
|
-
|
|
14512
|
-
|
|
14513
|
-
|
|
14514
|
-
|
|
14515
|
-
|
|
14516
|
-
|
|
14517
|
-
|
|
14518
|
-
|
|
14519
|
-
|
|
14520
|
-
|
|
14521
|
-
|
|
14522
|
-
|
|
14523
|
-
|
|
14524
|
-
|
|
14525
|
-
|
|
14526
|
-
|
|
14527
|
-
|
|
14528
|
-
|
|
14529
|
-
|
|
14530
|
-
|
|
14531
|
-
|
|
14532
|
-
|
|
14533
|
-
|
|
14534
|
-
|
|
14535
|
-
|
|
14536
|
-
|
|
14537
|
-
|
|
14538
|
-
|
|
14539
|
-
|
|
14540
|
-
|
|
14541
|
-
|
|
14542
|
-
|
|
14543
|
-
|
|
14544
|
-
|
|
14545
|
-
|
|
14546
|
-
|
|
14547
|
-
|
|
14548
|
-
|
|
14549
|
-
|
|
14550
|
-
|
|
14551
|
-
|
|
14552
|
-
|
|
14553
|
-
|
|
14554
|
-
|
|
14555
|
-
|
|
14556
|
-
|
|
14557
|
-
|
|
14558
|
-
|
|
14559
|
-
|
|
14560
|
-
|
|
14561
|
-
|
|
14562
|
-
|
|
14507
|
+
/**
|
|
14508
|
+
* The phase to run an `afterRender` or `afterNextRender` callback in.
|
|
14509
|
+
*
|
|
14510
|
+
* Callbacks in the same phase run in the order they are registered. Phases run in the
|
|
14511
|
+
* following order after each render:
|
|
14512
|
+
*
|
|
14513
|
+
* 1. `AfterRenderPhase.EarlyRead`
|
|
14514
|
+
* 2. `AfterRenderPhase.Write`
|
|
14515
|
+
* 3. `AfterRenderPhase.MixedReadWrite`
|
|
14516
|
+
* 4. `AfterRenderPhase.Read`
|
|
14517
|
+
*
|
|
14518
|
+
* Angular is unable to verify or enforce that phases are used correctly, and instead
|
|
14519
|
+
* relies on each developer to follow the guidelines documented for each value and
|
|
14520
|
+
* carefully choose the appropriate one, refactoring their code if necessary. By doing
|
|
14521
|
+
* so, Angular is better able to minimize the performance degradation associated with
|
|
14522
|
+
* manual DOM access, ensuring the best experience for the end users of your application
|
|
14523
|
+
* or library.
|
|
14524
|
+
*
|
|
14525
|
+
* @developerPreview
|
|
14526
|
+
*/
|
|
14527
|
+
var AfterRenderPhase;
|
|
14528
|
+
(function (AfterRenderPhase) {
|
|
14529
|
+
/**
|
|
14530
|
+
* Use `AfterRenderPhase.EarlyRead` for callbacks that only need to **read** from the
|
|
14531
|
+
* DOM before a subsequent `AfterRenderPhase.Write` callback, for example to perform
|
|
14532
|
+
* custom layout that the browser doesn't natively support. **Never** use this phase
|
|
14533
|
+
* for callbacks that can write to the DOM or when `AfterRenderPhase.Read` is adequate.
|
|
14534
|
+
*
|
|
14535
|
+
* <div class="alert is-important">
|
|
14536
|
+
*
|
|
14537
|
+
* Using this value can degrade performance.
|
|
14538
|
+
* Instead, prefer using built-in browser functionality when possible.
|
|
14539
|
+
*
|
|
14540
|
+
* </div>
|
|
14541
|
+
*/
|
|
14542
|
+
AfterRenderPhase[AfterRenderPhase["EarlyRead"] = 0] = "EarlyRead";
|
|
14543
|
+
/**
|
|
14544
|
+
* Use `AfterRenderPhase.Write` for callbacks that only **write** to the DOM. **Never**
|
|
14545
|
+
* use this phase for callbacks that can read from the DOM.
|
|
14546
|
+
*/
|
|
14547
|
+
AfterRenderPhase[AfterRenderPhase["Write"] = 1] = "Write";
|
|
14548
|
+
/**
|
|
14549
|
+
* Use `AfterRenderPhase.MixedReadWrite` for callbacks that read from or write to the
|
|
14550
|
+
* DOM, that haven't been refactored to use a different phase. **Never** use this phase
|
|
14551
|
+
* for callbacks that can use a different phase instead.
|
|
14552
|
+
*
|
|
14553
|
+
* <div class="alert is-critical">
|
|
14554
|
+
*
|
|
14555
|
+
* Using this value can **significantly** degrade performance.
|
|
14556
|
+
* Instead, prefer refactoring into multiple callbacks using a more specific phase.
|
|
14557
|
+
*
|
|
14558
|
+
* </div>
|
|
14559
|
+
*/
|
|
14560
|
+
AfterRenderPhase[AfterRenderPhase["MixedReadWrite"] = 2] = "MixedReadWrite";
|
|
14561
|
+
/**
|
|
14562
|
+
* Use `AfterRenderPhase.Read` for callbacks that only **read** from the DOM. **Never**
|
|
14563
|
+
* use this phase for callbacks that can write to the DOM.
|
|
14564
|
+
*/
|
|
14565
|
+
AfterRenderPhase[AfterRenderPhase["Read"] = 3] = "Read";
|
|
14566
|
+
})(AfterRenderPhase || (AfterRenderPhase = {}));
|
|
14567
|
+
/** `AfterRenderRef` that does nothing. */
|
|
14568
|
+
const NOOP_AFTER_RENDER_REF = {
|
|
14569
|
+
destroy() { }
|
|
14570
|
+
};
|
|
14571
|
+
/**
|
|
14572
|
+
* Register a callback to run once before any userspace `afterRender` or
|
|
14573
|
+
* `afterNextRender` callbacks.
|
|
14574
|
+
*
|
|
14575
|
+
* This function should almost always be used instead of `afterRender` or
|
|
14576
|
+
* `afterNextRender` for implementing framework functionality. Consider:
|
|
14577
|
+
*
|
|
14578
|
+
* 1.) `AfterRenderPhase.EarlyRead` is intended to be used for implementing
|
|
14579
|
+
* custom layout. If the framework itself mutates the DOM after *any*
|
|
14580
|
+
* `AfterRenderPhase.EarlyRead` callbacks are run, the phase can no
|
|
14581
|
+
* longer reliably serve its purpose.
|
|
14582
|
+
*
|
|
14583
|
+
* 2.) Importing `afterRender` in the framework can reduce the ability for it
|
|
14584
|
+
* to be tree-shaken, and the framework shouldn't need much of the behavior.
|
|
14585
|
+
*/
|
|
14586
|
+
function internalAfterNextRender(callback, options) {
|
|
14587
|
+
const injector = options?.injector ?? inject(Injector);
|
|
14588
|
+
// Similarly to the public `afterNextRender` function, an internal one
|
|
14589
|
+
// is only invoked in a browser as long as the runOnServer option is not set.
|
|
14590
|
+
if (!options?.runOnServer && !isPlatformBrowser(injector))
|
|
14591
|
+
return;
|
|
14592
|
+
const afterRenderEventManager = injector.get(AfterRenderEventManager);
|
|
14593
|
+
afterRenderEventManager.internalCallbacks.push(callback);
|
|
14563
14594
|
}
|
|
14564
|
-
|
|
14565
14595
|
/**
|
|
14566
|
-
*
|
|
14596
|
+
* Register a callback to be invoked each time the application
|
|
14597
|
+
* finishes rendering.
|
|
14567
14598
|
*
|
|
14568
|
-
*
|
|
14569
|
-
* one or more asynchronous tasks that don't require UI updates or error handling to be handled by
|
|
14570
|
-
* Angular. Such tasks can be kicked off via {@link #runOutsideAngular} and if needed, these tasks
|
|
14571
|
-
* can reenter the Angular zone via {@link #run}.
|
|
14599
|
+
* <div class="alert is-critical">
|
|
14572
14600
|
*
|
|
14573
|
-
*
|
|
14574
|
-
*
|
|
14575
|
-
* - link to runOutsideAngular/run (throughout this file!)
|
|
14576
|
-
* -->
|
|
14601
|
+
* You should always explicitly specify a non-default [phase](api/core/AfterRenderPhase), or you
|
|
14602
|
+
* risk significant performance degradation.
|
|
14577
14603
|
*
|
|
14578
|
-
*
|
|
14579
|
-
* ### Example
|
|
14604
|
+
* </div>
|
|
14580
14605
|
*
|
|
14581
|
-
*
|
|
14582
|
-
*
|
|
14583
|
-
*
|
|
14606
|
+
* Note that the callback will run
|
|
14607
|
+
* - in the order it was registered
|
|
14608
|
+
* - once per render
|
|
14609
|
+
* - on browser platforms only
|
|
14584
14610
|
*
|
|
14585
|
-
*
|
|
14586
|
-
* selector: 'ng-zone-demo',
|
|
14587
|
-
* template: `
|
|
14588
|
-
* <h2>Demo: NgZone</h2>
|
|
14611
|
+
* <div class="alert is-important">
|
|
14589
14612
|
*
|
|
14590
|
-
*
|
|
14591
|
-
*
|
|
14613
|
+
* Components are not guaranteed to be [hydrated](guide/hydration) before the callback runs.
|
|
14614
|
+
* You must use caution when directly reading or writing the DOM and layout.
|
|
14592
14615
|
*
|
|
14593
|
-
*
|
|
14594
|
-
* <button (click)="processOutsideOfAngularZone()">Process outside of Angular zone</button>
|
|
14595
|
-
* `,
|
|
14596
|
-
* })
|
|
14597
|
-
* export class NgZoneDemo {
|
|
14598
|
-
* progress: number = 0;
|
|
14599
|
-
* label: string;
|
|
14616
|
+
* </div>
|
|
14600
14617
|
*
|
|
14601
|
-
*
|
|
14618
|
+
* @param callback A callback function to register
|
|
14602
14619
|
*
|
|
14603
|
-
*
|
|
14604
|
-
* // so the UI DOES refresh after each setTimeout cycle
|
|
14605
|
-
* processWithinAngularZone() {
|
|
14606
|
-
* this.label = 'inside';
|
|
14607
|
-
* this.progress = 0;
|
|
14608
|
-
* this._increaseProgress(() => console.log('Inside Done!'));
|
|
14609
|
-
* }
|
|
14620
|
+
* @usageNotes
|
|
14610
14621
|
*
|
|
14611
|
-
*
|
|
14612
|
-
* // so the UI DOES NOT refresh after each setTimeout cycle
|
|
14613
|
-
* processOutsideOfAngularZone() {
|
|
14614
|
-
* this.label = 'outside';
|
|
14615
|
-
* this.progress = 0;
|
|
14616
|
-
* this._ngZone.runOutsideAngular(() => {
|
|
14617
|
-
* this._increaseProgress(() => {
|
|
14618
|
-
* // reenter the Angular zone and display done
|
|
14619
|
-
* this._ngZone.run(() => { console.log('Outside Done!'); });
|
|
14620
|
-
* });
|
|
14621
|
-
* });
|
|
14622
|
-
* }
|
|
14622
|
+
* Use `afterRender` to read or write the DOM after each render.
|
|
14623
14623
|
*
|
|
14624
|
-
*
|
|
14625
|
-
*
|
|
14626
|
-
*
|
|
14624
|
+
* ### Example
|
|
14625
|
+
* ```ts
|
|
14626
|
+
* @Component({
|
|
14627
|
+
* selector: 'my-cmp',
|
|
14628
|
+
* template: `<span #content>{{ ... }}</span>`,
|
|
14629
|
+
* })
|
|
14630
|
+
* export class MyComponent {
|
|
14631
|
+
* @ViewChild('content') contentRef: ElementRef;
|
|
14627
14632
|
*
|
|
14628
|
-
*
|
|
14629
|
-
*
|
|
14630
|
-
*
|
|
14631
|
-
*
|
|
14632
|
-
* }
|
|
14633
|
+
* constructor() {
|
|
14634
|
+
* afterRender(() => {
|
|
14635
|
+
* console.log('content height: ' + this.contentRef.nativeElement.scrollHeight);
|
|
14636
|
+
* }, {phase: AfterRenderPhase.Read});
|
|
14633
14637
|
* }
|
|
14634
14638
|
* }
|
|
14635
14639
|
* ```
|
|
14636
14640
|
*
|
|
14637
|
-
* @
|
|
14638
|
-
*/
|
|
14639
|
-
class NgZone {
|
|
14640
|
-
constructor({ enableLongStackTrace = false, shouldCoalesceEventChangeDetection = false, shouldCoalesceRunChangeDetection = false }) {
|
|
14641
|
-
this.hasPendingMacrotasks = false;
|
|
14642
|
-
this.hasPendingMicrotasks = false;
|
|
14643
|
-
/**
|
|
14644
|
-
* Whether there are no outstanding microtasks or macrotasks.
|
|
14645
|
-
*/
|
|
14646
|
-
this.isStable = true;
|
|
14647
|
-
/**
|
|
14648
|
-
* Notifies when code enters Angular Zone. This gets fired first on VM Turn.
|
|
14649
|
-
*/
|
|
14650
|
-
this.onUnstable = new EventEmitter(false);
|
|
14651
|
-
/**
|
|
14652
|
-
* Notifies when there is no more microtasks enqueued in the current VM Turn.
|
|
14653
|
-
* This is a hint for Angular to do change detection, which may enqueue more microtasks.
|
|
14654
|
-
* For this reason this event can fire multiple times per VM Turn.
|
|
14655
|
-
*/
|
|
14656
|
-
this.onMicrotaskEmpty = new EventEmitter(false);
|
|
14657
|
-
/**
|
|
14658
|
-
* Notifies when the last `onMicrotaskEmpty` has run and there are no more microtasks, which
|
|
14659
|
-
* implies we are about to relinquish VM turn.
|
|
14660
|
-
* This event gets called just once.
|
|
14661
|
-
*/
|
|
14662
|
-
this.onStable = new EventEmitter(false);
|
|
14663
|
-
/**
|
|
14664
|
-
* Notifies that an error has been delivered.
|
|
14665
|
-
*/
|
|
14666
|
-
this.onError = new EventEmitter(false);
|
|
14667
|
-
if (typeof Zone == 'undefined') {
|
|
14668
|
-
throw new RuntimeError(908 /* RuntimeErrorCode.MISSING_ZONEJS */, ngDevMode && `In this configuration Angular requires Zone.js`);
|
|
14669
|
-
}
|
|
14670
|
-
Zone.assertZonePatched();
|
|
14671
|
-
const self = this;
|
|
14672
|
-
self._nesting = 0;
|
|
14673
|
-
self._outer = self._inner = Zone.current;
|
|
14674
|
-
// AsyncStackTaggingZoneSpec provides `linked stack traces` to show
|
|
14675
|
-
// where the async operation is scheduled. For more details, refer
|
|
14676
|
-
// to this article, https://developer.chrome.com/blog/devtools-better-angular-debugging/
|
|
14677
|
-
// And we only import this AsyncStackTaggingZoneSpec in development mode,
|
|
14678
|
-
// in the production mode, the AsyncStackTaggingZoneSpec will be tree shaken away.
|
|
14679
|
-
if (ngDevMode) {
|
|
14680
|
-
self._inner = self._inner.fork(new AsyncStackTaggingZoneSpec('Angular'));
|
|
14681
|
-
}
|
|
14682
|
-
if (Zone['TaskTrackingZoneSpec']) {
|
|
14683
|
-
self._inner = self._inner.fork(new Zone['TaskTrackingZoneSpec']);
|
|
14684
|
-
}
|
|
14685
|
-
if (enableLongStackTrace && Zone['longStackTraceZoneSpec']) {
|
|
14686
|
-
self._inner = self._inner.fork(Zone['longStackTraceZoneSpec']);
|
|
14687
|
-
}
|
|
14688
|
-
// if shouldCoalesceRunChangeDetection is true, all tasks including event tasks will be
|
|
14689
|
-
// coalesced, so shouldCoalesceEventChangeDetection option is not necessary and can be skipped.
|
|
14690
|
-
self.shouldCoalesceEventChangeDetection =
|
|
14691
|
-
!shouldCoalesceRunChangeDetection && shouldCoalesceEventChangeDetection;
|
|
14692
|
-
self.shouldCoalesceRunChangeDetection = shouldCoalesceRunChangeDetection;
|
|
14693
|
-
self.lastRequestAnimationFrameId = -1;
|
|
14694
|
-
self.nativeRequestAnimationFrame = getNativeRequestAnimationFrame().nativeRequestAnimationFrame;
|
|
14695
|
-
forkInnerZoneWithAngularBehavior(self);
|
|
14696
|
-
}
|
|
14697
|
-
/**
|
|
14698
|
-
This method checks whether the method call happens within an Angular Zone instance.
|
|
14699
|
-
*/
|
|
14700
|
-
static isInAngularZone() {
|
|
14701
|
-
// Zone needs to be checked, because this method might be called even when NoopNgZone is used.
|
|
14702
|
-
return typeof Zone !== 'undefined' && Zone.current.get('isAngularZone') === true;
|
|
14703
|
-
}
|
|
14704
|
-
/**
|
|
14705
|
-
Assures that the method is called within the Angular Zone, otherwise throws an error.
|
|
14706
|
-
*/
|
|
14707
|
-
static assertInAngularZone() {
|
|
14708
|
-
if (!NgZone.isInAngularZone()) {
|
|
14709
|
-
throw new RuntimeError(909 /* RuntimeErrorCode.UNEXPECTED_ZONE_STATE */, ngDevMode && 'Expected to be in Angular Zone, but it is not!');
|
|
14710
|
-
}
|
|
14711
|
-
}
|
|
14712
|
-
/**
|
|
14713
|
-
Assures that the method is called outside of the Angular Zone, otherwise throws an error.
|
|
14714
|
-
*/
|
|
14715
|
-
static assertNotInAngularZone() {
|
|
14716
|
-
if (NgZone.isInAngularZone()) {
|
|
14717
|
-
throw new RuntimeError(909 /* RuntimeErrorCode.UNEXPECTED_ZONE_STATE */, ngDevMode && 'Expected to not be in Angular Zone, but it is!');
|
|
14718
|
-
}
|
|
14719
|
-
}
|
|
14720
|
-
/**
|
|
14721
|
-
* Executes the `fn` function synchronously within the Angular zone and returns value returned by
|
|
14722
|
-
* the function.
|
|
14723
|
-
*
|
|
14724
|
-
* Running functions via `run` allows you to reenter Angular zone from a task that was executed
|
|
14725
|
-
* outside of the Angular zone (typically started via {@link #runOutsideAngular}).
|
|
14726
|
-
*
|
|
14727
|
-
* Any future tasks or microtasks scheduled from within this function will continue executing from
|
|
14728
|
-
* within the Angular zone.
|
|
14729
|
-
*
|
|
14730
|
-
* If a synchronous error happens it will be rethrown and not reported via `onError`.
|
|
14731
|
-
*/
|
|
14732
|
-
run(fn, applyThis, applyArgs) {
|
|
14733
|
-
return this._inner.run(fn, applyThis, applyArgs);
|
|
14734
|
-
}
|
|
14735
|
-
/**
|
|
14736
|
-
* Executes the `fn` function synchronously within the Angular zone as a task and returns value
|
|
14737
|
-
* returned by the function.
|
|
14738
|
-
*
|
|
14739
|
-
* Running functions via `run` allows you to reenter Angular zone from a task that was executed
|
|
14740
|
-
* outside of the Angular zone (typically started via {@link #runOutsideAngular}).
|
|
14741
|
-
*
|
|
14742
|
-
* Any future tasks or microtasks scheduled from within this function will continue executing from
|
|
14743
|
-
* within the Angular zone.
|
|
14744
|
-
*
|
|
14745
|
-
* If a synchronous error happens it will be rethrown and not reported via `onError`.
|
|
14746
|
-
*/
|
|
14747
|
-
runTask(fn, applyThis, applyArgs, name) {
|
|
14748
|
-
const zone = this._inner;
|
|
14749
|
-
const task = zone.scheduleEventTask('NgZoneEvent: ' + name, fn, EMPTY_PAYLOAD, noop, noop);
|
|
14750
|
-
try {
|
|
14751
|
-
return zone.runTask(task, applyThis, applyArgs);
|
|
14752
|
-
}
|
|
14753
|
-
finally {
|
|
14754
|
-
zone.cancelTask(task);
|
|
14755
|
-
}
|
|
14756
|
-
}
|
|
14757
|
-
/**
|
|
14758
|
-
* Same as `run`, except that synchronous errors are caught and forwarded via `onError` and not
|
|
14759
|
-
* rethrown.
|
|
14760
|
-
*/
|
|
14761
|
-
runGuarded(fn, applyThis, applyArgs) {
|
|
14762
|
-
return this._inner.runGuarded(fn, applyThis, applyArgs);
|
|
14763
|
-
}
|
|
14764
|
-
/**
|
|
14765
|
-
* Executes the `fn` function synchronously in Angular's parent zone and returns value returned by
|
|
14766
|
-
* the function.
|
|
14767
|
-
*
|
|
14768
|
-
* Running functions via {@link #runOutsideAngular} allows you to escape Angular's zone and do
|
|
14769
|
-
* work that
|
|
14770
|
-
* doesn't trigger Angular change-detection or is subject to Angular's error handling.
|
|
14771
|
-
*
|
|
14772
|
-
* Any future tasks or microtasks scheduled from within this function will continue executing from
|
|
14773
|
-
* outside of the Angular zone.
|
|
14774
|
-
*
|
|
14775
|
-
* Use {@link #run} to reenter the Angular zone and do work that updates the application model.
|
|
14776
|
-
*/
|
|
14777
|
-
runOutsideAngular(fn) {
|
|
14778
|
-
return this._outer.run(fn);
|
|
14779
|
-
}
|
|
14780
|
-
}
|
|
14781
|
-
const EMPTY_PAYLOAD = {};
|
|
14782
|
-
function checkStable(zone) {
|
|
14783
|
-
// TODO: @JiaLiPassion, should check zone.isCheckStableRunning to prevent
|
|
14784
|
-
// re-entry. The case is:
|
|
14785
|
-
//
|
|
14786
|
-
// @Component({...})
|
|
14787
|
-
// export class AppComponent {
|
|
14788
|
-
// constructor(private ngZone: NgZone) {
|
|
14789
|
-
// this.ngZone.onStable.subscribe(() => {
|
|
14790
|
-
// this.ngZone.run(() => console.log('stable'););
|
|
14791
|
-
// });
|
|
14792
|
-
// }
|
|
14793
|
-
//
|
|
14794
|
-
// The onStable subscriber run another function inside ngZone
|
|
14795
|
-
// which causes `checkStable()` re-entry.
|
|
14796
|
-
// But this fix causes some issues in g3, so this fix will be
|
|
14797
|
-
// launched in another PR.
|
|
14798
|
-
if (zone._nesting == 0 && !zone.hasPendingMicrotasks && !zone.isStable) {
|
|
14799
|
-
try {
|
|
14800
|
-
zone._nesting++;
|
|
14801
|
-
zone.onMicrotaskEmpty.emit(null);
|
|
14802
|
-
}
|
|
14803
|
-
finally {
|
|
14804
|
-
zone._nesting--;
|
|
14805
|
-
if (!zone.hasPendingMicrotasks) {
|
|
14806
|
-
try {
|
|
14807
|
-
zone.runOutsideAngular(() => zone.onStable.emit(null));
|
|
14808
|
-
}
|
|
14809
|
-
finally {
|
|
14810
|
-
zone.isStable = true;
|
|
14811
|
-
}
|
|
14812
|
-
}
|
|
14813
|
-
}
|
|
14814
|
-
}
|
|
14815
|
-
}
|
|
14816
|
-
function delayChangeDetectionForEvents(zone) {
|
|
14817
|
-
/**
|
|
14818
|
-
* We also need to check _nesting here
|
|
14819
|
-
* Consider the following case with shouldCoalesceRunChangeDetection = true
|
|
14820
|
-
*
|
|
14821
|
-
* ngZone.run(() => {});
|
|
14822
|
-
* ngZone.run(() => {});
|
|
14823
|
-
*
|
|
14824
|
-
* We want the two `ngZone.run()` only trigger one change detection
|
|
14825
|
-
* when shouldCoalesceRunChangeDetection is true.
|
|
14826
|
-
* And because in this case, change detection run in async way(requestAnimationFrame),
|
|
14827
|
-
* so we also need to check the _nesting here to prevent multiple
|
|
14828
|
-
* change detections.
|
|
14829
|
-
*/
|
|
14830
|
-
if (zone.isCheckStableRunning || zone.lastRequestAnimationFrameId !== -1) {
|
|
14831
|
-
return;
|
|
14832
|
-
}
|
|
14833
|
-
zone.lastRequestAnimationFrameId = zone.nativeRequestAnimationFrame.call(_global, () => {
|
|
14834
|
-
// This is a work around for https://github.com/angular/angular/issues/36839.
|
|
14835
|
-
// The core issue is that when event coalescing is enabled it is possible for microtasks
|
|
14836
|
-
// to get flushed too early (As is the case with `Promise.then`) between the
|
|
14837
|
-
// coalescing eventTasks.
|
|
14838
|
-
//
|
|
14839
|
-
// To workaround this we schedule a "fake" eventTask before we process the
|
|
14840
|
-
// coalescing eventTasks. The benefit of this is that the "fake" container eventTask
|
|
14841
|
-
// will prevent the microtasks queue from getting drained in between the coalescing
|
|
14842
|
-
// eventTask execution.
|
|
14843
|
-
if (!zone.fakeTopEventTask) {
|
|
14844
|
-
zone.fakeTopEventTask = Zone.root.scheduleEventTask('fakeTopEventTask', () => {
|
|
14845
|
-
zone.lastRequestAnimationFrameId = -1;
|
|
14846
|
-
updateMicroTaskStatus(zone);
|
|
14847
|
-
zone.isCheckStableRunning = true;
|
|
14848
|
-
checkStable(zone);
|
|
14849
|
-
zone.isCheckStableRunning = false;
|
|
14850
|
-
}, undefined, () => { }, () => { });
|
|
14851
|
-
}
|
|
14852
|
-
zone.fakeTopEventTask.invoke();
|
|
14853
|
-
});
|
|
14854
|
-
updateMicroTaskStatus(zone);
|
|
14855
|
-
}
|
|
14856
|
-
function forkInnerZoneWithAngularBehavior(zone) {
|
|
14857
|
-
const delayChangeDetectionForEventsDelegate = () => {
|
|
14858
|
-
delayChangeDetectionForEvents(zone);
|
|
14859
|
-
};
|
|
14860
|
-
zone._inner = zone._inner.fork({
|
|
14861
|
-
name: 'angular',
|
|
14862
|
-
properties: { 'isAngularZone': true },
|
|
14863
|
-
onInvokeTask: (delegate, current, target, task, applyThis, applyArgs) => {
|
|
14864
|
-
if (shouldBeIgnoredByZone(applyArgs)) {
|
|
14865
|
-
return delegate.invokeTask(target, task, applyThis, applyArgs);
|
|
14866
|
-
}
|
|
14867
|
-
try {
|
|
14868
|
-
onEnter(zone);
|
|
14869
|
-
return delegate.invokeTask(target, task, applyThis, applyArgs);
|
|
14870
|
-
}
|
|
14871
|
-
finally {
|
|
14872
|
-
if ((zone.shouldCoalesceEventChangeDetection && task.type === 'eventTask') ||
|
|
14873
|
-
zone.shouldCoalesceRunChangeDetection) {
|
|
14874
|
-
delayChangeDetectionForEventsDelegate();
|
|
14875
|
-
}
|
|
14876
|
-
onLeave(zone);
|
|
14877
|
-
}
|
|
14878
|
-
},
|
|
14879
|
-
onInvoke: (delegate, current, target, callback, applyThis, applyArgs, source) => {
|
|
14880
|
-
try {
|
|
14881
|
-
onEnter(zone);
|
|
14882
|
-
return delegate.invoke(target, callback, applyThis, applyArgs, source);
|
|
14883
|
-
}
|
|
14884
|
-
finally {
|
|
14885
|
-
if (zone.shouldCoalesceRunChangeDetection) {
|
|
14886
|
-
delayChangeDetectionForEventsDelegate();
|
|
14887
|
-
}
|
|
14888
|
-
onLeave(zone);
|
|
14889
|
-
}
|
|
14890
|
-
},
|
|
14891
|
-
onHasTask: (delegate, current, target, hasTaskState) => {
|
|
14892
|
-
delegate.hasTask(target, hasTaskState);
|
|
14893
|
-
if (current === target) {
|
|
14894
|
-
// We are only interested in hasTask events which originate from our zone
|
|
14895
|
-
// (A child hasTask event is not interesting to us)
|
|
14896
|
-
if (hasTaskState.change == 'microTask') {
|
|
14897
|
-
zone._hasPendingMicrotasks = hasTaskState.microTask;
|
|
14898
|
-
updateMicroTaskStatus(zone);
|
|
14899
|
-
checkStable(zone);
|
|
14900
|
-
}
|
|
14901
|
-
else if (hasTaskState.change == 'macroTask') {
|
|
14902
|
-
zone.hasPendingMacrotasks = hasTaskState.macroTask;
|
|
14903
|
-
}
|
|
14904
|
-
}
|
|
14905
|
-
},
|
|
14906
|
-
onHandleError: (delegate, current, target, error) => {
|
|
14907
|
-
delegate.handleError(target, error);
|
|
14908
|
-
zone.runOutsideAngular(() => zone.onError.emit(error));
|
|
14909
|
-
return false;
|
|
14910
|
-
}
|
|
14911
|
-
});
|
|
14912
|
-
}
|
|
14913
|
-
function updateMicroTaskStatus(zone) {
|
|
14914
|
-
if (zone._hasPendingMicrotasks ||
|
|
14915
|
-
((zone.shouldCoalesceEventChangeDetection || zone.shouldCoalesceRunChangeDetection) &&
|
|
14916
|
-
zone.lastRequestAnimationFrameId !== -1)) {
|
|
14917
|
-
zone.hasPendingMicrotasks = true;
|
|
14918
|
-
}
|
|
14919
|
-
else {
|
|
14920
|
-
zone.hasPendingMicrotasks = false;
|
|
14921
|
-
}
|
|
14922
|
-
}
|
|
14923
|
-
function onEnter(zone) {
|
|
14924
|
-
zone._nesting++;
|
|
14925
|
-
if (zone.isStable) {
|
|
14926
|
-
zone.isStable = false;
|
|
14927
|
-
zone.onUnstable.emit(null);
|
|
14928
|
-
}
|
|
14929
|
-
}
|
|
14930
|
-
function onLeave(zone) {
|
|
14931
|
-
zone._nesting--;
|
|
14932
|
-
checkStable(zone);
|
|
14933
|
-
}
|
|
14934
|
-
/**
|
|
14935
|
-
* Provides a noop implementation of `NgZone` which does nothing. This zone requires explicit calls
|
|
14936
|
-
* to framework to perform rendering.
|
|
14937
|
-
*/
|
|
14938
|
-
class NoopNgZone {
|
|
14939
|
-
constructor() {
|
|
14940
|
-
this.hasPendingMicrotasks = false;
|
|
14941
|
-
this.hasPendingMacrotasks = false;
|
|
14942
|
-
this.isStable = true;
|
|
14943
|
-
this.onUnstable = new EventEmitter();
|
|
14944
|
-
this.onMicrotaskEmpty = new EventEmitter();
|
|
14945
|
-
this.onStable = new EventEmitter();
|
|
14946
|
-
this.onError = new EventEmitter();
|
|
14947
|
-
}
|
|
14948
|
-
run(fn, applyThis, applyArgs) {
|
|
14949
|
-
return fn.apply(applyThis, applyArgs);
|
|
14950
|
-
}
|
|
14951
|
-
runGuarded(fn, applyThis, applyArgs) {
|
|
14952
|
-
return fn.apply(applyThis, applyArgs);
|
|
14953
|
-
}
|
|
14954
|
-
runOutsideAngular(fn) {
|
|
14955
|
-
return fn();
|
|
14956
|
-
}
|
|
14957
|
-
runTask(fn, applyThis, applyArgs, name) {
|
|
14958
|
-
return fn.apply(applyThis, applyArgs);
|
|
14959
|
-
}
|
|
14960
|
-
}
|
|
14961
|
-
function shouldBeIgnoredByZone(applyArgs) {
|
|
14962
|
-
if (!Array.isArray(applyArgs)) {
|
|
14963
|
-
return false;
|
|
14964
|
-
}
|
|
14965
|
-
// We should only ever get 1 arg passed through to invokeTask.
|
|
14966
|
-
// Short circuit here incase that behavior changes.
|
|
14967
|
-
if (applyArgs.length !== 1) {
|
|
14968
|
-
return false;
|
|
14969
|
-
}
|
|
14970
|
-
// Prevent triggering change detection when the __ignore_ng_zone__ flag is detected.
|
|
14971
|
-
return applyArgs[0].data?.['__ignore_ng_zone__'] === true;
|
|
14972
|
-
}
|
|
14973
|
-
function getNgZone(ngZoneToUse = 'zone.js', options) {
|
|
14974
|
-
if (ngZoneToUse === 'noop') {
|
|
14975
|
-
return new NoopNgZone();
|
|
14976
|
-
}
|
|
14977
|
-
if (ngZoneToUse === 'zone.js') {
|
|
14978
|
-
return new NgZone(options);
|
|
14979
|
-
}
|
|
14980
|
-
return ngZoneToUse;
|
|
14981
|
-
}
|
|
14982
|
-
|
|
14983
|
-
/**
|
|
14984
|
-
* The phase to run an `afterRender` or `afterNextRender` callback in.
|
|
14985
|
-
*
|
|
14986
|
-
* Callbacks in the same phase run in the order they are registered. Phases run in the
|
|
14987
|
-
* following order after each render:
|
|
14988
|
-
*
|
|
14989
|
-
* 1. `AfterRenderPhase.EarlyRead`
|
|
14990
|
-
* 2. `AfterRenderPhase.Write`
|
|
14991
|
-
* 3. `AfterRenderPhase.MixedReadWrite`
|
|
14992
|
-
* 4. `AfterRenderPhase.Read`
|
|
14993
|
-
*
|
|
14994
|
-
* Angular is unable to verify or enforce that phases are used correctly, and instead
|
|
14995
|
-
* relies on each developer to follow the guidelines documented for each value and
|
|
14996
|
-
* carefully choose the appropriate one, refactoring their code if necessary. By doing
|
|
14997
|
-
* so, Angular is better able to minimize the performance degradation associated with
|
|
14998
|
-
* manual DOM access, ensuring the best experience for the end users of your application
|
|
14999
|
-
* or library.
|
|
15000
|
-
*
|
|
15001
|
-
* @developerPreview
|
|
15002
|
-
*/
|
|
15003
|
-
var AfterRenderPhase;
|
|
15004
|
-
(function (AfterRenderPhase) {
|
|
15005
|
-
/**
|
|
15006
|
-
* Use `AfterRenderPhase.EarlyRead` for callbacks that only need to **read** from the
|
|
15007
|
-
* DOM before a subsequent `AfterRenderPhase.Write` callback, for example to perform
|
|
15008
|
-
* custom layout that the browser doesn't natively support. **Never** use this phase
|
|
15009
|
-
* for callbacks that can write to the DOM or when `AfterRenderPhase.Read` is adequate.
|
|
15010
|
-
*
|
|
15011
|
-
* <div class="alert is-important">
|
|
15012
|
-
*
|
|
15013
|
-
* Using this value can degrade performance.
|
|
15014
|
-
* Instead, prefer using built-in browser functionality when possible.
|
|
15015
|
-
*
|
|
15016
|
-
* </div>
|
|
15017
|
-
*/
|
|
15018
|
-
AfterRenderPhase[AfterRenderPhase["EarlyRead"] = 0] = "EarlyRead";
|
|
15019
|
-
/**
|
|
15020
|
-
* Use `AfterRenderPhase.Write` for callbacks that only **write** to the DOM. **Never**
|
|
15021
|
-
* use this phase for callbacks that can read from the DOM.
|
|
15022
|
-
*/
|
|
15023
|
-
AfterRenderPhase[AfterRenderPhase["Write"] = 1] = "Write";
|
|
15024
|
-
/**
|
|
15025
|
-
* Use `AfterRenderPhase.MixedReadWrite` for callbacks that read from or write to the
|
|
15026
|
-
* DOM, that haven't been refactored to use a different phase. **Never** use this phase
|
|
15027
|
-
* for callbacks that can use a different phase instead.
|
|
15028
|
-
*
|
|
15029
|
-
* <div class="alert is-critical">
|
|
15030
|
-
*
|
|
15031
|
-
* Using this value can **significantly** degrade performance.
|
|
15032
|
-
* Instead, prefer refactoring into multiple callbacks using a more specific phase.
|
|
15033
|
-
*
|
|
15034
|
-
* </div>
|
|
15035
|
-
*/
|
|
15036
|
-
AfterRenderPhase[AfterRenderPhase["MixedReadWrite"] = 2] = "MixedReadWrite";
|
|
15037
|
-
/**
|
|
15038
|
-
* Use `AfterRenderPhase.Read` for callbacks that only **read** from the DOM. **Never**
|
|
15039
|
-
* use this phase for callbacks that can write to the DOM.
|
|
15040
|
-
*/
|
|
15041
|
-
AfterRenderPhase[AfterRenderPhase["Read"] = 3] = "Read";
|
|
15042
|
-
})(AfterRenderPhase || (AfterRenderPhase = {}));
|
|
15043
|
-
/** `AfterRenderRef` that does nothing. */
|
|
15044
|
-
const NOOP_AFTER_RENDER_REF = {
|
|
15045
|
-
destroy() { }
|
|
15046
|
-
};
|
|
15047
|
-
/**
|
|
15048
|
-
* Register a callback to run once before any userspace `afterRender` or
|
|
15049
|
-
* `afterNextRender` callbacks.
|
|
15050
|
-
*
|
|
15051
|
-
* This function should almost always be used instead of `afterRender` or
|
|
15052
|
-
* `afterNextRender` for implementing framework functionality. Consider:
|
|
15053
|
-
*
|
|
15054
|
-
* 1.) `AfterRenderPhase.EarlyRead` is intended to be used for implementing
|
|
15055
|
-
* custom layout. If the framework itself mutates the DOM after *any*
|
|
15056
|
-
* `AfterRenderPhase.EarlyRead` callbacks are run, the phase can no
|
|
15057
|
-
* longer reliably serve its purpose.
|
|
15058
|
-
*
|
|
15059
|
-
* 2.) Importing `afterRender` in the framework can reduce the ability for it
|
|
15060
|
-
* to be tree-shaken, and the framework shouldn't need much of the behavior.
|
|
15061
|
-
*/
|
|
15062
|
-
function internalAfterNextRender(callback, options) {
|
|
15063
|
-
const injector = options?.injector ?? inject(Injector);
|
|
15064
|
-
// Similarly to the public `afterNextRender` function, an internal one
|
|
15065
|
-
// is only invoked in a browser as long as the runOnServer option is not set.
|
|
15066
|
-
if (!options?.runOnServer && !isPlatformBrowser(injector))
|
|
15067
|
-
return;
|
|
15068
|
-
const afterRenderEventManager = injector.get(AfterRenderEventManager);
|
|
15069
|
-
afterRenderEventManager.internalCallbacks.push(callback);
|
|
15070
|
-
}
|
|
15071
|
-
/**
|
|
15072
|
-
* Register a callback to be invoked each time the application
|
|
15073
|
-
* finishes rendering.
|
|
15074
|
-
*
|
|
15075
|
-
* <div class="alert is-critical">
|
|
15076
|
-
*
|
|
15077
|
-
* You should always explicitly specify a non-default [phase](api/core/AfterRenderPhase), or you
|
|
15078
|
-
* risk significant performance degradation.
|
|
15079
|
-
*
|
|
15080
|
-
* </div>
|
|
15081
|
-
*
|
|
15082
|
-
* Note that the callback will run
|
|
15083
|
-
* - in the order it was registered
|
|
15084
|
-
* - once per render
|
|
15085
|
-
* - on browser platforms only
|
|
15086
|
-
*
|
|
15087
|
-
* <div class="alert is-important">
|
|
15088
|
-
*
|
|
15089
|
-
* Components are not guaranteed to be [hydrated](guide/hydration) before the callback runs.
|
|
15090
|
-
* You must use caution when directly reading or writing the DOM and layout.
|
|
15091
|
-
*
|
|
15092
|
-
* </div>
|
|
15093
|
-
*
|
|
15094
|
-
* @param callback A callback function to register
|
|
15095
|
-
*
|
|
15096
|
-
* @usageNotes
|
|
15097
|
-
*
|
|
15098
|
-
* Use `afterRender` to read or write the DOM after each render.
|
|
15099
|
-
*
|
|
15100
|
-
* ### Example
|
|
15101
|
-
* ```ts
|
|
15102
|
-
* @Component({
|
|
15103
|
-
* selector: 'my-cmp',
|
|
15104
|
-
* template: `<span #content>{{ ... }}</span>`,
|
|
15105
|
-
* })
|
|
15106
|
-
* export class MyComponent {
|
|
15107
|
-
* @ViewChild('content') contentRef: ElementRef;
|
|
15108
|
-
*
|
|
15109
|
-
* constructor() {
|
|
15110
|
-
* afterRender(() => {
|
|
15111
|
-
* console.log('content height: ' + this.contentRef.nativeElement.scrollHeight);
|
|
15112
|
-
* }, {phase: AfterRenderPhase.Read});
|
|
15113
|
-
* }
|
|
15114
|
-
* }
|
|
15115
|
-
* ```
|
|
15116
|
-
*
|
|
15117
|
-
* @developerPreview
|
|
14641
|
+
* @developerPreview
|
|
15118
14642
|
*/
|
|
15119
14643
|
function afterRender(callback, options) {
|
|
15120
14644
|
ngDevMode &&
|
|
@@ -15220,14 +14744,13 @@ class AfterRenderCallback {
|
|
|
15220
14744
|
constructor(phase, callbackFn) {
|
|
15221
14745
|
this.phase = phase;
|
|
15222
14746
|
this.callbackFn = callbackFn;
|
|
15223
|
-
this.zone = inject(NgZone);
|
|
15224
14747
|
this.errorHandler = inject(ErrorHandler, { optional: true });
|
|
15225
14748
|
// Registering a callback will notify the scheduler.
|
|
15226
14749
|
inject(ChangeDetectionScheduler, { optional: true })?.notify(1 /* NotificationType.AfterRenderHooks */);
|
|
15227
14750
|
}
|
|
15228
14751
|
invoke() {
|
|
15229
14752
|
try {
|
|
15230
|
-
this.
|
|
14753
|
+
this.callbackFn();
|
|
15231
14754
|
}
|
|
15232
14755
|
catch (err) {
|
|
15233
14756
|
this.errorHandler?.handleError(err);
|
|
@@ -16022,7 +15545,7 @@ function createRootComponent(componentView, rootComponentDef, rootDirectives, ho
|
|
|
16022
15545
|
function setRootNodeAttributes(hostRenderer, componentDef, hostRNode, rootSelectorOrNode) {
|
|
16023
15546
|
if (rootSelectorOrNode) {
|
|
16024
15547
|
// The placeholder will be replaced with the actual version at build time.
|
|
16025
|
-
setUpAttributes(hostRenderer, hostRNode, ['ng-version', '17.3.
|
|
15548
|
+
setUpAttributes(hostRenderer, hostRNode, ['ng-version', '17.3.7']);
|
|
16026
15549
|
}
|
|
16027
15550
|
else {
|
|
16028
15551
|
// If host element is created as a part of this function call (i.e. `rootSelectorOrNode`
|
|
@@ -17448,1210 +16971,1686 @@ function restoreComponentResolutionQueue(queue) {
|
|
|
17448
16971
|
function isComponentResourceResolutionQueueEmpty() {
|
|
17449
16972
|
return componentResourceResolutionQueue.size === 0;
|
|
17450
16973
|
}
|
|
17451
|
-
function unwrapResponse(response) {
|
|
17452
|
-
return typeof response == 'string' ? response : response.text();
|
|
16974
|
+
function unwrapResponse(response) {
|
|
16975
|
+
return typeof response == 'string' ? response : response.text();
|
|
16976
|
+
}
|
|
16977
|
+
function componentDefResolved(type) {
|
|
16978
|
+
componentDefPendingResolution.delete(type);
|
|
16979
|
+
}
|
|
16980
|
+
|
|
16981
|
+
/**
|
|
16982
|
+
* Map of module-id to the corresponding NgModule.
|
|
16983
|
+
*/
|
|
16984
|
+
const modules = new Map();
|
|
16985
|
+
/**
|
|
16986
|
+
* Whether to check for duplicate NgModule registrations.
|
|
16987
|
+
*
|
|
16988
|
+
* This can be disabled for testing.
|
|
16989
|
+
*/
|
|
16990
|
+
let checkForDuplicateNgModules = true;
|
|
16991
|
+
function assertSameOrNotExisting(id, type, incoming) {
|
|
16992
|
+
if (type && type !== incoming && checkForDuplicateNgModules) {
|
|
16993
|
+
throw new Error(`Duplicate module registered for ${id} - ${stringify(type)} vs ${stringify(type.name)}`);
|
|
16994
|
+
}
|
|
16995
|
+
}
|
|
16996
|
+
/**
|
|
16997
|
+
* Adds the given NgModule type to Angular's NgModule registry.
|
|
16998
|
+
*
|
|
16999
|
+
* This is generated as a side-effect of NgModule compilation. Note that the `id` is passed in
|
|
17000
|
+
* explicitly and not read from the NgModule definition. This is for two reasons: it avoids a
|
|
17001
|
+
* megamorphic read, and in JIT there's a chicken-and-egg problem where the NgModule may not be
|
|
17002
|
+
* fully resolved when it's registered.
|
|
17003
|
+
*
|
|
17004
|
+
* @codeGenApi
|
|
17005
|
+
*/
|
|
17006
|
+
function registerNgModuleType(ngModuleType, id) {
|
|
17007
|
+
const existing = modules.get(id) || null;
|
|
17008
|
+
assertSameOrNotExisting(id, existing, ngModuleType);
|
|
17009
|
+
modules.set(id, ngModuleType);
|
|
17010
|
+
}
|
|
17011
|
+
function clearModulesForTest() {
|
|
17012
|
+
modules.clear();
|
|
17013
|
+
}
|
|
17014
|
+
function getRegisteredNgModuleType(id) {
|
|
17015
|
+
return modules.get(id);
|
|
17016
|
+
}
|
|
17017
|
+
/**
|
|
17018
|
+
* Control whether the NgModule registration system enforces that each NgModule type registered has
|
|
17019
|
+
* a unique id.
|
|
17020
|
+
*
|
|
17021
|
+
* This is useful for testing as the NgModule registry cannot be properly reset between tests with
|
|
17022
|
+
* Angular's current API.
|
|
17023
|
+
*/
|
|
17024
|
+
function setAllowDuplicateNgModuleIdsForTest(allowDuplicates) {
|
|
17025
|
+
checkForDuplicateNgModules = !allowDuplicates;
|
|
17026
|
+
}
|
|
17027
|
+
|
|
17028
|
+
/**
|
|
17029
|
+
* Validation function invoked at runtime for each binding that might potentially
|
|
17030
|
+
* represent a security-sensitive attribute of an <iframe>.
|
|
17031
|
+
* See `IFRAME_SECURITY_SENSITIVE_ATTRS` in the
|
|
17032
|
+
* `packages/compiler/src/schema/dom_security_schema.ts` script for the full list
|
|
17033
|
+
* of such attributes.
|
|
17034
|
+
*
|
|
17035
|
+
* @codeGenApi
|
|
17036
|
+
*/
|
|
17037
|
+
function ɵɵvalidateIframeAttribute(attrValue, tagName, attrName) {
|
|
17038
|
+
const lView = getLView();
|
|
17039
|
+
const tNode = getSelectedTNode();
|
|
17040
|
+
const element = getNativeByTNode(tNode, lView);
|
|
17041
|
+
// Restrict any dynamic bindings of security-sensitive attributes/properties
|
|
17042
|
+
// on an <iframe> for security reasons.
|
|
17043
|
+
if (tNode.type === 2 /* TNodeType.Element */ && tagName.toLowerCase() === 'iframe') {
|
|
17044
|
+
const iframe = element;
|
|
17045
|
+
// Unset previously applied `src` and `srcdoc` if we come across a situation when
|
|
17046
|
+
// a security-sensitive attribute is set later via an attribute/property binding.
|
|
17047
|
+
iframe.src = '';
|
|
17048
|
+
iframe.srcdoc = trustedHTMLFromString('');
|
|
17049
|
+
// Also remove the <iframe> from the document.
|
|
17050
|
+
nativeRemoveNode(lView[RENDERER], iframe);
|
|
17051
|
+
const errorMessage = ngDevMode &&
|
|
17052
|
+
`Angular has detected that the \`${attrName}\` was applied ` +
|
|
17053
|
+
`as a binding to an <iframe>${getTemplateLocationDetails(lView)}. ` +
|
|
17054
|
+
`For security reasons, the \`${attrName}\` can be set on an <iframe> ` +
|
|
17055
|
+
`as a static attribute only. \n` +
|
|
17056
|
+
`To fix this, switch the \`${attrName}\` binding to a static attribute ` +
|
|
17057
|
+
`in a template or in host bindings section.`;
|
|
17058
|
+
throw new RuntimeError(-910 /* RuntimeErrorCode.UNSAFE_IFRAME_ATTRS */, errorMessage);
|
|
17059
|
+
}
|
|
17060
|
+
return attrValue;
|
|
17061
|
+
}
|
|
17062
|
+
|
|
17063
|
+
function getSuperType(type) {
|
|
17064
|
+
return Object.getPrototypeOf(type.prototype).constructor;
|
|
17065
|
+
}
|
|
17066
|
+
/**
|
|
17067
|
+
* Merges the definition from a super class to a sub class.
|
|
17068
|
+
* @param definition The definition that is a SubClass of another directive of component
|
|
17069
|
+
*
|
|
17070
|
+
* @codeGenApi
|
|
17071
|
+
*/
|
|
17072
|
+
function ɵɵInheritDefinitionFeature(definition) {
|
|
17073
|
+
let superType = getSuperType(definition.type);
|
|
17074
|
+
let shouldInheritFields = true;
|
|
17075
|
+
const inheritanceChain = [definition];
|
|
17076
|
+
while (superType) {
|
|
17077
|
+
let superDef = undefined;
|
|
17078
|
+
if (isComponentDef(definition)) {
|
|
17079
|
+
// Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.
|
|
17080
|
+
superDef = superType.ɵcmp || superType.ɵdir;
|
|
17081
|
+
}
|
|
17082
|
+
else {
|
|
17083
|
+
if (superType.ɵcmp) {
|
|
17084
|
+
throw new RuntimeError(903 /* RuntimeErrorCode.INVALID_INHERITANCE */, ngDevMode &&
|
|
17085
|
+
`Directives cannot inherit Components. Directive ${stringifyForError(definition.type)} is attempting to extend component ${stringifyForError(superType)}`);
|
|
17086
|
+
}
|
|
17087
|
+
// Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.
|
|
17088
|
+
superDef = superType.ɵdir;
|
|
17089
|
+
}
|
|
17090
|
+
if (superDef) {
|
|
17091
|
+
if (shouldInheritFields) {
|
|
17092
|
+
inheritanceChain.push(superDef);
|
|
17093
|
+
// Some fields in the definition may be empty, if there were no values to put in them that
|
|
17094
|
+
// would've justified object creation. Unwrap them if necessary.
|
|
17095
|
+
const writeableDef = definition;
|
|
17096
|
+
writeableDef.inputs = maybeUnwrapEmpty(definition.inputs);
|
|
17097
|
+
writeableDef.inputTransforms = maybeUnwrapEmpty(definition.inputTransforms);
|
|
17098
|
+
writeableDef.declaredInputs = maybeUnwrapEmpty(definition.declaredInputs);
|
|
17099
|
+
writeableDef.outputs = maybeUnwrapEmpty(definition.outputs);
|
|
17100
|
+
// Merge hostBindings
|
|
17101
|
+
const superHostBindings = superDef.hostBindings;
|
|
17102
|
+
superHostBindings && inheritHostBindings(definition, superHostBindings);
|
|
17103
|
+
// Merge queries
|
|
17104
|
+
const superViewQuery = superDef.viewQuery;
|
|
17105
|
+
const superContentQueries = superDef.contentQueries;
|
|
17106
|
+
superViewQuery && inheritViewQuery(definition, superViewQuery);
|
|
17107
|
+
superContentQueries && inheritContentQueries(definition, superContentQueries);
|
|
17108
|
+
// Merge inputs and outputs
|
|
17109
|
+
mergeInputsWithTransforms(definition, superDef);
|
|
17110
|
+
fillProperties(definition.outputs, superDef.outputs);
|
|
17111
|
+
// Merge animations metadata.
|
|
17112
|
+
// If `superDef` is a Component, the `data` field is present (defaults to an empty object).
|
|
17113
|
+
if (isComponentDef(superDef) && superDef.data.animation) {
|
|
17114
|
+
// If super def is a Component, the `definition` is also a Component, since Directives can
|
|
17115
|
+
// not inherit Components (we throw an error above and cannot reach this code).
|
|
17116
|
+
const defData = definition.data;
|
|
17117
|
+
defData.animation = (defData.animation || []).concat(superDef.data.animation);
|
|
17118
|
+
}
|
|
17119
|
+
}
|
|
17120
|
+
// Run parent features
|
|
17121
|
+
const features = superDef.features;
|
|
17122
|
+
if (features) {
|
|
17123
|
+
for (let i = 0; i < features.length; i++) {
|
|
17124
|
+
const feature = features[i];
|
|
17125
|
+
if (feature && feature.ngInherit) {
|
|
17126
|
+
feature(definition);
|
|
17127
|
+
}
|
|
17128
|
+
// If `InheritDefinitionFeature` is a part of the current `superDef`, it means that this
|
|
17129
|
+
// def already has all the necessary information inherited from its super class(es), so we
|
|
17130
|
+
// can stop merging fields from super classes. However we need to iterate through the
|
|
17131
|
+
// prototype chain to look for classes that might contain other "features" (like
|
|
17132
|
+
// NgOnChanges), which we should invoke for the original `definition`. We set the
|
|
17133
|
+
// `shouldInheritFields` flag to indicate that, essentially skipping fields inheritance
|
|
17134
|
+
// logic and only invoking functions from the "features" list.
|
|
17135
|
+
if (feature === ɵɵInheritDefinitionFeature) {
|
|
17136
|
+
shouldInheritFields = false;
|
|
17137
|
+
}
|
|
17138
|
+
}
|
|
17139
|
+
}
|
|
17140
|
+
}
|
|
17141
|
+
superType = Object.getPrototypeOf(superType);
|
|
17142
|
+
}
|
|
17143
|
+
mergeHostAttrsAcrossInheritance(inheritanceChain);
|
|
17144
|
+
}
|
|
17145
|
+
function mergeInputsWithTransforms(target, source) {
|
|
17146
|
+
for (const key in source.inputs) {
|
|
17147
|
+
if (!source.inputs.hasOwnProperty(key)) {
|
|
17148
|
+
continue;
|
|
17149
|
+
}
|
|
17150
|
+
if (target.inputs.hasOwnProperty(key)) {
|
|
17151
|
+
continue;
|
|
17152
|
+
}
|
|
17153
|
+
const value = source.inputs[key];
|
|
17154
|
+
if (value === undefined) {
|
|
17155
|
+
continue;
|
|
17156
|
+
}
|
|
17157
|
+
target.inputs[key] = value;
|
|
17158
|
+
target.declaredInputs[key] = source.declaredInputs[key];
|
|
17159
|
+
// If the input is inherited, and we have a transform for it, we also inherit it.
|
|
17160
|
+
// Note that transforms should not be inherited if the input has its own metadata
|
|
17161
|
+
// in the `source` directive itself already (i.e. the input is re-declared/overridden).
|
|
17162
|
+
if (source.inputTransforms !== null) {
|
|
17163
|
+
// Note: transforms are stored with their minified names.
|
|
17164
|
+
// Perf: only access the minified name when there are source transforms.
|
|
17165
|
+
const minifiedName = Array.isArray(value) ? value[0] : value;
|
|
17166
|
+
if (!source.inputTransforms.hasOwnProperty(minifiedName)) {
|
|
17167
|
+
continue;
|
|
17168
|
+
}
|
|
17169
|
+
target.inputTransforms ??= {};
|
|
17170
|
+
target.inputTransforms[minifiedName] = source.inputTransforms[minifiedName];
|
|
17171
|
+
}
|
|
17172
|
+
}
|
|
17173
|
+
}
|
|
17174
|
+
/**
|
|
17175
|
+
* Merge the `hostAttrs` and `hostVars` from the inherited parent to the base class.
|
|
17176
|
+
*
|
|
17177
|
+
* @param inheritanceChain A list of `WritableDefs` starting at the top most type and listing
|
|
17178
|
+
* sub-types in order. For each type take the `hostAttrs` and `hostVars` and merge it with the child
|
|
17179
|
+
* type.
|
|
17180
|
+
*/
|
|
17181
|
+
function mergeHostAttrsAcrossInheritance(inheritanceChain) {
|
|
17182
|
+
let hostVars = 0;
|
|
17183
|
+
let hostAttrs = null;
|
|
17184
|
+
// We process the inheritance order from the base to the leaves here.
|
|
17185
|
+
for (let i = inheritanceChain.length - 1; i >= 0; i--) {
|
|
17186
|
+
const def = inheritanceChain[i];
|
|
17187
|
+
// For each `hostVars`, we need to add the superclass amount.
|
|
17188
|
+
def.hostVars = (hostVars += def.hostVars);
|
|
17189
|
+
// for each `hostAttrs` we need to merge it with superclass.
|
|
17190
|
+
def.hostAttrs =
|
|
17191
|
+
mergeHostAttrs(def.hostAttrs, hostAttrs = mergeHostAttrs(hostAttrs, def.hostAttrs));
|
|
17192
|
+
}
|
|
17193
|
+
}
|
|
17194
|
+
function maybeUnwrapEmpty(value) {
|
|
17195
|
+
if (value === EMPTY_OBJ) {
|
|
17196
|
+
return {};
|
|
17197
|
+
}
|
|
17198
|
+
else if (value === EMPTY_ARRAY) {
|
|
17199
|
+
return [];
|
|
17200
|
+
}
|
|
17201
|
+
else {
|
|
17202
|
+
return value;
|
|
17203
|
+
}
|
|
17204
|
+
}
|
|
17205
|
+
function inheritViewQuery(definition, superViewQuery) {
|
|
17206
|
+
const prevViewQuery = definition.viewQuery;
|
|
17207
|
+
if (prevViewQuery) {
|
|
17208
|
+
definition.viewQuery = (rf, ctx) => {
|
|
17209
|
+
superViewQuery(rf, ctx);
|
|
17210
|
+
prevViewQuery(rf, ctx);
|
|
17211
|
+
};
|
|
17212
|
+
}
|
|
17213
|
+
else {
|
|
17214
|
+
definition.viewQuery = superViewQuery;
|
|
17215
|
+
}
|
|
17216
|
+
}
|
|
17217
|
+
function inheritContentQueries(definition, superContentQueries) {
|
|
17218
|
+
const prevContentQueries = definition.contentQueries;
|
|
17219
|
+
if (prevContentQueries) {
|
|
17220
|
+
definition.contentQueries = (rf, ctx, directiveIndex) => {
|
|
17221
|
+
superContentQueries(rf, ctx, directiveIndex);
|
|
17222
|
+
prevContentQueries(rf, ctx, directiveIndex);
|
|
17223
|
+
};
|
|
17224
|
+
}
|
|
17225
|
+
else {
|
|
17226
|
+
definition.contentQueries = superContentQueries;
|
|
17227
|
+
}
|
|
17453
17228
|
}
|
|
17454
|
-
function
|
|
17455
|
-
|
|
17229
|
+
function inheritHostBindings(definition, superHostBindings) {
|
|
17230
|
+
const prevHostBindings = definition.hostBindings;
|
|
17231
|
+
if (prevHostBindings) {
|
|
17232
|
+
definition.hostBindings = (rf, ctx) => {
|
|
17233
|
+
superHostBindings(rf, ctx);
|
|
17234
|
+
prevHostBindings(rf, ctx);
|
|
17235
|
+
};
|
|
17236
|
+
}
|
|
17237
|
+
else {
|
|
17238
|
+
definition.hostBindings = superHostBindings;
|
|
17239
|
+
}
|
|
17456
17240
|
}
|
|
17457
17241
|
|
|
17458
17242
|
/**
|
|
17459
|
-
*
|
|
17243
|
+
* Fields which exist on either directive or component definitions, and need to be copied from
|
|
17244
|
+
* parent to child classes by the `ɵɵCopyDefinitionFeature`.
|
|
17460
17245
|
*/
|
|
17461
|
-
const
|
|
17246
|
+
const COPY_DIRECTIVE_FIELDS = [
|
|
17247
|
+
// The child class should use the providers of its parent.
|
|
17248
|
+
'providersResolver',
|
|
17249
|
+
// Not listed here are any fields which are handled by the `ɵɵInheritDefinitionFeature`, such
|
|
17250
|
+
// as inputs, outputs, and host binding functions.
|
|
17251
|
+
];
|
|
17462
17252
|
/**
|
|
17463
|
-
*
|
|
17253
|
+
* Fields which exist only on component definitions, and need to be copied from parent to child
|
|
17254
|
+
* classes by the `ɵɵCopyDefinitionFeature`.
|
|
17464
17255
|
*
|
|
17465
|
-
*
|
|
17256
|
+
* The type here allows any field of `ComponentDef` which is not also a property of `DirectiveDef`,
|
|
17257
|
+
* since those should go in `COPY_DIRECTIVE_FIELDS` above.
|
|
17466
17258
|
*/
|
|
17467
|
-
|
|
17468
|
-
function
|
|
17469
|
-
|
|
17470
|
-
|
|
17259
|
+
const COPY_COMPONENT_FIELDS = [
|
|
17260
|
+
// The child class should use the template function of its parent, including all template
|
|
17261
|
+
// semantics.
|
|
17262
|
+
'template',
|
|
17263
|
+
'decls',
|
|
17264
|
+
'consts',
|
|
17265
|
+
'vars',
|
|
17266
|
+
'onPush',
|
|
17267
|
+
'ngContentSelectors',
|
|
17268
|
+
// The child class should use the CSS styles of its parent, including all styling semantics.
|
|
17269
|
+
'styles',
|
|
17270
|
+
'encapsulation',
|
|
17271
|
+
// The child class should be checked by the runtime in the same way as its parent.
|
|
17272
|
+
'schemas',
|
|
17273
|
+
];
|
|
17274
|
+
/**
|
|
17275
|
+
* Copies the fields not handled by the `ɵɵInheritDefinitionFeature` from the supertype of a
|
|
17276
|
+
* definition.
|
|
17277
|
+
*
|
|
17278
|
+
* This exists primarily to support ngcc migration of an existing View Engine pattern, where an
|
|
17279
|
+
* entire decorator is inherited from a parent to a child class. When ngcc detects this case, it
|
|
17280
|
+
* generates a skeleton definition on the child class, and applies this feature.
|
|
17281
|
+
*
|
|
17282
|
+
* The `ɵɵCopyDefinitionFeature` then copies any needed fields from the parent class' definition,
|
|
17283
|
+
* including things like the component template function.
|
|
17284
|
+
*
|
|
17285
|
+
* @param definition The definition of a child class which inherits from a parent class with its
|
|
17286
|
+
* own definition.
|
|
17287
|
+
*
|
|
17288
|
+
* @codeGenApi
|
|
17289
|
+
*/
|
|
17290
|
+
function ɵɵCopyDefinitionFeature(definition) {
|
|
17291
|
+
let superType = getSuperType(definition.type);
|
|
17292
|
+
let superDef = undefined;
|
|
17293
|
+
if (isComponentDef(definition)) {
|
|
17294
|
+
// Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.
|
|
17295
|
+
superDef = superType.ɵcmp;
|
|
17296
|
+
}
|
|
17297
|
+
else {
|
|
17298
|
+
// Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.
|
|
17299
|
+
superDef = superType.ɵdir;
|
|
17300
|
+
}
|
|
17301
|
+
// Needed because `definition` fields are readonly.
|
|
17302
|
+
const defAny = definition;
|
|
17303
|
+
// Copy over any fields that apply to either directives or components.
|
|
17304
|
+
for (const field of COPY_DIRECTIVE_FIELDS) {
|
|
17305
|
+
defAny[field] = superDef[field];
|
|
17306
|
+
}
|
|
17307
|
+
if (isComponentDef(superDef)) {
|
|
17308
|
+
// Copy over any component-specific fields.
|
|
17309
|
+
for (const field of COPY_COMPONENT_FIELDS) {
|
|
17310
|
+
defAny[field] = superDef[field];
|
|
17311
|
+
}
|
|
17471
17312
|
}
|
|
17472
17313
|
}
|
|
17314
|
+
|
|
17473
17315
|
/**
|
|
17474
|
-
*
|
|
17316
|
+
* This feature adds the host directives behavior to a directive definition by patching a
|
|
17317
|
+
* function onto it. The expectation is that the runtime will invoke the function during
|
|
17318
|
+
* directive matching.
|
|
17475
17319
|
*
|
|
17476
|
-
*
|
|
17477
|
-
*
|
|
17478
|
-
*
|
|
17479
|
-
*
|
|
17320
|
+
* For example:
|
|
17321
|
+
* ```ts
|
|
17322
|
+
* class ComponentWithHostDirective {
|
|
17323
|
+
* static ɵcmp = defineComponent({
|
|
17324
|
+
* type: ComponentWithHostDirective,
|
|
17325
|
+
* features: [ɵɵHostDirectivesFeature([
|
|
17326
|
+
* SimpleHostDirective,
|
|
17327
|
+
* {directive: AdvancedHostDirective, inputs: ['foo: alias'], outputs: ['bar']},
|
|
17328
|
+
* ])]
|
|
17329
|
+
* });
|
|
17330
|
+
* }
|
|
17331
|
+
* ```
|
|
17480
17332
|
*
|
|
17481
17333
|
* @codeGenApi
|
|
17482
17334
|
*/
|
|
17483
|
-
function
|
|
17484
|
-
const
|
|
17485
|
-
|
|
17486
|
-
|
|
17335
|
+
function ɵɵHostDirectivesFeature(rawHostDirectives) {
|
|
17336
|
+
const feature = (definition) => {
|
|
17337
|
+
const resolved = (Array.isArray(rawHostDirectives) ? rawHostDirectives : rawHostDirectives()).map(dir => {
|
|
17338
|
+
return typeof dir === 'function' ?
|
|
17339
|
+
{ directive: resolveForwardRef(dir), inputs: EMPTY_OBJ, outputs: EMPTY_OBJ } :
|
|
17340
|
+
{
|
|
17341
|
+
directive: resolveForwardRef(dir.directive),
|
|
17342
|
+
inputs: bindingArrayToMap(dir.inputs),
|
|
17343
|
+
outputs: bindingArrayToMap(dir.outputs)
|
|
17344
|
+
};
|
|
17345
|
+
});
|
|
17346
|
+
if (definition.hostDirectives === null) {
|
|
17347
|
+
definition.findHostDirectiveDefs = findHostDirectiveDefs;
|
|
17348
|
+
definition.hostDirectives = resolved;
|
|
17349
|
+
}
|
|
17350
|
+
else {
|
|
17351
|
+
definition.hostDirectives.unshift(...resolved);
|
|
17352
|
+
}
|
|
17353
|
+
};
|
|
17354
|
+
feature.ngInherit = true;
|
|
17355
|
+
return feature;
|
|
17487
17356
|
}
|
|
17488
|
-
function
|
|
17489
|
-
|
|
17357
|
+
function findHostDirectiveDefs(currentDef, matchedDefs, hostDirectiveDefs) {
|
|
17358
|
+
if (currentDef.hostDirectives !== null) {
|
|
17359
|
+
for (const hostDirectiveConfig of currentDef.hostDirectives) {
|
|
17360
|
+
const hostDirectiveDef = getDirectiveDef(hostDirectiveConfig.directive);
|
|
17361
|
+
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
17362
|
+
validateHostDirective(hostDirectiveConfig, hostDirectiveDef);
|
|
17363
|
+
}
|
|
17364
|
+
// We need to patch the `declaredInputs` so that
|
|
17365
|
+
// `ngOnChanges` can map the properties correctly.
|
|
17366
|
+
patchDeclaredInputs(hostDirectiveDef.declaredInputs, hostDirectiveConfig.inputs);
|
|
17367
|
+
// Host directives execute before the host so that its host bindings can be overwritten.
|
|
17368
|
+
findHostDirectiveDefs(hostDirectiveDef, matchedDefs, hostDirectiveDefs);
|
|
17369
|
+
hostDirectiveDefs.set(hostDirectiveDef, hostDirectiveConfig);
|
|
17370
|
+
matchedDefs.push(hostDirectiveDef);
|
|
17371
|
+
}
|
|
17372
|
+
}
|
|
17490
17373
|
}
|
|
17491
|
-
|
|
17492
|
-
|
|
17374
|
+
/**
|
|
17375
|
+
* Converts an array in the form of `['publicName', 'alias', 'otherPublicName', 'otherAlias']` into
|
|
17376
|
+
* a map in the form of `{publicName: 'alias', otherPublicName: 'otherAlias'}`.
|
|
17377
|
+
*/
|
|
17378
|
+
function bindingArrayToMap(bindings) {
|
|
17379
|
+
if (bindings === undefined || bindings.length === 0) {
|
|
17380
|
+
return EMPTY_OBJ;
|
|
17381
|
+
}
|
|
17382
|
+
const result = {};
|
|
17383
|
+
for (let i = 0; i < bindings.length; i += 2) {
|
|
17384
|
+
result[bindings[i]] = bindings[i + 1];
|
|
17385
|
+
}
|
|
17386
|
+
return result;
|
|
17493
17387
|
}
|
|
17494
17388
|
/**
|
|
17495
|
-
*
|
|
17496
|
-
*
|
|
17389
|
+
* `ngOnChanges` has some leftover legacy ViewEngine behavior where the keys inside the
|
|
17390
|
+
* `SimpleChanges` event refer to the *declared* name of the input, not its public name or its
|
|
17391
|
+
* minified name. E.g. in `@Input('alias') foo: string`, the name in the `SimpleChanges` object
|
|
17392
|
+
* will always be `foo`, and not `alias` or the minified name of `foo` in apps using property
|
|
17393
|
+
* minification.
|
|
17497
17394
|
*
|
|
17498
|
-
* This is
|
|
17499
|
-
*
|
|
17395
|
+
* This is achieved through the `DirectiveDef.declaredInputs` map that is constructed when the
|
|
17396
|
+
* definition is declared. When a property is written to the directive instance, the
|
|
17397
|
+
* `NgOnChangesFeature` will try to remap the property name being written to using the
|
|
17398
|
+
* `declaredInputs`.
|
|
17399
|
+
*
|
|
17400
|
+
* Since the host directive input remapping happens during directive matching, `declaredInputs`
|
|
17401
|
+
* won't contain the new alias that the input is available under. This function addresses the
|
|
17402
|
+
* issue by patching the host directive aliases to the `declaredInputs`. There is *not* a risk of
|
|
17403
|
+
* this patching accidentally introducing new inputs to the host directive, because `declaredInputs`
|
|
17404
|
+
* is used *only* by the `NgOnChangesFeature` when determining what name is used in the
|
|
17405
|
+
* `SimpleChanges` object which won't be reached if an input doesn't exist.
|
|
17500
17406
|
*/
|
|
17501
|
-
function
|
|
17502
|
-
|
|
17407
|
+
function patchDeclaredInputs(declaredInputs, exposedInputs) {
|
|
17408
|
+
for (const publicName in exposedInputs) {
|
|
17409
|
+
if (exposedInputs.hasOwnProperty(publicName)) {
|
|
17410
|
+
const remappedPublicName = exposedInputs[publicName];
|
|
17411
|
+
const privateName = declaredInputs[publicName];
|
|
17412
|
+
// We *technically* shouldn't be able to hit this case because we can't have multiple
|
|
17413
|
+
// inputs on the same property and we have validations against conflicting aliases in
|
|
17414
|
+
// `validateMappings`. If we somehow did, it would lead to `ngOnChanges` being invoked
|
|
17415
|
+
// with the wrong name so we have a non-user-friendly assertion here just in case.
|
|
17416
|
+
if ((typeof ngDevMode === 'undefined' || ngDevMode) &&
|
|
17417
|
+
declaredInputs.hasOwnProperty(remappedPublicName)) {
|
|
17418
|
+
assertEqual(declaredInputs[remappedPublicName], declaredInputs[publicName], `Conflicting host directive input alias ${publicName}.`);
|
|
17419
|
+
}
|
|
17420
|
+
declaredInputs[remappedPublicName] = privateName;
|
|
17421
|
+
}
|
|
17422
|
+
}
|
|
17423
|
+
}
|
|
17424
|
+
/**
|
|
17425
|
+
* Verifies that the host directive has been configured correctly.
|
|
17426
|
+
* @param hostDirectiveConfig Host directive configuration object.
|
|
17427
|
+
* @param directiveDef Directive definition of the host directive.
|
|
17428
|
+
*/
|
|
17429
|
+
function validateHostDirective(hostDirectiveConfig, directiveDef) {
|
|
17430
|
+
const type = hostDirectiveConfig.directive;
|
|
17431
|
+
if (directiveDef === null) {
|
|
17432
|
+
if (getComponentDef(type) !== null) {
|
|
17433
|
+
throw new RuntimeError(310 /* RuntimeErrorCode.HOST_DIRECTIVE_COMPONENT */, `Host directive ${type.name} cannot be a component.`);
|
|
17434
|
+
}
|
|
17435
|
+
throw new RuntimeError(307 /* RuntimeErrorCode.HOST_DIRECTIVE_UNRESOLVABLE */, `Could not resolve metadata for host directive ${type.name}. ` +
|
|
17436
|
+
`Make sure that the ${type.name} class is annotated with an @Directive decorator.`);
|
|
17437
|
+
}
|
|
17438
|
+
if (!directiveDef.standalone) {
|
|
17439
|
+
throw new RuntimeError(308 /* RuntimeErrorCode.HOST_DIRECTIVE_NOT_STANDALONE */, `Host directive ${directiveDef.type.name} must be standalone.`);
|
|
17440
|
+
}
|
|
17441
|
+
validateMappings('input', directiveDef, hostDirectiveConfig.inputs);
|
|
17442
|
+
validateMappings('output', directiveDef, hostDirectiveConfig.outputs);
|
|
17443
|
+
}
|
|
17444
|
+
/**
|
|
17445
|
+
* Checks that the host directive inputs/outputs configuration is valid.
|
|
17446
|
+
* @param bindingType Kind of binding that is being validated. Used in the error message.
|
|
17447
|
+
* @param def Definition of the host directive that is being validated against.
|
|
17448
|
+
* @param hostDirectiveBindings Host directive mapping object that shold be validated.
|
|
17449
|
+
*/
|
|
17450
|
+
function validateMappings(bindingType, def, hostDirectiveBindings) {
|
|
17451
|
+
const className = def.type.name;
|
|
17452
|
+
const bindings = bindingType === 'input' ? def.inputs : def.outputs;
|
|
17453
|
+
for (const publicName in hostDirectiveBindings) {
|
|
17454
|
+
if (hostDirectiveBindings.hasOwnProperty(publicName)) {
|
|
17455
|
+
if (!bindings.hasOwnProperty(publicName)) {
|
|
17456
|
+
throw new RuntimeError(311 /* RuntimeErrorCode.HOST_DIRECTIVE_UNDEFINED_BINDING */, `Directive ${className} does not have an ${bindingType} with a public name of ${publicName}.`);
|
|
17457
|
+
}
|
|
17458
|
+
const remappedPublicName = hostDirectiveBindings[publicName];
|
|
17459
|
+
if (bindings.hasOwnProperty(remappedPublicName) && remappedPublicName !== publicName) {
|
|
17460
|
+
throw new RuntimeError(312 /* RuntimeErrorCode.HOST_DIRECTIVE_CONFLICTING_ALIAS */, `Cannot alias ${bindingType} ${publicName} of host directive ${className} to ${remappedPublicName}, because it already has a different ${bindingType} with the same public name.`);
|
|
17461
|
+
}
|
|
17462
|
+
}
|
|
17463
|
+
}
|
|
17503
17464
|
}
|
|
17504
17465
|
|
|
17505
17466
|
/**
|
|
17506
|
-
*
|
|
17507
|
-
*
|
|
17508
|
-
*
|
|
17509
|
-
* `
|
|
17510
|
-
* of such attributes.
|
|
17467
|
+
* Decorates the directive definition with support for input transform functions.
|
|
17468
|
+
*
|
|
17469
|
+
* If the directive uses inheritance, the feature should be included before the
|
|
17470
|
+
* `InheritDefinitionFeature` to ensure that the `inputTransforms` field is populated.
|
|
17511
17471
|
*
|
|
17512
17472
|
* @codeGenApi
|
|
17513
17473
|
*/
|
|
17514
|
-
function
|
|
17515
|
-
const
|
|
17516
|
-
const
|
|
17517
|
-
const
|
|
17518
|
-
|
|
17519
|
-
|
|
17520
|
-
|
|
17521
|
-
|
|
17522
|
-
|
|
17523
|
-
|
|
17524
|
-
|
|
17525
|
-
|
|
17526
|
-
// Also remove the <iframe> from the document.
|
|
17527
|
-
nativeRemoveNode(lView[RENDERER], iframe);
|
|
17528
|
-
const errorMessage = ngDevMode &&
|
|
17529
|
-
`Angular has detected that the \`${attrName}\` was applied ` +
|
|
17530
|
-
`as a binding to an <iframe>${getTemplateLocationDetails(lView)}. ` +
|
|
17531
|
-
`For security reasons, the \`${attrName}\` can be set on an <iframe> ` +
|
|
17532
|
-
`as a static attribute only. \n` +
|
|
17533
|
-
`To fix this, switch the \`${attrName}\` binding to a static attribute ` +
|
|
17534
|
-
`in a template or in host bindings section.`;
|
|
17535
|
-
throw new RuntimeError(-910 /* RuntimeErrorCode.UNSAFE_IFRAME_ATTRS */, errorMessage);
|
|
17474
|
+
function ɵɵInputTransformsFeature(definition) {
|
|
17475
|
+
const inputs = definition.inputConfig;
|
|
17476
|
+
const inputTransforms = {};
|
|
17477
|
+
for (const minifiedKey in inputs) {
|
|
17478
|
+
if (inputs.hasOwnProperty(minifiedKey)) {
|
|
17479
|
+
// Note: the private names are used for the keys, rather than the public ones, because public
|
|
17480
|
+
// names can be re-aliased in host directives which would invalidate the lookup.
|
|
17481
|
+
const value = inputs[minifiedKey];
|
|
17482
|
+
if (Array.isArray(value) && value[3]) {
|
|
17483
|
+
inputTransforms[minifiedKey] = value[3];
|
|
17484
|
+
}
|
|
17485
|
+
}
|
|
17536
17486
|
}
|
|
17537
|
-
|
|
17487
|
+
definition.inputTransforms = inputTransforms;
|
|
17538
17488
|
}
|
|
17539
17489
|
|
|
17540
|
-
function getSuperType(type) {
|
|
17541
|
-
return Object.getPrototypeOf(type.prototype).constructor;
|
|
17542
|
-
}
|
|
17543
17490
|
/**
|
|
17544
|
-
*
|
|
17545
|
-
*
|
|
17491
|
+
* Represents an instance of an `NgModule` created by an `NgModuleFactory`.
|
|
17492
|
+
* Provides access to the `NgModule` instance and related objects.
|
|
17546
17493
|
*
|
|
17547
|
-
* @
|
|
17494
|
+
* @publicApi
|
|
17548
17495
|
*/
|
|
17549
|
-
|
|
17550
|
-
let superType = getSuperType(definition.type);
|
|
17551
|
-
let shouldInheritFields = true;
|
|
17552
|
-
const inheritanceChain = [definition];
|
|
17553
|
-
while (superType) {
|
|
17554
|
-
let superDef = undefined;
|
|
17555
|
-
if (isComponentDef(definition)) {
|
|
17556
|
-
// Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.
|
|
17557
|
-
superDef = superType.ɵcmp || superType.ɵdir;
|
|
17558
|
-
}
|
|
17559
|
-
else {
|
|
17560
|
-
if (superType.ɵcmp) {
|
|
17561
|
-
throw new RuntimeError(903 /* RuntimeErrorCode.INVALID_INHERITANCE */, ngDevMode &&
|
|
17562
|
-
`Directives cannot inherit Components. Directive ${stringifyForError(definition.type)} is attempting to extend component ${stringifyForError(superType)}`);
|
|
17563
|
-
}
|
|
17564
|
-
// Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.
|
|
17565
|
-
superDef = superType.ɵdir;
|
|
17566
|
-
}
|
|
17567
|
-
if (superDef) {
|
|
17568
|
-
if (shouldInheritFields) {
|
|
17569
|
-
inheritanceChain.push(superDef);
|
|
17570
|
-
// Some fields in the definition may be empty, if there were no values to put in them that
|
|
17571
|
-
// would've justified object creation. Unwrap them if necessary.
|
|
17572
|
-
const writeableDef = definition;
|
|
17573
|
-
writeableDef.inputs = maybeUnwrapEmpty(definition.inputs);
|
|
17574
|
-
writeableDef.inputTransforms = maybeUnwrapEmpty(definition.inputTransforms);
|
|
17575
|
-
writeableDef.declaredInputs = maybeUnwrapEmpty(definition.declaredInputs);
|
|
17576
|
-
writeableDef.outputs = maybeUnwrapEmpty(definition.outputs);
|
|
17577
|
-
// Merge hostBindings
|
|
17578
|
-
const superHostBindings = superDef.hostBindings;
|
|
17579
|
-
superHostBindings && inheritHostBindings(definition, superHostBindings);
|
|
17580
|
-
// Merge queries
|
|
17581
|
-
const superViewQuery = superDef.viewQuery;
|
|
17582
|
-
const superContentQueries = superDef.contentQueries;
|
|
17583
|
-
superViewQuery && inheritViewQuery(definition, superViewQuery);
|
|
17584
|
-
superContentQueries && inheritContentQueries(definition, superContentQueries);
|
|
17585
|
-
// Merge inputs and outputs
|
|
17586
|
-
mergeInputsWithTransforms(definition, superDef);
|
|
17587
|
-
fillProperties(definition.outputs, superDef.outputs);
|
|
17588
|
-
// Merge animations metadata.
|
|
17589
|
-
// If `superDef` is a Component, the `data` field is present (defaults to an empty object).
|
|
17590
|
-
if (isComponentDef(superDef) && superDef.data.animation) {
|
|
17591
|
-
// If super def is a Component, the `definition` is also a Component, since Directives can
|
|
17592
|
-
// not inherit Components (we throw an error above and cannot reach this code).
|
|
17593
|
-
const defData = definition.data;
|
|
17594
|
-
defData.animation = (defData.animation || []).concat(superDef.data.animation);
|
|
17595
|
-
}
|
|
17596
|
-
}
|
|
17597
|
-
// Run parent features
|
|
17598
|
-
const features = superDef.features;
|
|
17599
|
-
if (features) {
|
|
17600
|
-
for (let i = 0; i < features.length; i++) {
|
|
17601
|
-
const feature = features[i];
|
|
17602
|
-
if (feature && feature.ngInherit) {
|
|
17603
|
-
feature(definition);
|
|
17604
|
-
}
|
|
17605
|
-
// If `InheritDefinitionFeature` is a part of the current `superDef`, it means that this
|
|
17606
|
-
// def already has all the necessary information inherited from its super class(es), so we
|
|
17607
|
-
// can stop merging fields from super classes. However we need to iterate through the
|
|
17608
|
-
// prototype chain to look for classes that might contain other "features" (like
|
|
17609
|
-
// NgOnChanges), which we should invoke for the original `definition`. We set the
|
|
17610
|
-
// `shouldInheritFields` flag to indicate that, essentially skipping fields inheritance
|
|
17611
|
-
// logic and only invoking functions from the "features" list.
|
|
17612
|
-
if (feature === ɵɵInheritDefinitionFeature) {
|
|
17613
|
-
shouldInheritFields = false;
|
|
17614
|
-
}
|
|
17615
|
-
}
|
|
17616
|
-
}
|
|
17617
|
-
}
|
|
17618
|
-
superType = Object.getPrototypeOf(superType);
|
|
17619
|
-
}
|
|
17620
|
-
mergeHostAttrsAcrossInheritance(inheritanceChain);
|
|
17496
|
+
class NgModuleRef$1 {
|
|
17621
17497
|
}
|
|
17622
|
-
|
|
17623
|
-
|
|
17624
|
-
|
|
17625
|
-
|
|
17626
|
-
|
|
17627
|
-
|
|
17628
|
-
|
|
17629
|
-
|
|
17630
|
-
|
|
17631
|
-
|
|
17632
|
-
|
|
17633
|
-
|
|
17634
|
-
target.inputs[key] = value;
|
|
17635
|
-
target.declaredInputs[key] = source.declaredInputs[key];
|
|
17636
|
-
// If the input is inherited, and we have a transform for it, we also inherit it.
|
|
17637
|
-
// Note that transforms should not be inherited if the input has its own metadata
|
|
17638
|
-
// in the `source` directive itself already (i.e. the input is re-declared/overridden).
|
|
17639
|
-
if (source.inputTransforms !== null) {
|
|
17640
|
-
// Note: transforms are stored with their minified names.
|
|
17641
|
-
// Perf: only access the minified name when there are source transforms.
|
|
17642
|
-
const minifiedName = Array.isArray(value) ? value[0] : value;
|
|
17643
|
-
if (!source.inputTransforms.hasOwnProperty(minifiedName)) {
|
|
17644
|
-
continue;
|
|
17645
|
-
}
|
|
17646
|
-
target.inputTransforms ??= {};
|
|
17647
|
-
target.inputTransforms[minifiedName] = source.inputTransforms[minifiedName];
|
|
17648
|
-
}
|
|
17649
|
-
}
|
|
17498
|
+
/**
|
|
17499
|
+
* @publicApi
|
|
17500
|
+
*
|
|
17501
|
+
* @deprecated
|
|
17502
|
+
* This class was mostly used as a part of ViewEngine-based JIT API and is no longer needed in Ivy
|
|
17503
|
+
* JIT mode. See [JIT API changes due to ViewEngine deprecation](guide/deprecations#jit-api-changes)
|
|
17504
|
+
* for additional context. Angular provides APIs that accept NgModule classes directly (such as
|
|
17505
|
+
* [PlatformRef.bootstrapModule](api/core/PlatformRef#bootstrapModule) and
|
|
17506
|
+
* [createNgModule](api/core/createNgModule)), consider switching to those APIs instead of
|
|
17507
|
+
* using factory-based ones.
|
|
17508
|
+
*/
|
|
17509
|
+
class NgModuleFactory$1 {
|
|
17650
17510
|
}
|
|
17511
|
+
|
|
17651
17512
|
/**
|
|
17652
|
-
*
|
|
17513
|
+
* Returns a new NgModuleRef instance based on the NgModule class and parent injector provided.
|
|
17653
17514
|
*
|
|
17654
|
-
* @param
|
|
17655
|
-
*
|
|
17656
|
-
*
|
|
17515
|
+
* @param ngModule NgModule class.
|
|
17516
|
+
* @param parentInjector Optional injector instance to use as a parent for the module injector. If
|
|
17517
|
+
* not provided, `NullInjector` will be used instead.
|
|
17518
|
+
* @returns NgModuleRef that represents an NgModule instance.
|
|
17519
|
+
*
|
|
17520
|
+
* @publicApi
|
|
17657
17521
|
*/
|
|
17658
|
-
function
|
|
17659
|
-
|
|
17660
|
-
let hostAttrs = null;
|
|
17661
|
-
// We process the inheritance order from the base to the leaves here.
|
|
17662
|
-
for (let i = inheritanceChain.length - 1; i >= 0; i--) {
|
|
17663
|
-
const def = inheritanceChain[i];
|
|
17664
|
-
// For each `hostVars`, we need to add the superclass amount.
|
|
17665
|
-
def.hostVars = (hostVars += def.hostVars);
|
|
17666
|
-
// for each `hostAttrs` we need to merge it with superclass.
|
|
17667
|
-
def.hostAttrs =
|
|
17668
|
-
mergeHostAttrs(def.hostAttrs, hostAttrs = mergeHostAttrs(hostAttrs, def.hostAttrs));
|
|
17669
|
-
}
|
|
17522
|
+
function createNgModule(ngModule, parentInjector) {
|
|
17523
|
+
return new NgModuleRef(ngModule, parentInjector ?? null, []);
|
|
17670
17524
|
}
|
|
17671
|
-
|
|
17672
|
-
|
|
17673
|
-
|
|
17674
|
-
|
|
17675
|
-
|
|
17676
|
-
|
|
17525
|
+
/**
|
|
17526
|
+
* The `createNgModule` function alias for backwards-compatibility.
|
|
17527
|
+
* Please avoid using it directly and use `createNgModule` instead.
|
|
17528
|
+
*
|
|
17529
|
+
* @deprecated Use `createNgModule` instead.
|
|
17530
|
+
*/
|
|
17531
|
+
const createNgModuleRef = createNgModule;
|
|
17532
|
+
class NgModuleRef extends NgModuleRef$1 {
|
|
17533
|
+
constructor(ngModuleType, _parent, additionalProviders) {
|
|
17534
|
+
super();
|
|
17535
|
+
this._parent = _parent;
|
|
17536
|
+
// tslint:disable-next-line:require-internal-with-underscore
|
|
17537
|
+
this._bootstrapComponents = [];
|
|
17538
|
+
this.destroyCbs = [];
|
|
17539
|
+
// When bootstrapping a module we have a dependency graph that looks like this:
|
|
17540
|
+
// ApplicationRef -> ComponentFactoryResolver -> NgModuleRef. The problem is that if the
|
|
17541
|
+
// module being resolved tries to inject the ComponentFactoryResolver, it'll create a
|
|
17542
|
+
// circular dependency which will result in a runtime error, because the injector doesn't
|
|
17543
|
+
// exist yet. We work around the issue by creating the ComponentFactoryResolver ourselves
|
|
17544
|
+
// and providing it, rather than letting the injector resolve it.
|
|
17545
|
+
this.componentFactoryResolver = new ComponentFactoryResolver(this);
|
|
17546
|
+
const ngModuleDef = getNgModuleDef(ngModuleType);
|
|
17547
|
+
ngDevMode &&
|
|
17548
|
+
assertDefined(ngModuleDef, `NgModule '${stringify(ngModuleType)}' is not a subtype of 'NgModuleType'.`);
|
|
17549
|
+
this._bootstrapComponents = maybeUnwrapFn(ngModuleDef.bootstrap);
|
|
17550
|
+
this._r3Injector = createInjectorWithoutInjectorInstances(ngModuleType, _parent, [
|
|
17551
|
+
{ provide: NgModuleRef$1, useValue: this }, {
|
|
17552
|
+
provide: ComponentFactoryResolver$1,
|
|
17553
|
+
useValue: this.componentFactoryResolver
|
|
17554
|
+
},
|
|
17555
|
+
...additionalProviders
|
|
17556
|
+
], stringify(ngModuleType), new Set(['environment']));
|
|
17557
|
+
// We need to resolve the injector types separately from the injector creation, because
|
|
17558
|
+
// the module might be trying to use this ref in its constructor for DI which will cause a
|
|
17559
|
+
// circular error that will eventually error out, because the injector isn't created yet.
|
|
17560
|
+
this._r3Injector.resolveInjectorInitializers();
|
|
17561
|
+
this.instance = this._r3Injector.get(ngModuleType);
|
|
17677
17562
|
}
|
|
17678
|
-
|
|
17679
|
-
return
|
|
17563
|
+
get injector() {
|
|
17564
|
+
return this._r3Injector;
|
|
17680
17565
|
}
|
|
17681
|
-
|
|
17682
|
-
|
|
17683
|
-
|
|
17684
|
-
|
|
17685
|
-
|
|
17686
|
-
|
|
17687
|
-
prevViewQuery(rf, ctx);
|
|
17688
|
-
};
|
|
17566
|
+
destroy() {
|
|
17567
|
+
ngDevMode && assertDefined(this.destroyCbs, 'NgModule already destroyed');
|
|
17568
|
+
const injector = this._r3Injector;
|
|
17569
|
+
!injector.destroyed && injector.destroy();
|
|
17570
|
+
this.destroyCbs.forEach(fn => fn());
|
|
17571
|
+
this.destroyCbs = null;
|
|
17689
17572
|
}
|
|
17690
|
-
|
|
17691
|
-
|
|
17573
|
+
onDestroy(callback) {
|
|
17574
|
+
ngDevMode && assertDefined(this.destroyCbs, 'NgModule already destroyed');
|
|
17575
|
+
this.destroyCbs.push(callback);
|
|
17692
17576
|
}
|
|
17693
17577
|
}
|
|
17694
|
-
|
|
17695
|
-
|
|
17696
|
-
|
|
17697
|
-
|
|
17698
|
-
superContentQueries(rf, ctx, directiveIndex);
|
|
17699
|
-
prevContentQueries(rf, ctx, directiveIndex);
|
|
17700
|
-
};
|
|
17578
|
+
class NgModuleFactory extends NgModuleFactory$1 {
|
|
17579
|
+
constructor(moduleType) {
|
|
17580
|
+
super();
|
|
17581
|
+
this.moduleType = moduleType;
|
|
17701
17582
|
}
|
|
17702
|
-
|
|
17703
|
-
|
|
17583
|
+
create(parentInjector) {
|
|
17584
|
+
return new NgModuleRef(this.moduleType, parentInjector, []);
|
|
17704
17585
|
}
|
|
17705
17586
|
}
|
|
17706
|
-
function
|
|
17707
|
-
|
|
17708
|
-
|
|
17709
|
-
|
|
17710
|
-
|
|
17711
|
-
|
|
17712
|
-
|
|
17587
|
+
function createNgModuleRefWithProviders(moduleType, parentInjector, additionalProviders) {
|
|
17588
|
+
return new NgModuleRef(moduleType, parentInjector, additionalProviders);
|
|
17589
|
+
}
|
|
17590
|
+
class EnvironmentNgModuleRefAdapter extends NgModuleRef$1 {
|
|
17591
|
+
constructor(config) {
|
|
17592
|
+
super();
|
|
17593
|
+
this.componentFactoryResolver = new ComponentFactoryResolver(this);
|
|
17594
|
+
this.instance = null;
|
|
17595
|
+
const injector = new R3Injector([
|
|
17596
|
+
...config.providers,
|
|
17597
|
+
{ provide: NgModuleRef$1, useValue: this },
|
|
17598
|
+
{ provide: ComponentFactoryResolver$1, useValue: this.componentFactoryResolver },
|
|
17599
|
+
], config.parent || getNullInjector(), config.debugName, new Set(['environment']));
|
|
17600
|
+
this.injector = injector;
|
|
17601
|
+
if (config.runEnvironmentInitializers) {
|
|
17602
|
+
injector.resolveInjectorInitializers();
|
|
17603
|
+
}
|
|
17713
17604
|
}
|
|
17714
|
-
|
|
17715
|
-
|
|
17605
|
+
destroy() {
|
|
17606
|
+
this.injector.destroy();
|
|
17607
|
+
}
|
|
17608
|
+
onDestroy(callback) {
|
|
17609
|
+
this.injector.onDestroy(callback);
|
|
17716
17610
|
}
|
|
17717
17611
|
}
|
|
17718
|
-
|
|
17719
|
-
/**
|
|
17720
|
-
* Fields which exist on either directive or component definitions, and need to be copied from
|
|
17721
|
-
* parent to child classes by the `ɵɵCopyDefinitionFeature`.
|
|
17722
|
-
*/
|
|
17723
|
-
const COPY_DIRECTIVE_FIELDS = [
|
|
17724
|
-
// The child class should use the providers of its parent.
|
|
17725
|
-
'providersResolver',
|
|
17726
|
-
// Not listed here are any fields which are handled by the `ɵɵInheritDefinitionFeature`, such
|
|
17727
|
-
// as inputs, outputs, and host binding functions.
|
|
17728
|
-
];
|
|
17729
|
-
/**
|
|
17730
|
-
* Fields which exist only on component definitions, and need to be copied from parent to child
|
|
17731
|
-
* classes by the `ɵɵCopyDefinitionFeature`.
|
|
17732
|
-
*
|
|
17733
|
-
* The type here allows any field of `ComponentDef` which is not also a property of `DirectiveDef`,
|
|
17734
|
-
* since those should go in `COPY_DIRECTIVE_FIELDS` above.
|
|
17735
|
-
*/
|
|
17736
|
-
const COPY_COMPONENT_FIELDS = [
|
|
17737
|
-
// The child class should use the template function of its parent, including all template
|
|
17738
|
-
// semantics.
|
|
17739
|
-
'template',
|
|
17740
|
-
'decls',
|
|
17741
|
-
'consts',
|
|
17742
|
-
'vars',
|
|
17743
|
-
'onPush',
|
|
17744
|
-
'ngContentSelectors',
|
|
17745
|
-
// The child class should use the CSS styles of its parent, including all styling semantics.
|
|
17746
|
-
'styles',
|
|
17747
|
-
'encapsulation',
|
|
17748
|
-
// The child class should be checked by the runtime in the same way as its parent.
|
|
17749
|
-
'schemas',
|
|
17750
|
-
];
|
|
17751
17612
|
/**
|
|
17752
|
-
*
|
|
17753
|
-
* definition.
|
|
17613
|
+
* Create a new environment injector.
|
|
17754
17614
|
*
|
|
17755
|
-
*
|
|
17756
|
-
*
|
|
17757
|
-
* generates a skeleton definition on the child class, and applies this feature.
|
|
17615
|
+
* Learn more about environment injectors in
|
|
17616
|
+
* [this guide](guide/standalone-components#environment-injectors).
|
|
17758
17617
|
*
|
|
17759
|
-
*
|
|
17760
|
-
*
|
|
17618
|
+
* @param providers An array of providers.
|
|
17619
|
+
* @param parent A parent environment injector.
|
|
17620
|
+
* @param debugName An optional name for this injector instance, which will be used in error
|
|
17621
|
+
* messages.
|
|
17761
17622
|
*
|
|
17762
|
-
* @
|
|
17763
|
-
|
|
17623
|
+
* @publicApi
|
|
17624
|
+
*/
|
|
17625
|
+
function createEnvironmentInjector(providers, parent, debugName = null) {
|
|
17626
|
+
const adapter = new EnvironmentNgModuleRefAdapter({ providers, parent, debugName, runEnvironmentInitializers: true });
|
|
17627
|
+
return adapter.injector;
|
|
17628
|
+
}
|
|
17629
|
+
|
|
17630
|
+
/**
|
|
17631
|
+
* A service used by the framework to create and cache injector instances.
|
|
17764
17632
|
*
|
|
17765
|
-
*
|
|
17633
|
+
* This service is used to create a single injector instance for each defer
|
|
17634
|
+
* block definition, to avoid creating an injector for each defer block instance
|
|
17635
|
+
* of a certain type.
|
|
17766
17636
|
*/
|
|
17767
|
-
|
|
17768
|
-
|
|
17769
|
-
|
|
17770
|
-
if (isComponentDef(definition)) {
|
|
17771
|
-
// Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.
|
|
17772
|
-
superDef = superType.ɵcmp;
|
|
17773
|
-
}
|
|
17774
|
-
else {
|
|
17775
|
-
// Don't use getComponentDef/getDirectiveDef. This logic relies on inheritance.
|
|
17776
|
-
superDef = superType.ɵdir;
|
|
17637
|
+
class CachedInjectorService {
|
|
17638
|
+
constructor() {
|
|
17639
|
+
this.cachedInjectors = new Map();
|
|
17777
17640
|
}
|
|
17778
|
-
|
|
17779
|
-
|
|
17780
|
-
|
|
17781
|
-
|
|
17782
|
-
|
|
17641
|
+
getOrCreateInjector(key, parentInjector, providers, debugName) {
|
|
17642
|
+
if (!this.cachedInjectors.has(key)) {
|
|
17643
|
+
const injector = providers.length > 0 ?
|
|
17644
|
+
createEnvironmentInjector(providers, parentInjector, debugName) :
|
|
17645
|
+
null;
|
|
17646
|
+
this.cachedInjectors.set(key, injector);
|
|
17647
|
+
}
|
|
17648
|
+
return this.cachedInjectors.get(key);
|
|
17783
17649
|
}
|
|
17784
|
-
|
|
17785
|
-
|
|
17786
|
-
|
|
17787
|
-
|
|
17650
|
+
ngOnDestroy() {
|
|
17651
|
+
try {
|
|
17652
|
+
for (const injector of this.cachedInjectors.values()) {
|
|
17653
|
+
if (injector !== null) {
|
|
17654
|
+
injector.destroy();
|
|
17655
|
+
}
|
|
17656
|
+
}
|
|
17657
|
+
}
|
|
17658
|
+
finally {
|
|
17659
|
+
this.cachedInjectors.clear();
|
|
17788
17660
|
}
|
|
17789
17661
|
}
|
|
17662
|
+
/** @nocollapse */
|
|
17663
|
+
static { this.ɵprov = ɵɵdefineInjectable({
|
|
17664
|
+
token: CachedInjectorService,
|
|
17665
|
+
providedIn: 'environment',
|
|
17666
|
+
factory: () => new CachedInjectorService(),
|
|
17667
|
+
}); }
|
|
17790
17668
|
}
|
|
17791
17669
|
|
|
17792
17670
|
/**
|
|
17793
|
-
*
|
|
17794
|
-
*
|
|
17795
|
-
*
|
|
17796
|
-
|
|
17797
|
-
|
|
17798
|
-
|
|
17799
|
-
*
|
|
17800
|
-
*
|
|
17801
|
-
*
|
|
17802
|
-
|
|
17803
|
-
|
|
17804
|
-
|
|
17805
|
-
|
|
17806
|
-
|
|
17807
|
-
|
|
17808
|
-
*
|
|
17671
|
+
* The name of a field that Angular monkey-patches onto a component
|
|
17672
|
+
* class to store a function that loads defer-loadable dependencies
|
|
17673
|
+
* and applies metadata to a class.
|
|
17674
|
+
*/
|
|
17675
|
+
const ASYNC_COMPONENT_METADATA_FN = '__ngAsyncComponentMetadataFn__';
|
|
17676
|
+
/**
|
|
17677
|
+
* If a given component has unresolved async metadata - returns a reference
|
|
17678
|
+
* to a function that applies component metadata after resolving defer-loadable
|
|
17679
|
+
* dependencies. Otherwise - this function returns `null`.
|
|
17680
|
+
*/
|
|
17681
|
+
function getAsyncClassMetadataFn(type) {
|
|
17682
|
+
const componentClass = type; // cast to `any`, so that we can read a monkey-patched field
|
|
17683
|
+
return componentClass[ASYNC_COMPONENT_METADATA_FN] ?? null;
|
|
17684
|
+
}
|
|
17685
|
+
/**
|
|
17686
|
+
* Handles the process of applying metadata info to a component class in case
|
|
17687
|
+
* component template has defer blocks (thus some dependencies became deferrable).
|
|
17809
17688
|
*
|
|
17810
|
-
* @
|
|
17689
|
+
* @param type Component class where metadata should be added
|
|
17690
|
+
* @param dependencyLoaderFn Function that loads dependencies
|
|
17691
|
+
* @param metadataSetterFn Function that forms a scope in which the `setClassMetadata` is invoked
|
|
17811
17692
|
*/
|
|
17812
|
-
function
|
|
17813
|
-
const
|
|
17814
|
-
|
|
17815
|
-
|
|
17816
|
-
|
|
17817
|
-
|
|
17818
|
-
|
|
17819
|
-
|
|
17820
|
-
|
|
17821
|
-
|
|
17822
|
-
});
|
|
17823
|
-
if (definition.hostDirectives === null) {
|
|
17824
|
-
definition.findHostDirectiveDefs = findHostDirectiveDefs;
|
|
17825
|
-
definition.hostDirectives = resolved;
|
|
17826
|
-
}
|
|
17827
|
-
else {
|
|
17828
|
-
definition.hostDirectives.unshift(...resolved);
|
|
17829
|
-
}
|
|
17830
|
-
};
|
|
17831
|
-
feature.ngInherit = true;
|
|
17832
|
-
return feature;
|
|
17693
|
+
function setClassMetadataAsync(type, dependencyLoaderFn, metadataSetterFn) {
|
|
17694
|
+
const componentClass = type; // cast to `any`, so that we can monkey-patch it
|
|
17695
|
+
componentClass[ASYNC_COMPONENT_METADATA_FN] = () => Promise.all(dependencyLoaderFn()).then(dependencies => {
|
|
17696
|
+
metadataSetterFn(...dependencies);
|
|
17697
|
+
// Metadata is now set, reset field value to indicate that this component
|
|
17698
|
+
// can by used/compiled synchronously.
|
|
17699
|
+
componentClass[ASYNC_COMPONENT_METADATA_FN] = null;
|
|
17700
|
+
return dependencies;
|
|
17701
|
+
});
|
|
17702
|
+
return componentClass[ASYNC_COMPONENT_METADATA_FN];
|
|
17833
17703
|
}
|
|
17834
|
-
|
|
17835
|
-
|
|
17836
|
-
|
|
17837
|
-
|
|
17838
|
-
|
|
17839
|
-
|
|
17704
|
+
/**
|
|
17705
|
+
* Adds decorator, constructor, and property metadata to a given type via static metadata fields
|
|
17706
|
+
* on the type.
|
|
17707
|
+
*
|
|
17708
|
+
* These metadata fields can later be read with Angular's `ReflectionCapabilities` API.
|
|
17709
|
+
*
|
|
17710
|
+
* Calls to `setClassMetadata` can be guarded by ngDevMode, resulting in the metadata assignments
|
|
17711
|
+
* being tree-shaken away during production builds.
|
|
17712
|
+
*/
|
|
17713
|
+
function setClassMetadata(type, decorators, ctorParameters, propDecorators) {
|
|
17714
|
+
return noSideEffects(() => {
|
|
17715
|
+
const clazz = type;
|
|
17716
|
+
if (decorators !== null) {
|
|
17717
|
+
if (clazz.hasOwnProperty('decorators') && clazz.decorators !== undefined) {
|
|
17718
|
+
clazz.decorators.push(...decorators);
|
|
17719
|
+
}
|
|
17720
|
+
else {
|
|
17721
|
+
clazz.decorators = decorators;
|
|
17840
17722
|
}
|
|
17841
|
-
// We need to patch the `declaredInputs` so that
|
|
17842
|
-
// `ngOnChanges` can map the properties correctly.
|
|
17843
|
-
patchDeclaredInputs(hostDirectiveDef.declaredInputs, hostDirectiveConfig.inputs);
|
|
17844
|
-
// Host directives execute before the host so that its host bindings can be overwritten.
|
|
17845
|
-
findHostDirectiveDefs(hostDirectiveDef, matchedDefs, hostDirectiveDefs);
|
|
17846
|
-
hostDirectiveDefs.set(hostDirectiveDef, hostDirectiveConfig);
|
|
17847
|
-
matchedDefs.push(hostDirectiveDef);
|
|
17848
17723
|
}
|
|
17849
|
-
|
|
17724
|
+
if (ctorParameters !== null) {
|
|
17725
|
+
// Rather than merging, clobber the existing parameters. If other projects exist which
|
|
17726
|
+
// use tsickle-style annotations and reflect over them in the same way, this could
|
|
17727
|
+
// cause issues, but that is vanishingly unlikely.
|
|
17728
|
+
clazz.ctorParameters = ctorParameters;
|
|
17729
|
+
}
|
|
17730
|
+
if (propDecorators !== null) {
|
|
17731
|
+
// The property decorator objects are merged as it is possible different fields have
|
|
17732
|
+
// different decorator types. Decorators on individual fields are not merged, as it's
|
|
17733
|
+
// also incredibly unlikely that a field will be decorated both with an Angular
|
|
17734
|
+
// decorator and a non-Angular decorator that's also been downleveled.
|
|
17735
|
+
if (clazz.hasOwnProperty('propDecorators') && clazz.propDecorators !== undefined) {
|
|
17736
|
+
clazz.propDecorators = { ...clazz.propDecorators, ...propDecorators };
|
|
17737
|
+
}
|
|
17738
|
+
else {
|
|
17739
|
+
clazz.propDecorators = propDecorators;
|
|
17740
|
+
}
|
|
17741
|
+
}
|
|
17742
|
+
});
|
|
17850
17743
|
}
|
|
17744
|
+
|
|
17745
|
+
/*
|
|
17746
|
+
* This file exists to support compilation of @angular/core in Ivy mode.
|
|
17747
|
+
*
|
|
17748
|
+
* When the Angular compiler processes a compilation unit, it normally writes imports to
|
|
17749
|
+
* @angular/core. When compiling the core package itself this strategy isn't usable. Instead, the
|
|
17750
|
+
* compiler writes imports to this file.
|
|
17751
|
+
*
|
|
17752
|
+
* Only a subset of such imports are supported - core is not allowed to declare components or pipes.
|
|
17753
|
+
* A check in ngtsc's `R3SymbolsImportRewriter` validates this condition. The rewriter is only used
|
|
17754
|
+
* when compiling @angular/core and is responsible for translating an external name (prefixed with
|
|
17755
|
+
* ɵ) to the internal symbol name as exported below.
|
|
17756
|
+
*
|
|
17757
|
+
* The below symbols are used for @Injectable and @NgModule compilation.
|
|
17758
|
+
*/
|
|
17851
17759
|
/**
|
|
17852
|
-
*
|
|
17853
|
-
*
|
|
17760
|
+
* The existence of this constant (in this particular file) informs the Angular compiler that the
|
|
17761
|
+
* current program is actually @angular/core, which needs to be compiled specially.
|
|
17854
17762
|
*/
|
|
17855
|
-
|
|
17856
|
-
|
|
17857
|
-
return EMPTY_OBJ;
|
|
17858
|
-
}
|
|
17859
|
-
const result = {};
|
|
17860
|
-
for (let i = 0; i < bindings.length; i += 2) {
|
|
17861
|
-
result[bindings[i]] = bindings[i + 1];
|
|
17862
|
-
}
|
|
17863
|
-
return result;
|
|
17864
|
-
}
|
|
17763
|
+
const ITS_JUST_ANGULAR = true;
|
|
17764
|
+
|
|
17865
17765
|
/**
|
|
17866
|
-
*
|
|
17867
|
-
* `SimpleChanges` event refer to the *declared* name of the input, not its public name or its
|
|
17868
|
-
* minified name. E.g. in `@Input('alias') foo: string`, the name in the `SimpleChanges` object
|
|
17869
|
-
* will always be `foo`, and not `alias` or the minified name of `foo` in apps using property
|
|
17870
|
-
* minification.
|
|
17766
|
+
* *Internal* service that keeps track of pending tasks happening in the system.
|
|
17871
17767
|
*
|
|
17872
|
-
* This is
|
|
17873
|
-
*
|
|
17874
|
-
*
|
|
17875
|
-
* `declaredInputs`.
|
|
17768
|
+
* This information is needed to make sure that the serialization on the server
|
|
17769
|
+
* is delayed until all tasks in the queue (such as an initial navigation or a
|
|
17770
|
+
* pending HTTP request) are completed.
|
|
17876
17771
|
*
|
|
17877
|
-
*
|
|
17878
|
-
*
|
|
17879
|
-
* issue by patching the host directive aliases to the `declaredInputs`. There is *not* a risk of
|
|
17880
|
-
* this patching accidentally introducing new inputs to the host directive, because `declaredInputs`
|
|
17881
|
-
* is used *only* by the `NgOnChangesFeature` when determining what name is used in the
|
|
17882
|
-
* `SimpleChanges` object which won't be reached if an input doesn't exist.
|
|
17772
|
+
* Pending tasks continue to contribute to the stableness of `ApplicationRef`
|
|
17773
|
+
* throughout the lifetime of the application.
|
|
17883
17774
|
*/
|
|
17884
|
-
|
|
17885
|
-
|
|
17886
|
-
|
|
17887
|
-
|
|
17888
|
-
|
|
17889
|
-
|
|
17890
|
-
|
|
17891
|
-
|
|
17892
|
-
|
|
17893
|
-
|
|
17894
|
-
|
|
17895
|
-
|
|
17896
|
-
|
|
17897
|
-
|
|
17775
|
+
class PendingTasks {
|
|
17776
|
+
constructor() {
|
|
17777
|
+
this.taskId = 0;
|
|
17778
|
+
this.pendingTasks = new Set();
|
|
17779
|
+
this.hasPendingTasks = new BehaviorSubject(false);
|
|
17780
|
+
}
|
|
17781
|
+
get _hasPendingTasks() {
|
|
17782
|
+
return this.hasPendingTasks.value;
|
|
17783
|
+
}
|
|
17784
|
+
add() {
|
|
17785
|
+
if (!this._hasPendingTasks) {
|
|
17786
|
+
this.hasPendingTasks.next(true);
|
|
17787
|
+
}
|
|
17788
|
+
const taskId = this.taskId++;
|
|
17789
|
+
this.pendingTasks.add(taskId);
|
|
17790
|
+
return taskId;
|
|
17791
|
+
}
|
|
17792
|
+
remove(taskId) {
|
|
17793
|
+
this.pendingTasks.delete(taskId);
|
|
17794
|
+
if (this.pendingTasks.size === 0 && this._hasPendingTasks) {
|
|
17795
|
+
this.hasPendingTasks.next(false);
|
|
17796
|
+
}
|
|
17797
|
+
}
|
|
17798
|
+
ngOnDestroy() {
|
|
17799
|
+
this.pendingTasks.clear();
|
|
17800
|
+
if (this._hasPendingTasks) {
|
|
17801
|
+
this.hasPendingTasks.next(false);
|
|
17898
17802
|
}
|
|
17899
17803
|
}
|
|
17804
|
+
static { this.ɵfac = function PendingTasks_Factory(t) { return new (t || PendingTasks)(); }; }
|
|
17805
|
+
static { this.ɵprov = /*@__PURE__*/ ɵɵdefineInjectable({ token: PendingTasks, factory: PendingTasks.ɵfac, providedIn: 'root' }); }
|
|
17900
17806
|
}
|
|
17901
|
-
|
|
17902
|
-
|
|
17903
|
-
|
|
17904
|
-
|
|
17905
|
-
|
|
17906
|
-
function
|
|
17907
|
-
|
|
17908
|
-
|
|
17909
|
-
|
|
17910
|
-
|
|
17807
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && setClassMetadata(PendingTasks, [{
|
|
17808
|
+
type: Injectable,
|
|
17809
|
+
args: [{ providedIn: 'root' }]
|
|
17810
|
+
}], null, null); })();
|
|
17811
|
+
|
|
17812
|
+
function isIterable(obj) {
|
|
17813
|
+
return obj !== null && typeof obj === 'object' && obj[Symbol.iterator] !== undefined;
|
|
17814
|
+
}
|
|
17815
|
+
function isListLikeIterable(obj) {
|
|
17816
|
+
if (!isJsObject(obj))
|
|
17817
|
+
return false;
|
|
17818
|
+
return Array.isArray(obj) ||
|
|
17819
|
+
(!(obj instanceof Map) && // JS Map are iterables but return entries as [k, v]
|
|
17820
|
+
Symbol.iterator in obj); // JS Iterable have a Symbol.iterator prop
|
|
17821
|
+
}
|
|
17822
|
+
function areIterablesEqual(a, b, comparator) {
|
|
17823
|
+
const iterator1 = a[Symbol.iterator]();
|
|
17824
|
+
const iterator2 = b[Symbol.iterator]();
|
|
17825
|
+
while (true) {
|
|
17826
|
+
const item1 = iterator1.next();
|
|
17827
|
+
const item2 = iterator2.next();
|
|
17828
|
+
if (item1.done && item2.done)
|
|
17829
|
+
return true;
|
|
17830
|
+
if (item1.done || item2.done)
|
|
17831
|
+
return false;
|
|
17832
|
+
if (!comparator(item1.value, item2.value))
|
|
17833
|
+
return false;
|
|
17834
|
+
}
|
|
17835
|
+
}
|
|
17836
|
+
function iterateListLike(obj, fn) {
|
|
17837
|
+
if (Array.isArray(obj)) {
|
|
17838
|
+
for (let i = 0; i < obj.length; i++) {
|
|
17839
|
+
fn(obj[i]);
|
|
17911
17840
|
}
|
|
17912
|
-
throw new RuntimeError(307 /* RuntimeErrorCode.HOST_DIRECTIVE_UNRESOLVABLE */, `Could not resolve metadata for host directive ${type.name}. ` +
|
|
17913
|
-
`Make sure that the ${type.name} class is annotated with an @Directive decorator.`);
|
|
17914
17841
|
}
|
|
17915
|
-
|
|
17916
|
-
|
|
17842
|
+
else {
|
|
17843
|
+
const iterator = obj[Symbol.iterator]();
|
|
17844
|
+
let item;
|
|
17845
|
+
while (!((item = iterator.next()).done)) {
|
|
17846
|
+
fn(item.value);
|
|
17847
|
+
}
|
|
17917
17848
|
}
|
|
17918
|
-
validateMappings('input', directiveDef, hostDirectiveConfig.inputs);
|
|
17919
|
-
validateMappings('output', directiveDef, hostDirectiveConfig.outputs);
|
|
17920
17849
|
}
|
|
17921
|
-
|
|
17922
|
-
|
|
17923
|
-
|
|
17924
|
-
|
|
17925
|
-
|
|
17926
|
-
|
|
17927
|
-
|
|
17928
|
-
|
|
17929
|
-
|
|
17930
|
-
|
|
17931
|
-
|
|
17932
|
-
|
|
17933
|
-
|
|
17934
|
-
|
|
17935
|
-
|
|
17936
|
-
|
|
17937
|
-
|
|
17938
|
-
|
|
17850
|
+
function isJsObject(o) {
|
|
17851
|
+
return o !== null && (typeof o === 'function' || typeof o === 'object');
|
|
17852
|
+
}
|
|
17853
|
+
|
|
17854
|
+
function devModeEqual(a, b) {
|
|
17855
|
+
const isListLikeIterableA = isListLikeIterable(a);
|
|
17856
|
+
const isListLikeIterableB = isListLikeIterable(b);
|
|
17857
|
+
if (isListLikeIterableA && isListLikeIterableB) {
|
|
17858
|
+
return areIterablesEqual(a, b, devModeEqual);
|
|
17859
|
+
}
|
|
17860
|
+
else {
|
|
17861
|
+
const isAObject = a && (typeof a === 'object' || typeof a === 'function');
|
|
17862
|
+
const isBObject = b && (typeof b === 'object' || typeof b === 'function');
|
|
17863
|
+
if (!isListLikeIterableA && isAObject && !isListLikeIterableB && isBObject) {
|
|
17864
|
+
return true;
|
|
17865
|
+
}
|
|
17866
|
+
else {
|
|
17867
|
+
return Object.is(a, b);
|
|
17939
17868
|
}
|
|
17940
17869
|
}
|
|
17941
17870
|
}
|
|
17942
17871
|
|
|
17872
|
+
// TODO(misko): consider inlining
|
|
17873
|
+
/** Updates binding and returns the value. */
|
|
17874
|
+
function updateBinding(lView, bindingIndex, value) {
|
|
17875
|
+
return lView[bindingIndex] = value;
|
|
17876
|
+
}
|
|
17877
|
+
/** Gets the current binding value. */
|
|
17878
|
+
function getBinding(lView, bindingIndex) {
|
|
17879
|
+
ngDevMode && assertIndexInRange(lView, bindingIndex);
|
|
17880
|
+
ngDevMode &&
|
|
17881
|
+
assertNotSame(lView[bindingIndex], NO_CHANGE, 'Stored value should never be NO_CHANGE.');
|
|
17882
|
+
return lView[bindingIndex];
|
|
17883
|
+
}
|
|
17943
17884
|
/**
|
|
17944
|
-
*
|
|
17885
|
+
* Updates binding if changed, then returns whether it was updated.
|
|
17945
17886
|
*
|
|
17946
|
-
*
|
|
17947
|
-
*
|
|
17887
|
+
* This function also checks the `CheckNoChangesMode` and throws if changes are made.
|
|
17888
|
+
* Some changes (Objects/iterables) during `CheckNoChangesMode` are exempt to comply with VE
|
|
17889
|
+
* behavior.
|
|
17948
17890
|
*
|
|
17949
|
-
* @
|
|
17891
|
+
* @param lView current `LView`
|
|
17892
|
+
* @param bindingIndex The binding in the `LView` to check
|
|
17893
|
+
* @param value New value to check against `lView[bindingIndex]`
|
|
17894
|
+
* @returns `true` if the bindings has changed. (Throws if binding has changed during
|
|
17895
|
+
* `CheckNoChangesMode`)
|
|
17950
17896
|
*/
|
|
17951
|
-
function
|
|
17952
|
-
|
|
17953
|
-
|
|
17954
|
-
|
|
17955
|
-
|
|
17956
|
-
|
|
17957
|
-
|
|
17958
|
-
|
|
17959
|
-
|
|
17960
|
-
|
|
17897
|
+
function bindingUpdated(lView, bindingIndex, value) {
|
|
17898
|
+
ngDevMode && assertNotSame(value, NO_CHANGE, 'Incoming value should never be NO_CHANGE.');
|
|
17899
|
+
ngDevMode &&
|
|
17900
|
+
assertLessThan(bindingIndex, lView.length, `Slot should have been initialized to NO_CHANGE`);
|
|
17901
|
+
const oldValue = lView[bindingIndex];
|
|
17902
|
+
if (Object.is(oldValue, value)) {
|
|
17903
|
+
return false;
|
|
17904
|
+
}
|
|
17905
|
+
else {
|
|
17906
|
+
if (ngDevMode && isInCheckNoChangesMode()) {
|
|
17907
|
+
// View engine didn't report undefined values as changed on the first checkNoChanges pass
|
|
17908
|
+
// (before the change detection was run).
|
|
17909
|
+
const oldValueToCompare = oldValue !== NO_CHANGE ? oldValue : undefined;
|
|
17910
|
+
if (!devModeEqual(oldValueToCompare, value)) {
|
|
17911
|
+
const details = getExpressionChangedErrorDetails(lView, bindingIndex, oldValueToCompare, value);
|
|
17912
|
+
throwErrorIfNoChangesMode(oldValue === NO_CHANGE, details.oldValue, details.newValue, details.propName, lView);
|
|
17961
17913
|
}
|
|
17914
|
+
// There was a change, but the `devModeEqual` decided that the change is exempt from an error.
|
|
17915
|
+
// For this reason we exit as if no change. The early exit is needed to prevent the changed
|
|
17916
|
+
// value to be written into `LView` (If we would write the new value that we would not see it
|
|
17917
|
+
// as change on next CD.)
|
|
17918
|
+
return false;
|
|
17962
17919
|
}
|
|
17920
|
+
lView[bindingIndex] = value;
|
|
17921
|
+
return true;
|
|
17963
17922
|
}
|
|
17964
|
-
definition.inputTransforms = inputTransforms;
|
|
17965
17923
|
}
|
|
17966
|
-
|
|
17967
|
-
|
|
17968
|
-
|
|
17969
|
-
|
|
17970
|
-
|
|
17971
|
-
|
|
17972
|
-
|
|
17973
|
-
|
|
17924
|
+
/** Updates 2 bindings if changed, then returns whether either was updated. */
|
|
17925
|
+
function bindingUpdated2(lView, bindingIndex, exp1, exp2) {
|
|
17926
|
+
const different = bindingUpdated(lView, bindingIndex, exp1);
|
|
17927
|
+
return bindingUpdated(lView, bindingIndex + 1, exp2) || different;
|
|
17928
|
+
}
|
|
17929
|
+
/** Updates 3 bindings if changed, then returns whether any was updated. */
|
|
17930
|
+
function bindingUpdated3(lView, bindingIndex, exp1, exp2, exp3) {
|
|
17931
|
+
const different = bindingUpdated2(lView, bindingIndex, exp1, exp2);
|
|
17932
|
+
return bindingUpdated(lView, bindingIndex + 2, exp3) || different;
|
|
17933
|
+
}
|
|
17934
|
+
/** Updates 4 bindings if changed, then returns whether any was updated. */
|
|
17935
|
+
function bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4) {
|
|
17936
|
+
const different = bindingUpdated2(lView, bindingIndex, exp1, exp2);
|
|
17937
|
+
return bindingUpdated2(lView, bindingIndex + 2, exp3, exp4) || different;
|
|
17974
17938
|
}
|
|
17939
|
+
|
|
17975
17940
|
/**
|
|
17976
|
-
*
|
|
17977
|
-
*
|
|
17978
|
-
*
|
|
17979
|
-
* This class was mostly used as a part of ViewEngine-based JIT API and is no longer needed in Ivy
|
|
17980
|
-
* JIT mode. See [JIT API changes due to ViewEngine deprecation](guide/deprecations#jit-api-changes)
|
|
17981
|
-
* for additional context. Angular provides APIs that accept NgModule classes directly (such as
|
|
17982
|
-
* [PlatformRef.bootstrapModule](api/core/PlatformRef#bootstrapModule) and
|
|
17983
|
-
* [createNgModule](api/core/createNgModule)), consider switching to those APIs instead of
|
|
17984
|
-
* using factory-based ones.
|
|
17941
|
+
* Checks whether a TNode is considered detached, i.e. not present in the
|
|
17942
|
+
* translated i18n template. We should not attempt hydration for such nodes
|
|
17943
|
+
* and instead, use a regular "creation mode".
|
|
17985
17944
|
*/
|
|
17986
|
-
|
|
17945
|
+
function isDetachedByI18n(tNode) {
|
|
17946
|
+
return (tNode.flags & 32 /* TNodeFlags.isDetached */) === 32 /* TNodeFlags.isDetached */;
|
|
17987
17947
|
}
|
|
17988
17948
|
|
|
17949
|
+
function templateFirstCreatePass(index, tView, lView, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex) {
|
|
17950
|
+
ngDevMode && assertFirstCreatePass(tView);
|
|
17951
|
+
ngDevMode && ngDevMode.firstCreatePass++;
|
|
17952
|
+
const tViewConsts = tView.consts;
|
|
17953
|
+
// TODO(pk): refactor getOrCreateTNode to have the "create" only version
|
|
17954
|
+
const tNode = getOrCreateTNode(tView, index, 4 /* TNodeType.Container */, tagName || null, getConstant(tViewConsts, attrsIndex));
|
|
17955
|
+
resolveDirectives(tView, lView, tNode, getConstant(tViewConsts, localRefsIndex));
|
|
17956
|
+
registerPostOrderHooks(tView, tNode);
|
|
17957
|
+
const embeddedTView = tNode.tView = createTView(2 /* TViewType.Embedded */, tNode, templateFn, decls, vars, tView.directiveRegistry, tView.pipeRegistry, null, tView.schemas, tViewConsts, null /* ssrId */);
|
|
17958
|
+
if (tView.queries !== null) {
|
|
17959
|
+
tView.queries.template(tView, tNode);
|
|
17960
|
+
embeddedTView.queries = tView.queries.embeddedTView(tNode);
|
|
17961
|
+
}
|
|
17962
|
+
return tNode;
|
|
17963
|
+
}
|
|
17989
17964
|
/**
|
|
17990
|
-
*
|
|
17965
|
+
* Creates an LContainer for an ng-template (dynamically-inserted view), e.g.
|
|
17991
17966
|
*
|
|
17992
|
-
*
|
|
17993
|
-
*
|
|
17994
|
-
*
|
|
17995
|
-
* @returns NgModuleRef that represents an NgModule instance.
|
|
17967
|
+
* <ng-template #foo>
|
|
17968
|
+
* <div></div>
|
|
17969
|
+
* </ng-template>
|
|
17996
17970
|
*
|
|
17997
|
-
* @
|
|
17998
|
-
|
|
17999
|
-
|
|
18000
|
-
|
|
18001
|
-
|
|
18002
|
-
|
|
18003
|
-
*
|
|
18004
|
-
*
|
|
17971
|
+
* @param index The index of the container in the data array
|
|
17972
|
+
* @param templateFn Inline template
|
|
17973
|
+
* @param decls The number of nodes, local refs, and pipes for this template
|
|
17974
|
+
* @param vars The number of bindings for this template
|
|
17975
|
+
* @param tagName The name of the container element, if applicable
|
|
17976
|
+
* @param attrsIndex Index of template attributes in the `consts` array.
|
|
17977
|
+
* @param localRefs Index of the local references in the `consts` array.
|
|
17978
|
+
* @param localRefExtractor A function which extracts local-refs values from the template.
|
|
17979
|
+
* Defaults to the current element associated with the local-ref.
|
|
18005
17980
|
*
|
|
18006
|
-
* @
|
|
17981
|
+
* @codeGenApi
|
|
18007
17982
|
*/
|
|
18008
|
-
|
|
18009
|
-
|
|
18010
|
-
|
|
18011
|
-
|
|
18012
|
-
|
|
18013
|
-
|
|
18014
|
-
|
|
18015
|
-
|
|
18016
|
-
|
|
18017
|
-
|
|
18018
|
-
// module being resolved tries to inject the ComponentFactoryResolver, it'll create a
|
|
18019
|
-
// circular dependency which will result in a runtime error, because the injector doesn't
|
|
18020
|
-
// exist yet. We work around the issue by creating the ComponentFactoryResolver ourselves
|
|
18021
|
-
// and providing it, rather than letting the injector resolve it.
|
|
18022
|
-
this.componentFactoryResolver = new ComponentFactoryResolver(this);
|
|
18023
|
-
const ngModuleDef = getNgModuleDef(ngModuleType);
|
|
18024
|
-
ngDevMode &&
|
|
18025
|
-
assertDefined(ngModuleDef, `NgModule '${stringify(ngModuleType)}' is not a subtype of 'NgModuleType'.`);
|
|
18026
|
-
this._bootstrapComponents = maybeUnwrapFn(ngModuleDef.bootstrap);
|
|
18027
|
-
this._r3Injector = createInjectorWithoutInjectorInstances(ngModuleType, _parent, [
|
|
18028
|
-
{ provide: NgModuleRef$1, useValue: this }, {
|
|
18029
|
-
provide: ComponentFactoryResolver$1,
|
|
18030
|
-
useValue: this.componentFactoryResolver
|
|
18031
|
-
},
|
|
18032
|
-
...additionalProviders
|
|
18033
|
-
], stringify(ngModuleType), new Set(['environment']));
|
|
18034
|
-
// We need to resolve the injector types separately from the injector creation, because
|
|
18035
|
-
// the module might be trying to use this ref in its constructor for DI which will cause a
|
|
18036
|
-
// circular error that will eventually error out, because the injector isn't created yet.
|
|
18037
|
-
this._r3Injector.resolveInjectorInitializers();
|
|
18038
|
-
this.instance = this._r3Injector.get(ngModuleType);
|
|
18039
|
-
}
|
|
18040
|
-
get injector() {
|
|
18041
|
-
return this._r3Injector;
|
|
18042
|
-
}
|
|
18043
|
-
destroy() {
|
|
18044
|
-
ngDevMode && assertDefined(this.destroyCbs, 'NgModule already destroyed');
|
|
18045
|
-
const injector = this._r3Injector;
|
|
18046
|
-
!injector.destroyed && injector.destroy();
|
|
18047
|
-
this.destroyCbs.forEach(fn => fn());
|
|
18048
|
-
this.destroyCbs = null;
|
|
18049
|
-
}
|
|
18050
|
-
onDestroy(callback) {
|
|
18051
|
-
ngDevMode && assertDefined(this.destroyCbs, 'NgModule already destroyed');
|
|
18052
|
-
this.destroyCbs.push(callback);
|
|
17983
|
+
function ɵɵtemplate(index, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex, localRefExtractor) {
|
|
17984
|
+
const lView = getLView();
|
|
17985
|
+
const tView = getTView();
|
|
17986
|
+
const adjustedIndex = index + HEADER_OFFSET;
|
|
17987
|
+
const tNode = tView.firstCreatePass ? templateFirstCreatePass(adjustedIndex, tView, lView, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex) :
|
|
17988
|
+
tView.data[adjustedIndex];
|
|
17989
|
+
setCurrentTNode(tNode, false);
|
|
17990
|
+
const comment = _locateOrCreateContainerAnchor(tView, lView, tNode, index);
|
|
17991
|
+
if (wasLastNodeCreated()) {
|
|
17992
|
+
appendChild(tView, lView, comment, tNode);
|
|
18053
17993
|
}
|
|
18054
|
-
|
|
18055
|
-
|
|
18056
|
-
|
|
18057
|
-
|
|
18058
|
-
|
|
17994
|
+
attachPatchData(comment, lView);
|
|
17995
|
+
const lContainer = createLContainer(comment, lView, comment, tNode);
|
|
17996
|
+
lView[adjustedIndex] = lContainer;
|
|
17997
|
+
addToViewTree(lView, lContainer);
|
|
17998
|
+
// If hydration is enabled, looks up dehydrated views in the DOM
|
|
17999
|
+
// using hydration annotation info and stores those views on LContainer.
|
|
18000
|
+
// In client-only mode, this function is a noop.
|
|
18001
|
+
populateDehydratedViewsInLContainer(lContainer, tNode, lView);
|
|
18002
|
+
if (isDirectiveHost(tNode)) {
|
|
18003
|
+
createDirectivesInstances(tView, lView, tNode);
|
|
18059
18004
|
}
|
|
18060
|
-
|
|
18061
|
-
|
|
18005
|
+
if (localRefsIndex != null) {
|
|
18006
|
+
saveResolvedLocalsInData(lView, tNode, localRefExtractor);
|
|
18062
18007
|
}
|
|
18008
|
+
return ɵɵtemplate;
|
|
18063
18009
|
}
|
|
18064
|
-
|
|
18065
|
-
|
|
18010
|
+
let _locateOrCreateContainerAnchor = createContainerAnchorImpl;
|
|
18011
|
+
/**
|
|
18012
|
+
* Regular creation mode for LContainers and their anchor (comment) nodes.
|
|
18013
|
+
*/
|
|
18014
|
+
function createContainerAnchorImpl(tView, lView, tNode, index) {
|
|
18015
|
+
lastNodeWasCreated(true);
|
|
18016
|
+
return lView[RENDERER].createComment(ngDevMode ? 'container' : '');
|
|
18066
18017
|
}
|
|
18067
|
-
|
|
18068
|
-
|
|
18069
|
-
|
|
18070
|
-
|
|
18071
|
-
|
|
18072
|
-
|
|
18073
|
-
|
|
18074
|
-
|
|
18075
|
-
|
|
18076
|
-
|
|
18077
|
-
|
|
18078
|
-
|
|
18079
|
-
|
|
18080
|
-
}
|
|
18018
|
+
/**
|
|
18019
|
+
* Enables hydration code path (to lookup existing elements in DOM)
|
|
18020
|
+
* in addition to the regular creation mode for LContainers and their
|
|
18021
|
+
* anchor (comment) nodes.
|
|
18022
|
+
*/
|
|
18023
|
+
function locateOrCreateContainerAnchorImpl(tView, lView, tNode, index) {
|
|
18024
|
+
const hydrationInfo = lView[HYDRATION];
|
|
18025
|
+
const isNodeCreationMode = !hydrationInfo || isInSkipHydrationBlock$1() ||
|
|
18026
|
+
isDetachedByI18n(tNode) || isDisconnectedNode$1(hydrationInfo, index);
|
|
18027
|
+
lastNodeWasCreated(isNodeCreationMode);
|
|
18028
|
+
// Regular creation mode.
|
|
18029
|
+
if (isNodeCreationMode) {
|
|
18030
|
+
return createContainerAnchorImpl(tView, lView, tNode, index);
|
|
18081
18031
|
}
|
|
18082
|
-
|
|
18083
|
-
|
|
18032
|
+
const ssrId = hydrationInfo.data[TEMPLATES]?.[index] ?? null;
|
|
18033
|
+
// Apply `ssrId` value to the underlying TView if it was not previously set.
|
|
18034
|
+
//
|
|
18035
|
+
// There might be situations when the same component is present in a template
|
|
18036
|
+
// multiple times and some instances are opted-out of using hydration via
|
|
18037
|
+
// `ngSkipHydration` attribute. In this scenario, at the time a TView is created,
|
|
18038
|
+
// the `ssrId` might be `null` (if the first component is opted-out of hydration).
|
|
18039
|
+
// The code below makes sure that the `ssrId` is applied to the TView if it's still
|
|
18040
|
+
// `null` and verifies we never try to override it with a different value.
|
|
18041
|
+
if (ssrId !== null && tNode.tView !== null) {
|
|
18042
|
+
if (tNode.tView.ssrId === null) {
|
|
18043
|
+
tNode.tView.ssrId = ssrId;
|
|
18044
|
+
}
|
|
18045
|
+
else {
|
|
18046
|
+
ngDevMode &&
|
|
18047
|
+
assertEqual(tNode.tView.ssrId, ssrId, 'Unexpected value of the `ssrId` for this TView');
|
|
18048
|
+
}
|
|
18084
18049
|
}
|
|
18085
|
-
|
|
18086
|
-
|
|
18050
|
+
// Hydration mode, looking up existing elements in DOM.
|
|
18051
|
+
const currentRNode = locateNextRNode(hydrationInfo, tView, lView, tNode);
|
|
18052
|
+
ngDevMode && validateNodeExists(currentRNode, lView, tNode);
|
|
18053
|
+
setSegmentHead(hydrationInfo, index, currentRNode);
|
|
18054
|
+
const viewContainerSize = calcSerializedContainerSize(hydrationInfo, index);
|
|
18055
|
+
const comment = siblingAfter(viewContainerSize, currentRNode);
|
|
18056
|
+
if (ngDevMode) {
|
|
18057
|
+
validateMatchingNode(comment, Node.COMMENT_NODE, null, lView, tNode);
|
|
18058
|
+
markRNodeAsClaimedByHydration(comment);
|
|
18087
18059
|
}
|
|
18060
|
+
return comment;
|
|
18061
|
+
}
|
|
18062
|
+
function enableLocateOrCreateContainerAnchorImpl() {
|
|
18063
|
+
_locateOrCreateContainerAnchor = locateOrCreateContainerAnchorImpl;
|
|
18088
18064
|
}
|
|
18065
|
+
|
|
18066
|
+
/**
|
|
18067
|
+
* Describes the state of defer block dependency loading.
|
|
18068
|
+
*/
|
|
18069
|
+
var DeferDependenciesLoadingState;
|
|
18070
|
+
(function (DeferDependenciesLoadingState) {
|
|
18071
|
+
/** Initial state, dependency loading is not yet triggered */
|
|
18072
|
+
DeferDependenciesLoadingState[DeferDependenciesLoadingState["NOT_STARTED"] = 0] = "NOT_STARTED";
|
|
18073
|
+
/** Dependency loading is in progress */
|
|
18074
|
+
DeferDependenciesLoadingState[DeferDependenciesLoadingState["IN_PROGRESS"] = 1] = "IN_PROGRESS";
|
|
18075
|
+
/** Dependency loading has completed successfully */
|
|
18076
|
+
DeferDependenciesLoadingState[DeferDependenciesLoadingState["COMPLETE"] = 2] = "COMPLETE";
|
|
18077
|
+
/** Dependency loading has failed */
|
|
18078
|
+
DeferDependenciesLoadingState[DeferDependenciesLoadingState["FAILED"] = 3] = "FAILED";
|
|
18079
|
+
})(DeferDependenciesLoadingState || (DeferDependenciesLoadingState = {}));
|
|
18080
|
+
/** Slot index where `minimum` parameter value is stored. */
|
|
18081
|
+
const MINIMUM_SLOT = 0;
|
|
18082
|
+
/** Slot index where `after` parameter value is stored. */
|
|
18083
|
+
const LOADING_AFTER_SLOT = 1;
|
|
18089
18084
|
/**
|
|
18090
|
-
*
|
|
18091
|
-
*
|
|
18092
|
-
* Learn more about environment injectors in
|
|
18093
|
-
* [this guide](guide/standalone-components#environment-injectors).
|
|
18085
|
+
* Describes the current state of this defer block instance.
|
|
18094
18086
|
*
|
|
18095
|
-
* @
|
|
18096
|
-
* @
|
|
18097
|
-
|
|
18098
|
-
|
|
18087
|
+
* @publicApi
|
|
18088
|
+
* @developerPreview
|
|
18089
|
+
*/
|
|
18090
|
+
var DeferBlockState;
|
|
18091
|
+
(function (DeferBlockState) {
|
|
18092
|
+
/** The placeholder block content is rendered */
|
|
18093
|
+
DeferBlockState[DeferBlockState["Placeholder"] = 0] = "Placeholder";
|
|
18094
|
+
/** The loading block content is rendered */
|
|
18095
|
+
DeferBlockState[DeferBlockState["Loading"] = 1] = "Loading";
|
|
18096
|
+
/** The main content block content is rendered */
|
|
18097
|
+
DeferBlockState[DeferBlockState["Complete"] = 2] = "Complete";
|
|
18098
|
+
/** The error block content is rendered */
|
|
18099
|
+
DeferBlockState[DeferBlockState["Error"] = 3] = "Error";
|
|
18100
|
+
})(DeferBlockState || (DeferBlockState = {}));
|
|
18101
|
+
/**
|
|
18102
|
+
* Describes the initial state of this defer block instance.
|
|
18099
18103
|
*
|
|
18104
|
+
* Note: this state is internal only and *must* be represented
|
|
18105
|
+
* with a number lower than any value in the `DeferBlockState` enum.
|
|
18106
|
+
*/
|
|
18107
|
+
var DeferBlockInternalState;
|
|
18108
|
+
(function (DeferBlockInternalState) {
|
|
18109
|
+
/** Initial state. Nothing is rendered yet. */
|
|
18110
|
+
DeferBlockInternalState[DeferBlockInternalState["Initial"] = -1] = "Initial";
|
|
18111
|
+
})(DeferBlockInternalState || (DeferBlockInternalState = {}));
|
|
18112
|
+
const NEXT_DEFER_BLOCK_STATE = 0;
|
|
18113
|
+
// Note: it's *important* to keep the state in this slot, because this slot
|
|
18114
|
+
// is used by runtime logic to differentiate between LViews, LContainers and
|
|
18115
|
+
// other types (see `isLView` and `isLContainer` functions). In case of defer
|
|
18116
|
+
// blocks, this slot would always be a number.
|
|
18117
|
+
const DEFER_BLOCK_STATE = 1;
|
|
18118
|
+
const STATE_IS_FROZEN_UNTIL = 2;
|
|
18119
|
+
const LOADING_AFTER_CLEANUP_FN = 3;
|
|
18120
|
+
const TRIGGER_CLEANUP_FNS = 4;
|
|
18121
|
+
const PREFETCH_TRIGGER_CLEANUP_FNS = 5;
|
|
18122
|
+
/**
|
|
18123
|
+
* Options for configuring defer blocks behavior.
|
|
18100
18124
|
* @publicApi
|
|
18125
|
+
* @developerPreview
|
|
18101
18126
|
*/
|
|
18102
|
-
|
|
18103
|
-
|
|
18104
|
-
|
|
18105
|
-
|
|
18127
|
+
var DeferBlockBehavior;
|
|
18128
|
+
(function (DeferBlockBehavior) {
|
|
18129
|
+
/**
|
|
18130
|
+
* Manual triggering mode for defer blocks. Provides control over when defer blocks render
|
|
18131
|
+
* and which state they render.
|
|
18132
|
+
*/
|
|
18133
|
+
DeferBlockBehavior[DeferBlockBehavior["Manual"] = 0] = "Manual";
|
|
18134
|
+
/**
|
|
18135
|
+
* Playthrough mode for defer blocks. This mode behaves like defer blocks would in a browser.
|
|
18136
|
+
* This is the default behavior in test environments.
|
|
18137
|
+
*/
|
|
18138
|
+
DeferBlockBehavior[DeferBlockBehavior["Playthrough"] = 1] = "Playthrough";
|
|
18139
|
+
})(DeferBlockBehavior || (DeferBlockBehavior = {}));
|
|
18106
18140
|
|
|
18107
|
-
|
|
18108
|
-
*
|
|
18141
|
+
/*!
|
|
18142
|
+
* @license
|
|
18143
|
+
* Copyright Google LLC All Rights Reserved.
|
|
18109
18144
|
*
|
|
18110
|
-
*
|
|
18111
|
-
*
|
|
18112
|
-
* of a certain type.
|
|
18145
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
18146
|
+
* found in the LICENSE file at https://angular.io/license
|
|
18113
18147
|
*/
|
|
18114
|
-
|
|
18115
|
-
|
|
18116
|
-
|
|
18148
|
+
/**
|
|
18149
|
+
* Registers a cleanup function associated with a prefetching trigger
|
|
18150
|
+
* or a regular trigger of a defer block.
|
|
18151
|
+
*/
|
|
18152
|
+
function storeTriggerCleanupFn(type, lDetails, cleanupFn) {
|
|
18153
|
+
const key = type === 1 /* TriggerType.Prefetch */ ? PREFETCH_TRIGGER_CLEANUP_FNS : TRIGGER_CLEANUP_FNS;
|
|
18154
|
+
if (lDetails[key] === null) {
|
|
18155
|
+
lDetails[key] = [];
|
|
18117
18156
|
}
|
|
18118
|
-
|
|
18119
|
-
|
|
18120
|
-
|
|
18121
|
-
|
|
18122
|
-
|
|
18123
|
-
|
|
18157
|
+
lDetails[key].push(cleanupFn);
|
|
18158
|
+
}
|
|
18159
|
+
/**
|
|
18160
|
+
* Invokes registered cleanup functions either for prefetch or for regular triggers.
|
|
18161
|
+
*/
|
|
18162
|
+
function invokeTriggerCleanupFns(type, lDetails) {
|
|
18163
|
+
const key = type === 1 /* TriggerType.Prefetch */ ? PREFETCH_TRIGGER_CLEANUP_FNS : TRIGGER_CLEANUP_FNS;
|
|
18164
|
+
const cleanupFns = lDetails[key];
|
|
18165
|
+
if (cleanupFns !== null) {
|
|
18166
|
+
for (const cleanupFn of cleanupFns) {
|
|
18167
|
+
cleanupFn();
|
|
18124
18168
|
}
|
|
18125
|
-
|
|
18169
|
+
lDetails[key] = null;
|
|
18126
18170
|
}
|
|
18127
|
-
|
|
18128
|
-
|
|
18129
|
-
|
|
18130
|
-
|
|
18131
|
-
|
|
18132
|
-
|
|
18133
|
-
|
|
18171
|
+
}
|
|
18172
|
+
/**
|
|
18173
|
+
* Invokes registered cleanup functions for both prefetch and regular triggers.
|
|
18174
|
+
*/
|
|
18175
|
+
function invokeAllTriggerCleanupFns(lDetails) {
|
|
18176
|
+
invokeTriggerCleanupFns(1 /* TriggerType.Prefetch */, lDetails);
|
|
18177
|
+
invokeTriggerCleanupFns(0 /* TriggerType.Regular */, lDetails);
|
|
18178
|
+
}
|
|
18179
|
+
|
|
18180
|
+
function noop(...args) {
|
|
18181
|
+
// Do nothing.
|
|
18182
|
+
}
|
|
18183
|
+
|
|
18184
|
+
function getNativeRequestAnimationFrame() {
|
|
18185
|
+
// Note: the `getNativeRequestAnimationFrame` is used in the `NgZone` class, but we cannot use the
|
|
18186
|
+
// `inject` function. The `NgZone` instance may be created manually, and thus the injection
|
|
18187
|
+
// context will be unavailable. This might be enough to check whether `requestAnimationFrame` is
|
|
18188
|
+
// available because otherwise, we'll fall back to `setTimeout`.
|
|
18189
|
+
const isBrowser = typeof _global['requestAnimationFrame'] === 'function';
|
|
18190
|
+
// Note: `requestAnimationFrame` is unavailable when the code runs in the Node.js environment. We
|
|
18191
|
+
// use `setTimeout` because no changes are required other than checking if the current platform is
|
|
18192
|
+
// the browser. `setTimeout` is a well-established API that is available in both environments.
|
|
18193
|
+
// `requestAnimationFrame` is used in the browser to coalesce event tasks since event tasks are
|
|
18194
|
+
// usually executed within the same rendering frame (but this is more implementation details of
|
|
18195
|
+
// browsers).
|
|
18196
|
+
let nativeRequestAnimationFrame = _global[isBrowser ? 'requestAnimationFrame' : 'setTimeout'];
|
|
18197
|
+
let nativeCancelAnimationFrame = _global[isBrowser ? 'cancelAnimationFrame' : 'clearTimeout'];
|
|
18198
|
+
if (typeof Zone !== 'undefined' && nativeRequestAnimationFrame && nativeCancelAnimationFrame) {
|
|
18199
|
+
// Note: zone.js sets original implementations on patched APIs behind the
|
|
18200
|
+
// `__zone_symbol__OriginalDelegate` key (see `attachOriginToPatched`). Given the following
|
|
18201
|
+
// example: `window.requestAnimationFrame.__zone_symbol__OriginalDelegate`; this would return an
|
|
18202
|
+
// unpatched implementation of the `requestAnimationFrame`, which isn't intercepted by the
|
|
18203
|
+
// Angular zone. We use the unpatched implementation to avoid another change detection when
|
|
18204
|
+
// coalescing tasks.
|
|
18205
|
+
const unpatchedRequestAnimationFrame = nativeRequestAnimationFrame[Zone.__symbol__('OriginalDelegate')];
|
|
18206
|
+
if (unpatchedRequestAnimationFrame) {
|
|
18207
|
+
nativeRequestAnimationFrame = unpatchedRequestAnimationFrame;
|
|
18134
18208
|
}
|
|
18135
|
-
|
|
18136
|
-
|
|
18209
|
+
const unpatchedCancelAnimationFrame = nativeCancelAnimationFrame[Zone.__symbol__('OriginalDelegate')];
|
|
18210
|
+
if (unpatchedCancelAnimationFrame) {
|
|
18211
|
+
nativeCancelAnimationFrame = unpatchedCancelAnimationFrame;
|
|
18137
18212
|
}
|
|
18138
18213
|
}
|
|
18139
|
-
|
|
18140
|
-
static { this.ɵprov = ɵɵdefineInjectable({
|
|
18141
|
-
token: CachedInjectorService,
|
|
18142
|
-
providedIn: 'environment',
|
|
18143
|
-
factory: () => new CachedInjectorService(),
|
|
18144
|
-
}); }
|
|
18214
|
+
return { nativeRequestAnimationFrame, nativeCancelAnimationFrame };
|
|
18145
18215
|
}
|
|
18146
18216
|
|
|
18147
|
-
|
|
18148
|
-
|
|
18149
|
-
|
|
18150
|
-
|
|
18151
|
-
|
|
18152
|
-
|
|
18153
|
-
|
|
18154
|
-
|
|
18155
|
-
|
|
18156
|
-
|
|
18157
|
-
|
|
18158
|
-
|
|
18159
|
-
|
|
18160
|
-
|
|
18217
|
+
class AsyncStackTaggingZoneSpec {
|
|
18218
|
+
constructor(namePrefix, consoleAsyncStackTaggingImpl = console) {
|
|
18219
|
+
this.name = 'asyncStackTagging for ' + namePrefix;
|
|
18220
|
+
this.createTask = consoleAsyncStackTaggingImpl?.createTask ?? (() => null);
|
|
18221
|
+
}
|
|
18222
|
+
onScheduleTask(delegate, _current, target, task) {
|
|
18223
|
+
task.consoleTask = this.createTask(`Zone - ${task.source || task.type}`);
|
|
18224
|
+
return delegate.scheduleTask(target, task);
|
|
18225
|
+
}
|
|
18226
|
+
onInvokeTask(delegate, _currentZone, targetZone, task, applyThis, applyArgs) {
|
|
18227
|
+
let ret;
|
|
18228
|
+
if (task.consoleTask) {
|
|
18229
|
+
ret = task.consoleTask.run(() => delegate.invokeTask(targetZone, task, applyThis, applyArgs));
|
|
18230
|
+
}
|
|
18231
|
+
else {
|
|
18232
|
+
ret = delegate.invokeTask(targetZone, task, applyThis, applyArgs);
|
|
18233
|
+
}
|
|
18234
|
+
return ret;
|
|
18235
|
+
}
|
|
18161
18236
|
}
|
|
18237
|
+
|
|
18162
18238
|
/**
|
|
18163
|
-
*
|
|
18164
|
-
*
|
|
18239
|
+
* An injectable service for executing work inside or outside of the Angular zone.
|
|
18240
|
+
*
|
|
18241
|
+
* The most common use of this service is to optimize performance when starting a work consisting of
|
|
18242
|
+
* one or more asynchronous tasks that don't require UI updates or error handling to be handled by
|
|
18243
|
+
* Angular. Such tasks can be kicked off via {@link #runOutsideAngular} and if needed, these tasks
|
|
18244
|
+
* can reenter the Angular zone via {@link #run}.
|
|
18245
|
+
*
|
|
18246
|
+
* <!-- TODO: add/fix links to:
|
|
18247
|
+
* - docs explaining zones and the use of zones in Angular and change-detection
|
|
18248
|
+
* - link to runOutsideAngular/run (throughout this file!)
|
|
18249
|
+
* -->
|
|
18250
|
+
*
|
|
18251
|
+
* @usageNotes
|
|
18252
|
+
* ### Example
|
|
18253
|
+
*
|
|
18254
|
+
* ```
|
|
18255
|
+
* import {Component, NgZone} from '@angular/core';
|
|
18256
|
+
* import {NgIf} from '@angular/common';
|
|
18257
|
+
*
|
|
18258
|
+
* @Component({
|
|
18259
|
+
* selector: 'ng-zone-demo',
|
|
18260
|
+
* template: `
|
|
18261
|
+
* <h2>Demo: NgZone</h2>
|
|
18262
|
+
*
|
|
18263
|
+
* <p>Progress: {{progress}}%</p>
|
|
18264
|
+
* <p *ngIf="progress >= 100">Done processing {{label}} of Angular zone!</p>
|
|
18265
|
+
*
|
|
18266
|
+
* <button (click)="processWithinAngularZone()">Process within Angular zone</button>
|
|
18267
|
+
* <button (click)="processOutsideOfAngularZone()">Process outside of Angular zone</button>
|
|
18268
|
+
* `,
|
|
18269
|
+
* })
|
|
18270
|
+
* export class NgZoneDemo {
|
|
18271
|
+
* progress: number = 0;
|
|
18272
|
+
* label: string;
|
|
18273
|
+
*
|
|
18274
|
+
* constructor(private _ngZone: NgZone) {}
|
|
18275
|
+
*
|
|
18276
|
+
* // Loop inside the Angular zone
|
|
18277
|
+
* // so the UI DOES refresh after each setTimeout cycle
|
|
18278
|
+
* processWithinAngularZone() {
|
|
18279
|
+
* this.label = 'inside';
|
|
18280
|
+
* this.progress = 0;
|
|
18281
|
+
* this._increaseProgress(() => console.log('Inside Done!'));
|
|
18282
|
+
* }
|
|
18283
|
+
*
|
|
18284
|
+
* // Loop outside of the Angular zone
|
|
18285
|
+
* // so the UI DOES NOT refresh after each setTimeout cycle
|
|
18286
|
+
* processOutsideOfAngularZone() {
|
|
18287
|
+
* this.label = 'outside';
|
|
18288
|
+
* this.progress = 0;
|
|
18289
|
+
* this._ngZone.runOutsideAngular(() => {
|
|
18290
|
+
* this._increaseProgress(() => {
|
|
18291
|
+
* // reenter the Angular zone and display done
|
|
18292
|
+
* this._ngZone.run(() => { console.log('Outside Done!'); });
|
|
18293
|
+
* });
|
|
18294
|
+
* });
|
|
18295
|
+
* }
|
|
18165
18296
|
*
|
|
18166
|
-
*
|
|
18167
|
-
*
|
|
18168
|
-
*
|
|
18169
|
-
*/
|
|
18170
|
-
function setClassMetadataAsync(type, dependencyLoaderFn, metadataSetterFn) {
|
|
18171
|
-
const componentClass = type; // cast to `any`, so that we can monkey-patch it
|
|
18172
|
-
componentClass[ASYNC_COMPONENT_METADATA_FN] = () => Promise.all(dependencyLoaderFn()).then(dependencies => {
|
|
18173
|
-
metadataSetterFn(...dependencies);
|
|
18174
|
-
// Metadata is now set, reset field value to indicate that this component
|
|
18175
|
-
// can by used/compiled synchronously.
|
|
18176
|
-
componentClass[ASYNC_COMPONENT_METADATA_FN] = null;
|
|
18177
|
-
return dependencies;
|
|
18178
|
-
});
|
|
18179
|
-
return componentClass[ASYNC_COMPONENT_METADATA_FN];
|
|
18180
|
-
}
|
|
18181
|
-
/**
|
|
18182
|
-
* Adds decorator, constructor, and property metadata to a given type via static metadata fields
|
|
18183
|
-
* on the type.
|
|
18297
|
+
* _increaseProgress(doneCallback: () => void) {
|
|
18298
|
+
* this.progress += 1;
|
|
18299
|
+
* console.log(`Current progress: ${this.progress}%`);
|
|
18184
18300
|
*
|
|
18185
|
-
*
|
|
18301
|
+
* if (this.progress < 100) {
|
|
18302
|
+
* window.setTimeout(() => this._increaseProgress(doneCallback), 10);
|
|
18303
|
+
* } else {
|
|
18304
|
+
* doneCallback();
|
|
18305
|
+
* }
|
|
18306
|
+
* }
|
|
18307
|
+
* }
|
|
18308
|
+
* ```
|
|
18186
18309
|
*
|
|
18187
|
-
*
|
|
18188
|
-
* being tree-shaken away during production builds.
|
|
18310
|
+
* @publicApi
|
|
18189
18311
|
*/
|
|
18190
|
-
|
|
18191
|
-
|
|
18192
|
-
|
|
18193
|
-
|
|
18194
|
-
|
|
18195
|
-
|
|
18196
|
-
|
|
18197
|
-
|
|
18198
|
-
|
|
18199
|
-
|
|
18312
|
+
class NgZone {
|
|
18313
|
+
constructor({ enableLongStackTrace = false, shouldCoalesceEventChangeDetection = false, shouldCoalesceRunChangeDetection = false }) {
|
|
18314
|
+
this.hasPendingMacrotasks = false;
|
|
18315
|
+
this.hasPendingMicrotasks = false;
|
|
18316
|
+
/**
|
|
18317
|
+
* Whether there are no outstanding microtasks or macrotasks.
|
|
18318
|
+
*/
|
|
18319
|
+
this.isStable = true;
|
|
18320
|
+
/**
|
|
18321
|
+
* Notifies when code enters Angular Zone. This gets fired first on VM Turn.
|
|
18322
|
+
*/
|
|
18323
|
+
this.onUnstable = new EventEmitter(false);
|
|
18324
|
+
/**
|
|
18325
|
+
* Notifies when there is no more microtasks enqueued in the current VM Turn.
|
|
18326
|
+
* This is a hint for Angular to do change detection, which may enqueue more microtasks.
|
|
18327
|
+
* For this reason this event can fire multiple times per VM Turn.
|
|
18328
|
+
*/
|
|
18329
|
+
this.onMicrotaskEmpty = new EventEmitter(false);
|
|
18330
|
+
/**
|
|
18331
|
+
* Notifies when the last `onMicrotaskEmpty` has run and there are no more microtasks, which
|
|
18332
|
+
* implies we are about to relinquish VM turn.
|
|
18333
|
+
* This event gets called just once.
|
|
18334
|
+
*/
|
|
18335
|
+
this.onStable = new EventEmitter(false);
|
|
18336
|
+
/**
|
|
18337
|
+
* Notifies that an error has been delivered.
|
|
18338
|
+
*/
|
|
18339
|
+
this.onError = new EventEmitter(false);
|
|
18340
|
+
if (typeof Zone == 'undefined') {
|
|
18341
|
+
throw new RuntimeError(908 /* RuntimeErrorCode.MISSING_ZONEJS */, ngDevMode && `In this configuration Angular requires Zone.js`);
|
|
18200
18342
|
}
|
|
18201
|
-
|
|
18202
|
-
|
|
18203
|
-
|
|
18204
|
-
|
|
18205
|
-
|
|
18343
|
+
Zone.assertZonePatched();
|
|
18344
|
+
const self = this;
|
|
18345
|
+
self._nesting = 0;
|
|
18346
|
+
self._outer = self._inner = Zone.current;
|
|
18347
|
+
// AsyncStackTaggingZoneSpec provides `linked stack traces` to show
|
|
18348
|
+
// where the async operation is scheduled. For more details, refer
|
|
18349
|
+
// to this article, https://developer.chrome.com/blog/devtools-better-angular-debugging/
|
|
18350
|
+
// And we only import this AsyncStackTaggingZoneSpec in development mode,
|
|
18351
|
+
// in the production mode, the AsyncStackTaggingZoneSpec will be tree shaken away.
|
|
18352
|
+
if (ngDevMode) {
|
|
18353
|
+
self._inner = self._inner.fork(new AsyncStackTaggingZoneSpec('Angular'));
|
|
18206
18354
|
}
|
|
18207
|
-
if (
|
|
18208
|
-
|
|
18209
|
-
// different decorator types. Decorators on individual fields are not merged, as it's
|
|
18210
|
-
// also incredibly unlikely that a field will be decorated both with an Angular
|
|
18211
|
-
// decorator and a non-Angular decorator that's also been downleveled.
|
|
18212
|
-
if (clazz.hasOwnProperty('propDecorators') && clazz.propDecorators !== undefined) {
|
|
18213
|
-
clazz.propDecorators = { ...clazz.propDecorators, ...propDecorators };
|
|
18214
|
-
}
|
|
18215
|
-
else {
|
|
18216
|
-
clazz.propDecorators = propDecorators;
|
|
18217
|
-
}
|
|
18355
|
+
if (Zone['TaskTrackingZoneSpec']) {
|
|
18356
|
+
self._inner = self._inner.fork(new Zone['TaskTrackingZoneSpec']);
|
|
18218
18357
|
}
|
|
18219
|
-
|
|
18220
|
-
|
|
18221
|
-
|
|
18222
|
-
/*
|
|
18223
|
-
* This file exists to support compilation of @angular/core in Ivy mode.
|
|
18224
|
-
*
|
|
18225
|
-
* When the Angular compiler processes a compilation unit, it normally writes imports to
|
|
18226
|
-
* @angular/core. When compiling the core package itself this strategy isn't usable. Instead, the
|
|
18227
|
-
* compiler writes imports to this file.
|
|
18228
|
-
*
|
|
18229
|
-
* Only a subset of such imports are supported - core is not allowed to declare components or pipes.
|
|
18230
|
-
* A check in ngtsc's `R3SymbolsImportRewriter` validates this condition. The rewriter is only used
|
|
18231
|
-
* when compiling @angular/core and is responsible for translating an external name (prefixed with
|
|
18232
|
-
* ɵ) to the internal symbol name as exported below.
|
|
18233
|
-
*
|
|
18234
|
-
* The below symbols are used for @Injectable and @NgModule compilation.
|
|
18235
|
-
*/
|
|
18236
|
-
/**
|
|
18237
|
-
* The existence of this constant (in this particular file) informs the Angular compiler that the
|
|
18238
|
-
* current program is actually @angular/core, which needs to be compiled specially.
|
|
18239
|
-
*/
|
|
18240
|
-
const ITS_JUST_ANGULAR = true;
|
|
18241
|
-
|
|
18242
|
-
/**
|
|
18243
|
-
* *Internal* service that keeps track of pending tasks happening in the system.
|
|
18244
|
-
*
|
|
18245
|
-
* This information is needed to make sure that the serialization on the server
|
|
18246
|
-
* is delayed until all tasks in the queue (such as an initial navigation or a
|
|
18247
|
-
* pending HTTP request) are completed.
|
|
18248
|
-
*
|
|
18249
|
-
* Pending tasks continue to contribute to the stableness of `ApplicationRef`
|
|
18250
|
-
* throughout the lifetime of the application.
|
|
18251
|
-
*/
|
|
18252
|
-
class PendingTasks {
|
|
18253
|
-
constructor() {
|
|
18254
|
-
this.taskId = 0;
|
|
18255
|
-
this.pendingTasks = new Set();
|
|
18256
|
-
this.hasPendingTasks = new BehaviorSubject(false);
|
|
18257
|
-
}
|
|
18258
|
-
get _hasPendingTasks() {
|
|
18259
|
-
return this.hasPendingTasks.value;
|
|
18260
|
-
}
|
|
18261
|
-
add() {
|
|
18262
|
-
if (!this._hasPendingTasks) {
|
|
18263
|
-
this.hasPendingTasks.next(true);
|
|
18358
|
+
if (enableLongStackTrace && Zone['longStackTraceZoneSpec']) {
|
|
18359
|
+
self._inner = self._inner.fork(Zone['longStackTraceZoneSpec']);
|
|
18264
18360
|
}
|
|
18265
|
-
|
|
18266
|
-
|
|
18267
|
-
|
|
18361
|
+
// if shouldCoalesceRunChangeDetection is true, all tasks including event tasks will be
|
|
18362
|
+
// coalesced, so shouldCoalesceEventChangeDetection option is not necessary and can be skipped.
|
|
18363
|
+
self.shouldCoalesceEventChangeDetection =
|
|
18364
|
+
!shouldCoalesceRunChangeDetection && shouldCoalesceEventChangeDetection;
|
|
18365
|
+
self.shouldCoalesceRunChangeDetection = shouldCoalesceRunChangeDetection;
|
|
18366
|
+
self.lastRequestAnimationFrameId = -1;
|
|
18367
|
+
self.nativeRequestAnimationFrame = getNativeRequestAnimationFrame().nativeRequestAnimationFrame;
|
|
18368
|
+
forkInnerZoneWithAngularBehavior(self);
|
|
18268
18369
|
}
|
|
18269
|
-
|
|
18270
|
-
|
|
18271
|
-
|
|
18272
|
-
|
|
18370
|
+
/**
|
|
18371
|
+
This method checks whether the method call happens within an Angular Zone instance.
|
|
18372
|
+
*/
|
|
18373
|
+
static isInAngularZone() {
|
|
18374
|
+
// Zone needs to be checked, because this method might be called even when NoopNgZone is used.
|
|
18375
|
+
return typeof Zone !== 'undefined' && Zone.current.get('isAngularZone') === true;
|
|
18376
|
+
}
|
|
18377
|
+
/**
|
|
18378
|
+
Assures that the method is called within the Angular Zone, otherwise throws an error.
|
|
18379
|
+
*/
|
|
18380
|
+
static assertInAngularZone() {
|
|
18381
|
+
if (!NgZone.isInAngularZone()) {
|
|
18382
|
+
throw new RuntimeError(909 /* RuntimeErrorCode.UNEXPECTED_ZONE_STATE */, ngDevMode && 'Expected to be in Angular Zone, but it is not!');
|
|
18273
18383
|
}
|
|
18274
18384
|
}
|
|
18275
|
-
|
|
18276
|
-
|
|
18277
|
-
|
|
18278
|
-
|
|
18385
|
+
/**
|
|
18386
|
+
Assures that the method is called outside of the Angular Zone, otherwise throws an error.
|
|
18387
|
+
*/
|
|
18388
|
+
static assertNotInAngularZone() {
|
|
18389
|
+
if (NgZone.isInAngularZone()) {
|
|
18390
|
+
throw new RuntimeError(909 /* RuntimeErrorCode.UNEXPECTED_ZONE_STATE */, ngDevMode && 'Expected to not be in Angular Zone, but it is!');
|
|
18279
18391
|
}
|
|
18280
18392
|
}
|
|
18281
|
-
|
|
18282
|
-
|
|
18283
|
-
|
|
18284
|
-
|
|
18285
|
-
|
|
18286
|
-
|
|
18287
|
-
|
|
18288
|
-
|
|
18289
|
-
|
|
18290
|
-
|
|
18291
|
-
|
|
18292
|
-
|
|
18293
|
-
|
|
18294
|
-
return
|
|
18295
|
-
return Array.isArray(obj) ||
|
|
18296
|
-
(!(obj instanceof Map) && // JS Map are iterables but return entries as [k, v]
|
|
18297
|
-
Symbol.iterator in obj); // JS Iterable have a Symbol.iterator prop
|
|
18298
|
-
}
|
|
18299
|
-
function areIterablesEqual(a, b, comparator) {
|
|
18300
|
-
const iterator1 = a[Symbol.iterator]();
|
|
18301
|
-
const iterator2 = b[Symbol.iterator]();
|
|
18302
|
-
while (true) {
|
|
18303
|
-
const item1 = iterator1.next();
|
|
18304
|
-
const item2 = iterator2.next();
|
|
18305
|
-
if (item1.done && item2.done)
|
|
18306
|
-
return true;
|
|
18307
|
-
if (item1.done || item2.done)
|
|
18308
|
-
return false;
|
|
18309
|
-
if (!comparator(item1.value, item2.value))
|
|
18310
|
-
return false;
|
|
18393
|
+
/**
|
|
18394
|
+
* Executes the `fn` function synchronously within the Angular zone and returns value returned by
|
|
18395
|
+
* the function.
|
|
18396
|
+
*
|
|
18397
|
+
* Running functions via `run` allows you to reenter Angular zone from a task that was executed
|
|
18398
|
+
* outside of the Angular zone (typically started via {@link #runOutsideAngular}).
|
|
18399
|
+
*
|
|
18400
|
+
* Any future tasks or microtasks scheduled from within this function will continue executing from
|
|
18401
|
+
* within the Angular zone.
|
|
18402
|
+
*
|
|
18403
|
+
* If a synchronous error happens it will be rethrown and not reported via `onError`.
|
|
18404
|
+
*/
|
|
18405
|
+
run(fn, applyThis, applyArgs) {
|
|
18406
|
+
return this._inner.run(fn, applyThis, applyArgs);
|
|
18311
18407
|
}
|
|
18312
|
-
|
|
18313
|
-
|
|
18314
|
-
|
|
18315
|
-
|
|
18316
|
-
|
|
18408
|
+
/**
|
|
18409
|
+
* Executes the `fn` function synchronously within the Angular zone as a task and returns value
|
|
18410
|
+
* returned by the function.
|
|
18411
|
+
*
|
|
18412
|
+
* Running functions via `run` allows you to reenter Angular zone from a task that was executed
|
|
18413
|
+
* outside of the Angular zone (typically started via {@link #runOutsideAngular}).
|
|
18414
|
+
*
|
|
18415
|
+
* Any future tasks or microtasks scheduled from within this function will continue executing from
|
|
18416
|
+
* within the Angular zone.
|
|
18417
|
+
*
|
|
18418
|
+
* If a synchronous error happens it will be rethrown and not reported via `onError`.
|
|
18419
|
+
*/
|
|
18420
|
+
runTask(fn, applyThis, applyArgs, name) {
|
|
18421
|
+
const zone = this._inner;
|
|
18422
|
+
const task = zone.scheduleEventTask('NgZoneEvent: ' + name, fn, EMPTY_PAYLOAD, noop, noop);
|
|
18423
|
+
try {
|
|
18424
|
+
return zone.runTask(task, applyThis, applyArgs);
|
|
18425
|
+
}
|
|
18426
|
+
finally {
|
|
18427
|
+
zone.cancelTask(task);
|
|
18317
18428
|
}
|
|
18318
18429
|
}
|
|
18319
|
-
|
|
18320
|
-
|
|
18321
|
-
|
|
18322
|
-
|
|
18323
|
-
|
|
18324
|
-
|
|
18430
|
+
/**
|
|
18431
|
+
* Same as `run`, except that synchronous errors are caught and forwarded via `onError` and not
|
|
18432
|
+
* rethrown.
|
|
18433
|
+
*/
|
|
18434
|
+
runGuarded(fn, applyThis, applyArgs) {
|
|
18435
|
+
return this._inner.runGuarded(fn, applyThis, applyArgs);
|
|
18325
18436
|
}
|
|
18326
|
-
|
|
18327
|
-
function
|
|
18328
|
-
|
|
18329
|
-
|
|
18330
|
-
|
|
18331
|
-
|
|
18332
|
-
|
|
18333
|
-
|
|
18334
|
-
|
|
18335
|
-
|
|
18437
|
+
/**
|
|
18438
|
+
* Executes the `fn` function synchronously in Angular's parent zone and returns value returned by
|
|
18439
|
+
* the function.
|
|
18440
|
+
*
|
|
18441
|
+
* Running functions via {@link #runOutsideAngular} allows you to escape Angular's zone and do
|
|
18442
|
+
* work that
|
|
18443
|
+
* doesn't trigger Angular change-detection or is subject to Angular's error handling.
|
|
18444
|
+
*
|
|
18445
|
+
* Any future tasks or microtasks scheduled from within this function will continue executing from
|
|
18446
|
+
* outside of the Angular zone.
|
|
18447
|
+
*
|
|
18448
|
+
* Use {@link #run} to reenter the Angular zone and do work that updates the application model.
|
|
18449
|
+
*/
|
|
18450
|
+
runOutsideAngular(fn) {
|
|
18451
|
+
return this._outer.run(fn);
|
|
18336
18452
|
}
|
|
18337
|
-
|
|
18338
|
-
|
|
18339
|
-
|
|
18340
|
-
|
|
18341
|
-
|
|
18453
|
+
}
|
|
18454
|
+
const EMPTY_PAYLOAD = {};
|
|
18455
|
+
function checkStable(zone) {
|
|
18456
|
+
// TODO: @JiaLiPassion, should check zone.isCheckStableRunning to prevent
|
|
18457
|
+
// re-entry. The case is:
|
|
18458
|
+
//
|
|
18459
|
+
// @Component({...})
|
|
18460
|
+
// export class AppComponent {
|
|
18461
|
+
// constructor(private ngZone: NgZone) {
|
|
18462
|
+
// this.ngZone.onStable.subscribe(() => {
|
|
18463
|
+
// this.ngZone.run(() => console.log('stable'););
|
|
18464
|
+
// });
|
|
18465
|
+
// }
|
|
18466
|
+
//
|
|
18467
|
+
// The onStable subscriber run another function inside ngZone
|
|
18468
|
+
// which causes `checkStable()` re-entry.
|
|
18469
|
+
// But this fix causes some issues in g3, so this fix will be
|
|
18470
|
+
// launched in another PR.
|
|
18471
|
+
if (zone._nesting == 0 && !zone.hasPendingMicrotasks && !zone.isStable) {
|
|
18472
|
+
try {
|
|
18473
|
+
zone._nesting++;
|
|
18474
|
+
zone.onMicrotaskEmpty.emit(null);
|
|
18342
18475
|
}
|
|
18343
|
-
|
|
18344
|
-
|
|
18476
|
+
finally {
|
|
18477
|
+
zone._nesting--;
|
|
18478
|
+
if (!zone.hasPendingMicrotasks) {
|
|
18479
|
+
try {
|
|
18480
|
+
zone.runOutsideAngular(() => zone.onStable.emit(null));
|
|
18481
|
+
}
|
|
18482
|
+
finally {
|
|
18483
|
+
zone.isStable = true;
|
|
18484
|
+
}
|
|
18485
|
+
}
|
|
18345
18486
|
}
|
|
18346
18487
|
}
|
|
18347
18488
|
}
|
|
18348
|
-
|
|
18349
|
-
|
|
18350
|
-
|
|
18351
|
-
|
|
18352
|
-
|
|
18353
|
-
}
|
|
18354
|
-
|
|
18355
|
-
|
|
18356
|
-
|
|
18357
|
-
|
|
18358
|
-
|
|
18359
|
-
|
|
18360
|
-
|
|
18361
|
-
|
|
18362
|
-
|
|
18363
|
-
|
|
18364
|
-
* This function also checks the `CheckNoChangesMode` and throws if changes are made.
|
|
18365
|
-
* Some changes (Objects/iterables) during `CheckNoChangesMode` are exempt to comply with VE
|
|
18366
|
-
* behavior.
|
|
18367
|
-
*
|
|
18368
|
-
* @param lView current `LView`
|
|
18369
|
-
* @param bindingIndex The binding in the `LView` to check
|
|
18370
|
-
* @param value New value to check against `lView[bindingIndex]`
|
|
18371
|
-
* @returns `true` if the bindings has changed. (Throws if binding has changed during
|
|
18372
|
-
* `CheckNoChangesMode`)
|
|
18373
|
-
*/
|
|
18374
|
-
function bindingUpdated(lView, bindingIndex, value) {
|
|
18375
|
-
ngDevMode && assertNotSame(value, NO_CHANGE, 'Incoming value should never be NO_CHANGE.');
|
|
18376
|
-
ngDevMode &&
|
|
18377
|
-
assertLessThan(bindingIndex, lView.length, `Slot should have been initialized to NO_CHANGE`);
|
|
18378
|
-
const oldValue = lView[bindingIndex];
|
|
18379
|
-
if (Object.is(oldValue, value)) {
|
|
18380
|
-
return false;
|
|
18489
|
+
function delayChangeDetectionForEvents(zone) {
|
|
18490
|
+
/**
|
|
18491
|
+
* We also need to check _nesting here
|
|
18492
|
+
* Consider the following case with shouldCoalesceRunChangeDetection = true
|
|
18493
|
+
*
|
|
18494
|
+
* ngZone.run(() => {});
|
|
18495
|
+
* ngZone.run(() => {});
|
|
18496
|
+
*
|
|
18497
|
+
* We want the two `ngZone.run()` only trigger one change detection
|
|
18498
|
+
* when shouldCoalesceRunChangeDetection is true.
|
|
18499
|
+
* And because in this case, change detection run in async way(requestAnimationFrame),
|
|
18500
|
+
* so we also need to check the _nesting here to prevent multiple
|
|
18501
|
+
* change detections.
|
|
18502
|
+
*/
|
|
18503
|
+
if (zone.isCheckStableRunning || zone.lastRequestAnimationFrameId !== -1) {
|
|
18504
|
+
return;
|
|
18381
18505
|
}
|
|
18382
|
-
|
|
18383
|
-
|
|
18384
|
-
|
|
18385
|
-
|
|
18386
|
-
|
|
18387
|
-
|
|
18388
|
-
|
|
18389
|
-
|
|
18506
|
+
zone.lastRequestAnimationFrameId = zone.nativeRequestAnimationFrame.call(_global, () => {
|
|
18507
|
+
// This is a work around for https://github.com/angular/angular/issues/36839.
|
|
18508
|
+
// The core issue is that when event coalescing is enabled it is possible for microtasks
|
|
18509
|
+
// to get flushed too early (As is the case with `Promise.then`) between the
|
|
18510
|
+
// coalescing eventTasks.
|
|
18511
|
+
//
|
|
18512
|
+
// To workaround this we schedule a "fake" eventTask before we process the
|
|
18513
|
+
// coalescing eventTasks. The benefit of this is that the "fake" container eventTask
|
|
18514
|
+
// will prevent the microtasks queue from getting drained in between the coalescing
|
|
18515
|
+
// eventTask execution.
|
|
18516
|
+
if (!zone.fakeTopEventTask) {
|
|
18517
|
+
zone.fakeTopEventTask = Zone.root.scheduleEventTask('fakeTopEventTask', () => {
|
|
18518
|
+
zone.lastRequestAnimationFrameId = -1;
|
|
18519
|
+
updateMicroTaskStatus(zone);
|
|
18520
|
+
zone.isCheckStableRunning = true;
|
|
18521
|
+
checkStable(zone);
|
|
18522
|
+
zone.isCheckStableRunning = false;
|
|
18523
|
+
}, undefined, () => { }, () => { });
|
|
18524
|
+
}
|
|
18525
|
+
zone.fakeTopEventTask.invoke();
|
|
18526
|
+
});
|
|
18527
|
+
updateMicroTaskStatus(zone);
|
|
18528
|
+
}
|
|
18529
|
+
function forkInnerZoneWithAngularBehavior(zone) {
|
|
18530
|
+
const delayChangeDetectionForEventsDelegate = () => {
|
|
18531
|
+
delayChangeDetectionForEvents(zone);
|
|
18532
|
+
};
|
|
18533
|
+
zone._inner = zone._inner.fork({
|
|
18534
|
+
name: 'angular',
|
|
18535
|
+
properties: { 'isAngularZone': true },
|
|
18536
|
+
onInvokeTask: (delegate, current, target, task, applyThis, applyArgs) => {
|
|
18537
|
+
if (shouldBeIgnoredByZone(applyArgs)) {
|
|
18538
|
+
return delegate.invokeTask(target, task, applyThis, applyArgs);
|
|
18390
18539
|
}
|
|
18391
|
-
|
|
18392
|
-
|
|
18393
|
-
|
|
18394
|
-
|
|
18540
|
+
try {
|
|
18541
|
+
onEnter(zone);
|
|
18542
|
+
return delegate.invokeTask(target, task, applyThis, applyArgs);
|
|
18543
|
+
}
|
|
18544
|
+
finally {
|
|
18545
|
+
if ((zone.shouldCoalesceEventChangeDetection && task.type === 'eventTask') ||
|
|
18546
|
+
zone.shouldCoalesceRunChangeDetection) {
|
|
18547
|
+
delayChangeDetectionForEventsDelegate();
|
|
18548
|
+
}
|
|
18549
|
+
onLeave(zone);
|
|
18550
|
+
}
|
|
18551
|
+
},
|
|
18552
|
+
onInvoke: (delegate, current, target, callback, applyThis, applyArgs, source) => {
|
|
18553
|
+
try {
|
|
18554
|
+
onEnter(zone);
|
|
18555
|
+
return delegate.invoke(target, callback, applyThis, applyArgs, source);
|
|
18556
|
+
}
|
|
18557
|
+
finally {
|
|
18558
|
+
if (zone.shouldCoalesceRunChangeDetection) {
|
|
18559
|
+
delayChangeDetectionForEventsDelegate();
|
|
18560
|
+
}
|
|
18561
|
+
onLeave(zone);
|
|
18562
|
+
}
|
|
18563
|
+
},
|
|
18564
|
+
onHasTask: (delegate, current, target, hasTaskState) => {
|
|
18565
|
+
delegate.hasTask(target, hasTaskState);
|
|
18566
|
+
if (current === target) {
|
|
18567
|
+
// We are only interested in hasTask events which originate from our zone
|
|
18568
|
+
// (A child hasTask event is not interesting to us)
|
|
18569
|
+
if (hasTaskState.change == 'microTask') {
|
|
18570
|
+
zone._hasPendingMicrotasks = hasTaskState.microTask;
|
|
18571
|
+
updateMicroTaskStatus(zone);
|
|
18572
|
+
checkStable(zone);
|
|
18573
|
+
}
|
|
18574
|
+
else if (hasTaskState.change == 'macroTask') {
|
|
18575
|
+
zone.hasPendingMacrotasks = hasTaskState.macroTask;
|
|
18576
|
+
}
|
|
18577
|
+
}
|
|
18578
|
+
},
|
|
18579
|
+
onHandleError: (delegate, current, target, error) => {
|
|
18580
|
+
delegate.handleError(target, error);
|
|
18581
|
+
zone.runOutsideAngular(() => zone.onError.emit(error));
|
|
18395
18582
|
return false;
|
|
18396
18583
|
}
|
|
18397
|
-
|
|
18398
|
-
return true;
|
|
18399
|
-
}
|
|
18400
|
-
}
|
|
18401
|
-
/** Updates 2 bindings if changed, then returns whether either was updated. */
|
|
18402
|
-
function bindingUpdated2(lView, bindingIndex, exp1, exp2) {
|
|
18403
|
-
const different = bindingUpdated(lView, bindingIndex, exp1);
|
|
18404
|
-
return bindingUpdated(lView, bindingIndex + 1, exp2) || different;
|
|
18405
|
-
}
|
|
18406
|
-
/** Updates 3 bindings if changed, then returns whether any was updated. */
|
|
18407
|
-
function bindingUpdated3(lView, bindingIndex, exp1, exp2, exp3) {
|
|
18408
|
-
const different = bindingUpdated2(lView, bindingIndex, exp1, exp2);
|
|
18409
|
-
return bindingUpdated(lView, bindingIndex + 2, exp3) || different;
|
|
18410
|
-
}
|
|
18411
|
-
/** Updates 4 bindings if changed, then returns whether any was updated. */
|
|
18412
|
-
function bindingUpdated4(lView, bindingIndex, exp1, exp2, exp3, exp4) {
|
|
18413
|
-
const different = bindingUpdated2(lView, bindingIndex, exp1, exp2);
|
|
18414
|
-
return bindingUpdated2(lView, bindingIndex + 2, exp3, exp4) || different;
|
|
18415
|
-
}
|
|
18416
|
-
|
|
18417
|
-
/**
|
|
18418
|
-
* Checks whether a TNode is considered detached, i.e. not present in the
|
|
18419
|
-
* translated i18n template. We should not attempt hydration for such nodes
|
|
18420
|
-
* and instead, use a regular "creation mode".
|
|
18421
|
-
*/
|
|
18422
|
-
function isDetachedByI18n(tNode) {
|
|
18423
|
-
return (tNode.flags & 32 /* TNodeFlags.isDetached */) === 32 /* TNodeFlags.isDetached */;
|
|
18424
|
-
}
|
|
18425
|
-
|
|
18426
|
-
function templateFirstCreatePass(index, tView, lView, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex) {
|
|
18427
|
-
ngDevMode && assertFirstCreatePass(tView);
|
|
18428
|
-
ngDevMode && ngDevMode.firstCreatePass++;
|
|
18429
|
-
const tViewConsts = tView.consts;
|
|
18430
|
-
// TODO(pk): refactor getOrCreateTNode to have the "create" only version
|
|
18431
|
-
const tNode = getOrCreateTNode(tView, index, 4 /* TNodeType.Container */, tagName || null, getConstant(tViewConsts, attrsIndex));
|
|
18432
|
-
resolveDirectives(tView, lView, tNode, getConstant(tViewConsts, localRefsIndex));
|
|
18433
|
-
registerPostOrderHooks(tView, tNode);
|
|
18434
|
-
const embeddedTView = tNode.tView = createTView(2 /* TViewType.Embedded */, tNode, templateFn, decls, vars, tView.directiveRegistry, tView.pipeRegistry, null, tView.schemas, tViewConsts, null /* ssrId */);
|
|
18435
|
-
if (tView.queries !== null) {
|
|
18436
|
-
tView.queries.template(tView, tNode);
|
|
18437
|
-
embeddedTView.queries = tView.queries.embeddedTView(tNode);
|
|
18438
|
-
}
|
|
18439
|
-
return tNode;
|
|
18584
|
+
});
|
|
18440
18585
|
}
|
|
18441
|
-
|
|
18442
|
-
|
|
18443
|
-
|
|
18444
|
-
|
|
18445
|
-
|
|
18446
|
-
* </ng-template>
|
|
18447
|
-
*
|
|
18448
|
-
* @param index The index of the container in the data array
|
|
18449
|
-
* @param templateFn Inline template
|
|
18450
|
-
* @param decls The number of nodes, local refs, and pipes for this template
|
|
18451
|
-
* @param vars The number of bindings for this template
|
|
18452
|
-
* @param tagName The name of the container element, if applicable
|
|
18453
|
-
* @param attrsIndex Index of template attributes in the `consts` array.
|
|
18454
|
-
* @param localRefs Index of the local references in the `consts` array.
|
|
18455
|
-
* @param localRefExtractor A function which extracts local-refs values from the template.
|
|
18456
|
-
* Defaults to the current element associated with the local-ref.
|
|
18457
|
-
*
|
|
18458
|
-
* @codeGenApi
|
|
18459
|
-
*/
|
|
18460
|
-
function ɵɵtemplate(index, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex, localRefExtractor) {
|
|
18461
|
-
const lView = getLView();
|
|
18462
|
-
const tView = getTView();
|
|
18463
|
-
const adjustedIndex = index + HEADER_OFFSET;
|
|
18464
|
-
const tNode = tView.firstCreatePass ? templateFirstCreatePass(adjustedIndex, tView, lView, templateFn, decls, vars, tagName, attrsIndex, localRefsIndex) :
|
|
18465
|
-
tView.data[adjustedIndex];
|
|
18466
|
-
setCurrentTNode(tNode, false);
|
|
18467
|
-
const comment = _locateOrCreateContainerAnchor(tView, lView, tNode, index);
|
|
18468
|
-
if (wasLastNodeCreated()) {
|
|
18469
|
-
appendChild(tView, lView, comment, tNode);
|
|
18586
|
+
function updateMicroTaskStatus(zone) {
|
|
18587
|
+
if (zone._hasPendingMicrotasks ||
|
|
18588
|
+
((zone.shouldCoalesceEventChangeDetection || zone.shouldCoalesceRunChangeDetection) &&
|
|
18589
|
+
zone.lastRequestAnimationFrameId !== -1)) {
|
|
18590
|
+
zone.hasPendingMicrotasks = true;
|
|
18470
18591
|
}
|
|
18471
|
-
|
|
18472
|
-
|
|
18473
|
-
lView[adjustedIndex] = lContainer;
|
|
18474
|
-
addToViewTree(lView, lContainer);
|
|
18475
|
-
// If hydration is enabled, looks up dehydrated views in the DOM
|
|
18476
|
-
// using hydration annotation info and stores those views on LContainer.
|
|
18477
|
-
// In client-only mode, this function is a noop.
|
|
18478
|
-
populateDehydratedViewsInLContainer(lContainer, tNode, lView);
|
|
18479
|
-
if (isDirectiveHost(tNode)) {
|
|
18480
|
-
createDirectivesInstances(tView, lView, tNode);
|
|
18592
|
+
else {
|
|
18593
|
+
zone.hasPendingMicrotasks = false;
|
|
18481
18594
|
}
|
|
18482
|
-
|
|
18483
|
-
|
|
18595
|
+
}
|
|
18596
|
+
function onEnter(zone) {
|
|
18597
|
+
zone._nesting++;
|
|
18598
|
+
if (zone.isStable) {
|
|
18599
|
+
zone.isStable = false;
|
|
18600
|
+
zone.onUnstable.emit(null);
|
|
18484
18601
|
}
|
|
18485
|
-
return ɵɵtemplate;
|
|
18486
18602
|
}
|
|
18487
|
-
|
|
18488
|
-
|
|
18489
|
-
|
|
18490
|
-
*/
|
|
18491
|
-
function createContainerAnchorImpl(tView, lView, tNode, index) {
|
|
18492
|
-
lastNodeWasCreated(true);
|
|
18493
|
-
return lView[RENDERER].createComment(ngDevMode ? 'container' : '');
|
|
18603
|
+
function onLeave(zone) {
|
|
18604
|
+
zone._nesting--;
|
|
18605
|
+
checkStable(zone);
|
|
18494
18606
|
}
|
|
18495
18607
|
/**
|
|
18496
|
-
*
|
|
18497
|
-
*
|
|
18498
|
-
* anchor (comment) nodes.
|
|
18608
|
+
* Provides a noop implementation of `NgZone` which does nothing. This zone requires explicit calls
|
|
18609
|
+
* to framework to perform rendering.
|
|
18499
18610
|
*/
|
|
18500
|
-
|
|
18501
|
-
|
|
18502
|
-
|
|
18503
|
-
|
|
18504
|
-
|
|
18505
|
-
|
|
18506
|
-
|
|
18507
|
-
|
|
18611
|
+
class NoopNgZone {
|
|
18612
|
+
constructor() {
|
|
18613
|
+
this.hasPendingMicrotasks = false;
|
|
18614
|
+
this.hasPendingMacrotasks = false;
|
|
18615
|
+
this.isStable = true;
|
|
18616
|
+
this.onUnstable = new EventEmitter();
|
|
18617
|
+
this.onMicrotaskEmpty = new EventEmitter();
|
|
18618
|
+
this.onStable = new EventEmitter();
|
|
18619
|
+
this.onError = new EventEmitter();
|
|
18508
18620
|
}
|
|
18509
|
-
|
|
18510
|
-
|
|
18511
|
-
//
|
|
18512
|
-
// There might be situations when the same component is present in a template
|
|
18513
|
-
// multiple times and some instances are opted-out of using hydration via
|
|
18514
|
-
// `ngSkipHydration` attribute. In this scenario, at the time a TView is created,
|
|
18515
|
-
// the `ssrId` might be `null` (if the first component is opted-out of hydration).
|
|
18516
|
-
// The code below makes sure that the `ssrId` is applied to the TView if it's still
|
|
18517
|
-
// `null` and verifies we never try to override it with a different value.
|
|
18518
|
-
if (ssrId !== null && tNode.tView !== null) {
|
|
18519
|
-
if (tNode.tView.ssrId === null) {
|
|
18520
|
-
tNode.tView.ssrId = ssrId;
|
|
18521
|
-
}
|
|
18522
|
-
else {
|
|
18523
|
-
ngDevMode &&
|
|
18524
|
-
assertEqual(tNode.tView.ssrId, ssrId, 'Unexpected value of the `ssrId` for this TView');
|
|
18525
|
-
}
|
|
18621
|
+
run(fn, applyThis, applyArgs) {
|
|
18622
|
+
return fn.apply(applyThis, applyArgs);
|
|
18526
18623
|
}
|
|
18527
|
-
|
|
18528
|
-
|
|
18529
|
-
ngDevMode && validateNodeExists(currentRNode, lView, tNode);
|
|
18530
|
-
setSegmentHead(hydrationInfo, index, currentRNode);
|
|
18531
|
-
const viewContainerSize = calcSerializedContainerSize(hydrationInfo, index);
|
|
18532
|
-
const comment = siblingAfter(viewContainerSize, currentRNode);
|
|
18533
|
-
if (ngDevMode) {
|
|
18534
|
-
validateMatchingNode(comment, Node.COMMENT_NODE, null, lView, tNode);
|
|
18535
|
-
markRNodeAsClaimedByHydration(comment);
|
|
18624
|
+
runGuarded(fn, applyThis, applyArgs) {
|
|
18625
|
+
return fn.apply(applyThis, applyArgs);
|
|
18536
18626
|
}
|
|
18537
|
-
|
|
18538
|
-
|
|
18539
|
-
|
|
18540
|
-
|
|
18541
|
-
|
|
18542
|
-
|
|
18543
|
-
/**
|
|
18544
|
-
* Describes the state of defer block dependency loading.
|
|
18545
|
-
*/
|
|
18546
|
-
var DeferDependenciesLoadingState;
|
|
18547
|
-
(function (DeferDependenciesLoadingState) {
|
|
18548
|
-
/** Initial state, dependency loading is not yet triggered */
|
|
18549
|
-
DeferDependenciesLoadingState[DeferDependenciesLoadingState["NOT_STARTED"] = 0] = "NOT_STARTED";
|
|
18550
|
-
/** Dependency loading is in progress */
|
|
18551
|
-
DeferDependenciesLoadingState[DeferDependenciesLoadingState["IN_PROGRESS"] = 1] = "IN_PROGRESS";
|
|
18552
|
-
/** Dependency loading has completed successfully */
|
|
18553
|
-
DeferDependenciesLoadingState[DeferDependenciesLoadingState["COMPLETE"] = 2] = "COMPLETE";
|
|
18554
|
-
/** Dependency loading has failed */
|
|
18555
|
-
DeferDependenciesLoadingState[DeferDependenciesLoadingState["FAILED"] = 3] = "FAILED";
|
|
18556
|
-
})(DeferDependenciesLoadingState || (DeferDependenciesLoadingState = {}));
|
|
18557
|
-
/** Slot index where `minimum` parameter value is stored. */
|
|
18558
|
-
const MINIMUM_SLOT = 0;
|
|
18559
|
-
/** Slot index where `after` parameter value is stored. */
|
|
18560
|
-
const LOADING_AFTER_SLOT = 1;
|
|
18561
|
-
/**
|
|
18562
|
-
* Describes the current state of this defer block instance.
|
|
18563
|
-
*
|
|
18564
|
-
* @publicApi
|
|
18565
|
-
* @developerPreview
|
|
18566
|
-
*/
|
|
18567
|
-
var DeferBlockState;
|
|
18568
|
-
(function (DeferBlockState) {
|
|
18569
|
-
/** The placeholder block content is rendered */
|
|
18570
|
-
DeferBlockState[DeferBlockState["Placeholder"] = 0] = "Placeholder";
|
|
18571
|
-
/** The loading block content is rendered */
|
|
18572
|
-
DeferBlockState[DeferBlockState["Loading"] = 1] = "Loading";
|
|
18573
|
-
/** The main content block content is rendered */
|
|
18574
|
-
DeferBlockState[DeferBlockState["Complete"] = 2] = "Complete";
|
|
18575
|
-
/** The error block content is rendered */
|
|
18576
|
-
DeferBlockState[DeferBlockState["Error"] = 3] = "Error";
|
|
18577
|
-
})(DeferBlockState || (DeferBlockState = {}));
|
|
18578
|
-
/**
|
|
18579
|
-
* Describes the initial state of this defer block instance.
|
|
18580
|
-
*
|
|
18581
|
-
* Note: this state is internal only and *must* be represented
|
|
18582
|
-
* with a number lower than any value in the `DeferBlockState` enum.
|
|
18583
|
-
*/
|
|
18584
|
-
var DeferBlockInternalState;
|
|
18585
|
-
(function (DeferBlockInternalState) {
|
|
18586
|
-
/** Initial state. Nothing is rendered yet. */
|
|
18587
|
-
DeferBlockInternalState[DeferBlockInternalState["Initial"] = -1] = "Initial";
|
|
18588
|
-
})(DeferBlockInternalState || (DeferBlockInternalState = {}));
|
|
18589
|
-
const NEXT_DEFER_BLOCK_STATE = 0;
|
|
18590
|
-
// Note: it's *important* to keep the state in this slot, because this slot
|
|
18591
|
-
// is used by runtime logic to differentiate between LViews, LContainers and
|
|
18592
|
-
// other types (see `isLView` and `isLContainer` functions). In case of defer
|
|
18593
|
-
// blocks, this slot would always be a number.
|
|
18594
|
-
const DEFER_BLOCK_STATE = 1;
|
|
18595
|
-
const STATE_IS_FROZEN_UNTIL = 2;
|
|
18596
|
-
const LOADING_AFTER_CLEANUP_FN = 3;
|
|
18597
|
-
const TRIGGER_CLEANUP_FNS = 4;
|
|
18598
|
-
const PREFETCH_TRIGGER_CLEANUP_FNS = 5;
|
|
18599
|
-
/**
|
|
18600
|
-
* Options for configuring defer blocks behavior.
|
|
18601
|
-
* @publicApi
|
|
18602
|
-
* @developerPreview
|
|
18603
|
-
*/
|
|
18604
|
-
var DeferBlockBehavior;
|
|
18605
|
-
(function (DeferBlockBehavior) {
|
|
18606
|
-
/**
|
|
18607
|
-
* Manual triggering mode for defer blocks. Provides control over when defer blocks render
|
|
18608
|
-
* and which state they render.
|
|
18609
|
-
*/
|
|
18610
|
-
DeferBlockBehavior[DeferBlockBehavior["Manual"] = 0] = "Manual";
|
|
18611
|
-
/**
|
|
18612
|
-
* Playthrough mode for defer blocks. This mode behaves like defer blocks would in a browser.
|
|
18613
|
-
* This is the default behavior in test environments.
|
|
18614
|
-
*/
|
|
18615
|
-
DeferBlockBehavior[DeferBlockBehavior["Playthrough"] = 1] = "Playthrough";
|
|
18616
|
-
})(DeferBlockBehavior || (DeferBlockBehavior = {}));
|
|
18617
|
-
|
|
18618
|
-
/*!
|
|
18619
|
-
* @license
|
|
18620
|
-
* Copyright Google LLC All Rights Reserved.
|
|
18621
|
-
*
|
|
18622
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
18623
|
-
* found in the LICENSE file at https://angular.io/license
|
|
18624
|
-
*/
|
|
18625
|
-
/**
|
|
18626
|
-
* Registers a cleanup function associated with a prefetching trigger
|
|
18627
|
-
* or a regular trigger of a defer block.
|
|
18628
|
-
*/
|
|
18629
|
-
function storeTriggerCleanupFn(type, lDetails, cleanupFn) {
|
|
18630
|
-
const key = type === 1 /* TriggerType.Prefetch */ ? PREFETCH_TRIGGER_CLEANUP_FNS : TRIGGER_CLEANUP_FNS;
|
|
18631
|
-
if (lDetails[key] === null) {
|
|
18632
|
-
lDetails[key] = [];
|
|
18627
|
+
runOutsideAngular(fn) {
|
|
18628
|
+
return fn();
|
|
18629
|
+
}
|
|
18630
|
+
runTask(fn, applyThis, applyArgs, name) {
|
|
18631
|
+
return fn.apply(applyThis, applyArgs);
|
|
18633
18632
|
}
|
|
18634
|
-
lDetails[key].push(cleanupFn);
|
|
18635
18633
|
}
|
|
18636
|
-
|
|
18637
|
-
|
|
18638
|
-
|
|
18639
|
-
|
|
18640
|
-
|
|
18641
|
-
|
|
18642
|
-
if (
|
|
18643
|
-
|
|
18644
|
-
cleanupFn();
|
|
18645
|
-
}
|
|
18646
|
-
lDetails[key] = null;
|
|
18634
|
+
function shouldBeIgnoredByZone(applyArgs) {
|
|
18635
|
+
if (!Array.isArray(applyArgs)) {
|
|
18636
|
+
return false;
|
|
18637
|
+
}
|
|
18638
|
+
// We should only ever get 1 arg passed through to invokeTask.
|
|
18639
|
+
// Short circuit here incase that behavior changes.
|
|
18640
|
+
if (applyArgs.length !== 1) {
|
|
18641
|
+
return false;
|
|
18647
18642
|
}
|
|
18643
|
+
// Prevent triggering change detection when the __ignore_ng_zone__ flag is detected.
|
|
18644
|
+
return applyArgs[0].data?.['__ignore_ng_zone__'] === true;
|
|
18648
18645
|
}
|
|
18649
|
-
|
|
18650
|
-
|
|
18651
|
-
|
|
18652
|
-
|
|
18653
|
-
|
|
18654
|
-
|
|
18646
|
+
function getNgZone(ngZoneToUse = 'zone.js', options) {
|
|
18647
|
+
if (ngZoneToUse === 'noop') {
|
|
18648
|
+
return new NoopNgZone();
|
|
18649
|
+
}
|
|
18650
|
+
if (ngZoneToUse === 'zone.js') {
|
|
18651
|
+
return new NgZone(options);
|
|
18652
|
+
}
|
|
18653
|
+
return ngZoneToUse;
|
|
18655
18654
|
}
|
|
18656
18655
|
|
|
18657
18656
|
// Public API for Zone
|
|
@@ -29853,7 +29852,7 @@ class Version {
|
|
|
29853
29852
|
/**
|
|
29854
29853
|
* @publicApi
|
|
29855
29854
|
*/
|
|
29856
|
-
const VERSION = new Version('17.3.
|
|
29855
|
+
const VERSION = new Version('17.3.7');
|
|
29857
29856
|
|
|
29858
29857
|
class Console {
|
|
29859
29858
|
log(message) {
|
|
@@ -30714,7 +30713,10 @@ let _published = false;
|
|
|
30714
30713
|
function publishDefaultGlobalUtils$1() {
|
|
30715
30714
|
if (!_published) {
|
|
30716
30715
|
_published = true;
|
|
30717
|
-
|
|
30716
|
+
if (typeof window !== 'undefined') {
|
|
30717
|
+
// Only configure the injector profiler when running in the browser.
|
|
30718
|
+
setupFrameworkInjectorProfiler();
|
|
30719
|
+
}
|
|
30718
30720
|
for (const [methodName, method] of Object.entries(globalUtilsFunctions)) {
|
|
30719
30721
|
publishGlobalUtil(methodName, method);
|
|
30720
30722
|
}
|