@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.
Files changed (143) hide show
  1. package/README.md +202 -159
  2. package/dist/builder/page-files.d.ts.map +1 -1
  3. package/dist/builder/page-files.js +7 -3
  4. package/dist/builder/page-files.js.map +1 -1
  5. package/dist/builder/public-env.d.ts +6 -0
  6. package/dist/builder/public-env.d.ts.map +1 -1
  7. package/dist/builder/public-env.js +6 -0
  8. package/dist/builder/public-env.js.map +1 -1
  9. package/dist/builder/rspack-config.d.ts +3 -3
  10. package/dist/builder/rspack-config.d.ts.map +1 -1
  11. package/dist/builder/rspack-config.js +62 -16
  12. package/dist/builder/rspack-config.js.map +1 -1
  13. package/dist/cli/build.d.ts +2 -2
  14. package/dist/cli/build.js.map +1 -1
  15. package/dist/cli/dev.d.ts +2 -2
  16. package/dist/cli/dev.d.ts.map +1 -1
  17. package/dist/cli/dev.js +63 -35
  18. package/dist/cli/dev.js.map +1 -1
  19. package/dist/cli/index.js +10 -10
  20. package/dist/cli/index.js.map +1 -1
  21. package/dist/config.d.ts +58 -70
  22. package/dist/config.d.ts.map +1 -1
  23. package/dist/config.js +17 -1
  24. package/dist/config.js.map +1 -1
  25. package/dist/deploy/cloudflare/build.js +1 -1
  26. package/dist/deploy/cloudflare/build.js.map +1 -1
  27. package/dist/deploy/cloudflare/runtime.d.ts.map +1 -1
  28. package/dist/deploy/cloudflare/runtime.js +7 -37
  29. package/dist/deploy/cloudflare/runtime.js.map +1 -1
  30. package/dist/deploy/contract.d.ts +22 -16
  31. package/dist/deploy/contract.d.ts.map +1 -1
  32. package/dist/deploy/contract.js.map +1 -1
  33. package/dist/deploy/filesystem.d.ts +1 -1
  34. package/dist/deploy/filesystem.d.ts.map +1 -1
  35. package/dist/deploy/filesystem.js +7 -10
  36. package/dist/deploy/filesystem.js.map +1 -1
  37. package/dist/deploy/node/runtime.d.ts +4 -0
  38. package/dist/deploy/node/runtime.d.ts.map +1 -1
  39. package/dist/deploy/node/runtime.js +24 -3
  40. package/dist/deploy/node/runtime.js.map +1 -1
  41. package/dist/deploy/presets.d.ts +3 -3
  42. package/dist/deploy/presets.d.ts.map +1 -1
  43. package/dist/deploy/presets.js +13 -30
  44. package/dist/deploy/presets.js.map +1 -1
  45. package/dist/deploy/vercel/runtime.d.ts.map +1 -1
  46. package/dist/deploy/vercel/runtime.js +0 -3
  47. package/dist/deploy/vercel/runtime.js.map +1 -1
  48. package/dist/index.d.ts +6 -9
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +8 -3
  51. package/dist/index.js.map +1 -1
  52. package/dist/router.d.ts +85 -48
  53. package/dist/router.d.ts.map +1 -1
  54. package/dist/router.js +4 -6
  55. package/dist/router.js.map +1 -1
  56. package/dist/runtime/boundaries.d.ts +39 -25
  57. package/dist/runtime/boundaries.d.ts.map +1 -1
  58. package/dist/runtime/boundaries.js +22 -17
  59. package/dist/runtime/boundaries.js.map +1 -1
  60. package/dist/runtime/client.d.ts +9 -8
  61. package/dist/runtime/client.d.ts.map +1 -1
  62. package/dist/runtime/client.js +9 -8
  63. package/dist/runtime/client.js.map +1 -1
  64. package/dist/runtime/context.d.ts +216 -70
  65. package/dist/runtime/context.d.ts.map +1 -1
  66. package/dist/runtime/context.js +299 -93
  67. package/dist/runtime/context.js.map +1 -1
  68. package/dist/runtime/control.d.ts.map +1 -1
  69. package/dist/runtime/control.js +7 -0
  70. package/dist/runtime/control.js.map +1 -1
  71. package/dist/runtime/dev-protocol.d.ts.map +1 -1
  72. package/dist/runtime/dev-protocol.js.map +1 -1
  73. package/dist/runtime/entry.client.d.ts +4 -0
  74. package/dist/runtime/entry.client.d.ts.map +1 -1
  75. package/dist/runtime/entry.client.js +190 -154
  76. package/dist/runtime/entry.client.js.map +1 -1
  77. package/dist/runtime/entry.rsc.d.ts.map +1 -1
  78. package/dist/runtime/entry.rsc.js +145 -159
  79. package/dist/runtime/entry.rsc.js.map +1 -1
  80. package/dist/runtime/entry.ssr.d.ts +9 -1
  81. package/dist/runtime/entry.ssr.d.ts.map +1 -1
  82. package/dist/runtime/entry.ssr.js +36 -18
  83. package/dist/runtime/entry.ssr.js.map +1 -1
  84. package/dist/runtime/flight-inject.d.ts +31 -0
  85. package/dist/runtime/flight-inject.d.ts.map +1 -0
  86. package/dist/runtime/flight-inject.js +221 -0
  87. package/dist/runtime/flight-inject.js.map +1 -0
  88. package/dist/runtime/navigation.d.ts +20 -38
  89. package/dist/runtime/navigation.d.ts.map +1 -1
  90. package/dist/runtime/navigation.js +10 -53
  91. package/dist/runtime/navigation.js.map +1 -1
  92. package/dist/runtime/request.d.ts +6 -0
  93. package/dist/runtime/request.d.ts.map +1 -1
  94. package/dist/runtime/request.js +8 -0
  95. package/dist/runtime/request.js.map +1 -1
  96. package/dist/runtime/server.d.ts +7 -12
  97. package/dist/runtime/server.d.ts.map +1 -1
  98. package/dist/runtime/server.js +15 -12
  99. package/dist/runtime/server.js.map +1 -1
  100. package/dist/server/headers.d.ts +9 -9
  101. package/dist/server/headers.js +9 -9
  102. package/dist/server/headers.js.map +1 -1
  103. package/dist/server/load-config.d.ts +2 -2
  104. package/dist/server/load-config.d.ts.map +1 -1
  105. package/dist/server/load-config.js +22 -11
  106. package/dist/server/load-config.js.map +1 -1
  107. package/dist/server/prerendered.d.ts +43 -15
  108. package/dist/server/prerendered.d.ts.map +1 -1
  109. package/dist/server/prerendered.js +47 -0
  110. package/dist/server/prerendered.js.map +1 -1
  111. package/dist/server/server-config.d.ts +13 -39
  112. package/dist/server/server-config.d.ts.map +1 -1
  113. package/dist/server/server-config.js +5 -74
  114. package/dist/server/server-config.js.map +1 -1
  115. package/dist/server/ssg.d.ts +2 -2
  116. package/dist/server/ssg.d.ts.map +1 -1
  117. package/dist/server/ssg.js +21 -34
  118. package/dist/server/ssg.js.map +1 -1
  119. package/package.json +13 -16
  120. package/dist/deploy/bun/runtime.d.ts +0 -11
  121. package/dist/deploy/bun/runtime.d.ts.map +0 -1
  122. package/dist/deploy/bun/runtime.js +0 -22
  123. package/dist/deploy/bun/runtime.js.map +0 -1
  124. package/dist/deploy/deno/runtime.d.ts +0 -11
  125. package/dist/deploy/deno/runtime.d.ts.map +0 -1
  126. package/dist/deploy/deno/runtime.js +0 -16
  127. package/dist/deploy/deno/runtime.js.map +0 -1
  128. package/dist/deploy/listen.d.ts +0 -20
  129. package/dist/deploy/listen.d.ts.map +0 -1
  130. package/dist/deploy/listen.js +0 -24
  131. package/dist/deploy/listen.js.map +0 -1
  132. package/dist/deploy/netlify/build.d.ts +0 -8
  133. package/dist/deploy/netlify/build.d.ts.map +0 -1
  134. package/dist/deploy/netlify/build.js +0 -52
  135. package/dist/deploy/netlify/build.js.map +0 -1
  136. package/dist/deploy/netlify/runtime.d.ts +0 -13
  137. package/dist/deploy/netlify/runtime.d.ts.map +0 -1
  138. package/dist/deploy/netlify/runtime.js +0 -24
  139. package/dist/deploy/netlify/runtime.js.map +0 -1
  140. package/dist/server/compress.d.ts +0 -15
  141. package/dist/server/compress.d.ts.map +0 -1
  142. package/dist/server/compress.js +0 -76
  143. 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
