Skip to content

Commit e3038ac

Browse files
committed
work
1 parent 0477844 commit e3038ac

9 files changed

Lines changed: 188 additions & 80 deletions

File tree

packages/frontend/navi/dist/dev/jsenv_navi.js

Lines changed: 51 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26510,9 +26510,10 @@ const setupBrowserIntegrationViaHistory = ({
2651026510
const {
2651126511
reason,
2651226512
navigationType, // "load", "reload", "replace", "push", "traverse"
26513-
state,
2651426513
redirected,
26514+
landOn,
2651526515
} = options;
26516+
let { state } = options;
2651626517

2651726518
// Where the entry being reached stands in this document's own stack —
2651826519
// decided before the state that carries it is built (see
@@ -26540,7 +26541,22 @@ const setupBrowserIntegrationViaHistory = ({
2654026541
} else {
2654126542
// traverse / reload: state comes from the history entry, no push/replace needed.
2654226543
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) {
2654426560
// The entry the browser is on names an address that only sends
2654526561
// elsewhere — a cold load on it, or a back into it. Written over where
2654626562
// it stands (the entry keeps its place in the stack, hence its state
@@ -26704,6 +26720,17 @@ const setupBrowserIntegrationViaHistory = ({
2670426720
window.addEventListener("popstate", (popstateEvent) => {
2670526721
const url = window.location.href;
2670626722
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+
}
2670726734
handleRoutingTask(url, {
2670826735
reason: `"popstate" event for ${url}`,
2670926736
navigationType: "traverse",
@@ -26745,7 +26772,11 @@ const setupBrowserIntegrationViaHistory = ({
2674526772
});
2674626773
};
2674726774

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 } = {}) => {
2674926780
if (canNavBackSignal.peek()) {
2675026781
// Resolved once the back has landed: the "popstate" it is answered with
2675126782
// reaches the routing listener first (registered at setup, before this
@@ -26756,6 +26787,7 @@ const setupBrowserIntegrationViaHistory = ({
2675626787
once: true,
2675726788
});
2675826789
});
26790+
landOnPending = landOn || null;
2675926791
window.history.back();
2676026792
return landedPromise;
2676126793
}
@@ -26958,6 +26990,12 @@ const reload = browserIntegration.reload;
2695826990
* Where to land when there is nothing of this document behind. It takes the
2695926991
* place of the current entry rather than stacking on it. Without it, a
2696026992
* 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()).
2696126999
* @returns {Promise<boolean>|undefined}
2696227000
* When there is something to go back to: a promise resolved once the back
2696327001
* has landed and been applied (`true` — the document url and state say
@@ -27086,10 +27124,13 @@ const useNavStateBasic = (
2708627124
// Both push-mode closes pop the pushed entry. A keep-close that merely
2708727125
// rewrote it in place would leave two entries describing the same closed
2708827126
// 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.
2709327134
const leave = ({ isBack } = {}) => {
2709427135
enteredRef.current = false;
2709527136
const currentStateCopy = browserIntegration.getDocumentState() || {};
@@ -27101,13 +27142,9 @@ const useNavStateBasic = (
2710127142
browserIntegration.navBack();
2710227143
return;
2710327144
}
27104-
const urlToKeep = window.location.href;
2710527145
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 },
2711127148
});
2711227149
return;
2711327150
}
@@ -45579,16 +45616,7 @@ const writeOpenedInSignal = (signal, opened, event) => {
4557945616
return;
4558045617
}
4558145618
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 } });
4559245620
return;
4559345621
}
4559445622
writeInSignal(signal, false, { history: "replace" });

packages/frontend/navi/dist/dev/jsenv_navi.js.map

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/frontend/navi/dist/jsenv_navi.js

