@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.
@@ -9102,11 +9102,7 @@ const route = (pattern, options = {}) => {
9102
9102
  );
9103
9103
  }
9104
9104
  // eslint-disable-next-line no-loop-func
9105
- const cleanupSignalUrlEffect = effect(() => {
9106
- const value = paramSignal.value;
9107
- // Use peek() to avoid subscribing to URL-derived signals.
9108
- // This effect should only re-run when the param signal changes,
9109
- // not when the URL changes (which would create a cycle: signal→URL→signal).
9105
+ const writeValueInUrl = (value) => {
9110
9106
  const rawParams = route.rawParamsSignal.peek();
9111
9107
  const urlParamValue = rawParams[paramName];
9112
9108
  const matching = route.matchingSignal.peek();
@@ -9181,6 +9177,14 @@ const route = (pattern, options = {}) => {
9181
9177
  debounceUrl,
9182
9178
  },
9183
9179
  );
9180
+ };
9181
+ const cleanupSignalUrlEffect = effect(() => {
9182
+ const value = paramSignal.value;
9183
+ // Only the param signal re-runs this effect. Writing the url reads
9184
+ // more (the route's other params, to build it): subscribed to those,
9185
+ // the write is made again whenever one of them changes — a second
9186
+ // entry when the write pushes.
9187
+ untracked(() => writeValueInUrl(value));
9184
9188
  });
9185
9189
  cleanupSignalUrlEffectSet.add(cleanupSignalUrlEffect);
9186
9190
  }
@@ -14962,7 +14966,21 @@ const setupBrowserIntegrationViaHistory = ({
14962
14966
  // asked for it (see navBack's `landOn`). Read by the popstate listener,
14963
14967
  // which is the one place the landing is applied.
14964
14968
  let landOnPending = null;
14965
- const navBack = ({ fallback, landOn } = {}) => {
14969
+ // The back navBack asked for, from history.back() to the "popstate" that
14970
+ // answers it. Meanwhile the document still reads the entry being left (see
14971
+ // whenBackLanded).
14972
+ let backInFlight = null;
14973
+ const whenBackLanded = (callback) => {
14974
+ if (backInFlight) {
14975
+ return backInFlight.then(callback);
14976
+ }
14977
+ return callback();
14978
+ };
14979
+ // A second back asked before the first one landed (two popups closed in the
14980
+ // same handler) waits for it: the browser would queue both, but the landing
14981
+ // has one slot, and its `landOn` was read on the entry the first back leaves.
14982
+ const navBack = (options) => whenBackLanded(() => navBackNow(options));
14983
+ const navBackNow = ({ fallback, landOn } = {}) => {
14966
14984
  if (canNavBackSignal.peek()) {
14967
14985
  // Resolved once the back has landed: the "popstate" it is answered with
14968
14986
  // reaches the routing listener first (registered at setup, before this
@@ -14974,10 +14992,12 @@ const setupBrowserIntegrationViaHistory = ({
14974
14992
  return;
14975
14993
  }
14976
14994
  window.removeEventListener("popstate", onPopstate);
14995
+ backInFlight = null;
14977
14996
  resolve(true);
14978
14997
  };
14979
14998
  window.addEventListener("popstate", onPopstate);
14980
14999
  });
15000
+ backInFlight = landedPromise;
14981
15001
  landOnPending = landOn || null;
14982
15002
  window.history.back();
14983
15003
  return landedPromise;
@@ -15021,6 +15041,7 @@ const setupBrowserIntegrationViaHistory = ({
15021
15041
  stop,
15022
15042
  reload,
15023
15043
  navBack,
15044
+ whenBackLanded,
15024
15045
  navForward,
15025
15046
  getDocumentState,
15026
15047
  carryByLinkNavigation,
@@ -15367,6 +15388,10 @@ const reload = browserIntegration.reload;
15367
15388
  * current entry's place.
15368
15389
  */
15369
15390
  const navBack = browserIntegration.navBack;
15391
+ // Runs `callback` once the back navBack started has landed, at once when there
15392
+ // is none: until then the document reads the entry that back is leaving, and
15393
+ // a write made there is gone with it.
15394
+ const whenBackLanded = browserIntegration.whenBackLanded;
15370
15395
  const navForward = browserIntegration.navForward;
15371
15396
  const isVisited = browserIntegration.isVisited;
15372
15397
  const visitedUrlsSignal = browserIntegration.visitedUrlsSignal;
@@ -15617,7 +15642,14 @@ const useNavStateBasic = (
15617
15642
  }
15618
15643
  leaveEntry({ isBack, discard });
15619
15644
  };
15645
+ // Read and written on the entry the document lands on: a leave asked while
15646
+ // another one's back is in flight (a popup closed with the one under it)
15647
+ // would otherwise carry that entry's url and state — the other key
15648
+ // included — onto the wrong one.
15620
15649
  const leaveEntry = ({ isBack, discard }) => {
15650
+ whenBackLanded(() => leaveLandedEntry({ isBack, discard }));
15651
+ };
15652
+ const leaveLandedEntry = ({ isBack, discard }) => {
15621
15653
  if (!Object.hasOwn(browserIntegration.getDocumentState() || {}, id)) {
15622
15654
  return;
15623
15655
  }
@@ -18921,7 +18953,14 @@ const writeInSignal = (signal, value, { history }) => {
18921
18953
  // `discard` empties what belongs to the popup alone (its `ownSignals`): before
18922
18954
  // a keep-close reads the url it lands on, and once a back has landed — the
18923
18955
  // entry behind may hold them too, written by an `onOpen` before the push.
18924
- const writeOpenedInSignal = (
18956
+ //
18957
+ // Read and written on the entry the document lands on: a close asked while
18958
+ // another popup's back is in flight (a popup closed with the one under it)
18959
+ // would otherwise read the url that back is leaving, and write onto it.
18960
+ const writeOpenedInSignal = (...args) => {
18961
+ whenBackLanded(() => writeOpenedInLandedSignal(...args));
18962
+ };
18963
+ const writeOpenedInLandedSignal = (
18925
18964
  signal,
18926
18965
  opened,
18927
18966
  event,