@angular/core 19.2.0 → 19.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/core.mjs +52 -69
- package/fesm2022/core.mjs.map +1 -1
- package/fesm2022/primitives/di.mjs +45 -0
- package/fesm2022/primitives/di.mjs.map +1 -0
- package/fesm2022/primitives/event-dispatch.mjs +2 -2
- package/fesm2022/primitives/signals.mjs +2 -2
- package/fesm2022/rxjs-interop.mjs +2 -2
- package/fesm2022/testing.mjs +280 -119
- package/fesm2022/testing.mjs.map +1 -1
- package/index.d.ts +27 -30
- package/package.json +5 -1
- package/primitives/di/index.d.ts +99 -0
- package/primitives/event-dispatch/index.d.ts +2 -2
- package/primitives/signals/index.d.ts +2 -2
- package/rxjs-interop/index.d.ts +2 -2
- package/schematics/bundles/{apply_import_manager-a4e62ded.js → apply_import_manager-b8d6885d.js} +4 -4
- package/schematics/bundles/{checker-2eecc677.js → checker-89987c98.js} +11 -15
- package/schematics/bundles/cleanup-unused-imports.js +8 -8
- package/schematics/bundles/{compiler_host-f313eac9.js → compiler_host-2398e4ca.js} +3 -3
- package/schematics/bundles/control-flow-migration.js +4 -4
- package/schematics/bundles/explicit-standalone-flag.js +6 -6
- package/schematics/bundles/{imports-31a38653.js → imports-047fbbc8.js} +2 -2
- package/schematics/bundles/{index-3891dd55.js → index-10911843.js} +5 -5
- package/schematics/bundles/{index-afc3f749.js → index-e0b2e4a7.js} +5 -5
- package/schematics/bundles/inject-migration.js +8 -8
- package/schematics/bundles/{leading_space-6e7a8ec6.js → leading_space-f8944434.js} +2 -2
- package/schematics/bundles/{migrate_ts_type_references-1abf1f5f.js → migrate_ts_type_references-52508cd4.js} +7 -7
- package/schematics/bundles/{ng_decorators-6878e227.js → ng_decorators-b0d8b324.js} +3 -3
- package/schematics/bundles/{nodes-ffdce442.js → nodes-7758dbf6.js} +2 -2
- package/schematics/bundles/output-migration.js +8 -8
- package/schematics/bundles/pending-tasks.js +6 -6
- package/schematics/bundles/{program-24da9092.js → program-0e1d4f10.js} +13 -13
- package/schematics/bundles/{project_paths-64bc3947.js → project_paths-c48796dd.js} +4 -4
- package/schematics/bundles/{project_tsconfig_paths-6c9cde78.js → project_tsconfig_paths-b558633b.js} +2 -2
- package/schematics/bundles/{property_name-42030525.js → property_name-ac18447e.js} +2 -2
- package/schematics/bundles/provide-initializer.js +6 -6
- package/schematics/bundles/route-lazy-loading.js +6 -6
- package/schematics/bundles/self-closing-tags-migration.js +44 -28
- package/schematics/bundles/signal-input-migration.js +10 -10
- package/schematics/bundles/signal-queries-migration.js +10 -10
- package/schematics/bundles/signals.js +10 -10
- package/schematics/bundles/standalone-migration.js +10 -10
- package/testing/index.d.ts +25 -14
package/fesm2022/testing.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v19.2.
|
|
3
|
-
* (c) 2010-
|
|
2
|
+
* @license Angular v19.2.1
|
|
3
|
+
* (c) 2010-2025 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -175,10 +175,10 @@ class TestBedApplicationErrorHandler {
|
|
|
175
175
|
throw e;
|
|
176
176
|
}
|
|
177
177
|
}
|
|
178
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.
|
|
179
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.
|
|
178
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: TestBedApplicationErrorHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
179
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: TestBedApplicationErrorHandler });
|
|
180
180
|
}
|
|
181
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.
|
|
181
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: TestBedApplicationErrorHandler, decorators: [{
|
|
182
182
|
type: Injectable
|
|
183
183
|
}] });
|
|
184
184
|
|
|
@@ -2326,8 +2326,9 @@ class FakeNavigation {
|
|
|
2326
2326
|
currentEntryIndex = 0;
|
|
2327
2327
|
/**
|
|
2328
2328
|
* The current navigate event.
|
|
2329
|
+
* @internal
|
|
2329
2330
|
*/
|
|
2330
|
-
navigateEvent =
|
|
2331
|
+
navigateEvent = null;
|
|
2331
2332
|
/**
|
|
2332
2333
|
* A Map of pending traversals, so that traversals to the same entry can be
|
|
2333
2334
|
* re-used.
|
|
@@ -2350,7 +2351,10 @@ class FakeNavigation {
|
|
|
2350
2351
|
synchronousTraversals = false;
|
|
2351
2352
|
/** Whether to allow a call to setInitialEntryForTesting. */
|
|
2352
2353
|
canSetInitialEntry = true;
|
|
2353
|
-
/**
|
|
2354
|
+
/**
|
|
2355
|
+
* `EventTarget` to dispatch events.
|
|
2356
|
+
* @internal
|
|
2357
|
+
*/
|
|
2354
2358
|
eventTarget;
|
|
2355
2359
|
/** The next unique id for created entries. Replace recreates this id. */
|
|
2356
2360
|
nextId = 0;
|
|
@@ -2382,7 +2386,7 @@ class FakeNavigation {
|
|
|
2382
2386
|
throw new Error('setInitialEntryForTesting can only be called before any ' + 'navigation has occurred');
|
|
2383
2387
|
}
|
|
2384
2388
|
const currentInitialEntry = this.entriesArr[0];
|
|
2385
|
-
this.entriesArr[0] = new FakeNavigationHistoryEntry(new URL(url).toString(), {
|
|
2389
|
+
this.entriesArr[0] = new FakeNavigationHistoryEntry(this.window.document.createElement('div'), new URL(url).toString(), {
|
|
2386
2390
|
index: 0,
|
|
2387
2391
|
key: currentInitialEntry?.key ?? String(this.nextKey++),
|
|
2388
2392
|
id: currentInitialEntry?.id ?? String(this.nextId++),
|
|
@@ -2430,7 +2434,7 @@ class FakeNavigation {
|
|
|
2430
2434
|
sameDocument: hashChange,
|
|
2431
2435
|
historyState: null,
|
|
2432
2436
|
});
|
|
2433
|
-
const result = new InternalNavigationResult();
|
|
2437
|
+
const result = new InternalNavigationResult(this);
|
|
2434
2438
|
this.userAgentNavigate(destination, result, {
|
|
2435
2439
|
navigationType,
|
|
2436
2440
|
cancelable: true,
|
|
@@ -2462,7 +2466,7 @@ class FakeNavigation {
|
|
|
2462
2466
|
sameDocument: true,
|
|
2463
2467
|
historyState: data,
|
|
2464
2468
|
});
|
|
2465
|
-
const result = new InternalNavigationResult();
|
|
2469
|
+
const result = new InternalNavigationResult(this);
|
|
2466
2470
|
this.userAgentNavigate(destination, result, {
|
|
2467
2471
|
navigationType,
|
|
2468
2472
|
cancelable: true,
|
|
@@ -2470,7 +2474,6 @@ class FakeNavigation {
|
|
|
2470
2474
|
// Always false for pushState() or replaceState().
|
|
2471
2475
|
userInitiated: false,
|
|
2472
2476
|
hashChange,
|
|
2473
|
-
skipPopState: true,
|
|
2474
2477
|
});
|
|
2475
2478
|
}
|
|
2476
2479
|
/** Equivalent to `navigation.traverseTo()`. */
|
|
@@ -2512,11 +2515,11 @@ class FakeNavigation {
|
|
|
2512
2515
|
sameDocument: entry.sameDocument,
|
|
2513
2516
|
});
|
|
2514
2517
|
this.prospectiveEntryIndex = entry.index;
|
|
2515
|
-
const result = new InternalNavigationResult();
|
|
2518
|
+
const result = new InternalNavigationResult(this);
|
|
2516
2519
|
this.traversalQueue.set(entry.key, result);
|
|
2517
2520
|
this.runTraversal(() => {
|
|
2518
2521
|
this.traversalQueue.delete(entry.key);
|
|
2519
|
-
this.userAgentNavigate(destination, result, {
|
|
2522
|
+
const event = this.userAgentNavigate(destination, result, {
|
|
2520
2523
|
navigationType: 'traverse',
|
|
2521
2524
|
cancelable: true,
|
|
2522
2525
|
canIntercept: true,
|
|
@@ -2525,6 +2528,8 @@ class FakeNavigation {
|
|
|
2525
2528
|
hashChange,
|
|
2526
2529
|
info: options?.info,
|
|
2527
2530
|
});
|
|
2531
|
+
// Note this does not pay attention at all to the commit status of the event (and thus, does not support deferred commit for traversals)
|
|
2532
|
+
this.userAgentTraverse(event);
|
|
2528
2533
|
});
|
|
2529
2534
|
return {
|
|
2530
2535
|
committed: result.committed,
|
|
@@ -2593,8 +2598,8 @@ class FakeNavigation {
|
|
|
2593
2598
|
index: entry.index,
|
|
2594
2599
|
sameDocument: entry.sameDocument,
|
|
2595
2600
|
});
|
|
2596
|
-
const result = new InternalNavigationResult();
|
|
2597
|
-
this.userAgentNavigate(destination, result, {
|
|
2601
|
+
const result = new InternalNavigationResult(this);
|
|
2602
|
+
const event = this.userAgentNavigate(destination, result, {
|
|
2598
2603
|
navigationType: 'traverse',
|
|
2599
2604
|
cancelable: true,
|
|
2600
2605
|
canIntercept: true,
|
|
@@ -2602,6 +2607,8 @@ class FakeNavigation {
|
|
|
2602
2607
|
userInitiated: false,
|
|
2603
2608
|
hashChange,
|
|
2604
2609
|
});
|
|
2610
|
+
// Note this does not pay attention at all to the commit status of the event (and thus, does not support deferred commit for traversals)
|
|
2611
|
+
this.userAgentTraverse(event);
|
|
2605
2612
|
});
|
|
2606
2613
|
}
|
|
2607
2614
|
/** Runs a traversal synchronously or asynchronously */
|
|
@@ -2652,9 +2659,9 @@ class FakeNavigation {
|
|
|
2652
2659
|
this.canSetInitialEntry = false;
|
|
2653
2660
|
if (this.navigateEvent) {
|
|
2654
2661
|
this.navigateEvent.cancel(new DOMException('Navigation was aborted', 'AbortError'));
|
|
2655
|
-
this.navigateEvent =
|
|
2662
|
+
this.navigateEvent = null;
|
|
2656
2663
|
}
|
|
2657
|
-
|
|
2664
|
+
return dispatchNavigateEvent({
|
|
2658
2665
|
navigationType: options.navigationType,
|
|
2659
2666
|
cancelable: options.cancelable,
|
|
2660
2667
|
canIntercept: options.canIntercept,
|
|
@@ -2664,78 +2671,103 @@ class FakeNavigation {
|
|
|
2664
2671
|
destination,
|
|
2665
2672
|
info: options.info,
|
|
2666
2673
|
sameDocument: destination.sameDocument,
|
|
2667
|
-
skipPopState: options.skipPopState,
|
|
2668
2674
|
result,
|
|
2669
|
-
userAgentCommit: () => {
|
|
2670
|
-
this.userAgentCommit();
|
|
2671
|
-
},
|
|
2672
2675
|
});
|
|
2673
|
-
this.navigateEvent = navigateEvent;
|
|
2674
|
-
this.eventTarget.dispatchEvent(navigateEvent);
|
|
2675
|
-
navigateEvent.dispatchedNavigateEvent();
|
|
2676
|
-
if (navigateEvent.commitOption === 'immediate') {
|
|
2677
|
-
navigateEvent.commit(/* internal= */ true);
|
|
2678
|
-
}
|
|
2679
2676
|
}
|
|
2680
|
-
/**
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2677
|
+
/**
|
|
2678
|
+
* Implementation to commit a navigation.
|
|
2679
|
+
* https://whatpr.org/html/10919/nav-history-apis.html#navigateevent-commit
|
|
2680
|
+
* @internal
|
|
2681
|
+
*/
|
|
2682
|
+
commitNavigateEvent(navigateEvent) {
|
|
2683
|
+
navigateEvent.interceptionState = 'committed';
|
|
2685
2684
|
const from = this.currentEntry;
|
|
2686
|
-
if (!
|
|
2685
|
+
if (!from) {
|
|
2686
|
+
throw new Error('cannot commit navigation when current entry is null');
|
|
2687
|
+
}
|
|
2688
|
+
if (!navigateEvent.sameDocument) {
|
|
2687
2689
|
const error = new Error('Cannot navigate to a non-same-document URL.');
|
|
2688
|
-
|
|
2690
|
+
navigateEvent.cancel(error);
|
|
2689
2691
|
throw error;
|
|
2690
2692
|
}
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
this.
|
|
2694
|
-
navigationType: this.navigateEvent.navigationType,
|
|
2695
|
-
});
|
|
2693
|
+
// "If navigationType is "push" or "replace", then run the URL and history update steps given document and event's destination's URL, with serialiedData set to event's classic history API state and historyHandling set to navigationType."
|
|
2694
|
+
if (navigateEvent.navigationType === 'push' || navigateEvent.navigationType === 'replace') {
|
|
2695
|
+
this.urlAndHistoryUpdateSteps(navigateEvent);
|
|
2696
2696
|
}
|
|
2697
|
-
else if (
|
|
2698
|
-
this.
|
|
2697
|
+
else if (navigateEvent.navigationType === 'reload') {
|
|
2698
|
+
this.updateNavigationEntriesForSameDocumentNavigation(navigateEvent);
|
|
2699
2699
|
}
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
from,
|
|
2703
|
-
navigationType: this.navigateEvent.navigationType,
|
|
2704
|
-
});
|
|
2705
|
-
this.eventTarget.dispatchEvent(currentEntryChangeEvent);
|
|
2706
|
-
if (!this.navigateEvent.skipPopState) {
|
|
2707
|
-
const popStateEvent = createPopStateEvent({
|
|
2708
|
-
state: this.navigateEvent.destination.getHistoryState(),
|
|
2709
|
-
});
|
|
2710
|
-
this.window.dispatchEvent(popStateEvent);
|
|
2700
|
+
else if (navigateEvent.navigationType === 'traverse') {
|
|
2701
|
+
// "If navigationType is "traverse", then this event firing is happening as part of the traversal process, and that process will take care of performing the appropriate session history entry updates."
|
|
2711
2702
|
}
|
|
2712
2703
|
}
|
|
2713
|
-
/**
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2704
|
+
/**
|
|
2705
|
+
* Implementation for a push or replace navigation.
|
|
2706
|
+
* https://whatpr.org/html/10919/browsing-the-web.html#url-and-history-update-steps
|
|
2707
|
+
* https://whatpr.org/html/10919/nav-history-apis.html#update-the-navigation-api-entries-for-a-same-document-navigation
|
|
2708
|
+
*/
|
|
2709
|
+
urlAndHistoryUpdateSteps(navigateEvent) {
|
|
2710
|
+
this.updateNavigationEntriesForSameDocumentNavigation(navigateEvent);
|
|
2711
|
+
}
|
|
2712
|
+
/**
|
|
2713
|
+
* Implementation for a traverse navigation.
|
|
2714
|
+
*
|
|
2715
|
+
* https://whatpr.org/html/10919/browsing-the-web.html#apply-the-traverse-history-step
|
|
2716
|
+
* ...
|
|
2717
|
+
* > Let updateDocument be an algorithm step which performs update document for history step application given targetEntry's document, targetEntry, changingNavigableContinuation's update-only, scriptHistoryLength, scriptHistoryIndex, navigationType, entriesForNavigationAPI, and previousEntry.
|
|
2718
|
+
* > If targetEntry's document is equal to displayedDocument, then perform updateDocument.
|
|
2719
|
+
* https://whatpr.org/html/10919/browsing-the-web.html#update-document-for-history-step-application
|
|
2720
|
+
* which then goes to https://whatpr.org/html/10919/nav-history-apis.html#update-the-navigation-api-entries-for-a-same-document-navigation
|
|
2721
|
+
*/
|
|
2722
|
+
userAgentTraverse(navigateEvent) {
|
|
2723
|
+
this.updateNavigationEntriesForSameDocumentNavigation(navigateEvent);
|
|
2724
|
+
// Happens as part of "updating the document" steps https://whatpr.org/html/10919/browsing-the-web.html#updating-the-document
|
|
2725
|
+
const popStateEvent = createPopStateEvent({
|
|
2726
|
+
state: navigateEvent.destination.getHistoryState(),
|
|
2728
2727
|
});
|
|
2729
|
-
|
|
2730
|
-
|
|
2728
|
+
this.window.dispatchEvent(popStateEvent);
|
|
2729
|
+
// TODO(atscott): If oldURL's fragment is not equal to entry's URL's fragment, then queue a global task to fire an event named hashchange
|
|
2730
|
+
}
|
|
2731
|
+
/** https://whatpr.org/html/10919/nav-history-apis.html#update-the-navigation-api-entries-for-a-same-document-navigation */
|
|
2732
|
+
updateNavigationEntriesForSameDocumentNavigation({ destination, navigationType, result, }) {
|
|
2733
|
+
const oldCurrentNHE = this.currentEntry;
|
|
2734
|
+
const disposedNHEs = [];
|
|
2735
|
+
if (navigationType === 'traverse') {
|
|
2736
|
+
this.currentEntryIndex = destination.index;
|
|
2737
|
+
if (this.currentEntryIndex === -1) {
|
|
2738
|
+
throw new Error('unexpected current entry index');
|
|
2739
|
+
}
|
|
2731
2740
|
}
|
|
2732
|
-
else {
|
|
2733
|
-
this.
|
|
2741
|
+
else if (navigationType === 'push') {
|
|
2742
|
+
this.currentEntryIndex++;
|
|
2743
|
+
this.prospectiveEntryIndex = this.currentEntryIndex; // prospectiveEntryIndex isn't in the spec but is an implementation detail
|
|
2744
|
+
disposedNHEs.push(...this.entriesArr.splice(this.currentEntryIndex));
|
|
2745
|
+
}
|
|
2746
|
+
else if (navigationType === 'replace') {
|
|
2747
|
+
disposedNHEs.push(oldCurrentNHE);
|
|
2748
|
+
}
|
|
2749
|
+
if (navigationType === 'push' || navigationType === 'replace') {
|
|
2750
|
+
const index = this.currentEntryIndex;
|
|
2751
|
+
const key = navigationType === 'push' ? String(this.nextKey++) : this.currentEntry.key;
|
|
2752
|
+
const newNHE = new FakeNavigationHistoryEntry(this.window.document.createElement('div'), destination.url, {
|
|
2753
|
+
id: String(this.nextId++),
|
|
2754
|
+
key,
|
|
2755
|
+
index,
|
|
2756
|
+
sameDocument: true,
|
|
2757
|
+
state: destination.getState(),
|
|
2758
|
+
historyState: destination.getHistoryState(),
|
|
2759
|
+
});
|
|
2760
|
+
this.entriesArr[this.currentEntryIndex] = newNHE;
|
|
2761
|
+
}
|
|
2762
|
+
result.committedResolve(this.currentEntry);
|
|
2763
|
+
const currentEntryChangeEvent = createFakeNavigationCurrentEntryChangeEvent({
|
|
2764
|
+
from: oldCurrentNHE,
|
|
2765
|
+
navigationType: navigationType,
|
|
2766
|
+
});
|
|
2767
|
+
this.eventTarget.dispatchEvent(currentEntryChangeEvent);
|
|
2768
|
+
for (const disposedNHE of disposedNHEs) {
|
|
2769
|
+
disposedNHE.dispose();
|
|
2734
2770
|
}
|
|
2735
|
-
}
|
|
2736
|
-
/** Implementation for a traverse navigation. */
|
|
2737
|
-
userAgentTraverse(destination) {
|
|
2738
|
-
this.currentEntryIndex = destination.index;
|
|
2739
2771
|
}
|
|
2740
2772
|
/** Utility method for finding entries with the given `key`. */
|
|
2741
2773
|
findEntry(key) {
|
|
@@ -2778,8 +2810,13 @@ class FakeNavigation {
|
|
|
2778
2810
|
get onnavigateerror() {
|
|
2779
2811
|
throw new Error('unimplemented');
|
|
2780
2812
|
}
|
|
2813
|
+
_transition = null;
|
|
2814
|
+
/** @internal */
|
|
2815
|
+
set transition(t) {
|
|
2816
|
+
this._transition = t;
|
|
2817
|
+
}
|
|
2781
2818
|
get transition() {
|
|
2782
|
-
|
|
2819
|
+
return this._transition;
|
|
2783
2820
|
}
|
|
2784
2821
|
updateCurrentEntry(_options) {
|
|
2785
2822
|
throw new Error('unimplemented');
|
|
@@ -2792,6 +2829,7 @@ class FakeNavigation {
|
|
|
2792
2829
|
* Fake equivalent of `NavigationHistoryEntry`.
|
|
2793
2830
|
*/
|
|
2794
2831
|
class FakeNavigationHistoryEntry {
|
|
2832
|
+
eventTarget;
|
|
2795
2833
|
url;
|
|
2796
2834
|
sameDocument;
|
|
2797
2835
|
id;
|
|
@@ -2801,7 +2839,8 @@ class FakeNavigationHistoryEntry {
|
|
|
2801
2839
|
historyState;
|
|
2802
2840
|
// tslint:disable-next-line:no-any
|
|
2803
2841
|
ondispose = null;
|
|
2804
|
-
constructor(url, { id, key, index, sameDocument, state, historyState, }) {
|
|
2842
|
+
constructor(eventTarget, url, { id, key, index, sameDocument, state, historyState, }) {
|
|
2843
|
+
this.eventTarget = eventTarget;
|
|
2805
2844
|
this.url = url;
|
|
2806
2845
|
this.id = id;
|
|
2807
2846
|
this.key = key;
|
|
@@ -2821,21 +2860,34 @@ class FakeNavigationHistoryEntry {
|
|
|
2821
2860
|
: this.historyState;
|
|
2822
2861
|
}
|
|
2823
2862
|
addEventListener(type, callback, options) {
|
|
2824
|
-
|
|
2863
|
+
this.eventTarget.addEventListener(type, callback, options);
|
|
2825
2864
|
}
|
|
2826
2865
|
removeEventListener(type, callback, options) {
|
|
2827
|
-
|
|
2866
|
+
this.eventTarget.removeEventListener(type, callback, options);
|
|
2828
2867
|
}
|
|
2829
2868
|
dispatchEvent(event) {
|
|
2830
|
-
|
|
2869
|
+
return this.eventTarget.dispatchEvent(event);
|
|
2870
|
+
}
|
|
2871
|
+
/** internal */
|
|
2872
|
+
dispose() {
|
|
2873
|
+
const disposeEvent = new Event('disposed');
|
|
2874
|
+
this.dispatchEvent(disposeEvent);
|
|
2875
|
+
// release current listeners
|
|
2876
|
+
this.eventTarget = null;
|
|
2831
2877
|
}
|
|
2832
2878
|
}
|
|
2833
2879
|
/**
|
|
2834
2880
|
* Create a fake equivalent of `NavigateEvent`. This is not a class because ES5
|
|
2835
2881
|
* transpiled JavaScript cannot extend native Event.
|
|
2882
|
+
*
|
|
2883
|
+
* https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigate-event-firing
|
|
2836
2884
|
*/
|
|
2837
|
-
function
|
|
2885
|
+
function dispatchNavigateEvent({ cancelable, canIntercept, userInitiated, hashChange, navigationType, signal, destination, info, sameDocument, result, }) {
|
|
2886
|
+
const { navigation } = result;
|
|
2838
2887
|
const event = new Event('navigate', { bubbles: false, cancelable });
|
|
2888
|
+
event.focusResetBehavior = null;
|
|
2889
|
+
event.scrollBehavior = null;
|
|
2890
|
+
event.interceptionState = 'none';
|
|
2839
2891
|
event.canIntercept = canIntercept;
|
|
2840
2892
|
event.userInitiated = userInitiated;
|
|
2841
2893
|
event.hashChange = hashChange;
|
|
@@ -2845,71 +2897,151 @@ function createFakeNavigateEvent({ cancelable, canIntercept, userInitiated, hash
|
|
|
2845
2897
|
event.info = info;
|
|
2846
2898
|
event.downloadRequest = null;
|
|
2847
2899
|
event.formData = null;
|
|
2900
|
+
event.result = result;
|
|
2848
2901
|
event.sameDocument = sameDocument;
|
|
2849
|
-
event.skipPopState = skipPopState;
|
|
2850
2902
|
event.commitOption = 'immediate';
|
|
2851
|
-
let
|
|
2852
|
-
let interceptCalled = false;
|
|
2903
|
+
let handlersFinished = [Promise.resolve()];
|
|
2853
2904
|
let dispatchedNavigateEvent = false;
|
|
2854
|
-
let commitCalled = false;
|
|
2855
2905
|
event.intercept = function (options) {
|
|
2856
|
-
|
|
2906
|
+
if (!this.canIntercept) {
|
|
2907
|
+
throw new DOMException(`Cannot intercept when canIntercept is 'false'`, 'SecurityError');
|
|
2908
|
+
}
|
|
2909
|
+
this.interceptionState = 'intercepted';
|
|
2857
2910
|
event.sameDocument = true;
|
|
2858
2911
|
const handler = options?.handler;
|
|
2859
2912
|
if (handler) {
|
|
2860
|
-
|
|
2861
|
-
}
|
|
2862
|
-
if (options?.commit) {
|
|
2863
|
-
event.commitOption = options.commit;
|
|
2913
|
+
handlersFinished.push(handler());
|
|
2864
2914
|
}
|
|
2865
|
-
//
|
|
2915
|
+
// override old options with new ones. UA _may_ report a console warning if new options differ from previous
|
|
2916
|
+
event.commitOption = options?.commit ?? event.commitOption;
|
|
2917
|
+
event.scrollBehavior = options?.scroll ?? event.scrollBehavior;
|
|
2918
|
+
event.focusResetBehavior = options?.focusReset ?? event.focusResetBehavior;
|
|
2866
2919
|
};
|
|
2867
2920
|
event.scroll = function () {
|
|
2868
|
-
|
|
2921
|
+
if (event.interceptionState !== 'committed') {
|
|
2922
|
+
throw new DOMException(`Failed to execute 'scroll' on 'NavigateEvent': scroll() must be ` +
|
|
2923
|
+
`called after commit() and interception options must specify manual scroll.`, 'InvalidStateError');
|
|
2924
|
+
}
|
|
2925
|
+
processScrollBehavior(event);
|
|
2869
2926
|
};
|
|
2870
2927
|
event.commit = function (internal = false) {
|
|
2871
|
-
if (!internal &&
|
|
2928
|
+
if (!internal && this.interceptionState !== 'intercepted') {
|
|
2872
2929
|
throw new DOMException(`Failed to execute 'commit' on 'NavigateEvent': intercept() must be ` +
|
|
2873
|
-
`called before commit().`, 'InvalidStateError');
|
|
2930
|
+
`called before commit() and commit() cannot be already called.`, 'InvalidStateError');
|
|
2931
|
+
}
|
|
2932
|
+
if (!internal && event.commitOption !== 'after-transition') {
|
|
2933
|
+
throw new DOMException(`Failed to execute 'commit' on 'NavigateEvent': commit() may not be ` +
|
|
2934
|
+
`called if commit behavior is not "after-transition",.`, 'InvalidStateError');
|
|
2874
2935
|
}
|
|
2875
2936
|
if (!dispatchedNavigateEvent) {
|
|
2876
2937
|
throw new DOMException(`Failed to execute 'commit' on 'NavigateEvent': commit() may not be ` +
|
|
2877
2938
|
`called during event dispatch.`, 'InvalidStateError');
|
|
2878
2939
|
}
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
}
|
|
2882
|
-
commitCalled = true;
|
|
2883
|
-
userAgentCommit();
|
|
2940
|
+
this.interceptionState = 'committed';
|
|
2941
|
+
result.navigation.commitNavigateEvent(event);
|
|
2884
2942
|
};
|
|
2885
2943
|
// Internal only.
|
|
2886
2944
|
event.cancel = function (reason) {
|
|
2887
2945
|
result.committedReject(reason);
|
|
2888
2946
|
result.finishedReject(reason);
|
|
2889
2947
|
};
|
|
2890
|
-
|
|
2891
|
-
|
|
2948
|
+
function dispatch() {
|
|
2949
|
+
navigation.navigateEvent = event;
|
|
2950
|
+
navigation.eventTarget.dispatchEvent(event);
|
|
2892
2951
|
dispatchedNavigateEvent = true;
|
|
2893
|
-
if (event.
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
}
|
|
2899
|
-
}, () => { });
|
|
2952
|
+
if (event.interceptionState !== 'none') {
|
|
2953
|
+
navigation.transition = new InternalNavigationTransition(navigation.currentEntry, navigationType);
|
|
2954
|
+
if (event.commitOption !== 'after-transition') {
|
|
2955
|
+
event.commit(/** internal */ true);
|
|
2956
|
+
}
|
|
2900
2957
|
}
|
|
2901
|
-
|
|
2902
|
-
|
|
2958
|
+
else {
|
|
2959
|
+
// In the spec, this isn't really part of the navigate API. Instead, the navigate event firing returns "true" to indicate
|
|
2960
|
+
// navigation steps should "continue" (https://whatpr.org/html/10919/browsing-the-web.html#beginning-navigation)
|
|
2961
|
+
event.commit(/** internal */ true);
|
|
2962
|
+
}
|
|
2963
|
+
Promise.all(handlersFinished).then(() => {
|
|
2964
|
+
// Follows steps outlined under "Wait for all of promisesList, with the following success steps:"
|
|
2965
|
+
// in the spec https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigate-event-firing.
|
|
2966
|
+
if (result.signal.aborted) {
|
|
2967
|
+
return;
|
|
2968
|
+
}
|
|
2969
|
+
if (event !== navigation.navigateEvent) {
|
|
2970
|
+
throw new Error("Navigation's ongoing event not equal to resolved event");
|
|
2971
|
+
}
|
|
2972
|
+
navigation.navigateEvent = null;
|
|
2973
|
+
if (event.interceptionState === 'intercepted') {
|
|
2974
|
+
navigation.commitNavigateEvent(event);
|
|
2975
|
+
}
|
|
2976
|
+
finishNavigationEvent(event, true);
|
|
2977
|
+
const navigatesuccessEvent = new Event('navigatesuccess', { bubbles: false, cancelable });
|
|
2978
|
+
navigation.eventTarget.dispatchEvent(navigatesuccessEvent);
|
|
2979
|
+
result.finishedResolve();
|
|
2980
|
+
if (navigation.transition !== null) {
|
|
2981
|
+
navigation.transition.finishedResolve();
|
|
2982
|
+
}
|
|
2983
|
+
navigation.transition = null;
|
|
2903
2984
|
}, (reason) => {
|
|
2985
|
+
if (result.signal.aborted) {
|
|
2986
|
+
return;
|
|
2987
|
+
}
|
|
2988
|
+
if (event !== navigation.navigateEvent) {
|
|
2989
|
+
throw new Error("Navigation's ongoing event not equal to resolved event");
|
|
2990
|
+
}
|
|
2991
|
+
navigation.navigateEvent = null;
|
|
2992
|
+
event.interceptionState = 'rejected'; // TODO(atscott): this is not in the spec https://github.com/whatwg/html/issues/11087
|
|
2993
|
+
finishNavigationEvent(event, false);
|
|
2994
|
+
const navigateerrorEvent = new Event('navigateerror', { bubbles: false, cancelable });
|
|
2995
|
+
navigation.eventTarget.dispatchEvent(navigateerrorEvent);
|
|
2904
2996
|
result.finishedReject(reason);
|
|
2997
|
+
if (navigation.transition !== null) {
|
|
2998
|
+
navigation.transition.finishedResolve();
|
|
2999
|
+
}
|
|
3000
|
+
navigation.transition = null;
|
|
2905
3001
|
});
|
|
2906
|
-
}
|
|
2907
|
-
|
|
2908
|
-
event.userAgentNavigated = function (entry) {
|
|
2909
|
-
result.committedResolve(entry);
|
|
2910
|
-
};
|
|
3002
|
+
}
|
|
3003
|
+
dispatch();
|
|
2911
3004
|
return event;
|
|
2912
3005
|
}
|
|
3006
|
+
/** https://whatpr.org/html/10919/nav-history-apis.html#navigateevent-finish */
|
|
3007
|
+
function finishNavigationEvent(event, didFulfill) {
|
|
3008
|
+
if (event.interceptionState === 'intercepted' || event.interceptionState === 'finished') {
|
|
3009
|
+
throw new Error('Attempting to finish navigation event that was incomplete or already finished');
|
|
3010
|
+
}
|
|
3011
|
+
if (event.interceptionState === 'none') {
|
|
3012
|
+
return;
|
|
3013
|
+
}
|
|
3014
|
+
if (didFulfill) {
|
|
3015
|
+
// TODO(atscott): https://github.com/whatwg/html/issues/11087 focus reset is not guarded by didFulfill in the spec
|
|
3016
|
+
potentiallyResetFocus(event);
|
|
3017
|
+
potentiallyResetScroll(event);
|
|
3018
|
+
}
|
|
3019
|
+
event.interceptionState = 'finished';
|
|
3020
|
+
}
|
|
3021
|
+
/** https://whatpr.org/html/10919/nav-history-apis.html#potentially-reset-the-focus */
|
|
3022
|
+
function potentiallyResetFocus(event) {
|
|
3023
|
+
if (event.interceptionState !== 'committed' && event.interceptionState !== 'scrolled') {
|
|
3024
|
+
throw new Error('cannot reset focus if navigation event is not committed or scrolled');
|
|
3025
|
+
}
|
|
3026
|
+
// TODO(atscott): The rest of the steps
|
|
3027
|
+
}
|
|
3028
|
+
function potentiallyResetScroll(event) {
|
|
3029
|
+
if (event.interceptionState !== 'committed' && event.interceptionState !== 'scrolled') {
|
|
3030
|
+
throw new Error('cannot reset scroll if navigation event is not committed or scrolled');
|
|
3031
|
+
}
|
|
3032
|
+
if (event.interceptionState === 'scrolled' || event.scrollBehavior === 'manual') {
|
|
3033
|
+
return;
|
|
3034
|
+
}
|
|
3035
|
+
processScrollBehavior(event);
|
|
3036
|
+
}
|
|
3037
|
+
/* https://whatpr.org/html/10919/nav-history-apis.html#process-scroll-behavior */
|
|
3038
|
+
function processScrollBehavior(event) {
|
|
3039
|
+
if (event.interceptionState !== 'committed') {
|
|
3040
|
+
throw new Error('invalid event interception state when processing scroll behavior');
|
|
3041
|
+
}
|
|
3042
|
+
event.interceptionState = 'scrolled';
|
|
3043
|
+
// TODO(atscott): the rest of the steps
|
|
3044
|
+
}
|
|
2913
3045
|
/**
|
|
2914
3046
|
* Create a fake equivalent of `NavigationCurrentEntryChange`. This does not use
|
|
2915
3047
|
* a class because ES5 transpiled JavaScript cannot extend native Event.
|
|
@@ -2969,8 +3101,28 @@ function isHashChange(from, to) {
|
|
|
2969
3101
|
to.pathname === from.pathname &&
|
|
2970
3102
|
to.search === from.search);
|
|
2971
3103
|
}
|
|
2972
|
-
|
|
3104
|
+
class InternalNavigationTransition {
|
|
3105
|
+
from;
|
|
3106
|
+
navigationType;
|
|
3107
|
+
finished;
|
|
3108
|
+
finishedResolve;
|
|
3109
|
+
finishedReject;
|
|
3110
|
+
constructor(from, navigationType) {
|
|
3111
|
+
this.from = from;
|
|
3112
|
+
this.navigationType = navigationType;
|
|
3113
|
+
this.finished = new Promise((resolve, reject) => {
|
|
3114
|
+
this.finishedReject = reject;
|
|
3115
|
+
this.finishedResolve = resolve;
|
|
3116
|
+
});
|
|
3117
|
+
}
|
|
3118
|
+
}
|
|
3119
|
+
/**
|
|
3120
|
+
* Internal utility class for representing the result of a navigation.
|
|
3121
|
+
* Generally equivalent to the "apiMethodTracker" in the spec.
|
|
3122
|
+
*/
|
|
2973
3123
|
class InternalNavigationResult {
|
|
3124
|
+
navigation;
|
|
3125
|
+
committedTo = null;
|
|
2974
3126
|
committedResolve;
|
|
2975
3127
|
committedReject;
|
|
2976
3128
|
finishedResolve;
|
|
@@ -2981,13 +3133,22 @@ class InternalNavigationResult {
|
|
|
2981
3133
|
return this.abortController.signal;
|
|
2982
3134
|
}
|
|
2983
3135
|
abortController = new AbortController();
|
|
2984
|
-
constructor() {
|
|
3136
|
+
constructor(navigation) {
|
|
3137
|
+
this.navigation = navigation;
|
|
2985
3138
|
this.committed = new Promise((resolve, reject) => {
|
|
2986
|
-
this.committedResolve =
|
|
3139
|
+
this.committedResolve = (entry) => {
|
|
3140
|
+
this.committedTo = entry;
|
|
3141
|
+
resolve(entry);
|
|
3142
|
+
};
|
|
2987
3143
|
this.committedReject = reject;
|
|
2988
3144
|
});
|
|
2989
3145
|
this.finished = new Promise(async (resolve, reject) => {
|
|
2990
|
-
this.finishedResolve =
|
|
3146
|
+
this.finishedResolve = () => {
|
|
3147
|
+
if (this.committedTo === null) {
|
|
3148
|
+
throw new Error('NavigateEvent should have been committed before resolving finished promise.');
|
|
3149
|
+
}
|
|
3150
|
+
resolve(this.committedTo);
|
|
3151
|
+
};
|
|
2991
3152
|
this.finishedReject = (reason) => {
|
|
2992
3153
|
reject(reason);
|
|
2993
3154
|
this.abortController.abort(reason);
|