@angular/core 20.0.0-next.5 → 20.0.0-next.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.
Files changed (69) hide show
  1. package/{api.d-mxcXqDpA.d.ts → api.d-KjtSQajV.d.ts} +4 -4
  2. package/{ng_i18n_closure_mode.d-DLxSUiDr.d.ts → chrome_dev_tools_performance.d-qv7drdAl.d.ts} +20 -5
  3. package/{discovery.d-CyYpOJ7j.d.ts → discovery.d-D6xf1HH-.d.ts} +8 -79
  4. package/{event_dispatcher.d-PWnbqZDx.d.ts → event_dispatcher.d-DlbccpYq.d.ts} +3 -3
  5. package/fesm2022/{attribute-B17mgaqe.mjs → attribute-BWp59EjE.mjs} +3 -3
  6. package/fesm2022/{attribute-B17mgaqe.mjs.map → attribute-BWp59EjE.mjs.map} +1 -1
  7. package/fesm2022/core.mjs +22 -31
  8. package/fesm2022/core.mjs.map +1 -1
  9. package/fesm2022/{debug_node-xKpCIZm-.mjs → debug_node-B3CixwNH.mjs} +218 -141
  10. package/fesm2022/debug_node-B3CixwNH.mjs.map +1 -0
  11. package/fesm2022/primitives/di.mjs +1 -1
  12. package/fesm2022/primitives/event-dispatch.mjs +2 -2
  13. package/fesm2022/primitives/signals.mjs +5 -5
  14. package/fesm2022/{resource-BPpYEDic.mjs → resource-DtpS_sTw.mjs} +6 -8
  15. package/fesm2022/resource-DtpS_sTw.mjs.map +1 -0
  16. package/fesm2022/{root_effect_scheduler-D0_b1cf_.mjs → root_effect_scheduler-BK3l7wIO.mjs} +144 -68
  17. package/fesm2022/root_effect_scheduler-BK3l7wIO.mjs.map +1 -0
  18. package/fesm2022/rxjs-interop.mjs +7 -84
  19. package/fesm2022/rxjs-interop.mjs.map +1 -1
  20. package/fesm2022/{signal-DhRAAi7R.mjs → signal-B6pMq7KS.mjs} +3 -3
  21. package/fesm2022/{signal-DhRAAi7R.mjs.map → signal-B6pMq7KS.mjs.map} +1 -1
  22. package/fesm2022/testing.mjs +167 -103
  23. package/fesm2022/testing.mjs.map +1 -1
  24. package/fesm2022/{untracked-DaaW3JJm.mjs → untracked-Bz5WMeU1.mjs} +4 -4
  25. package/fesm2022/{untracked-DaaW3JJm.mjs.map → untracked-Bz5WMeU1.mjs.map} +1 -1
  26. package/fesm2022/{weak_ref-DrMdAIDh.mjs → weak_ref-BaIq-pgY.mjs} +3 -3
  27. package/fesm2022/{weak_ref-DrMdAIDh.mjs.map → weak_ref-BaIq-pgY.mjs.map} +1 -1
  28. package/{graph.d-StYigYp1.d.ts → graph.d-BcIOep_B.d.ts} +3 -3
  29. package/index.d.ts +34 -41
  30. package/package.json +2 -2
  31. package/primitives/di/index.d.ts +1 -1
  32. package/primitives/event-dispatch/index.d.ts +3 -3
  33. package/primitives/signals/index.d.ts +6 -6
  34. package/rxjs-interop/index.d.ts +8 -17
  35. package/schematics/bundles/{apply_import_manager-C-ysxahq.js → apply_import_manager-DczRKpTm.js} +6 -6
  36. package/schematics/bundles/{change_tracker-0Ktek5Xl.js → change_tracker-CWLh-wes.js} +3 -3
  37. package/schematics/bundles/{checker-DqUKCGda.js → checker-_f5wM7PH.js} +20 -3
  38. package/schematics/bundles/cleanup-unused-imports.js +25 -20
  39. package/schematics/bundles/{compiler-CuoiHqkc.js → compiler-BaCbbux6.js} +964 -298
  40. package/schematics/bundles/compiler_host-CAfDJO3W.js +1 -1
  41. package/schematics/bundles/control-flow-migration.js +2 -2
  42. package/schematics/bundles/document-core.js +12 -12
  43. package/schematics/bundles/imports-CIX-JgAN.js +1 -1
  44. package/schematics/bundles/{index-CwFQSYXZ.js → index--W6S49uu.js} +10 -10
  45. package/schematics/bundles/{index-WFXCe5Q0.js → index-rsJ8I_hu.js} +131 -64
  46. package/schematics/bundles/inject-flags.js +14 -14
  47. package/schematics/bundles/inject-migration.js +108 -19
  48. package/schematics/bundles/leading_space-D9nQ8UQC.js +1 -1
  49. package/schematics/bundles/{migrate_ts_type_references-BNuHufqZ.js → migrate_ts_type_references-C4D_SzJk.js} +21 -21
  50. package/schematics/bundles/ng_decorators-DznZ5jMl.js +1 -1
  51. package/schematics/bundles/nodes-B16H9JUd.js +1 -1
  52. package/schematics/bundles/output-migration.js +80 -22
  53. package/schematics/bundles/{run_in_devkit-CmHxABFr.js → project_paths-Ce0O2u-M.js} +254 -244
  54. package/schematics/bundles/project_tsconfig_paths-CDVxT6Ov.js +1 -1
  55. package/schematics/bundles/property_name-BBwFuqMe.js +1 -1
  56. package/schematics/bundles/route-lazy-loading.js +4 -4
  57. package/schematics/bundles/self-closing-tags-migration.js +20 -15
  58. package/schematics/bundles/signal-input-migration.js +26 -21
  59. package/schematics/bundles/signal-queries-migration.js +32 -27
  60. package/schematics/bundles/signals.js +8 -8
  61. package/schematics/bundles/standalone-migration.js +5 -5
  62. package/schematics/bundles/symbol-VPWguRxr.js +1 -1
  63. package/schematics/bundles/test-bed-get.js +13 -13
  64. package/{signal.d-BeaTIeOE.d.ts → signal.d-E0e5nW1p.d.ts} +4 -4
  65. package/testing/index.d.ts +9 -25
  66. package/{weak_ref.d-ttyj86RV.d.ts → weak_ref.d-eGOEP9S1.d.ts} +2 -2
  67. package/fesm2022/debug_node-xKpCIZm-.mjs.map +0 -1
  68. package/fesm2022/resource-BPpYEDic.mjs.map +0 -1
  69. package/fesm2022/root_effect_scheduler-D0_b1cf_.mjs.map +0 -1