Lines changed: 51 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26152,9 +26152,10 @@ const setupBrowserIntegrationViaHistory = ({
2615226152
const {
2615326153
reason,
2615426154
navigationType, // "load", "reload", "replace", "push", "traverse"
26155-
state,
2615626155
redirected,
26156+
landOn,
2615726157
} = options;
26158+
let { state } = options;
2615826159

2615926160
// Where the entry being reached stands in this document's own stack —
2616026161
// decided before the state that carries it is built (see
@@ -26182,7 +26183,22 @@ const setupBrowserIntegrationViaHistory = ({
2618226183
} else {
2618326184
// traverse / reload: state comes from the history entry, no push/replace needed.
2618426185
markUrlAsVisited(url);
26185-
if (redirected) {
26186+
if (landOn) {
26187+
// The entry the back landed on, written over where it stands with
26188+
// what must outlive the popped one (see navBack's `landOn`) — before
26189+
// the routes read anything, so the only address they ever see is the
26190+
// one being kept.
26191+
state = resolveEffectiveDocumentState(landOn.state, {
26192+
navigationType: "replace",
26193+
currentState: state,
26194+
sharedState: {
26195+
jsenv_visited_urls: Array.from(visitedUrlSet),
26196+
[NAV_DEPTH_STATE_KEY]: getNavDepth(),
26197+
},
26198+
});
26199+
window.history.replaceState(state, null, url);
26200+
rememberEntryIsOfThisDocument();
26201+
} else if (redirected) {
2618626202
// The entry the browser is on names an address that only sends
2618726203
// elsewhere — a cold load on it, or a back into it. Written over where
2618826204
// it stands (the entry keeps its place in the stack, hence its state
@@ -26346,6 +26362,17 @@ const setupBrowserIntegrationViaHistory = ({
2634626362
window.addEventListener("popstate", (popstateEvent) => {
2634726363
const url = window.location.href;
2634826364
const state = popstateEvent.state;
26365+
const landOn = landOnPending;
26366+
landOnPending = null;
26367+
if (landOn) {
26368+
handleRoutingTask(landOn.url, {
26369+
reason: `"popstate" event for ${url}, landing on ${landOn.url}`,
26370+
navigationType: "traverse",
26371+
state,
26372+
landOn,
26373+
});
26374+
return;
26375+
}
2634926376
handleRoutingTask(url, {
2635026377
reason: `"popstate" event for ${url}`,
2635126378
navigationType: "traverse",
@@ -26387,7 +26414,11 @@ const setupBrowserIntegrationViaHistory = ({
2638726414
});
2638826415
};
2638926416

26390-
const navBack = ({ fallback } = {}) => {
26417+
// What the next "popstate" writes over the entry it lands on, when a back
26418+
// asked for it (see navBack's `landOn`). Read by the popstate listener,
26419+
// which is the one place the landing is applied.
26420+
let landOnPending = null;
26421+
const navBack = ({ fallback, landOn } = {}) => {
2639126422
if (canNavBackSignal.peek()) {
2639226423
// Resolved once the back has landed: the "popstate" it is answered with
2639326424
// reaches the routing listener first (registered at setup, before this
@@ -26398,6 +26429,7 @@ const setupBrowserIntegrationViaHistory = ({
2639826429
once: true,
2639926430
});
2640026431
});
26432+
landOnPending = landOn || null;
2640126433
window.history.back();
2640226434
return landedPromise;
2640326435
}
@@ -26600,6 +26632,12 @@ const reload = browserIntegration.reload;
2660026632
* Where to land when there is nothing of this document behind. It takes the
2660126633
* place of the current entry rather than stacking on it. Without it, a
2660226634
* navBack() with nowhere to go does nothing.
26635+
* @param {{ url: string, state?: object }} [options.landOn]
26636+
* What the entry the back lands on reads once landed: its url, and its state
26637+
* (`undefined` keeps the state it has). Written over that entry within the
26638+
* back's own navigation, so the routes never see the entry as it was — the
26639+
* way a screen closed over a url keeps what was written to the url while it
26640+
* was open (see useNavState's leave()).
2660326641
* @returns {Promise<boolean>|undefined}
2660426642
* When there is something to go back to: a promise resolved once the back
2660526643
* has landed and been applied (`true` — the document url and state say
@@ -26691,10 +26729,13 @@ const useNavStateBasic = (
2669126729
// Both push-mode closes pop the pushed entry. A keep-close that merely
2669226730
// rewrote it in place would leave two entries describing the same closed
2669326731
// screen — same url, same state — and the next back press would appear to do
26694-
// nothing. So the keep path goes back like the cancel does, then writes what
26695-
// must be kept onto the entry the back lands on. Only with nothing of this
26696-
// document behind (the state was entered on a cold-loaded url, navBack has
26697-
// nowhere to go) does it rewrite in place.
26732+
// nothing. So the keep path goes back like the cancel does, with what must
26733+
// be kept written onto the entry the back lands on, in the same navigation:
26734+
// a route param written while the state was entered is in the url being
26735+
// kept, and a routing pass reading the entry behind as it was would take
26736+
// that param for gone. Only with nothing of this document behind (the state
26737+
// was entered on a cold-loaded url, navBack has nowhere to go) does it
26738+
// rewrite in place.
2669826739
const leave = ({ isBack } = {}) => {
2669926740
enteredRef.current = false;
2670026741
const currentStateCopy = browserIntegration.getDocumentState() || {};
@@ -26706,13 +26747,9 @@ const useNavStateBasic = (
2670626747
browserIntegration.navBack();
2670726748
return;
2670826749
}
26709-
const urlToKeep = window.location.href;
2671026750
delete currentStateCopy[id];
26711-
browserIntegration.navBack().then((landed) => {
26712-
if (!landed) {
26713-
return;
26714-
}
26715-
navTo(urlToKeep, { replace: true, state: currentStateCopy });
26751+
browserIntegration.navBack({
26752+
landOn: { url: window.location.href, state: currentStateCopy },
2671626753
});
2671726754
return;
2671826755
}
@@ -45007,16 +45044,7 @@ const writeOpenedInSignal = (signal, opened, event) => {
4500745044
return;
4500845045
}
4500945046
writeInSignal(signal, false, { history: "replace" });
45010-
const urlToKeep = window.location.href;
45011-
navBack().then((landed) => {
45012-
if (!landed) {
45013-
return;
45014-
}
45015-
// Often nothing at all: with no other write made while the popup was
45016-
// open, the entry landed on already reads urlToKeep and navTo skips
45017-
// the navigation entirely.
45018-
navTo(urlToKeep, { replace: true });
45019-
});
45047+
navBack({ landOn: { url: window.location.href } });
4502045048
return;
4502145049
}
4502245050
writeInSignal(signal, false, { history: "replace" });

packages/frontend/navi/dist/jsenv_navi.js.map

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/frontend/navi/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@jsenv/navi",
3-
"version": "0.29.217",
3+
"version": "0.29.218",
44
"type": "module",
55
"description": "Library of components including navigation to create frontend applications",
66
"repository": {

packages/frontend/navi/src/layout/open_controller.js

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import { useDebugInteraction } from "@jsenv/navi/src/navi_debug.jsx";
1111
import { canNavBackSignal } from "../nav/browser_integration/document_back_and_forward.js";
1212
import {
1313
navBack,
14-
navTo,
1514
useNavState,
1615
} from "../nav/browser_integration/browser_integration.js";
1716
import { warnSignalCollision } from "../control/control_value.js";
@@ -733,16 +732,7 @@ const writeOpenedInSignal = (signal, opened, event) => {
733732
return;
734733
}
735734
writeInSignal(signal, false, { history: "replace" });
736-
const urlToKeep = window.location.href;
737-
navBack().then((landed) => {
738-
if (!landed) {
739-
return;
740-
}
741-
// Often nothing at all: with no other write made while the popup was
742-
// open, the entry landed on already reads urlToKeep and navTo skips
743-
// the navigation entirely.
744-
navTo(urlToKeep, { replace: true });
745-
});
735+
navBack({ landOn: { url: window.location.href } });
746736
return;
747737
}
748738
writeInSignal(signal, false, { history: "replace" });

packages/frontend/navi/src/nav/browser_integration/browser_integration.js

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,12 @@ export const reload = browserIntegration.reload;
190190
* Where to land when there is nothing of this document behind. It takes the
191191
* place of the current entry rather than stacking on it. Without it, a
192192
* navBack() with nowhere to go does nothing.
193+
* @param {{ url: string, state?: object }} [options.landOn]
194+
* What the entry the back lands on reads once landed: its url, and its state
195+
* (`undefined` keeps the state it has). Written over that entry within the
196+
* back's own navigation, so the routes never see the entry as it was — the
197+
* way a screen closed over a url keeps what was written to the url while it
198+
* was open (see useNavState's leave()).
193199
* @returns {Promise<boolean>|undefined}
194200
* When there is something to go back to: a promise resolved once the back
195201
* has landed and been applied (`true` — the document url and state say
@@ -324,10 +330,13 @@ const useNavStateBasic = (
324330
// Both push-mode closes pop the pushed entry. A keep-close that merely
325331
// rewrote it in place would leave two entries describing the same closed
326332
// screen — same url, same state — and the next back press would appear to do
327-
// nothing. So the keep path goes back like the cancel does, then writes what
328-
// must be kept onto the entry the back lands on. Only with nothing of this
329-
// document behind (the state was entered on a cold-loaded url, navBack has
330-
// nowhere to go) does it rewrite in place.
333+
// nothing. So the keep path goes back like the cancel does, with what must
334+
// be kept written onto the entry the back lands on, in the same navigation:
335+
// a route param written while the state was entered is in the url being
336+
// kept, and a routing pass reading the entry behind as it was would take
337+
// that param for gone. Only with nothing of this document behind (the state
338+
// was entered on a cold-loaded url, navBack has nowhere to go) does it
339+
// rewrite in place.
331340
const leave = ({ isBack } = {}) => {
332341
enteredRef.current = false;
333342
const currentStateCopy = browserIntegration.getDocumentState() || {};
@@ -339,13 +348,9 @@ const useNavStateBasic = (
339348
browserIntegration.navBack();
340349
return;
341350
}
342-
const urlToKeep = window.location.href;
343351
delete currentStateCopy[id];
344-
browserIntegration.navBack().then((landed) => {
345-
if (!landed) {
346-
return;
347-
}
348-
navTo(urlToKeep, { replace: true, state: currentStateCopy });
352+
browserIntegration.navBack({
353+
landOn: { url: window.location.href, state: currentStateCopy },
349354
});
350355
return;
351356
}

0 commit comments

Comments
 (0)