- // In-memory flight-payload cache keyed by same-origin path+search. `data-prefetch`
72
- // links warm it on hover/focus; a navigation to a warmed URL resolves instantly and
73
- // clears the entry (a prefetch is used at most once, so re-visits always re-fetch).
74
- const payloadCache = new Map();
75
- // Bounded so a long session over a link-dense app can't grow it without limit. Insertion-ordered,
76
- // so the first key is the least recently warmed.
77
- const MAX_WARMED_PAYLOADS = 8;
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(rscStream);
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
- const back = () => window.history.back();
145
- const forward = () => window.history.forward();
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(true);
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(force = false) {
173
+ async function fetchRscPayload() {
181
174
  let payload;
182
175
  try {
183
- payload = await (force ? requestPayload(window.location.href) : takePayload(window.location.href));
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
- React.useEffect(() => listenNavigation((restoreScroll) => startNav(async () => {
202
- try {
203
- await fetchRscPayload();
204
- restoreScroll();
205
- }
206
- catch {
207
- window.location.reload();
208
- }
209
- }), warmPayload), []);
210
- const router = React.useMemo(() => ({ push, replace, back, forward, refresh, pending }), [pending]);
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 can only reach us through
244
- // React: it rides the flight payload as an error at that component's position, and boundaries
245
- // re-throw it (see boundaries.tsx) so it lands here rather than rendering an error fallback.
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
- // Anything that isn't a control signal falls back to what React would have done on its own —
248
- // console for a caught error, `reportError` (i.e. window.onerror, so error-reporting tools still
249
- // see it) for an uncaught one. Overriding these hooks means opting out of that default, so it has
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
- // Server code may have changed, so drop any warmed payloads and re-fetch fresh.
271
- initDevRefresh(() => {
272
- payloadCache.clear();
273
- return fetchRscPayload(true);
274
- });
280
+ initDevRefresh(fetchRscPayload);
275
281
  }
276
282
  }
277
- /** Hover/focus dwell time before a `data-prefetch` link warms its payload. */
278
- const PREFETCH_DELAY_MS = 120;
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
- function listenNavigation(onNavigation, prefetch) {
289
- // Scroll restoration. We tag each history entry with a stable numeric key in its
290
- // `history.state` and remember scrollY per key, so back/forward restores the exact
291
- // position while push scrolls to the top. `manual` hands restoration to us.
292
- const scrollByKey = new Map();
293
- let seq = 0;
294
- const prevRestoration = window.history.scrollRestoration;
295
- try {
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
- // A prefetch is a full server render, so it waits out a short dwell time on one shared timer:
362
- // sweeping the cursor across a list of prefetch links costs one request (for the link the pointer
363
- // settled on), not one per link.
364
- let prefetchTimer;
365
- function onPrefetch(e) {
366
- const target = e.target;
367
- if (!(target instanceof Element))
368
- return;
369
- const link = target.closest('a[data-prefetch]');
370
- if (!(link instanceof HTMLAnchorElement) || !isRouterLink(link))
371
- return;
372
- const { href } = link;
373
- clearTimeout(prefetchTimer);
374
- prefetchTimer = setTimeout(() => prefetch(href), PREFETCH_DELAY_MS);
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
- document.addEventListener('pointerover', onPrefetch);
377
- document.addEventListener('focusin', onPrefetch);
378
- return () => {
379
- clearTimeout(prefetchTimer);
380
- document.removeEventListener('click', onClick);
381
- document.removeEventListener('pointerover', onPrefetch);
382
- document.removeEventListener('focusin', onPrefetch);
383
- window.removeEventListener('popstate', onPopState);
384
- window.removeEventListener('scroll', onScroll);
385
- window.history.pushState = oldPushState;
386
- window.history.replaceState = oldReplaceState;
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;AAG5B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAwBvD,OAAO,EAAsF,KAAK,KAAK,EAAoB,MAAM,cAAc,CAAC;AAyChJ,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;AAycF,eAAO,MAAM,GAAG,4EAAa,CAAC;AAE9B;;;;;;;GAOG"}
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"}