@@ -1,18 +1,18 @@
1
1
  /**
2
- * @license Angular v20.0.0-next.5
2
+ * @license Angular v20.0.0-next.7
3
3
  * (c) 2010-2025 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
6
6
 
7
7
  import { Subscription } from 'rxjs';
8
- import { D as DeferBlockState, t as triggerResourceLoading, r as renderDeferBlockState, g as getDeferBlocks, a as DeferBlockBehavior, N as NgZone, I as Injectable, b as NoopNgZone, A as ApplicationRef, c as getDebugNode, R as RendererFactory2, P as Pipe, d as Directive, C as Component, e as NgModule, f as ReflectionCapabilities, h as depsTracker, i as isComponentDefPendingResolution, j as getAsyncClassMetadataFn, k as resolveComponentResources, l as NgModuleRef, m as ApplicationInitStatus, L as LOCALE_ID, n as DEFAULT_LOCALE_ID, s as setLocaleId, o as ComponentFactory, p as compileComponent, q as compileDirective, u as compilePipe, v as patchComponentDefWithScope, w as compileNgModuleDefs, x as clearResolutionOfComponentResourcesQueue, y as restoreComponentResolutionQueue, z as internalProvideZoneChangeDetection, B as ChangeDetectionSchedulerImpl, E as Compiler, F as DEFER_BLOCK_CONFIG, G as COMPILER_OPTIONS, H as transitiveScopesFor, J as generateStandaloneInDeclarationsError, K as NgModuleFactory, M as ModuleWithComponentFactories, O as resetCompiledComponents, ɵ as _setUnknownElementStrictMode, Q as _setUnknownPropertyStrictMode, S as _getUnknownElementStrictMode, T as _getUnknownPropertyStrictMode, U as flushModuleScopingQueueAsMuchAsPossible, V as setAllowDuplicateNgModuleIdsForTest } from './debug_node-xKpCIZm-.mjs';
9
- import { l as CONTAINER_HEADER_OFFSET, j as InjectionToken, i as inject$1, E as ErrorHandler, o as PendingTasksInternal, Z as ZONELESS_ENABLED, C as ChangeDetectionScheduler, c as EffectScheduler, p as stringify, q as getInjectableDef, r as resolveForwardRef, t as NG_COMP_DEF, u as NG_DIR_DEF, v as NG_PIPE_DEF, w as NG_INJ_DEF, x as NG_MOD_DEF, y as INTERNAL_APPLICATION_ERROR_HANDLER, I as Injector, z as isEnvironmentProviders, A as runInInjectionContext, B as EnvironmentInjector } from './root_effect_scheduler-D0_b1cf_.mjs';
8
+ import { DeferBlockState, triggerResourceLoading, renderDeferBlockState, getDeferBlocks, DeferBlockBehavior, NgZone, Injectable, NoopNgZone, ApplicationRef, getDebugNode, RendererFactory2, Pipe, Directive, Component, NgModule, ReflectionCapabilities, depsTracker, isComponentDefPendingResolution, getAsyncClassMetadataFn, resolveComponentResources, NgModuleRef, ApplicationInitStatus, LOCALE_ID, DEFAULT_LOCALE_ID, setLocaleId, ComponentFactory, compileComponent, compileDirective, compilePipe, patchComponentDefWithScope, compileNgModuleDefs, clearResolutionOfComponentResourcesQueue, restoreComponentResolutionQueue, internalProvideZoneChangeDetection, ChangeDetectionSchedulerImpl, Compiler, DEFER_BLOCK_CONFIG, COMPILER_OPTIONS, transitiveScopesFor, generateStandaloneInDeclarationsError, NgModuleFactory, ModuleWithComponentFactories, resetCompiledComponents, ɵsetUnknownElementStrictMode as _setUnknownElementStrictMode, ɵsetUnknownPropertyStrictMode as _setUnknownPropertyStrictMode, ɵgetUnknownElementStrictMode as _getUnknownElementStrictMode, ɵgetUnknownPropertyStrictMode as _getUnknownPropertyStrictMode, flushModuleScopingQueueAsMuchAsPossible, setAllowDuplicateNgModuleIdsForTest } from './debug_node-B3CixwNH.mjs';
9
+ import { CONTAINER_HEADER_OFFSET, InjectionToken, inject as inject$1, EnvironmentInjector, ErrorHandler, PendingTasksInternal, ZONELESS_ENABLED, ChangeDetectionScheduler, EffectScheduler, stringify, getInjectableDef, resolveForwardRef, NG_COMP_DEF, NG_DIR_DEF, NG_PIPE_DEF, NG_INJ_DEF, NG_MOD_DEF, ENVIRONMENT_INITIALIZER, INTERNAL_APPLICATION_ERROR_HANDLER, Injector, isEnvironmentProviders, runInInjectionContext } from './root_effect_scheduler-BK3l7wIO.mjs';
10
10
  import * as i0 from '@angular/core';
11
11
  import { ResourceLoader } from '@angular/compiler';
12
- import './signal-DhRAAi7R.mjs';
12
+ import './signal-B6pMq7KS.mjs';
13
13
  import '@angular/core/primitives/signals';
14
14
  import 'rxjs/operators';
15
- import './attribute-B17mgaqe.mjs';
15
+ import './attribute-BWp59EjE.mjs';
16
16
  import './primitives/di.mjs';
17
17
  import '@angular/core/primitives/di';
18
18
 
@@ -159,11 +159,15 @@ const ComponentFixtureNoNgZone = new InjectionToken('ComponentFixtureNoNgZone');
159
159
  const RETHROW_APPLICATION_ERRORS_DEFAULT = true;
160
160
  class TestBedApplicationErrorHandler {
161
161
  zone = inject$1(NgZone);
162
- userErrorHandler = inject$1(ErrorHandler);
162
+ injector = inject$1(EnvironmentInjector);
163
+ userErrorHandler;
163
164
  whenStableRejectFunctions = new Set();
164
165
  handleError(e) {
165
166
  try {
166
- this.zone.runOutsideAngular(() => this.userErrorHandler.handleError(e));
167
+ this.zone.runOutsideAngular(() => {
168
+ this.userErrorHandler ??= this.injector.get(ErrorHandler);
169
+ this.userErrorHandler.handleError(e);
170
+ });
167
171
  }
168
172
  catch (userError) {
169
173
  e = userError;
@@ -1484,6 +1488,13 @@ class TestBedCompiler {
1484
1488
  internalProvideZoneChangeDetection({}),
1485
1489
  TestBedApplicationErrorHandler,
1486
1490
  { provide: ChangeDetectionScheduler, useExisting: ChangeDetectionSchedulerImpl },
1491
+ {
1492
+ provide: ENVIRONMENT_INITIALIZER,
1493
+ multi: true,
1494
+ useValue: () => {
1495
+ inject$1(ErrorHandler);
1496
+ },
1497
+ },
1487
1498
  ],
1488
1499
  });
1489
1500
  const providers = [
@@ -2432,7 +2443,7 @@ class FakeNavigation {
2432
2443
  historyState: null,
2433
2444
  });
2434
2445
  const result = new InternalNavigationResult(this);
2435
- this.userAgentNavigate(destination, result, {
2446
+ const intercepted = this.userAgentNavigate(destination, result, {
2436
2447
  navigationType,
2437
2448
  cancelable: true,
2438
2449
  canIntercept: true,
@@ -2441,6 +2452,9 @@ class FakeNavigation {
2441
2452
  hashChange,
2442
2453
  info: options?.info,
2443
2454
  });
2455
+ if (!intercepted) {
2456
+ this.updateNavigationEntriesForSameDocumentNavigation(this.navigateEvent);
2457
+ }
2444
2458
  return {
2445
2459
  committed: result.committed,
2446
2460
  finished: result.finished,
@@ -2464,7 +2478,7 @@ class FakeNavigation {
2464
2478
  historyState: data,
2465
2479
  });
2466
2480
  const result = new InternalNavigationResult(this);
2467
- this.userAgentNavigate(destination, result, {
2481
+ const intercepted = this.userAgentNavigate(destination, result, {
2468
2482
  navigationType,
2469
2483
  cancelable: true,
2470
2484
  canIntercept: true,
@@ -2472,6 +2486,10 @@ class FakeNavigation {
2472
2486
  userInitiated: false,
2473
2487
  hashChange,
2474
2488
  });
2489
+ if (intercepted) {
2490
+ return;
2491
+ }
2492
+ this.updateNavigationEntriesForSameDocumentNavigation(this.navigateEvent);
2475
2493
  }
2476
2494
  /** Equivalent to `navigation.traverseTo()`. */
