@jsenv/navi 0.29.499 → 0.29.501

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.
@@ -8727,11 +8727,7 @@ const route = (pattern, options = {}) => {
8727
8727
  );
8728
8728
  }
8729
8729
  // eslint-disable-next-line no-loop-func
8730
- const cleanupSignalUrlEffect = effect(() => {
8731
- const value = paramSignal.value;
8732
- // Use peek() to avoid subscribing to URL-derived signals.
8733
- // This effect should only re-run when the param signal changes,
8734
- // not when the URL changes (which would create a cycle: signal→URL→signal).
8730
+ const writeValueInUrl = (value) => {
8735
8731
  const rawParams = route.rawParamsSignal.peek();
8736
8732
  const urlParamValue = rawParams[paramName];
8737
8733
  const matching = route.matchingSignal.peek();
@@ -8806,6 +8802,14 @@ const route = (pattern, options = {}) => {
8806
8802
  debounceUrl,
8807
8803
  },
8808
8804
  );
8805
+ };
8806
+ const cleanupSignalUrlEffect = effect(() => {
8807
+ const value = paramSignal.value;
8808
+ // Only the param signal re-runs this effect. Writing the url reads
8809
+ // more (the route's other params, to build it): subscribed to those,
8810
+ // the write is made again whenever one of them changes — a second
8811
+ // entry when the write pushes.
8812
+ untracked(() => writeValueInUrl(value));
8809
8813
  });
8810
8814
  cleanupSignalUrlEffectSet.add(cleanupSignalUrlEffect);
8811
8815
  }
@@ -14356,7 +14360,21 @@ const setupBrowserIntegrationViaHistory = ({
14356
14360
  // asked for it (see navBack's `landOn`). Read by the popstate listener,
14357
14361
  // which is the one place the landing is applied.
14358
14362
  let landOnPending = null;
14359
- const navBack = ({ fallback, landOn } = {}) => {
14363
+ // The back navBack asked for, from history.back() to the "popstate" that
14364
+ // answers it. Meanwhile the document still reads the entry being left (see
14365
+ // whenBackLanded).
14366
+ let backInFlight = null;
14367
+ const whenBackLanded = (callback) => {
14368
+ if (backInFlight) {
14369
+ return backInFlight.then(callback);
14370
+ }
14371
+ return callback();
14372
+ };
14373
+ // A second back asked before the first one landed (two popups closed in the
14374
+ // same handler) waits for it: the browser would queue both, but the landing
14375
+ // has one slot, and its `landOn` was read on the entry the first back leaves.
14376
+ const navBack = (options) => whenBackLanded(() => navBackNow(options));
14377
+ const navBackNow = ({ fallback, landOn } = {}) => {
14360
14378
  if (canNavBackSignal.peek()) {
14361
14379
  // Resolved once the back has landed: the "popstate" it is answered with
14362
14380
  // reaches the routing listener first (registered at setup, before this
@@ -14368,10 +14386,12 @@ const setupBrowserIntegrationViaHistory = ({
14368
14386
  return;
14369
14387
  }
14370
14388
  window.removeEventListener("popstate", onPopstate);
14389
+ backInFlight = null;
14371
14390
  resolve(true);
14372
14391
  };
14373
14392
  window.addEventListener("popstate", onPopstate);
14374
14393
  });
14394
+ backInFlight = landedPromise;
14375
14395
  landOnPending = landOn || null;
14376
14396
  window.history.back();
14377
14397
  return landedPromise;
@@ -14415,6 +14435,7 @@ const setupBrowserIntegrationViaHistory = ({
14415
14435
  stop,
14416
14436
  reload,
14417
14437
  navBack,
14438
+ whenBackLanded,
14418
14439
  navForward,
14419
14440
  getDocumentState,
14420
14441
  carryByLinkNavigation,
@@ -14708,6 +14729,10 @@ const reload = browserIntegration.reload;
14708
14729
  * current entry's place.
14709
14730
  */
14710
14731
  const navBack = browserIntegration.navBack;
14732
+ // Runs `callback` once the back navBack started has landed, at once when there
14733
+ // is none: until then the document reads the entry that back is leaving, and
14734
+ // a write made there is gone with it.
14735
+ const whenBackLanded = browserIntegration.whenBackLanded;
14711
14736
  const navForward = browserIntegration.navForward;
14712
14737
  const isVisited = browserIntegration.isVisited;
14713
14738
  const visitedUrlsSignal = browserIntegration.visitedUrlsSignal;
@@ -14873,7 +14898,14 @@ const useNavStateBasic = (
14873
14898
  }
14874
14899
  leaveEntry({ isBack, discard });
14875
14900
  };
14901
+ // Read and written on the entry the document lands on: a leave asked while
14902
+ // another one's back is in flight (a popup closed with the one under it)
14903
+ // would otherwise carry that entry's url and state — the other key
14904
+ // included — onto the wrong one.
14876
14905
  const leaveEntry = ({ isBack, discard }) => {
14906
+ whenBackLanded(() => leaveLandedEntry({ isBack, discard }));
14907
+ };
14908
+ const leaveLandedEntry = ({ isBack, discard }) => {
14877
14909
  if (!Object.hasOwn(browserIntegration.getDocumentState() || {}, id)) {
14878
14910
  return;
14879
14911
  }
@@ -18143,7 +18175,14 @@ const writeInSignal = (signal, value, { history }) => {
18143
18175
  // `discard` empties what belongs to the popup alone (its `ownSignals`): before
18144
18176
  // a keep-close reads the url it lands on, and once a back has landed — the
18145
18177
  // entry behind may hold them too, written by an `onOpen` before the push.
18146
- const writeOpenedInSignal = (
18178
+ //
18179
+ // Read and written on the entry the document lands on: a close asked while
18180
+ // another popup's back is in flight (a popup closed with the one under it)
18181
+ // would otherwise read the url that back is leaving, and write onto it.
18182
+ const writeOpenedInSignal = (...args) => {
18183
+ whenBackLanded(() => writeOpenedInLandedSignal(...args));
18184
+ };
18185
+ const writeOpenedInLandedSignal = (
18147
18186
  signal,
18148
18187
  opened,
18149
18188
  event,