Skip to content

Commit 716e9ff

Browse files
committed
work
1 parent cc70128 commit 716e9ff

17 files changed

Lines changed: 109 additions & 13 deletions

File tree

dist/build/build.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2131,6 +2131,10 @@ const createUrlInfo = (url, context) => {
21312131
modifiedTimestamp: 0,
21322132
descendantModifiedTimestamp: 0,
21332133
dereferencedTimestamp: 0,
2134+
// when a client last fetched this url outside a hot request; in other
2135+
// words the last time this url entered a fresh page (see
2136+
// jsenv_plugin_hot_search_param)
2137+
servedWithoutHotTimestamp: 0,
21342138
originalContentEtag: null,
21352139
contentEtag: null,
21362140
isValid: () => false,
@@ -9445,6 +9449,7 @@ const jsenvPluginHotSearchParam = () => {
94459449
modifiedTimestamp,
94469450
descendantModifiedTimestamp,
94479451
dereferencedTimestamp,
9452+
servedWithoutHotTimestamp,
94489453
} = referencedUrlInfo;
94499454
if (
94509455
!modifiedTimestamp &&
@@ -9468,6 +9473,18 @@ const jsenvPluginHotSearchParam = () => {
94689473
descendantModifiedTimestamp,
94699474
dereferencedTimestamp,
94709475
);
9476+
// These timestamps say "this url changed at some point", not "the client
9477+
// is running an outdated version of it": they are never cleared, so a
9478+
// file modified once keeps them for the rest of the dev server's life.
9479+
// A client that fetched this url after that modification (a page load:
9480+
// see rememberServedWithoutHot in the dev server) already runs the
9481+
// latest content. Sending it "?hot" then makes the browser evaluate a
9482+
// second, identical copy of a module it already has — a second module
9483+
// scope for a file that never changed, which breaks everything a module
9484+
// holds once (registries, contexts, singletons).
9485+
if (latestTimestamp <= servedWithoutHotTimestamp) {
9486+
return null;
9487+
}
94719488
return {
94729489
hot: latestTimestamp,
94739490
};

dist/start_dev_server/start_dev_server.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7170,6 +7170,7 @@ const jsenvPluginHotSearchParam = () => {
71707170
modifiedTimestamp,
71717171
descendantModifiedTimestamp,
71727172
dereferencedTimestamp,
7173+
servedWithoutHotTimestamp,
71737174
} = referencedUrlInfo;
71747175
if (
71757176
!modifiedTimestamp &&
@@ -7193,6 +7194,18 @@ const jsenvPluginHotSearchParam = () => {
71937194
descendantModifiedTimestamp,
71947195
dereferencedTimestamp,
71957196
);
7197+
// These timestamps say "this url changed at some point", not "the client
7198+
// is running an outdated version of it": they are never cleared, so a
7199+
// file modified once keeps them for the rest of the dev server's life.
7200+
// A client that fetched this url after that modification (a page load:
7201+
// see rememberServedWithoutHot in the dev server) already runs the
7202+
// latest content. Sending it "?hot" then makes the browser evaluate a
7203+
// second, identical copy of a module it already has — a second module
7204+
// scope for a file that never changed, which breaks everything a module
7205+
// holds once (registries, contexts, singletons).
7206+
if (latestTimestamp <= servedWithoutHotTimestamp) {
7207+
return null;
7208+
}
71967209
return {
71977210
hot: latestTimestamp,
71987211
};
@@ -9675,6 +9688,10 @@ const createUrlInfo = (url, context) => {
96759688
modifiedTimestamp: 0,
96769689
descendantModifiedTimestamp: 0,
96779690
dereferencedTimestamp: 0,
9691+
// when a client last fetched this url outside a hot request; in other
9692+
// words the last time this url entered a fresh page (see
9693+
// jsenv_plugin_hot_search_param)
9694+
servedWithoutHotTimestamp: 0,
96789695
originalContentEtag: null,
96799696
contentEtag: null,
96809697
isValid: () => false,
@@ -11922,7 +11939,20 @@ const devServerPluginServeSourceFiles = ({
1192211939
);
1192311940
return response;
1192411941
};
11942+
// What the client holds for this url is what we last sent it: a
11943+
// request without "?hot" is a page loading this url into an empty
11944+
// module registry, so from here on the client runs this exact
11945+
// content. Remembering when that happened is what allows
11946+
// jsenv_plugin_hot_search_param to tell a modification the client
11947+
// has already received from one it must re-execute to see.
11948+
const rememberServedWithoutHot = () => {
11949+
if (request.searchParams.has("hot")) {
11950+
return;
11951+
}
11952+
urlInfo.servedWithoutHotTimestamp = Date.now();
11953+
};
1192511954
const respondWithNotModified = () => {
11955+
rememberServedWithoutHot();
1192611956
const headers = {
1192711957
"cache-control": `private,max-age=0,must-revalidate`,
1192811958
};
@@ -12007,6 +12037,9 @@ const devServerPluginServeSourceFiles = ({
1200712037
) {
1200812038
return respondWithNotModified();
1200912039
}
12040+
if (urlInfo.status === 200) {
12041+
rememberServedWithoutHot();
12042+
}
1201012043
response = {
1201112044
url: reference.url,
1201212045
// a plugin can cook a complete response body for an url that is

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@jsenv/core",
3-
"version": "41.5.14",
3+
"version": "41.5.15",
44
"type": "module",
55
"description": "Tool to develop, test and build js projects",
66
"repository": {

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

Lines changed: 2 additions & 2 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.map

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

packages/frontend/navi/docs/actions.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,17 @@ invisible at the call site and expensive on screen: the request then leaves with
244244
the gesture instead of with the screen, one waterfall behind everything else the
245245
address needed.
246246

247+
**A route action is a read.** The parameter says whose data it is; it does not
248+
say who may ask for it. An address asks again on every arrival — a reload, a
249+
pasted link, a step back — which is exactly what a read is for and what a write
250+
cannot survive: `POST /users/:id/invitations` hung on `/users/:id` mints a token
251+
per reload, for ever, and nothing at the call site says so. So a run that writes
252+
belongs to the component that decided to write, whatever its parameter, and
253+
`{ run: true }` is what says it. That is the shape of a request prepared for a
254+
gesture — a token a share button must already hold when it is pressed, since the
255+
OS share sheet only opens inside the gesture and never after an `await`: it runs
256+
at mount because the press cannot wait for it, not because the address changed.
257+
247258
`{ onLoad }` is what the screen does with the data **once, when it becomes
248259
known** — seed the fields someone is about to edit, focus something, remember
249260
where a list was:

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.219",
3+
"version": "0.29.220",
44
"type": "module",
55
"description": "Library of components including navigation to create frontend applications",
66
"repository": {

packages/frontend/navi/src/state/async/use_async_data.jsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,9 @@ import { usePromiseAsyncData } from "./use_promise_async_data.js";
8787
* needs, whereas this one cannot start before the component that draws it
8888
* exists — one render late, and behind whatever gesture mounted it. What is
8989
* left for `run` is the parameter chosen inside the component and dying with
90-
* it (see docs/actions.md and docs/popup_open.md).
90+
* it — and any run that WRITES, whatever its parameter: an address asks again
91+
* on every arrival, which is right for a read and wrong for a write (see
92+
* docs/actions.md and docs/popup_open.md).
9193
* @param {(data: any, context: {params: any}) => void} [options.onLoad] - what
9294
* this screen does with the data ONCE, when it becomes known: seed the fields
9395
* someone is about to edit, remember where a list was, focus something.

packages/related/cli/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@jsenv/cli",
3-
"version": "0.3.178",
3+
"version": "0.3.179",
44
"type": "module",
55
"description": "Command Line Interface for jsenv",
66
"repository": {

packages/related/cli/template-node-package/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
},
1414
"devDependencies": {
1515
"@jsenv/assert": "4.5.7",
16-
"@jsenv/core": "41.5.14",
16+
"@jsenv/core": "41.5.15",
1717
"@jsenv/eslint-config-relax": "2.0.3",
1818
"@jsenv/test": "3.7.45",
1919
"eslint": "10.9.1",

0 commit comments

Comments
 (0)