@jsenv/navi 0.29.217 → 0.29.218

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.
@@ -26510,9 +26510,10 @@ const setupBrowserIntegrationViaHistory = ({
26510
26510
  const {
26511
26511
  reason,
26512
26512
  navigationType, // "load", "reload", "replace", "push", "traverse"
26513
- state,
26514
26513
  redirected,
26514
+ landOn,
26515
26515
  } = options;
26516
+ let { state } = options;
26516
26517
 
26517
26518
  // Where the entry being reached stands in this document's own stack —
26518
26519
  // decided before the state that carries it is built (see
@@ -26540,7 +26541,22 @@ const setupBrowserIntegrationViaHistory = ({
26540
26541
  } else {
26541
26542
  // traverse / reload: state comes from the history entry, no push/replace needed.
26542
26543
  markUrlAsVisited(url);
26543
- if (redirected) {
26544
+ if (landOn) {
26545
+ // The entry the back landed on, written over where it stands with
26546
+ // what must outlive the popped one (see navBack's `landOn`) — before
26547
+ // the routes read anything, so the only address they ever see is the
26548
+ // one being kept.
26549
+ state = resolveEffectiveDocumentState(landOn.state, {
26550
+ navigationType: "replace",
26551
+ currentState: state,
26552
+ sharedState: {
26553
+ jsenv_visited_urls: Array.from(visitedUrlSet),
26554
+ [NAV_DEPTH_STATE_KEY]: getNavDepth(),
26555
+ },
26556
+ });
26557
+ window.history.replaceState(state, null, url);
26558
+ rememberEntryIsOfThisDocument();
26559
+ } else if (redirected) {
26544
26560
  // The entry the browser is on names an address that only sends
26545
26561
  // elsewhere — a cold load on it, or a back into it. Written over where
26546
26562
  // it stands (the entry keeps its place in the stack, hence its state
@@ -26704,6 +26720,17 @@ const setupBrowserIntegrationViaHistory = ({
26704
26720
  window.addEventListener("popstate", (popstateEvent) => {
26705
26721
  const url = window.location.href;
26706
26722
  const state = popstateEvent.state;
26723
+ const landOn = landOnPending;
26724
+ landOnPending = null;
26725
+ if (landOn) {
26726
+ handleRoutingTask(landOn.url, {
26727
+ reason: `"popstate" event for ${url}, landing on ${landOn.url}`,
26728
+ navigationType: "traverse",
26729
+ state,
26730
+ landOn,
26731
+ });
26732
+ return;
26733
+ }
26707
26734
  handleRoutingTask(url, {
26708
26735
  reason: `"popstate" event for ${url}`,
26709
26736
  navigationType: "traverse",
@@ -26745,7 +26772,11 @@ const setupBrowserIntegrationViaHistory = ({
26745
26772
  });
26746
26773
  };
26747
26774
 
26748
- const navBack = ({ fallback } = {}) => {
26775
+ // What the next "popstate" writes over the entry it lands on, when a back
26776
+ // asked for it (see navBack's `landOn`). Read by the popstate listener,
26777
+ // which is the one place the landing is applied.
26778
+ let landOnPending = null;
26779
+ const navBack = ({ fallback, landOn } = {}) => {
26749
26780
  if (canNavBackSignal.peek()) {
26750
26781
  // Resolved once the back has landed: the "popstate" it is answered with
26751
26782
  // reaches the routing listener first (registered at setup, before this
@@ -26756,6 +26787,7 @@ const setupBrowserIntegrationViaHistory = ({
26756
26787
  once: true,
26757
26788
  });
26758
26789
  });
26790
+ landOnPending = landOn || null;
26759
26791
  window.history.back();
26760
26792
  return landedPromise;
26761
26793
  }
@@ -26958,6 +26990,12 @@ const reload = browserIntegration.reload;
26958
26990
  * Where to land when there is nothing of this document behind. It takes the
26959
26991
  * place of the current entry rather than stacking on it. Without it, a
26960
26992
  * navBack() with nowhere to go does nothing.
26993
+ * @param {{ url: string, state?: object }} [options.landOn]
26994
+ * What the entry the back lands on reads once landed: its url, and its state
26995
+ * (`undefined` keeps the state it has). Written over that entry within the
26996
+ * back's own navigation, so the routes never see the entry as it was — the
26997
+ * way a screen closed over a url keeps what was written to the url while it
26998
+ * was open (see useNavState's leave()).
26961
26999
  * @returns {Promise<boolean>|undefined}
26962
27000
  * When there is something to go back to: a promise resolved once the back
26963
27001
  * has landed and been applied (`true` — the document url and state say
@@ -27086,10 +27124,13 @@ const useNavStateBasic = (
27086
27124
  // Both push-mode closes pop the pushed entry. A keep-close that merely
27087
27125
  // rewrote it in place would leave two entries describing the same closed
27088
27126
  // screen — same url, same state — and the next back press would appear to do
27089
- // nothing. So the keep path goes back like the cancel does, then writes what
27090
- // must be kept onto the entry the back lands on. Only with nothing of this
27091
- // document behind (the state was entered on a cold-loaded url, navBack has
27092
- // nowhere to go) does it rewrite in place.
27127
+ // nothing. So the keep path goes back like the cancel does, with what must
27128
+ // be kept written onto the entry the back lands on, in the same navigation:
27129
+ // a route param written while the state was entered is in the url being
27130
+ // kept, and a routing pass reading the entry behind as it was would take
27131
+ // that param for gone. Only with nothing of this document behind (the state
27132
+ // was entered on a cold-loaded url, navBack has nowhere to go) does it
27133
+ // rewrite in place.
27093
27134
  const leave = ({ isBack } = {}) => {
27094
27135
  enteredRef.current = false;
27095
27136
  const currentStateCopy = browserIntegration.getDocumentState() || {};
@@ -27101,13 +27142,9 @@ const useNavStateBasic = (
27101
27142
  browserIntegration.navBack();
27102
27143
  return;
27103
27144
  }
27104
- const urlToKeep = window.location.href;
27105
27145
  delete currentStateCopy[id];
27106
- browserIntegration.navBack().then((landed) => {
27107
- if (!landed) {
27108
- return;
27109
- }
27110
- navTo(urlToKeep, { replace: true, state: currentStateCopy });
27146
+ browserIntegration.navBack({
27147
+ landOn: { url: window.location.href, state: currentStateCopy },
27111
27148
  });
27112
27149
  return;
27113
27150
  }
@@ -45579,16 +45616,7 @@ const writeOpenedInSignal = (signal, opened, event) => {
45579
45616
  return;
45580
45617
  }
45581
45618
  writeInSignal(signal, false, { history: "replace" });
45582
- const urlToKeep = window.location.href;
45583
- navBack().then((landed) => {
45584
- if (!landed) {
45585
- return;
45586
- }
45587
- // Often nothing at all: with no other write made while the popup was
45588
- // open, the entry landed on already reads urlToKeep and navTo skips
45589
- // the navigation entirely.
45590
- navTo(urlToKeep, { replace: true });
45591
- });
45619
+ navBack({ landOn: { url: window.location.href } });
45592
45620
  return;
45593
45621
  }
45594
45622
  writeInSignal(signal, false, { history: "replace" });