2477
2495
  traverseTo(key, options) {
@@ -2516,7 +2534,7 @@ class FakeNavigation {
2516
2534
  this.traversalQueue.set(entry.key, result);
2517
2535
  this.runTraversal(() => {
2518
2536
  this.traversalQueue.delete(entry.key);
2519
- const event = this.userAgentNavigate(destination, result, {
2537
+ const intercepted = this.userAgentNavigate(destination, result, {
2520
2538
  navigationType: 'traverse',
2521
2539
  cancelable: true,
2522
2540
  canIntercept: true,
@@ -2525,8 +2543,9 @@ class FakeNavigation {
2525
2543
  hashChange,
2526
2544
  info: options?.info,
2527
2545
  });
2528
- // Note this does not pay attention at all to the commit status of the event (and thus, does not support deferred commit for traversals)
2529
- this.userAgentTraverse(event);
2546
+ if (!intercepted) {
2547
+ this.userAgentTraverse(this.navigateEvent);
2548
+ }
2530
2549
  });
2531
2550
  return {
2532
2551
  committed: result.committed,
@@ -2596,7 +2615,7 @@ class FakeNavigation {
2596
2615
  sameDocument: entry.sameDocument,
2597
2616
  });
2598
2617
  const result = new InternalNavigationResult(this);
2599
- const event = this.userAgentNavigate(destination, result, {
2618
+ const intercepted = this.userAgentNavigate(destination, result, {
2600
2619
  navigationType: 'traverse',
2601
2620
  cancelable: true,
2602
2621
  canIntercept: true,
@@ -2604,8 +2623,9 @@ class FakeNavigation {
2604
2623
  userInitiated: false,
2605
2624
  hashChange,
2606
2625
  });
2607
- // Note this does not pay attention at all to the commit status of the event (and thus, does not support deferred commit for traversals)
2608
- this.userAgentTraverse(event);
2626
+ if (!intercepted) {
2627
+ this.userAgentTraverse(this.navigateEvent);
2628
+ }
2609
2629
  });
2610
2630
  }
2611
2631
  /** Runs a traversal synchronously or asynchronously */
@@ -2649,7 +2669,10 @@ class FakeNavigation {
2649
2669
  isDisposed() {
2650
2670
  return this.disposed;
2651
2671
  }
2652
- /** Implementation for all navigations and traversals. */
2672
+ /**
2673
+ * Implementation for all navigations and traversals.
2674
+ * @returns true if the event was intercepted, otherwise false
2675
+ */
2653
2676
  userAgentNavigate(destination, result, options) {
2654
2677
  // The first navigation should disallow any future calls to set the initial
2655
2678
  // entry.
@@ -2671,35 +2694,11 @@ class FakeNavigation {
2671
2694
  result,
2672
2695
  });
2673
2696
  }
2674
- /**
2675
- * Implementation to commit a navigation.
2676
- * https://whatpr.org/html/10919/nav-history-apis.html#navigateevent-commit
2677
- * @internal
2678
- */
2679
- commitNavigateEvent(navigateEvent) {
2680
- navigateEvent.interceptionState = 'committed';
2681
- const from = this.currentEntry;
2682
- if (!from) {
2683
- throw new Error('cannot commit navigation when current entry is null');
2684
- }
2685
- if (!navigateEvent.sameDocument) {
2686
- const error = new Error('Cannot navigate to a non-same-document URL.');
2687
- navigateEvent.cancel(error);
2688
- throw error;
2689
- }
2690
- // "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."
2691
- if (navigateEvent.navigationType === 'push' || navigateEvent.navigationType === 'replace') {
2692
- this.urlAndHistoryUpdateSteps(navigateEvent);
2693
- }
2694
- else if (navigateEvent.navigationType === 'reload') {
2695
- this.updateNavigationEntriesForSameDocumentNavigation(navigateEvent);
2696
- }
2697
- else ;
2698
- }
2699
2697
  /**
2700
2698
  * Implementation for a push or replace navigation.
2701
2699
  * https://whatpr.org/html/10919/browsing-the-web.html#url-and-history-update-steps
2702
2700
  * https://whatpr.org/html/10919/nav-history-apis.html#update-the-navigation-api-entries-for-a-same-document-navigation
2701
+ * @internal
2703
2702
  */
2704
2703
  urlAndHistoryUpdateSteps(navigateEvent) {
2705
2704
  this.updateNavigationEntriesForSameDocumentNavigation(navigateEvent);
@@ -2713,17 +2712,25 @@ class FakeNavigation {
2713
2712
  * > If targetEntry's document is equal to displayedDocument, then perform updateDocument.
2714
2713
  * https://whatpr.org/html/10919/browsing-the-web.html#update-document-for-history-step-application
2715
2714
  * which then goes to https://whatpr.org/html/10919/nav-history-apis.html#update-the-navigation-api-entries-for-a-same-document-navigation
2715
+ * @internal
2716
2716
  */
2717
2717
  userAgentTraverse(navigateEvent) {
2718
+ const oldUrl = this.currentEntry.url;
2718
2719
  this.updateNavigationEntriesForSameDocumentNavigation(navigateEvent);
2719
2720
  // Happens as part of "updating the document" steps https://whatpr.org/html/10919/browsing-the-web.html#updating-the-document
2720
2721
  const popStateEvent = createPopStateEvent({
2721
2722
  state: navigateEvent.destination.getHistoryState(),
2722
2723
  });
2723
2724
  this.window.dispatchEvent(popStateEvent);
2724
- // 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
2725
+ if (navigateEvent.hashChange) {
2726
+ const hashchangeEvent = createHashChangeEvent(oldUrl, this.currentEntry.url);
2727
+ this.window.dispatchEvent(hashchangeEvent);
2728
+ }
2725
2729
  }
2726
- /** https://whatpr.org/html/10919/nav-history-apis.html#update-the-navigation-api-entries-for-a-same-document-navigation */
2730
+ /**
2731
+ * https://whatpr.org/html/10919/nav-history-apis.html#update-the-navigation-api-entries-for-a-same-document-navigation
2732
+ * @internal
2733
+ */
2727
2734
  updateNavigationEntriesForSameDocumentNavigation({ destination, navigationType, result, }) {
2728
2735
  const oldCurrentNHE = this.currentEntry;
2729
2736
  const disposedNHEs = [];
@@ -2894,24 +2901,35 @@ function dispatchNavigateEvent({ cancelable, canIntercept, userInitiated, hashCh
2894
2901
  event.formData = null;
2895
2902
  event.result = result;
2896
2903
  event.sameDocument = sameDocument;
2897
- event.commitOption = 'immediate';
2898
- let handlersFinished = [Promise.resolve()];
2899
- let dispatchedNavigateEvent = false;
2904
+ let precommitHandlers = [];
2905
+ let handlers = [];
2906
+ // https://whatpr.org/html/10919/nav-history-apis.html#dom-navigateevent-intercept
2900
2907
  event.intercept = function (options) {
2901
2908
  if (!this.canIntercept) {
2902
2909
  throw new DOMException(`Cannot intercept when canIntercept is 'false'`, 'SecurityError');
2903
2910
  }
2904
2911
  this.interceptionState = 'intercepted';
2905
2912
  event.sameDocument = true;
2913
+ const precommitHandler = options?.precommitHandler;
2914
+ if (precommitHandler) {
2915
+ if (!this.cancelable) {
2916
+ throw new DOMException(`Cannot use precommitHandler when cancelable is 'false'`, 'InvalidStateError');
2917
+ }
2918
+ precommitHandlers.push(precommitHandler);
2919
+ }
2920
+ if (event.interceptionState !== 'none' && event.interceptionState !== 'intercepted') {
2921
+ throw new Error('Event interceptionState should be "none" or "intercepted"');
2922
+ }
2923
+ event.interceptionState = 'intercepted';
2906
2924
  const handler = options?.handler;
2907
2925
  if (handler) {
2908
- handlersFinished.push(handler());
2926
+ handlers.push(handler);
2909
2927
  }
2910
2928
  // override old options with new ones. UA _may_ report a console warning if new options differ from previous
2911
- event.commitOption = options?.commit ?? event.commitOption;
2912
- event.scrollBehavior = options?.scroll ?? event.scrollBehavior;
2913
2929
  event.focusResetBehavior = options?.focusReset ?? event.focusResetBehavior;
2930
+ event.scrollBehavior = options?.scroll ?? event.scrollBehavior;
2914
2931
  };
2932
+ // https://whatpr.org/html/10919/nav-history-apis.html#dom-navigateevent-scroll
2915
2933
  event.scroll = function () {
2916
2934
  if (event.interceptionState !== 'committed') {
2917
2935
  throw new DOMException(`Failed to execute 'scroll' on 'NavigateEvent': scroll() must be ` +
@@ -2919,43 +2937,54 @@ function dispatchNavigateEvent({ cancelable, canIntercept, userInitiated, hashCh
2919
2937
  }
2920
2938
  processScrollBehavior(event);
2921
2939
  };
2922
- event.commit = function (internal = false) {
2923
- if (!internal && this.interceptionState !== 'intercepted') {
2924
- throw new DOMException(`Failed to execute 'commit' on 'NavigateEvent': intercept() must be ` +
2925
- `called before commit() and commit() cannot be already called.`, 'InvalidStateError');
2940
+ // https://whatpr.org/html/10919/nav-history-apis.html#dom-navigationprecommitcontroller-redirect
2941
+ function redirect(url) {
2942
+ if (event.interceptionState === 'none') {
2943
+ throw new Error('cannot redirect when event is not intercepted');
2926
2944
  }
2927
- if (!internal && event.commitOption !== 'after-transition') {
2928
- throw new DOMException(`Failed to execute 'commit' on 'NavigateEvent': commit() may not be ` +
2929
- `called if commit behavior is not "after-transition",.`, 'InvalidStateError');
2945
+ if (event.interceptionState !== 'intercepted') {
2946
+ throw new DOMException(`cannot redirect when event is not in 'intercepted' state`, 'InvalidStateError');
2930
2947
  }
2931
- if (!dispatchedNavigateEvent) {
2932
- throw new DOMException(`Failed to execute 'commit' on 'NavigateEvent': commit() may not be ` +
2933
- `called during event dispatch.`, 'InvalidStateError');
2948
+ if (event.navigationType !== 'push' && event.navigationType !== 'replace') {
2949
+ throw new DOMException(`cannot redirect when navigationType is not 'push' or 'replace`, 'InvalidStateError');
2950
+ }
2951
+ const toUrl = new URL(url, navigation.currentEntry.url);
2952
+ event.destination.url = toUrl.href;
2953
+ }
2954
+ // https://whatpr.org/html/10919/nav-history-apis.html#inner-navigate-event-firing-algorithm
2955
+ // "Let commit be the following steps:"
2956
+ function commit() {
2957
+ if (result.signal.aborted) {
2958
+ return;
2934
2959
  }
2935
- this.interceptionState = 'committed';
2936
- result.navigation.commitNavigateEvent(event);
2937
- };
2938
- // Internal only.
2939
- event.cancel = function (reason) {
2940
- result.committedReject(reason);
2941
- result.finishedReject(reason);
2942
- };
2943
- function dispatch() {
2944
- navigation.navigateEvent = event;
2945
- navigation.eventTarget.dispatchEvent(event);
2946
- dispatchedNavigateEvent = true;
2947
2960
  if (event.interceptionState !== 'none') {
2961
+ event.interceptionState = 'committed';
2962
+ if (!navigation.currentEntry) {
2963
+ throw new Error('from history entry should not be null');
2964
+ }
2948
2965
  navigation.transition = new InternalNavigationTransition(navigation.currentEntry, navigationType);
2949
- if (event.commitOption !== 'after-transition') {
2950
- event.commit(/** internal */ true);
2966
+ switch (event.navigationType) {
2967
+ case 'push':
2968
+ case 'replace': {
2969
+ navigation.urlAndHistoryUpdateSteps(event);
2970
+ break;
2971
+ }
2972
+ case 'reload': {
2973
+ navigation.updateNavigationEntriesForSameDocumentNavigation(event);
2974
+ break;
2975
+ }
2976
+ case 'traverse': {
2977
+ navigation.userAgentTraverse(event);
2978
+ break;
2979
+ }
2951
2980
  }
2952
2981
  }
2953
- else {
2954
- // In the spec, this isn't really part of the navigate API. Instead, the navigate event firing returns "true" to indicate
2955
- // navigation steps should "continue" (https://whatpr.org/html/10919/browsing-the-web.html#beginning-navigation)
2956
- event.commit(/** internal */ true);
2982
+ const promisesList = handlers.map((handler) => handler());
2983
+ if (promisesList.length === 0) {
2984
+ promisesList.push(Promise.resolve());
2957
2985
  }
2958
- Promise.all(handlersFinished).then(() => {
2986
+ Promise.all(promisesList)
2987
+ .then(() => {
2959
2988
  // Follows steps outlined under "Wait for all of promisesList, with the following success steps:"
2960
2989
  // in the spec https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigate-event-firing.
2961
2990
  if (result.signal.aborted) {
@@ -2965,9 +2994,6 @@ function dispatchNavigateEvent({ cancelable, canIntercept, userInitiated, hashCh
2965
2994
  throw new Error("Navigation's ongoing event not equal to resolved event");
2966
2995
  }
2967
2996
  navigation.navigateEvent = null;
2968
- if (event.interceptionState === 'intercepted') {
2969
- navigation.commitNavigateEvent(event);
2970
- }
2971
2997
  finishNavigationEvent(event, true);
2972
2998
  const navigatesuccessEvent = new Event('navigatesuccess', { bubbles: false, cancelable });
2973
2999
  navigation.eventTarget.dispatchEvent(navigatesuccessEvent);
@@ -2976,39 +3002,66 @@ function dispatchNavigateEvent({ cancelable, canIntercept, userInitiated, hashCh
2976
3002
  navigation.transition.finishedResolve();
2977
3003
  }
2978
3004
  navigation.transition = null;
2979
- }, (reason) => {
2980
- if (result.signal.aborted) {
2981
- return;
2982
- }
2983
- if (event !== navigation.navigateEvent) {
2984
- throw new Error("Navigation's ongoing event not equal to resolved event");
2985
- }
2986
- navigation.navigateEvent = null;
2987
- event.interceptionState = 'rejected'; // TODO(atscott): this is not in the spec https://github.com/whatwg/html/issues/11087
3005
+ })
3006
+ .catch((reason) => event.cancel(reason));
3007
+ }
3008
+ // Internal only.
3009
+ // https://whatpr.org/html/10919/nav-history-apis.html#inner-navigate-event-firing-algorithm
3010
+ // "Let cancel be the following steps given reason"
3011
+ event.cancel = function (reason) {
3012
+ if (result.signal.aborted) {
3013
+ return;
3014
+ }
3015
+ if (event !== navigation.navigateEvent) {
3016
+ throw new Error("Navigation's ongoing event not equal to resolved event");
3017
+ }
3018
+ navigation.navigateEvent = null;
3019
+ if (event.interceptionState !== 'intercepted') {
2988
3020
  finishNavigationEvent(event, false);
2989
- const navigateerrorEvent = new Event('navigateerror', { bubbles: false, cancelable });
2990
- navigation.eventTarget.dispatchEvent(navigateerrorEvent);
2991
- result.finishedReject(reason);
2992
- if (navigation.transition !== null) {
2993
- navigation.transition.finishedResolve();
2994
- }
2995
- navigation.transition = null;
2996
- });
3021
+ }
3022
+ const navigateerrorEvent = new Event('navigateerror', { bubbles: false, cancelable });
3023
+ navigation.eventTarget.dispatchEvent(navigateerrorEvent);
3024
+ result.finishedReject(reason);
3025
+ if (navigation.transition !== null) {
3026
+ navigation.transition.finishedReject(reason);
3027
+ }
3028
+ navigation.transition = null;
3029
+ };
3030
+ function dispatch() {
3031
+ navigation.navigateEvent = event;
3032
+ navigation.eventTarget.dispatchEvent(event);
3033
+ if (precommitHandlers.length === 0) {
3034
+ commit();
3035
+ }
3036
+ else {
3037
+ const precommitController = { redirect };
3038
+ const precommitPromisesList = precommitHandlers.map((handler) => handler(precommitController));
3039
+ Promise.all(precommitPromisesList)
3040
+ .then(() => commit())
3041
+ .catch((reason) => event.cancel(reason));
3042
+ }
2997
3043
  }
2998
3044
  dispatch();
2999
- return event;
3045
+ return event.interceptionState !== 'none';
3000
3046
  }
3001
3047
  /** https://whatpr.org/html/10919/nav-history-apis.html#navigateevent-finish */
3002
3048
  function finishNavigationEvent(event, didFulfill) {
3003
- if (event.interceptionState === 'intercepted' || event.interceptionState === 'finished') {
3004
- throw new Error('Attempting to finish navigation event that was incomplete or already finished');
3049
+ if (event.interceptionState === 'finished') {
3050
+ throw new Error('Attempting to finish navigation event that was already finished');
3051
+ }
3052
+ if (event.interceptionState === 'intercepted') {
3053
+ if (didFulfill === true) {
3054
+ throw new Error('didFulfill should be false');
3055
+ }
3056
+ // assert precommit handlers is not empty
3057
+ event.interceptionState = 'finished';
3058
+ return;
3005
3059
  }
3006
3060
  if (event.interceptionState === 'none') {
3007
3061
  return;
3008
3062
  }
3063
+ potentiallyResetFocus(event);
3009
3064
  if (didFulfill) {
3010
- // TODO(atscott): https://github.com/whatwg/html/issues/11087 focus reset is not guarded by didFulfill in the spec
3011
- potentiallyResetFocus(event);
3012
3065
  potentiallyResetScroll(event);
3013
3066
  }
3014
3067
  event.interceptionState = 'finished';
@@ -3062,6 +3115,15 @@ function createPopStateEvent({ state }) {
3062
3115
  event.state = state;
3063
3116
  return event;
3064
3117
  }
3118
+ function createHashChangeEvent(newURL, oldURL) {
3119
+ const event = new Event('hashchange', {
3120
+ bubbles: false,
3121
+ cancelable: false,
3122
+ });
3123
+ event.newURL = newURL;
3124
+ event.oldURL = oldURL;
3125
+ return event;
3126
+ }
3065
3127
  /**
3066
3128
  * Fake equivalent of `NavigationDestination`.
3067
3129
  */
@@ -3109,6 +3171,8 @@ class InternalNavigationTransition {
3109
3171
  this.finishedReject = reject;
3110
3172
  this.finishedResolve = resolve;
3111
3173
  });
3174
+ // All rejections are handled.
3175
+ this.finished.catch(() => { });
3112
3176
  }
3113
3177
  }
3114
3178
  /**