@rshono/core 1.0.0-rc.0 → 1.0.0-rc.10
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.
- package/README.md +202 -159
- package/dist/builder/page-files.d.ts.map +1 -1
- package/dist/builder/page-files.js +7 -3
- package/dist/builder/page-files.js.map +1 -1
- package/dist/builder/public-env.d.ts +6 -0
- package/dist/builder/public-env.d.ts.map +1 -1
- package/dist/builder/public-env.js +6 -0
- package/dist/builder/public-env.js.map +1 -1
- package/dist/builder/rspack-config.d.ts +3 -3
- package/dist/builder/rspack-config.d.ts.map +1 -1
- package/dist/builder/rspack-config.js +62 -16
- package/dist/builder/rspack-config.js.map +1 -1
- package/dist/cli/build.d.ts +2 -2
- package/dist/cli/build.js.map +1 -1
- package/dist/cli/dev.d.ts +2 -2
- package/dist/cli/dev.d.ts.map +1 -1
- package/dist/cli/dev.js +63 -35
- package/dist/cli/dev.js.map +1 -1
- package/dist/cli/index.js +10 -10
- package/dist/cli/index.js.map +1 -1
- package/dist/config.d.ts +58 -70
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +17 -1
- package/dist/config.js.map +1 -1
- package/dist/deploy/cloudflare/build.js +1 -1
- package/dist/deploy/cloudflare/build.js.map +1 -1
- package/dist/deploy/cloudflare/runtime.d.ts.map +1 -1
- package/dist/deploy/cloudflare/runtime.js +7 -37
- package/dist/deploy/cloudflare/runtime.js.map +1 -1
- package/dist/deploy/contract.d.ts +22 -16
- package/dist/deploy/contract.d.ts.map +1 -1
- package/dist/deploy/contract.js.map +1 -1
- package/dist/deploy/filesystem.d.ts +1 -1
- package/dist/deploy/filesystem.d.ts.map +1 -1
- package/dist/deploy/filesystem.js +7 -10
- package/dist/deploy/filesystem.js.map +1 -1
- package/dist/deploy/node/runtime.d.ts +4 -0
- package/dist/deploy/node/runtime.d.ts.map +1 -1
- package/dist/deploy/node/runtime.js +24 -3
- package/dist/deploy/node/runtime.js.map +1 -1
- package/dist/deploy/presets.d.ts +3 -3
- package/dist/deploy/presets.d.ts.map +1 -1
- package/dist/deploy/presets.js +13 -30
- package/dist/deploy/presets.js.map +1 -1
- package/dist/deploy/vercel/runtime.d.ts.map +1 -1
- package/dist/deploy/vercel/runtime.js +0 -3
- package/dist/deploy/vercel/runtime.js.map +1 -1
- package/dist/index.d.ts +6 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -3
- package/dist/index.js.map +1 -1
- package/dist/router.d.ts +85 -48
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +4 -6
- package/dist/router.js.map +1 -1
- package/dist/runtime/boundaries.d.ts +39 -25
- package/dist/runtime/boundaries.d.ts.map +1 -1
- package/dist/runtime/boundaries.js +22 -17
- package/dist/runtime/boundaries.js.map +1 -1
- package/dist/runtime/client.d.ts +9 -8
- package/dist/runtime/client.d.ts.map +1 -1
- package/dist/runtime/client.js +9 -8
- package/dist/runtime/client.js.map +1 -1
- package/dist/runtime/context.d.ts +216 -70
- package/dist/runtime/context.d.ts.map +1 -1
- package/dist/runtime/context.js +299 -93
- package/dist/runtime/context.js.map +1 -1
- package/dist/runtime/control.d.ts.map +1 -1
- package/dist/runtime/control.js +7 -0
- package/dist/runtime/control.js.map +1 -1
- package/dist/runtime/dev-protocol.d.ts.map +1 -1
- package/dist/runtime/dev-protocol.js.map +1 -1
- package/dist/runtime/entry.client.d.ts +4 -0
- package/dist/runtime/entry.client.d.ts.map +1 -1
- package/dist/runtime/entry.client.js +190 -154
- package/dist/runtime/entry.client.js.map +1 -1
- package/dist/runtime/entry.rsc.d.ts.map +1 -1
- package/dist/runtime/entry.rsc.js +145 -159
- package/dist/runtime/entry.rsc.js.map +1 -1
- package/dist/runtime/entry.ssr.d.ts +9 -1
- package/dist/runtime/entry.ssr.d.ts.map +1 -1
- package/dist/runtime/entry.ssr.js +36 -18
- package/dist/runtime/entry.ssr.js.map +1 -1
- package/dist/runtime/flight-inject.d.ts +31 -0
- package/dist/runtime/flight-inject.d.ts.map +1 -0
- package/dist/runtime/flight-inject.js +221 -0
- package/dist/runtime/flight-inject.js.map +1 -0
- package/dist/runtime/navigation.d.ts +20 -38
- package/dist/runtime/navigation.d.ts.map +1 -1
- package/dist/runtime/navigation.js +10 -53
- package/dist/runtime/navigation.js.map +1 -1
- package/dist/runtime/request.d.ts +6 -0
- package/dist/runtime/request.d.ts.map +1 -1
- package/dist/runtime/request.js +8 -0
- package/dist/runtime/request.js.map +1 -1
- package/dist/runtime/server.d.ts +7 -12
- package/dist/runtime/server.d.ts.map +1 -1
- package/dist/runtime/server.js +15 -12
- package/dist/runtime/server.js.map +1 -1
- package/dist/server/headers.d.ts +9 -9
- package/dist/server/headers.js +9 -9
- package/dist/server/headers.js.map +1 -1
- package/dist/server/load-config.d.ts +2 -2
- package/dist/server/load-config.d.ts.map +1 -1
- package/dist/server/load-config.js +22 -11
- package/dist/server/load-config.js.map +1 -1
- package/dist/server/prerendered.d.ts +43 -15
- package/dist/server/prerendered.d.ts.map +1 -1
- package/dist/server/prerendered.js +47 -0
- package/dist/server/prerendered.js.map +1 -1
- package/dist/server/server-config.d.ts +13 -39
- package/dist/server/server-config.d.ts.map +1 -1
- package/dist/server/server-config.js +5 -74
- package/dist/server/server-config.js.map +1 -1
- package/dist/server/ssg.d.ts +2 -2
- package/dist/server/ssg.d.ts.map +1 -1
- package/dist/server/ssg.js +21 -34
- package/dist/server/ssg.js.map +1 -1
- package/package.json +13 -16
- package/dist/deploy/bun/runtime.d.ts +0 -11
- package/dist/deploy/bun/runtime.d.ts.map +0 -1
- package/dist/deploy/bun/runtime.js +0 -22
- package/dist/deploy/bun/runtime.js.map +0 -1
- package/dist/deploy/deno/runtime.d.ts +0 -11
- package/dist/deploy/deno/runtime.d.ts.map +0 -1
- package/dist/deploy/deno/runtime.js +0 -16
- package/dist/deploy/deno/runtime.js.map +0 -1
- package/dist/deploy/listen.d.ts +0 -20
- package/dist/deploy/listen.d.ts.map +0 -1
- package/dist/deploy/listen.js +0 -24
- package/dist/deploy/listen.js.map +0 -1
- package/dist/deploy/netlify/build.d.ts +0 -8
- package/dist/deploy/netlify/build.d.ts.map +0 -1
- package/dist/deploy/netlify/build.js +0 -52
- package/dist/deploy/netlify/build.js.map +0 -1
- package/dist/deploy/netlify/runtime.d.ts +0 -13
- package/dist/deploy/netlify/runtime.d.ts.map +0 -1
- package/dist/deploy/netlify/runtime.js +0 -24
- package/dist/deploy/netlify/runtime.js.map +0 -1
- package/dist/server/compress.d.ts +0 -15
- package/dist/server/compress.d.ts.map +0 -1
- package/dist/server/compress.js +0 -76
- package/dist/server/compress.js.map +0 -1
|
@@ -2,11 +2,37 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { hydrateRoot } from 'react-dom/client';
|
|
4
4
|
import { createFromFetch, createFromReadableStream, createTemporaryReferenceSet, encodeReply, setServerCallback, } from 'react-server-dom-rspack/client.browser';
|
|
5
|
-
import { rscStream } from 'rsc-html-stream/client';
|
|
6
5
|
import { isControlDigest, parseRedirectDigest } from './control.js';
|
|
7
6
|
import { RouterContext } from './navigation.js';
|
|
8
7
|
import { createRscRequest } from './request.js';
|
|
9
8
|
const isDev = process.env.NODE_ENV === 'development';
|
|
9
|
+
/** The flight payload the document carried, read back out of `__FLIGHT_DATA` — see `flight-inject.ts`, which writes it. */
|
|
10
|
+
function readFlightPayload() {
|
|
11
|
+
const encoder = new TextEncoder();
|
|
12
|
+
// Assigned synchronously by `start`, which `new ReadableStream` runs before it returns.
|
|
13
|
+
let controller;
|
|
14
|
+
const stream = new ReadableStream({
|
|
15
|
+
start: (c) => void (controller = c),
|
|
16
|
+
});
|
|
17
|
+
const enqueue = (chunk) => controller.enqueue(typeof chunk === 'string' ? encoder.encode(chunk) : chunk);
|
|
18
|
+
// Payload scripts interleave with the document, so some have already run by the time this module
|
|
19
|
+
// is evaluated — those are in the array — and the rest run after it, arriving through `push`.
|
|
20
|
+
const data = (self.__FLIGHT_DATA ??= []);
|
|
21
|
+
for (const chunk of data)
|
|
22
|
+
enqueue(chunk);
|
|
23
|
+
data.push = enqueue;
|
|
24
|
+
// The last payload script lands before the document finishes parsing, so that is what says there
|
|
25
|
+
// is no more of it to come.
|
|
26
|
+
if (document.readyState === 'loading') {
|
|
27
|
+
document.addEventListener('DOMContentLoaded', () => controller.close(), { once: true });
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
controller.close();
|
|
31
|
+
}
|
|
32
|
+
return stream;
|
|
33
|
+
}
|
|
34
|
+
/** Created at module evaluation, not inside `main()`, so no chunk can be pushed before it is watching. */
|
|
35
|
+
const flightStream = readFlightPayload();
|
|
10
36
|
/**
|
|
11
37
|
* Guarantees somewhere to attach the fatal overlay. React's root container is the whole `document`,
|
|
12
38
|
* so by the time an uncaught error has torn the tree down, `<body>` — or even `<html>` — may be gone.
|
|
@@ -68,48 +94,16 @@ function showFatal(error, componentStack) {
|
|
|
68
94
|
host.appendChild(box);
|
|
69
95
|
}, 0);
|
|
70
96
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
function cacheKey(href) {
|
|
79
|
-
const url = new URL(href, location.href);
|
|
80
|
-
if (url.origin !== location.origin)
|
|
81
|
-
return null;
|
|
82
|
-
return url.pathname + url.search;
|
|
83
|
-
}
|
|
97
|
+
/**
|
|
98
|
+
* Asks a URL for its flight payload.
|
|
99
|
+
*
|
|
100
|
+
* Deliberately uncached: every navigation fetches at the moment it is asked for, so a payload can
|
|
101
|
+
* never be staler than the click that wanted it, and the browser's own HTTP cache is what makes a
|
|
102
|
+
* repeat visit cheap.
|
|
103
|
+
*/
|
|
84
104
|
function requestPayload(href) {
|
|
85
105
|
return createFromFetch(fetch(createRscRequest(new URL(href, location.href).href)));
|
|
86
106
|
}
|
|
87
|
-
function warmPayload(href) {
|
|
88
|
-
const key = cacheKey(href);
|
|
89
|
-
if (!key || key === cacheKey(location.href) || payloadCache.has(key))
|
|
90
|
-
return;
|
|
91
|
-
const promise = requestPayload(href);
|
|
92
|
-
payloadCache.set(key, promise);
|
|
93
|
-
// One entry in means at most one out, and the first key is the oldest.
|
|
94
|
-
if (payloadCache.size > MAX_WARMED_PAYLOADS)
|
|
95
|
-
payloadCache.delete(payloadCache.keys().next().value);
|
|
96
|
-
// Don't cache failures, and swallow the rejection until (or unless) a nav awaits it.
|
|
97
|
-
promise.catch(() => {
|
|
98
|
-
if (payloadCache.get(key) === promise)
|
|
99
|
-
payloadCache.delete(key);
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
function takePayload(href) {
|
|
103
|
-
const key = cacheKey(href);
|
|
104
|
-
if (key) {
|
|
105
|
-
const cached = payloadCache.get(key);
|
|
106
|
-
if (cached) {
|
|
107
|
-
payloadCache.delete(key);
|
|
108
|
-
return cached;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
return requestPayload(href);
|
|
112
|
-
}
|
|
113
107
|
async function main() {
|
|
114
108
|
const cspMeta = document.querySelector('meta[property="csp-nonce"]');
|
|
115
109
|
if (cspMeta?.nonce)
|
|
@@ -124,7 +118,7 @@ async function main() {
|
|
|
124
118
|
let startNav = (run) => {
|
|
125
119
|
void run();
|
|
126
120
|
};
|
|
127
|
-
const initialPayload = await createFromReadableStream(
|
|
121
|
+
const initialPayload = await createFromReadableStream(flightStream);
|
|
128
122
|
function push(href) {
|
|
129
123
|
const target = new URL(href, window.location.href);
|
|
130
124
|
if (target.origin !== window.location.origin) {
|
|
@@ -141,12 +135,11 @@ async function main() {
|
|
|
141
135
|
}
|
|
142
136
|
window.history.replaceState(null, '', target.href);
|
|
143
137
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
// A refresh keeps the URL, so it can't ride the history patch like push/replace — it drives the flight re-fetch directly (bypassing any warmed cache to get fresh data).
|
|
138
|
+
// A refresh keeps the URL, so it can't ride the history patch like push/replace — it drives the
|
|
139
|
+
// flight re-fetch directly.
|
|
147
140
|
const refresh = () => startNav(async () => {
|
|
148
141
|
try {
|
|
149
|
-
await fetchRscPayload(
|
|
142
|
+
await fetchRscPayload();
|
|
150
143
|
}
|
|
151
144
|
catch {
|
|
152
145
|
window.location.reload();
|
|
@@ -177,10 +170,10 @@ async function main() {
|
|
|
177
170
|
}
|
|
178
171
|
return true;
|
|
179
172
|
}
|
|
180
|
-
async function fetchRscPayload(
|
|
173
|
+
async function fetchRscPayload() {
|
|
181
174
|
let payload;
|
|
182
175
|
try {
|
|
183
|
-
payload = await
|
|
176
|
+
payload = await requestPayload(window.location.href);
|
|
184
177
|
}
|
|
185
178
|
catch (error) {
|
|
186
179
|
if (handleControlDigest(error))
|
|
@@ -194,20 +187,41 @@ async function main() {
|
|
|
194
187
|
function BrowserRoot() {
|
|
195
188
|
const [payload, setPayloadState] = React.useState(initialPayload);
|
|
196
189
|
const [pending, startTransition] = React.useTransition();
|
|
190
|
+
// The scroll a fetched navigation still owes, held until its payload is on screen.
|
|
191
|
+
const pendingScroll = React.useRef(null);
|
|
197
192
|
React.useEffect(() => {
|
|
198
193
|
setPayload = (v) => setPayloadState(v);
|
|
199
194
|
startNav = (run) => startTransition(run);
|
|
200
195
|
}, [startTransition]);
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
196
|
+
/**
|
|
197
|
+
* Scrolls where the navigation asked, once React has put its payload in the DOM.
|
|
198
|
+
*
|
|
199
|
+
* This has to wait for the commit rather than the fetch: a `#hash` target does not exist until the
|
|
200
|
+
* new tree does, and until then the page a scroll would move is still the outgoing one. A layout
|
|
201
|
+
* effect runs before the browser paints, so the pre-scroll position is never on screen.
|
|
202
|
+
*/
|
|
203
|
+
React.useLayoutEffect(() => {
|
|
204
|
+
const scroll = pendingScroll.current;
|
|
205
|
+
pendingScroll.current = null;
|
|
206
|
+
scroll?.();
|
|
207
|
+
}, [payload]);
|
|
208
|
+
React.useEffect(() => {
|
|
209
|
+
const stopNavigating = listenNavigation((afterRender) => startNav(async () => {
|
|
210
|
+
try {
|
|
211
|
+
await fetchRscPayload();
|
|
212
|
+
pendingScroll.current = afterRender;
|
|
213
|
+
}
|
|
214
|
+
catch {
|
|
215
|
+
window.location.reload();
|
|
216
|
+
}
|
|
217
|
+
}));
|
|
218
|
+
const stopUpgradingLinks = listenLinks();
|
|
219
|
+
return () => {
|
|
220
|
+
stopUpgradingLinks();
|
|
221
|
+
stopNavigating();
|
|
222
|
+
};
|
|
223
|
+
}, []);
|
|
224
|
+
const router = React.useMemo(() => ({ push, replace, refresh, pending }), [pending]);
|
|
211
225
|
return _jsx(RouterContext.Provider, { value: router, children: payload.root });
|
|
212
226
|
}
|
|
213
227
|
setServerCallback(async (id, args) => {
|
|
@@ -216,9 +230,6 @@ async function main() {
|
|
|
216
230
|
id,
|
|
217
231
|
body: await encodeReply(args, { temporaryReferences }),
|
|
218
232
|
});
|
|
219
|
-
// The action is about to mutate who-knows-what, so anything warmed up to now is pre-mutation
|
|
220
|
-
// data. Cleared before the round-trip so it happens even if the action throws.
|
|
221
|
-
payloadCache.clear();
|
|
222
233
|
let payload;
|
|
223
234
|
try {
|
|
224
235
|
payload = await createFromFetch(fetch(request), { temporaryReferences });
|
|
@@ -240,14 +251,13 @@ async function main() {
|
|
|
240
251
|
throw result.error;
|
|
241
252
|
return result.value;
|
|
242
253
|
});
|
|
243
|
-
// A `redirect()` / `notFound()` from a component *below* the page root
|
|
244
|
-
//
|
|
245
|
-
//
|
|
254
|
+
// A `redirect()` / `notFound()` from a component *below* the page root reaches us through React: it
|
|
255
|
+
// rides the flight payload as an error at that component's position, and boundaries re-throw it
|
|
256
|
+
// (see boundaries.tsx) so it lands here rather than rendering an error fallback.
|
|
246
257
|
//
|
|
247
|
-
//
|
|
248
|
-
// console for a caught error, `reportError` (i.e. window.onerror, so
|
|
249
|
-
// see it) for an uncaught one.
|
|
250
|
-
// to be put back by hand.
|
|
258
|
+
// Installing these hooks opts out of React's own defaults, so anything that isn't a control signal
|
|
259
|
+
// has to be put back by hand: console for a caught error, `reportError` (i.e. window.onerror, so
|
|
260
|
+
// error-reporting tools still see it) for an uncaught one.
|
|
251
261
|
hydrateRoot(document, _jsx(BrowserRoot, {}), {
|
|
252
262
|
formState: initialPayload.formState,
|
|
253
263
|
onCaughtError: (error, errorInfo) => {
|
|
@@ -267,15 +277,17 @@ async function main() {
|
|
|
267
277
|
},
|
|
268
278
|
});
|
|
269
279
|
if (import.meta.webpackHot) {
|
|
270
|
-
|
|
271
|
-
initDevRefresh(() => {
|
|
272
|
-
payloadCache.clear();
|
|
273
|
-
return fetchRscPayload(true);
|
|
274
|
-
});
|
|
280
|
+
initDevRefresh(fetchRscPayload);
|
|
275
281
|
}
|
|
276
282
|
}
|
|
277
|
-
/**
|
|
278
|
-
|
|
283
|
+
/**
|
|
284
|
+
* Runs teardown in reverse and empties the list, so a second call is a no-op. Collecting these as
|
|
285
|
+
* setup goes keeps each undo next to the thing it undoes.
|
|
286
|
+
*/
|
|
287
|
+
function disposeAll(undo) {
|
|
288
|
+
for (const dispose of undo.splice(0).reverse())
|
|
289
|
+
dispose();
|
|
290
|
+
}
|
|
279
291
|
// An `<a>` we intercept for soft navigation: same-origin, same tab, not a download,
|
|
280
292
|
// and not explicitly opted out with `data-native` (which forces a full browser navigation).
|
|
281
293
|
function isRouterLink(link) {
|
|
@@ -285,61 +297,14 @@ function isRouterLink(link) {
|
|
|
285
297
|
!link.hasAttribute('download') &&
|
|
286
298
|
!link.hasAttribute('data-native'));
|
|
287
299
|
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
window.history.scrollRestoration = 'manual';
|
|
297
|
-
}
|
|
298
|
-
catch { }
|
|
299
|
-
const keyOf = () => {
|
|
300
|
-
const state = window.history.state;
|
|
301
|
-
return state && typeof state.__rshonoScroll === 'number' ? state.__rshonoScroll : null;
|
|
302
|
-
};
|
|
303
|
-
const tag = (state, key) => ({ ...state, __rshonoScroll: key });
|
|
304
|
-
if (keyOf() === null) {
|
|
305
|
-
window.history.replaceState(tag(window.history.state, seq++), '');
|
|
306
|
-
}
|
|
307
|
-
let scrollRaf = 0;
|
|
308
|
-
const onScroll = () => {
|
|
309
|
-
if (scrollRaf)
|
|
310
|
-
return;
|
|
311
|
-
scrollRaf = requestAnimationFrame(() => {
|
|
312
|
-
scrollRaf = 0;
|
|
313
|
-
const key = keyOf();
|
|
314
|
-
if (key !== null)
|
|
315
|
-
scrollByKey.set(key, window.scrollY);
|
|
316
|
-
});
|
|
317
|
-
};
|
|
318
|
-
window.addEventListener('scroll', onScroll, { passive: true });
|
|
319
|
-
const restoreScrollFor = (type) => () => {
|
|
320
|
-
if (type === 'replace')
|
|
321
|
-
return;
|
|
322
|
-
const key = keyOf();
|
|
323
|
-
requestAnimationFrame(() => {
|
|
324
|
-
const y = type === 'pop' && key !== null ? (scrollByKey.get(key) ?? 0) : 0;
|
|
325
|
-
window.scrollTo(0, y);
|
|
326
|
-
});
|
|
327
|
-
};
|
|
328
|
-
const notify = (type) => onNavigation(restoreScrollFor(type));
|
|
329
|
-
const onPopState = () => notify('pop');
|
|
330
|
-
window.addEventListener('popstate', onPopState);
|
|
331
|
-
const oldPushState = window.history.pushState;
|
|
332
|
-
window.history.pushState = function (state, unused, url) {
|
|
333
|
-
const res = oldPushState.call(this, tag(state, seq++), unused, url);
|
|
334
|
-
notify('push');
|
|
335
|
-
return res;
|
|
336
|
-
};
|
|
337
|
-
const oldReplaceState = window.history.replaceState;
|
|
338
|
-
window.history.replaceState = function (state, unused, url) {
|
|
339
|
-
const res = oldReplaceState.call(this, tag(state, keyOf() ?? seq++), unused, url);
|
|
340
|
-
notify('replace');
|
|
341
|
-
return res;
|
|
342
|
-
};
|
|
300
|
+
/**
|
|
301
|
+
* Upgrades the app's anchors: a plain left-click becomes a soft navigation.
|
|
302
|
+
*
|
|
303
|
+
* Kept apart from `listenNavigation` because the two share no state — a click here only calls
|
|
304
|
+
* `history.pushState`, which is where that function picks the navigation up.
|
|
305
|
+
*/
|
|
306
|
+
function listenLinks() {
|
|
307
|
+
const undo = [];
|
|
343
308
|
function onClick(e) {
|
|
344
309
|
const link = e.target.closest('a');
|
|
345
310
|
if (link &&
|
|
@@ -358,37 +323,108 @@ function listenNavigation(onNavigation, prefetch) {
|
|
|
358
323
|
}
|
|
359
324
|
}
|
|
360
325
|
document.addEventListener('click', onClick);
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
326
|
+
undo.push(() => document.removeEventListener('click', onClick));
|
|
327
|
+
return () => disposeAll(undo);
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* The element the current `#fragment` names, if it is on the page.
|
|
331
|
+
*
|
|
332
|
+
* A fragment is percent-encoded and an `id` attribute is not, so it has to be decoded first. A
|
|
333
|
+
* hand-written URL can carry a `%` that is not an escape, which throws — take the fragment literally
|
|
334
|
+
* then, since that is the closest thing to an id it could have meant.
|
|
335
|
+
*/
|
|
336
|
+
function fragmentTarget() {
|
|
337
|
+
const fragment = location.hash.slice(1);
|
|
338
|
+
if (!fragment)
|
|
339
|
+
return null;
|
|
340
|
+
let id = fragment;
|
|
341
|
+
try {
|
|
342
|
+
id = decodeURIComponent(fragment);
|
|
375
343
|
}
|
|
376
|
-
|
|
377
|
-
document.
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
window.history.
|
|
344
|
+
catch { }
|
|
345
|
+
return document.getElementById(id);
|
|
346
|
+
}
|
|
347
|
+
function listenNavigation(onNavigation) {
|
|
348
|
+
const undo = [];
|
|
349
|
+
// Scroll restoration is the browser's. `auto` is set explicitly rather than left at the default,
|
|
350
|
+
// because it is a statement: the browser remembers a traversal's offset for us, and nothing here
|
|
351
|
+
// tracks one.
|
|
352
|
+
const prevRestoration = window.history.scrollRestoration;
|
|
353
|
+
try {
|
|
354
|
+
window.history.scrollRestoration = 'auto';
|
|
355
|
+
}
|
|
356
|
+
catch { }
|
|
357
|
+
undo.push(() => {
|
|
387
358
|
try {
|
|
388
359
|
window.history.scrollRestoration = prevRestoration;
|
|
389
360
|
}
|
|
390
361
|
catch { }
|
|
362
|
+
});
|
|
363
|
+
/**
|
|
364
|
+
* A push is not a real navigation to the browser, so nothing resets the scroll offset — without
|
|
365
|
+
* this a click through to a new page lands wherever the last one was scrolled to. A `#hash` names
|
|
366
|
+
* where to land instead, and one naming nothing on the page falls back to the top, as a browser
|
|
367
|
+
* does. `replace` keeps its position deliberately, and a traversal is the browser's to restore.
|
|
368
|
+
*
|
|
369
|
+
* `scrollIntoView` rather than `scrollTo`, because it is the algorithm a browser's own fragment jump
|
|
370
|
+
* uses — so `scroll-padding-top` still applies. Neither call passes a `behavior`, leaving
|
|
371
|
+
* `scroll-behavior: smooth` the app's to ask for.
|
|
372
|
+
*
|
|
373
|
+
* The caller decides *when* this runs; for a navigation that fetched a payload it has to be after
|
|
374
|
+
* the commit — see the layout effect in `BrowserRoot`.
|
|
375
|
+
*/
|
|
376
|
+
const afterRenderFor = (type) => () => {
|
|
377
|
+
if (type !== 'push')
|
|
378
|
+
return;
|
|
379
|
+
const target = fragmentTarget();
|
|
380
|
+
if (target)
|
|
381
|
+
target.scrollIntoView();
|
|
382
|
+
else
|
|
383
|
+
window.scrollTo(0, 0);
|
|
384
|
+
};
|
|
385
|
+
const documentUrl = () => location.pathname + location.search;
|
|
386
|
+
// What the payload on screen was rendered for. Only the document part: the server never sees the
|
|
387
|
+
// fragment, so two URLs differing by one render identically.
|
|
388
|
+
let renderedUrl = documentUrl();
|
|
389
|
+
/**
|
|
390
|
+
* A navigation that moves only the fragment — `#a` → `#b`, or back out of a same-page anchor —
|
|
391
|
+
* leaves the document unchanged, so the payload already on screen is the right one. Fetching
|
|
392
|
+
* another would be a wasted round-trip that re-renders the page out from under the jump.
|
|
393
|
+
*
|
|
394
|
+
* `router.refresh()` is unaffected: it drives the re-fetch directly rather than through here, and
|
|
395
|
+
* remains the way to ask for fresh data at an unchanged URL.
|
|
396
|
+
*/
|
|
397
|
+
const notify = (type) => {
|
|
398
|
+
const afterRender = afterRenderFor(type);
|
|
399
|
+
if (documentUrl() === renderedUrl) {
|
|
400
|
+
afterRender();
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
renderedUrl = documentUrl();
|
|
404
|
+
onNavigation(afterRender);
|
|
391
405
|
};
|
|
406
|
+
const onPopState = () => notify('pop');
|
|
407
|
+
window.addEventListener('popstate', onPopState);
|
|
408
|
+
undo.push(() => window.removeEventListener('popstate', onPopState));
|
|
409
|
+
const oldPushState = window.history.pushState;
|
|
410
|
+
window.history.pushState = function (state, unused, url) {
|
|
411
|
+
const res = oldPushState.call(this, state, unused, url);
|
|
412
|
+
notify('push');
|
|
413
|
+
return res;
|
|
414
|
+
};
|
|
415
|
+
undo.push(() => {
|
|
416
|
+
window.history.pushState = oldPushState;
|
|
417
|
+
});
|
|
418
|
+
const oldReplaceState = window.history.replaceState;
|
|
419
|
+
window.history.replaceState = function (state, unused, url) {
|
|
420
|
+
const res = oldReplaceState.call(this, state, unused, url);
|
|
421
|
+
notify('replace');
|
|
422
|
+
return res;
|
|
423
|
+
};
|
|
424
|
+
undo.push(() => {
|
|
425
|
+
window.history.replaceState = oldReplaceState;
|
|
426
|
+
});
|
|
427
|
+
return () => disposeAll(undo);
|
|
392
428
|
}
|
|
393
429
|
/**
|
|
394
430
|
* Dev-only refresh client (stripped from prod bundles: the whole call is
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry.client.js","sourceRoot":"","sources":["../../src/runtime/entry.client.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\nimport { hydrateRoot } from 'react-dom/client';\nimport {\n createFromFetch,\n createFromReadableStream,\n createTemporaryReferenceSet,\n encodeReply,\n setServerCallback,\n} from 'react-server-dom-rspack/client.browser';\nimport { rscStream } from 'rsc-html-stream/client';\nimport { isControlDigest, parseRedirectDigest } from './control.js';\nimport type { DevMessage } from './dev-protocol.js';\nimport type { RscPayload } from './entry.rsc.js';\nimport { RouterContext, type Router } from './navigation.js';\nimport { createRscRequest } from './request.js';\n\nconst isDev = process.env.NODE_ENV === 'development';\n\n/**\n * Guarantees somewhere to attach the fatal overlay. React's root container is the whole `document`,\n * so by the time an uncaught error has torn the tree down, `<body>` — or even `<html>` — may be gone.\n */\nfunction overlayHost(): HTMLElement {\n if (!document.documentElement) document.appendChild(document.createElement('html'));\n if (!document.body) document.documentElement.appendChild(document.createElement('body'));\n return document.body;\n}\n\n/**\n * Replaces the white screen of death with something readable.\n *\n * Because the root container is `document`, an uncaught render error leaves a genuinely blank page\n * with the reason only in the console — so this paints the reason over it instead. In development\n * that's the full stack; in production it's a generic notice plus a reload button, since the tree is\n * unrecoverable and reloading is the only way forward.\n *\n * Written with DOM calls rather than React (the renderer is what just failed) and `textContent`\n * rather than `innerHTML` (an error message is untrusted input).\n */\nfunction showFatal(error: unknown, componentStack?: string | null): void {\n // Queued rather than run inline: React's teardown happens after this callback returns, and would\n // remove a node appended synchronously along with the rest of the tree.\n setTimeout(() => {\n const host = overlayHost();\n host.querySelector('[data-rshono-fatal]')?.remove();\n\n const box = document.createElement('div');\n box.setAttribute('data-rshono-fatal', '');\n box.setAttribute('role', 'alert'); // the page is gone; announce it rather than leaving silence\n box.style.cssText =\n 'position:fixed;inset:0;z-index:2147483647;overflow:auto;padding:1.5rem;background:#18181b;color:#f4f4f5;' +\n 'font:14px/1.6 ui-monospace,SFMono-Regular,Menlo,monospace;text-align:left';\n\n const title = document.createElement('div');\n title.textContent = isDev ? 'Unhandled error' : 'Something went wrong';\n title.style.cssText = 'font-size:1.0625rem;font-weight:700;color:#f87171;margin:0 0 0.75rem';\n box.appendChild(title);\n\n if (isDev) {\n const detail = document.createElement('pre');\n detail.style.cssText = 'margin:0;white-space:pre-wrap;word-break:break-word';\n detail.textContent =\n (error instanceof Error ? (error.stack ?? `${error.name}: ${error.message}`) : String(error)) +\n (componentStack ? `\\n\\nComponent stack:${componentStack}` : '');\n box.appendChild(detail);\n } else {\n const message = document.createElement('p');\n message.textContent = 'This page hit an unexpected error and can’t continue.';\n message.style.cssText = 'margin:0 0 1rem;color:#d4d4d8';\n box.appendChild(message);\n }\n\n const reload = document.createElement('button');\n reload.textContent = 'Reload page';\n reload.style.cssText =\n 'margin-top:1.25rem;padding:0.5rem 1rem;font:inherit;color:#18181b;background:#f4f4f5;border:0;border-radius:4px;cursor:pointer';\n reload.addEventListener('click', () => window.location.reload());\n box.appendChild(reload);\n\n host.appendChild(box);\n }, 0);\n}\n\n// In-memory flight-payload cache keyed by same-origin path+search. `data-prefetch`\n// links warm it on hover/focus; a navigation to a warmed URL resolves instantly and\n// clears the entry (a prefetch is used at most once, so re-visits always re-fetch).\nconst payloadCache = new Map<string, Promise<RscPayload>>();\n\n// Bounded so a long session over a link-dense app can't grow it without limit. Insertion-ordered,\n// so the first key is the least recently warmed.\nconst MAX_WARMED_PAYLOADS = 8;\n\nfunction cacheKey(href: string): string | null {\n const url = new URL(href, location.href);\n if (url.origin !== location.origin) return null;\n return url.pathname + url.search;\n}\n\nfunction requestPayload(href: string): Promise<RscPayload> {\n return createFromFetch<RscPayload>(fetch(createRscRequest(new URL(href, location.href).href)));\n}\n\nfunction warmPayload(href: string): void {\n const key = cacheKey(href);\n if (!key || key === cacheKey(location.href) || payloadCache.has(key)) return;\n const promise = requestPayload(href);\n payloadCache.set(key, promise);\n // One entry in means at most one out, and the first key is the oldest.\n if (payloadCache.size > MAX_WARMED_PAYLOADS) payloadCache.delete(payloadCache.keys().next().value!);\n // Don't cache failures, and swallow the rejection until (or unless) a nav awaits it.\n promise.catch(() => {\n if (payloadCache.get(key) === promise) payloadCache.delete(key);\n });\n}\n\nfunction takePayload(href: string): Promise<RscPayload> {\n const key = cacheKey(href);\n if (key) {\n const cached = payloadCache.get(key);\n if (cached) {\n payloadCache.delete(key);\n return cached;\n }\n }\n return requestPayload(href);\n}\n\nasync function main() {\n const cspMeta = document.querySelector('meta[property=\"csp-nonce\"]') as HTMLMetaElement | null;\n if (cspMeta?.nonce) __webpack_nonce__ = cspMeta.nonce;\n\n // Both are replaced by BrowserRoot's own on mount. The defaults matter: `setServerCallback` is\n // registered before hydration, so an action or refresh firing in that window would otherwise call\n // an unassigned binding. Until there's a root to update, a full reload is the honest fallback.\n let setPayload: (v: RscPayload) => void = () => {\n window.location.reload();\n };\n // Runs work inside the nav transition so useNavigation().pending stays true across the round-trip.\n let startNav: (run: () => void | Promise<void>) => void = (run) => {\n void run();\n };\n\n const initialPayload = await createFromReadableStream<RscPayload>(rscStream);\n\n function push(href: string) {\n const target = new URL(href, window.location.href);\n if (target.origin !== window.location.origin) {\n window.location.assign(target.href);\n return;\n }\n window.history.pushState(null, '', target.href);\n }\n\n function replace(href: string) {\n const target = new URL(href, window.location.href);\n if (target.origin !== window.location.origin) {\n window.location.replace(target.href);\n return;\n }\n window.history.replaceState(null, '', target.href);\n }\n\n const back = () => window.history.back();\n const forward = () => window.history.forward();\n // A refresh keeps the URL, so it can't ride the history patch like push/replace — it drives the flight re-fetch directly (bypassing any warmed cache to get fresh data).\n const refresh = () =>\n startNav(async () => {\n try {\n await fetchRscPayload(true);\n } catch {\n window.location.reload();\n }\n });\n\n /**\n * Turns a control-signal digest — how `redirect()` / `notFound()` reach the browser — into a real\n * navigation. Returns false for anything else, so callers can fall through to their own handling.\n *\n * `hard` forces a full document load, for signals that surfaced *through React* (a nested\n * component's redirect, reported via the root error handlers). React unmounts the root on an\n * uncaught error, so there is no live tree left to soft-navigate with. A signal caught earlier —\n * a top-level payload rejection — still swaps the payload in place.\n */\n function handleControlDigest(error: unknown, { hard = false }: { hard?: boolean } = {}): boolean {\n const digest = (error as { digest?: unknown } | null)?.digest;\n if (!isControlDigest(digest)) return false;\n const redirect = parseRedirectDigest(digest);\n if (!redirect) {\n window.location.reload();\n } else if (hard) {\n window.location.assign(new URL(redirect.location, window.location.href).href);\n } else {\n push(redirect.location);\n }\n return true;\n }\n\n async function fetchRscPayload(force = false) {\n let payload: RscPayload;\n try {\n payload = await (force ? requestPayload(window.location.href) : takePayload(window.location.href));\n } catch (error) {\n if (handleControlDigest(error)) return;\n throw error;\n }\n if (payload.redirect) return push(payload.redirect);\n setPayload(payload);\n }\n\n function BrowserRoot() {\n const [payload, setPayloadState] = React.useState(initialPayload);\n const [pending, startTransition] = React.useTransition();\n\n React.useEffect(() => {\n setPayload = (v) => setPayloadState(v);\n startNav = (run) => startTransition(run);\n }, [startTransition]);\n\n React.useEffect(\n () =>\n listenNavigation(\n (restoreScroll) =>\n startNav(async () => {\n try {\n await fetchRscPayload();\n restoreScroll();\n } catch {\n window.location.reload();\n }\n }),\n warmPayload,\n ),\n [],\n );\n\n const router = React.useMemo<Router>(() => ({ push, replace, back, forward, refresh, pending }), [pending]);\n\n return <RouterContext.Provider value={router}>{payload.root}</RouterContext.Provider>;\n }\n\n setServerCallback(async (id, args) => {\n const temporaryReferences = createTemporaryReferenceSet();\n const request = createRscRequest(window.location.href, {\n id,\n body: await encodeReply(args, { temporaryReferences }),\n });\n // The action is about to mutate who-knows-what, so anything warmed up to now is pre-mutation\n // data. Cleared before the round-trip so it happens even if the action throws.\n payloadCache.clear();\n let payload: RscPayload;\n try {\n payload = await createFromFetch<RscPayload>(fetch(request), { temporaryReferences });\n } catch (error) {\n if (handleControlDigest(error)) return undefined;\n throw error;\n }\n if (payload.redirect) {\n push(payload.redirect);\n return undefined;\n }\n React.startTransition(() => setPayload(payload));\n if (payload.notFound) return undefined;\n const result = payload.returnValue!;\n if (!result.ok) throw result.error;\n return result.value;\n });\n\n // A `redirect()` / `notFound()` from a component *below* the page root can only reach us through\n // React: it rides the flight payload as an error at that component's position, and boundaries\n // re-throw it (see boundaries.tsx) so it lands here rather than rendering an error fallback.\n //\n // Anything that isn't a control signal falls back to what React would have done on its own —\n // console for a caught error, `reportError` (i.e. window.onerror, so error-reporting tools still\n // see it) for an uncaught one. Overriding these hooks means opting out of that default, so it has\n // to be put back by hand.\n hydrateRoot(document, <BrowserRoot />, {\n formState: initialPayload.formState,\n onCaughtError: (error, errorInfo) => {\n if (handleControlDigest(error, { hard: true })) return;\n // A boundary handled this and the tree is intact, so no overlay: whatever fallback the app\n // chose is the right thing to have on screen.\n console.error(error, errorInfo.componentStack ?? '');\n },\n onUncaughtError: (error, errorInfo) => {\n if (handleControlDigest(error, { hard: true })) return;\n // Nothing caught it, so React tears the root down — and the root is `document`. This is the\n // white screen; paint the reason over it.\n globalThis.reportError(error);\n showFatal(error, errorInfo.componentStack);\n },\n });\n\n if (import.meta.webpackHot) {\n // Server code may have changed, so drop any warmed payloads and re-fetch fresh.\n initDevRefresh(() => {\n payloadCache.clear();\n return fetchRscPayload(true);\n });\n }\n}\n\ntype NavigationType = 'push' | 'replace' | 'pop';\n\n/** Hover/focus dwell time before a `data-prefetch` link warms its payload. */\nconst PREFETCH_DELAY_MS = 120;\n\n// An `<a>` we intercept for soft navigation: same-origin, same tab, not a download,\n// and not explicitly opted out with `data-native` (which forces a full browser navigation).\nfunction isRouterLink(link: HTMLAnchorElement): boolean {\n return (\n !!link.href &&\n (!link.target || link.target === '_self') &&\n link.origin === location.origin &&\n !link.hasAttribute('download') &&\n !link.hasAttribute('data-native')\n );\n}\n\nfunction listenNavigation(onNavigation: (restoreScroll: () => void) => void, prefetch: (href: string) => void): () => void {\n // Scroll restoration. We tag each history entry with a stable numeric key in its\n // `history.state` and remember scrollY per key, so back/forward restores the exact\n // position while push scrolls to the top. `manual` hands restoration to us.\n const scrollByKey = new Map<number, number>();\n let seq = 0;\n const prevRestoration = window.history.scrollRestoration;\n try {\n window.history.scrollRestoration = 'manual';\n } catch {}\n\n const keyOf = (): number | null => {\n const state = window.history.state as { __rshonoScroll?: unknown } | null;\n return state && typeof state.__rshonoScroll === 'number' ? state.__rshonoScroll : null;\n };\n const tag = (state: unknown, key: number) => ({ ...(state as object | null), __rshonoScroll: key });\n\n if (keyOf() === null) {\n window.history.replaceState(tag(window.history.state, seq++), '');\n }\n\n let scrollRaf = 0;\n const onScroll = () => {\n if (scrollRaf) return;\n scrollRaf = requestAnimationFrame(() => {\n scrollRaf = 0;\n const key = keyOf();\n if (key !== null) scrollByKey.set(key, window.scrollY);\n });\n };\n window.addEventListener('scroll', onScroll, { passive: true });\n\n const restoreScrollFor = (type: NavigationType) => () => {\n if (type === 'replace') return;\n const key = keyOf();\n requestAnimationFrame(() => {\n const y = type === 'pop' && key !== null ? (scrollByKey.get(key) ?? 0) : 0;\n window.scrollTo(0, y);\n });\n };\n const notify = (type: NavigationType) => onNavigation(restoreScrollFor(type));\n\n const onPopState = () => notify('pop');\n window.addEventListener('popstate', onPopState);\n\n const oldPushState = window.history.pushState;\n window.history.pushState = function (state, unused, url) {\n const res = oldPushState.call(this, tag(state, seq++), unused, url as string);\n notify('push');\n return res;\n };\n\n const oldReplaceState = window.history.replaceState;\n window.history.replaceState = function (state, unused, url) {\n const res = oldReplaceState.call(this, tag(state, keyOf() ?? seq++), unused, url as string);\n notify('replace');\n return res;\n };\n\n function onClick(e: MouseEvent) {\n const link = (e.target as Element).closest('a');\n if (\n link &&\n link instanceof HTMLAnchorElement &&\n isRouterLink(link) &&\n e.button === 0 &&\n !e.metaKey &&\n !e.ctrlKey &&\n !e.altKey &&\n !e.shiftKey &&\n !e.defaultPrevented\n ) {\n if (link.hash && link.pathname === location.pathname && link.search === location.search) return;\n e.preventDefault();\n history.pushState(null, '', link.href);\n }\n }\n document.addEventListener('click', onClick);\n\n // A prefetch is a full server render, so it waits out a short dwell time on one shared timer:\n // sweeping the cursor across a list of prefetch links costs one request (for the link the pointer\n // settled on), not one per link.\n let prefetchTimer: ReturnType<typeof setTimeout> | undefined;\n function onPrefetch(e: Event) {\n const target = e.target;\n if (!(target instanceof Element)) return;\n const link = target.closest('a[data-prefetch]');\n if (!(link instanceof HTMLAnchorElement) || !isRouterLink(link)) return;\n const { href } = link;\n clearTimeout(prefetchTimer);\n prefetchTimer = setTimeout(() => prefetch(href), PREFETCH_DELAY_MS);\n }\n document.addEventListener('pointerover', onPrefetch);\n document.addEventListener('focusin', onPrefetch);\n\n return () => {\n clearTimeout(prefetchTimer);\n document.removeEventListener('click', onClick);\n document.removeEventListener('pointerover', onPrefetch);\n document.removeEventListener('focusin', onPrefetch);\n window.removeEventListener('popstate', onPopState);\n window.removeEventListener('scroll', onScroll);\n window.history.pushState = oldPushState;\n window.history.replaceState = oldReplaceState;\n try {\n window.history.scrollRestoration = prevRestoration;\n } catch {}\n };\n}\n\n/**\n * Dev-only refresh client (stripped from prod bundles: the whole call is\n * guarded by import.meta.webpackHot). Listens to the CLI's SSE endpoint:\n *\n * client-built → hot-apply the waiting updates (react-refresh keeps\n * component state); any failure falls back to reload.\n * rsc-update → server component code changed: re-fetch the flight\n * payload for the current URL, state preserved.\n * hello → sent on (re)connect with the latest build hash; a\n * mismatch means events were missed — resync.\n */\nfunction initDevRefresh(fetchRscPayload: () => Promise<void>) {\n let connectedOnce = false;\n\n async function applyClientUpdate(hash: string) {\n const hot = import.meta.webpackHot!;\n if (hash === __webpack_hash__) return;\n if (hot.status() !== 'idle') {\n window.location.reload();\n return;\n }\n try {\n await hot.check(true);\n if (hash !== __webpack_hash__) await applyClientUpdate(hash);\n } catch (error) {\n console.warn('[rshono] hot update failed, reloading:', error);\n window.location.reload();\n }\n }\n\n const source = new EventSource('/_rshono/hmr');\n source.onmessage = async (event) => {\n const message = JSON.parse(event.data) as DevMessage;\n switch (message.type) {\n case 'hello':\n if (connectedOnce) {\n if (message.hash && message.hash !== __webpack_hash__) await applyClientUpdate(message.hash);\n await fetchRscPayload().catch(() => window.location.reload());\n }\n connectedOnce = true;\n break;\n case 'client-built':\n if (message.hash) await applyClientUpdate(message.hash);\n break;\n case 'rsc-update':\n console.log('[rshono] server components updated');\n await fetchRscPayload().catch(() => window.location.reload());\n break;\n }\n };\n}\n\n// Bootstrap failures (a truncated or malformed initial flight payload, most likely) would otherwise\n// be an unhandled rejection: nothing hydrates, nothing is reported, and the page just sits there.\nmain().catch((error) => {\n console.error('[rshono] the client runtime failed to start:', error);\n showFatal(error);\n});\n"]}
|
|
1
|
+
{"version":3,"file":"entry.client.js","sourceRoot":"","sources":["../../src/runtime/entry.client.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\nimport { hydrateRoot } from 'react-dom/client';\nimport {\n createFromFetch,\n createFromReadableStream,\n createTemporaryReferenceSet,\n encodeReply,\n setServerCallback,\n} from 'react-server-dom-rspack/client.browser';\nimport { isControlDigest, parseRedirectDigest } from './control.js';\nimport type { DevMessage } from './dev-protocol.js';\nimport type { RscPayload } from './entry.rsc.js';\nimport { RouterContext, type NavigationRouter } from './navigation.js';\nimport { createRscRequest } from './request.js';\n\nconst isDev = process.env.NODE_ENV === 'development';\n\ndeclare global {\n /** The array the payload `<script>` tags `flight-inject.ts` emits push their chunks into. */\n var __FLIGHT_DATA: Array<string | Uint8Array> | undefined;\n}\n\n/** The flight payload the document carried, read back out of `__FLIGHT_DATA` — see `flight-inject.ts`, which writes it. */\nfunction readFlightPayload(): ReadableStream<Uint8Array> {\n const encoder = new TextEncoder();\n // Assigned synchronously by `start`, which `new ReadableStream` runs before it returns.\n let controller!: ReadableStreamDefaultController<Uint8Array>;\n const stream = new ReadableStream<Uint8Array>({\n start: (c) => void (controller = c),\n });\n const enqueue = (chunk: string | Uint8Array) => controller.enqueue(typeof chunk === 'string' ? encoder.encode(chunk) : chunk);\n\n // Payload scripts interleave with the document, so some have already run by the time this module\n // is evaluated — those are in the array — and the rest run after it, arriving through `push`.\n const data = (self.__FLIGHT_DATA ??= []);\n for (const chunk of data) enqueue(chunk);\n data.push = enqueue as typeof data.push;\n\n // The last payload script lands before the document finishes parsing, so that is what says there\n // is no more of it to come.\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => controller.close(), { once: true });\n } else {\n controller.close();\n }\n return stream;\n}\n\n/** Created at module evaluation, not inside `main()`, so no chunk can be pushed before it is watching. */\nconst flightStream = readFlightPayload();\n\n/**\n * Guarantees somewhere to attach the fatal overlay. React's root container is the whole `document`,\n * so by the time an uncaught error has torn the tree down, `<body>` — or even `<html>` — may be gone.\n */\nfunction overlayHost(): HTMLElement {\n if (!document.documentElement) document.appendChild(document.createElement('html'));\n if (!document.body) document.documentElement.appendChild(document.createElement('body'));\n return document.body;\n}\n\n/**\n * Replaces the white screen of death with something readable.\n *\n * Because the root container is `document`, an uncaught render error leaves a genuinely blank page\n * with the reason only in the console — so this paints the reason over it instead. In development\n * that's the full stack; in production it's a generic notice plus a reload button, since the tree is\n * unrecoverable and reloading is the only way forward.\n *\n * Written with DOM calls rather than React (the renderer is what just failed) and `textContent`\n * rather than `innerHTML` (an error message is untrusted input).\n */\nfunction showFatal(error: unknown, componentStack?: string | null): void {\n // Queued rather than run inline: React's teardown happens after this callback returns, and would\n // remove a node appended synchronously along with the rest of the tree.\n setTimeout(() => {\n const host = overlayHost();\n host.querySelector('[data-rshono-fatal]')?.remove();\n\n const box = document.createElement('div');\n box.setAttribute('data-rshono-fatal', '');\n box.setAttribute('role', 'alert'); // the page is gone; announce it rather than leaving silence\n box.style.cssText =\n 'position:fixed;inset:0;z-index:2147483647;overflow:auto;padding:1.5rem;background:#18181b;color:#f4f4f5;' +\n 'font:14px/1.6 ui-monospace,SFMono-Regular,Menlo,monospace;text-align:left';\n\n const title = document.createElement('div');\n title.textContent = isDev ? 'Unhandled error' : 'Something went wrong';\n title.style.cssText = 'font-size:1.0625rem;font-weight:700;color:#f87171;margin:0 0 0.75rem';\n box.appendChild(title);\n\n if (isDev) {\n const detail = document.createElement('pre');\n detail.style.cssText = 'margin:0;white-space:pre-wrap;word-break:break-word';\n detail.textContent =\n (error instanceof Error ? (error.stack ?? `${error.name}: ${error.message}`) : String(error)) +\n (componentStack ? `\\n\\nComponent stack:${componentStack}` : '');\n box.appendChild(detail);\n } else {\n const message = document.createElement('p');\n message.textContent = 'This page hit an unexpected error and can’t continue.';\n message.style.cssText = 'margin:0 0 1rem;color:#d4d4d8';\n box.appendChild(message);\n }\n\n const reload = document.createElement('button');\n reload.textContent = 'Reload page';\n reload.style.cssText =\n 'margin-top:1.25rem;padding:0.5rem 1rem;font:inherit;color:#18181b;background:#f4f4f5;border:0;border-radius:4px;cursor:pointer';\n reload.addEventListener('click', () => window.location.reload());\n box.appendChild(reload);\n\n host.appendChild(box);\n }, 0);\n}\n\n/**\n * Asks a URL for its flight payload.\n *\n * Deliberately uncached: every navigation fetches at the moment it is asked for, so a payload can\n * never be staler than the click that wanted it, and the browser's own HTTP cache is what makes a\n * repeat visit cheap.\n */\nfunction requestPayload(href: string): Promise<RscPayload> {\n return createFromFetch<RscPayload>(fetch(createRscRequest(new URL(href, location.href).href)));\n}\n\nasync function main() {\n const cspMeta = document.querySelector('meta[property=\"csp-nonce\"]') as HTMLMetaElement | null;\n if (cspMeta?.nonce) __webpack_nonce__ = cspMeta.nonce;\n\n // Both are replaced by BrowserRoot's own on mount. The defaults matter: `setServerCallback` is\n // registered before hydration, so an action or refresh firing in that window would otherwise call\n // an unassigned binding. Until there's a root to update, a full reload is the honest fallback.\n let setPayload: (v: RscPayload) => void = () => {\n window.location.reload();\n };\n // Runs work inside the nav transition so useNavigation().pending stays true across the round-trip.\n let startNav: (run: () => void | Promise<void>) => void = (run) => {\n void run();\n };\n\n const initialPayload = await createFromReadableStream<RscPayload>(flightStream);\n\n function push(href: string) {\n const target = new URL(href, window.location.href);\n if (target.origin !== window.location.origin) {\n window.location.assign(target.href);\n return;\n }\n window.history.pushState(null, '', target.href);\n }\n\n function replace(href: string) {\n const target = new URL(href, window.location.href);\n if (target.origin !== window.location.origin) {\n window.location.replace(target.href);\n return;\n }\n window.history.replaceState(null, '', target.href);\n }\n\n // A refresh keeps the URL, so it can't ride the history patch like push/replace — it drives the\n // flight re-fetch directly.\n const refresh = () =>\n startNav(async () => {\n try {\n await fetchRscPayload();\n } catch {\n window.location.reload();\n }\n });\n\n /**\n * Turns a control-signal digest — how `redirect()` / `notFound()` reach the browser — into a real\n * navigation. Returns false for anything else, so callers can fall through to their own handling.\n *\n * `hard` forces a full document load, for signals that surfaced *through React* (a nested\n * component's redirect, reported via the root error handlers). React unmounts the root on an\n * uncaught error, so there is no live tree left to soft-navigate with. A signal caught earlier —\n * a top-level payload rejection — still swaps the payload in place.\n */\n function handleControlDigest(error: unknown, { hard = false }: { hard?: boolean } = {}): boolean {\n const digest = (error as { digest?: unknown } | null)?.digest;\n if (!isControlDigest(digest)) return false;\n const redirect = parseRedirectDigest(digest);\n if (!redirect) {\n window.location.reload();\n } else if (hard) {\n window.location.assign(new URL(redirect.location, window.location.href).href);\n } else {\n push(redirect.location);\n }\n return true;\n }\n\n async function fetchRscPayload() {\n let payload: RscPayload;\n try {\n payload = await requestPayload(window.location.href);\n } catch (error) {\n if (handleControlDigest(error)) return;\n throw error;\n }\n if (payload.redirect) return push(payload.redirect);\n setPayload(payload);\n }\n\n function BrowserRoot() {\n const [payload, setPayloadState] = React.useState(initialPayload);\n const [pending, startTransition] = React.useTransition();\n // The scroll a fetched navigation still owes, held until its payload is on screen.\n const pendingScroll = React.useRef<(() => void) | null>(null);\n\n React.useEffect(() => {\n setPayload = (v) => setPayloadState(v);\n startNav = (run) => startTransition(run);\n }, [startTransition]);\n\n /**\n * Scrolls where the navigation asked, once React has put its payload in the DOM.\n *\n * This has to wait for the commit rather than the fetch: a `#hash` target does not exist until the\n * new tree does, and until then the page a scroll would move is still the outgoing one. A layout\n * effect runs before the browser paints, so the pre-scroll position is never on screen.\n */\n React.useLayoutEffect(() => {\n const scroll = pendingScroll.current;\n pendingScroll.current = null;\n scroll?.();\n }, [payload]);\n\n React.useEffect(() => {\n const stopNavigating = listenNavigation((afterRender) =>\n startNav(async () => {\n try {\n await fetchRscPayload();\n pendingScroll.current = afterRender;\n } catch {\n window.location.reload();\n }\n }),\n );\n const stopUpgradingLinks = listenLinks();\n return () => {\n stopUpgradingLinks();\n stopNavigating();\n };\n }, []);\n\n const router = React.useMemo<NavigationRouter>(() => ({ push, replace, refresh, pending }), [pending]);\n\n return <RouterContext.Provider value={router}>{payload.root}</RouterContext.Provider>;\n }\n\n setServerCallback(async (id, args) => {\n const temporaryReferences = createTemporaryReferenceSet();\n const request = createRscRequest(window.location.href, {\n id,\n body: await encodeReply(args, { temporaryReferences }),\n });\n let payload: RscPayload;\n try {\n payload = await createFromFetch<RscPayload>(fetch(request), { temporaryReferences });\n } catch (error) {\n if (handleControlDigest(error)) return undefined;\n throw error;\n }\n if (payload.redirect) {\n push(payload.redirect);\n return undefined;\n }\n React.startTransition(() => setPayload(payload));\n if (payload.notFound) return undefined;\n const result = payload.returnValue!;\n if (!result.ok) throw result.error;\n return result.value;\n });\n\n // A `redirect()` / `notFound()` from a component *below* the page root reaches us through React: it\n // rides the flight payload as an error at that component's position, and boundaries re-throw it\n // (see boundaries.tsx) so it lands here rather than rendering an error fallback.\n //\n // Installing these hooks opts out of React's own defaults, so anything that isn't a control signal\n // has to be put back by hand: console for a caught error, `reportError` (i.e. window.onerror, so\n // error-reporting tools still see it) for an uncaught one.\n hydrateRoot(document, <BrowserRoot />, {\n formState: initialPayload.formState,\n onCaughtError: (error, errorInfo) => {\n if (handleControlDigest(error, { hard: true })) return;\n // A boundary handled this and the tree is intact, so no overlay: whatever fallback the app\n // chose is the right thing to have on screen.\n console.error(error, errorInfo.componentStack ?? '');\n },\n onUncaughtError: (error, errorInfo) => {\n if (handleControlDigest(error, { hard: true })) return;\n // Nothing caught it, so React tears the root down — and the root is `document`. This is the\n // white screen; paint the reason over it.\n globalThis.reportError(error);\n showFatal(error, errorInfo.componentStack);\n },\n });\n\n if (import.meta.webpackHot) {\n initDevRefresh(fetchRscPayload);\n }\n}\n\ntype NavigationType = 'push' | 'replace' | 'pop';\n\n/**\n * Runs teardown in reverse and empties the list, so a second call is a no-op. Collecting these as\n * setup goes keeps each undo next to the thing it undoes.\n */\nfunction disposeAll(undo: Array<() => void>): void {\n for (const dispose of undo.splice(0).reverse()) dispose();\n}\n\n// An `<a>` we intercept for soft navigation: same-origin, same tab, not a download,\n// and not explicitly opted out with `data-native` (which forces a full browser navigation).\nfunction isRouterLink(link: HTMLAnchorElement): boolean {\n return (\n !!link.href &&\n (!link.target || link.target === '_self') &&\n link.origin === location.origin &&\n !link.hasAttribute('download') &&\n !link.hasAttribute('data-native')\n );\n}\n\n/**\n * Upgrades the app's anchors: a plain left-click becomes a soft navigation.\n *\n * Kept apart from `listenNavigation` because the two share no state — a click here only calls\n * `history.pushState`, which is where that function picks the navigation up.\n */\nfunction listenLinks(): () => void {\n const undo: Array<() => void> = [];\n\n function onClick(e: MouseEvent) {\n const link = (e.target as Element).closest('a');\n if (\n link &&\n link instanceof HTMLAnchorElement &&\n isRouterLink(link) &&\n e.button === 0 &&\n !e.metaKey &&\n !e.ctrlKey &&\n !e.altKey &&\n !e.shiftKey &&\n !e.defaultPrevented\n ) {\n if (link.hash && link.pathname === location.pathname && link.search === location.search) return;\n e.preventDefault();\n history.pushState(null, '', link.href);\n }\n }\n document.addEventListener('click', onClick);\n undo.push(() => document.removeEventListener('click', onClick));\n\n return () => disposeAll(undo);\n}\n\n/**\n * The element the current `#fragment` names, if it is on the page.\n *\n * A fragment is percent-encoded and an `id` attribute is not, so it has to be decoded first. A\n * hand-written URL can carry a `%` that is not an escape, which throws — take the fragment literally\n * then, since that is the closest thing to an id it could have meant.\n */\nfunction fragmentTarget(): HTMLElement | null {\n const fragment = location.hash.slice(1);\n if (!fragment) return null;\n let id = fragment;\n try {\n id = decodeURIComponent(fragment);\n } catch {}\n return document.getElementById(id);\n}\n\nfunction listenNavigation(onNavigation: (afterRender: () => void) => void): () => void {\n const undo: Array<() => void> = [];\n\n // Scroll restoration is the browser's. `auto` is set explicitly rather than left at the default,\n // because it is a statement: the browser remembers a traversal's offset for us, and nothing here\n // tracks one.\n const prevRestoration = window.history.scrollRestoration;\n try {\n window.history.scrollRestoration = 'auto';\n } catch {}\n undo.push(() => {\n try {\n window.history.scrollRestoration = prevRestoration;\n } catch {}\n });\n\n /**\n * A push is not a real navigation to the browser, so nothing resets the scroll offset — without\n * this a click through to a new page lands wherever the last one was scrolled to. A `#hash` names\n * where to land instead, and one naming nothing on the page falls back to the top, as a browser\n * does. `replace` keeps its position deliberately, and a traversal is the browser's to restore.\n *\n * `scrollIntoView` rather than `scrollTo`, because it is the algorithm a browser's own fragment jump\n * uses — so `scroll-padding-top` still applies. Neither call passes a `behavior`, leaving\n * `scroll-behavior: smooth` the app's to ask for.\n *\n * The caller decides *when* this runs; for a navigation that fetched a payload it has to be after\n * the commit — see the layout effect in `BrowserRoot`.\n */\n const afterRenderFor = (type: NavigationType) => () => {\n if (type !== 'push') return;\n const target = fragmentTarget();\n if (target) target.scrollIntoView();\n else window.scrollTo(0, 0);\n };\n\n const documentUrl = () => location.pathname + location.search;\n\n // What the payload on screen was rendered for. Only the document part: the server never sees the\n // fragment, so two URLs differing by one render identically.\n let renderedUrl = documentUrl();\n\n /**\n * A navigation that moves only the fragment — `#a` → `#b`, or back out of a same-page anchor —\n * leaves the document unchanged, so the payload already on screen is the right one. Fetching\n * another would be a wasted round-trip that re-renders the page out from under the jump.\n *\n * `router.refresh()` is unaffected: it drives the re-fetch directly rather than through here, and\n * remains the way to ask for fresh data at an unchanged URL.\n */\n const notify = (type: NavigationType) => {\n const afterRender = afterRenderFor(type);\n if (documentUrl() === renderedUrl) {\n afterRender();\n return;\n }\n renderedUrl = documentUrl();\n onNavigation(afterRender);\n };\n\n const onPopState = () => notify('pop');\n window.addEventListener('popstate', onPopState);\n undo.push(() => window.removeEventListener('popstate', onPopState));\n\n const oldPushState = window.history.pushState;\n window.history.pushState = function (state, unused, url) {\n const res = oldPushState.call(this, state, unused, url as string);\n notify('push');\n return res;\n };\n undo.push(() => {\n window.history.pushState = oldPushState;\n });\n\n const oldReplaceState = window.history.replaceState;\n window.history.replaceState = function (state, unused, url) {\n const res = oldReplaceState.call(this, state, unused, url as string);\n notify('replace');\n return res;\n };\n undo.push(() => {\n window.history.replaceState = oldReplaceState;\n });\n\n return () => disposeAll(undo);\n}\n\n/**\n * Dev-only refresh client (stripped from prod bundles: the whole call is\n * guarded by import.meta.webpackHot). Listens to the CLI's SSE endpoint:\n *\n * client-built → hot-apply the waiting updates (react-refresh keeps\n * component state); any failure falls back to reload.\n * rsc-update → server component code changed: re-fetch the flight\n * payload for the current URL, state preserved.\n * hello → sent on (re)connect with the latest build hash; a\n * mismatch means events were missed — resync.\n */\nfunction initDevRefresh(fetchRscPayload: () => Promise<void>) {\n let connectedOnce = false;\n\n async function applyClientUpdate(hash: string) {\n const hot = import.meta.webpackHot!;\n if (hash === __webpack_hash__) return;\n if (hot.status() !== 'idle') {\n window.location.reload();\n return;\n }\n try {\n await hot.check(true);\n if (hash !== __webpack_hash__) await applyClientUpdate(hash);\n } catch (error) {\n console.warn('[rshono] hot update failed, reloading:', error);\n window.location.reload();\n }\n }\n\n const source = new EventSource('/_rshono/hmr');\n source.onmessage = async (event) => {\n const message = JSON.parse(event.data) as DevMessage;\n switch (message.type) {\n case 'hello':\n if (connectedOnce) {\n if (message.hash && message.hash !== __webpack_hash__) await applyClientUpdate(message.hash);\n await fetchRscPayload().catch(() => window.location.reload());\n }\n connectedOnce = true;\n break;\n case 'client-built':\n if (message.hash) await applyClientUpdate(message.hash);\n break;\n case 'rsc-update':\n console.log('[rshono] server components updated');\n await fetchRscPayload().catch(() => window.location.reload());\n break;\n }\n };\n}\n\n// Bootstrap failures (a truncated or malformed initial flight payload, most likely) would otherwise\n// be an unhandled rejection: nothing hydrates, nothing is reported, and the page just sits there.\nmain().catch((error) => {\n console.error('[rshono] the client runtime failed to start:', error);\n showFatal(error);\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry.rsc.d.ts","sourceRoot":"","sources":["../../src/runtime/entry.rsc.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"entry.rsc.d.ts","sourceRoot":"","sources":["../../src/runtime/entry.rsc.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAO5B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAwBvD,OAAO,EAA0F,KAAK,KAAK,EAAoB,MAAM,cAAc,CAAC;AAgCpJ,eAAO,MAAM,MAAM,EAAE,SAAS,KAAK,EAAuB,CAAC;AAE3D,0HAA0H;AAC1H,MAAM,MAAM,YAAY,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC;AAExF,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC;IACtB,WAAW,CAAC,EAAE,YAAY,CAAC;IAC3B,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAqbF,eAAO,MAAM,GAAG,4EAAa,CAAC;AAE9B;;;;;;;GAOG"}
|