@rshono/core 1.0.0-rc.11 → 1.0.0-rc.13

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 (145) hide show
  1. package/README.md +2 -1
  2. package/bin/rshono.mjs +3 -4
  3. package/dist/builder/env-shadow-loader.cjs +5 -5
  4. package/dist/builder/page-files.js +5 -5
  5. package/dist/builder/page-files.js.map +1 -1
  6. package/dist/builder/public-env.d.ts +5 -4
  7. package/dist/builder/public-env.d.ts.map +1 -1
  8. package/dist/builder/public-env.js +5 -4
  9. package/dist/builder/public-env.js.map +1 -1
  10. package/dist/builder/rspack-config.d.ts +10 -0
  11. package/dist/builder/rspack-config.d.ts.map +1 -1
  12. package/dist/builder/rspack-config.js +38 -40
  13. package/dist/builder/rspack-config.js.map +1 -1
  14. package/dist/cli/build.js +4 -4
  15. package/dist/cli/build.js.map +1 -1
  16. package/dist/cli/dev.d.ts.map +1 -1
  17. package/dist/cli/dev.js +50 -37
  18. package/dist/cli/dev.js.map +1 -1
  19. package/dist/cli/index.js +4 -4
  20. package/dist/cli/index.js.map +1 -1
  21. package/dist/cli/start.d.ts.map +1 -1
  22. package/dist/cli/start.js +2 -3
  23. package/dist/cli/start.js.map +1 -1
  24. package/dist/config.d.ts +28 -31
  25. package/dist/config.d.ts.map +1 -1
  26. package/dist/config.js +2 -2
  27. package/dist/config.js.map +1 -1
  28. package/dist/deploy/aws-lambda/runtime.d.ts +4 -6
  29. package/dist/deploy/aws-lambda/runtime.d.ts.map +1 -1
  30. package/dist/deploy/aws-lambda/runtime.js +5 -8
  31. package/dist/deploy/aws-lambda/runtime.js.map +1 -1
  32. package/dist/deploy/build-marker.d.ts +3 -5
  33. package/dist/deploy/build-marker.d.ts.map +1 -1
  34. package/dist/deploy/build-marker.js +3 -5
  35. package/dist/deploy/build-marker.js.map +1 -1
  36. package/dist/deploy/cloudflare/build.d.ts.map +1 -1
  37. package/dist/deploy/cloudflare/build.js +6 -10
  38. package/dist/deploy/cloudflare/build.js.map +1 -1
  39. package/dist/deploy/cloudflare/runtime.d.ts +2 -5
  40. package/dist/deploy/cloudflare/runtime.d.ts.map +1 -1
  41. package/dist/deploy/cloudflare/runtime.js +19 -32
  42. package/dist/deploy/cloudflare/runtime.js.map +1 -1
  43. package/dist/deploy/contract.d.ts +25 -42
  44. package/dist/deploy/contract.d.ts.map +1 -1
  45. package/dist/deploy/contract.js.map +1 -1
  46. package/dist/deploy/filesystem.d.ts +3 -5
  47. package/dist/deploy/filesystem.d.ts.map +1 -1
  48. package/dist/deploy/filesystem.js +12 -15
  49. package/dist/deploy/filesystem.js.map +1 -1
  50. package/dist/deploy/node/runtime.d.ts +4 -5
  51. package/dist/deploy/node/runtime.d.ts.map +1 -1
  52. package/dist/deploy/node/runtime.js +9 -15
  53. package/dist/deploy/node/runtime.js.map +1 -1
  54. package/dist/deploy/presets.d.ts +19 -29
  55. package/dist/deploy/presets.d.ts.map +1 -1
  56. package/dist/deploy/presets.js +18 -25
  57. package/dist/deploy/presets.js.map +1 -1
  58. package/dist/deploy/vercel/build.d.ts.map +1 -1
  59. package/dist/deploy/vercel/build.js +9 -12
  60. package/dist/deploy/vercel/build.js.map +1 -1
  61. package/dist/deploy/vercel/runtime.d.ts +4 -7
  62. package/dist/deploy/vercel/runtime.d.ts.map +1 -1
  63. package/dist/deploy/vercel/runtime.js +4 -7
  64. package/dist/deploy/vercel/runtime.js.map +1 -1
  65. package/dist/index.d.ts +13 -9
  66. package/dist/index.d.ts.map +1 -1
  67. package/dist/index.js +15 -12
  68. package/dist/index.js.map +1 -1
  69. package/dist/router.d.ts +65 -93
  70. package/dist/router.d.ts.map +1 -1
  71. package/dist/router.js +2 -5
  72. package/dist/router.js.map +1 -1
  73. package/dist/runtime/boundaries.d.ts +24 -30
  74. package/dist/runtime/boundaries.d.ts.map +1 -1
  75. package/dist/runtime/boundaries.js +15 -22
  76. package/dist/runtime/boundaries.js.map +1 -1
  77. package/dist/runtime/client.d.ts +16 -7
  78. package/dist/runtime/client.d.ts.map +1 -1
  79. package/dist/runtime/client.js +16 -7
  80. package/dist/runtime/client.js.map +1 -1
  81. package/dist/runtime/context.d.ts +89 -118
  82. package/dist/runtime/context.d.ts.map +1 -1
  83. package/dist/runtime/context.js +107 -167
  84. package/dist/runtime/context.js.map +1 -1
  85. package/dist/runtime/control.js +3 -3
  86. package/dist/runtime/control.js.map +1 -1
  87. package/dist/runtime/dev-protocol.d.ts +4 -8
  88. package/dist/runtime/dev-protocol.d.ts.map +1 -1
  89. package/dist/runtime/dev-protocol.js.map +1 -1
  90. package/dist/runtime/entry.client.d.ts.map +1 -1
  91. package/dist/runtime/entry.client.js +92 -120
  92. package/dist/runtime/entry.client.js.map +1 -1
  93. package/dist/runtime/entry.rsc.d.ts +5 -6
  94. package/dist/runtime/entry.rsc.d.ts.map +1 -1
  95. package/dist/runtime/entry.rsc.js +67 -122
  96. package/dist/runtime/entry.rsc.js.map +1 -1
  97. package/dist/runtime/entry.ssr.d.ts +7 -12
  98. package/dist/runtime/entry.ssr.d.ts.map +1 -1
  99. package/dist/runtime/entry.ssr.js +13 -24
  100. package/dist/runtime/entry.ssr.js.map +1 -1
  101. package/dist/runtime/flight-inject.d.ts +10 -17
  102. package/dist/runtime/flight-inject.d.ts.map +1 -1
  103. package/dist/runtime/flight-inject.js +35 -53
  104. package/dist/runtime/flight-inject.js.map +1 -1
  105. package/dist/runtime/hot-update.d.ts +45 -0
  106. package/dist/runtime/hot-update.d.ts.map +1 -0
  107. package/dist/runtime/hot-update.js +44 -0
  108. package/dist/runtime/hot-update.js.map +1 -0
  109. package/dist/runtime/navigation.d.ts +14 -19
  110. package/dist/runtime/navigation.d.ts.map +1 -1
  111. package/dist/runtime/navigation.js +9 -13
  112. package/dist/runtime/navigation.js.map +1 -1
  113. package/dist/runtime/request.d.ts +4 -6
  114. package/dist/runtime/request.d.ts.map +1 -1
  115. package/dist/runtime/request.js +2 -3
  116. package/dist/runtime/request.js.map +1 -1
  117. package/dist/runtime/server.d.ts +18 -10
  118. package/dist/runtime/server.d.ts.map +1 -1
  119. package/dist/runtime/server.js +21 -19
  120. package/dist/runtime/server.js.map +1 -1
  121. package/dist/server/headers.d.ts +8 -15
  122. package/dist/server/headers.d.ts.map +1 -1
  123. package/dist/server/headers.js +8 -15
  124. package/dist/server/headers.js.map +1 -1
  125. package/dist/server/load-config.d.ts +2 -2
  126. package/dist/server/load-config.d.ts.map +1 -1
  127. package/dist/server/load-config.js +6 -9
  128. package/dist/server/load-config.js.map +1 -1
  129. package/dist/server/prerendered.d.ts +30 -43
  130. package/dist/server/prerendered.d.ts.map +1 -1
  131. package/dist/server/prerendered.js +20 -29
  132. package/dist/server/prerendered.js.map +1 -1
  133. package/dist/server/server-config.d.ts +18 -25
  134. package/dist/server/server-config.d.ts.map +1 -1
  135. package/dist/server/server-config.js +7 -11
  136. package/dist/server/server-config.js.map +1 -1
  137. package/dist/server/shutdown.d.ts +2 -3
  138. package/dist/server/shutdown.d.ts.map +1 -1
  139. package/dist/server/shutdown.js +2 -3
  140. package/dist/server/shutdown.js.map +1 -1
  141. package/dist/server/ssg.d.ts +3 -6
  142. package/dist/server/ssg.d.ts.map +1 -1
  143. package/dist/server/ssg.js +11 -20
  144. package/dist/server/ssg.js.map +1 -1
  145. package/package.json +1 -1
@@ -3,10 +3,13 @@ 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
5
  import { isControlDigest, parseRedirectDigest } from './control.js';
6
+ // Dev-only: its one caller sits behind `import.meta.webpackHot`, which a production build compiles to
7
+ // `false` — so this module is dropped there.
8
+ import { walkHotUpdates } from './hot-update.js';
6
9
  import { RouterContext } from './navigation.js';
7
10
  import { createRscRequest } from './request.js';
8
11
  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. */
12
+ /** The flight payload the document carried, read back out of `__FLIGHT_DATA` — see `flight-inject.ts`. */
10
13
  function readFlightPayload() {
11
14
  const encoder = new TextEncoder();
12
15
  // Assigned synchronously by `start`, which `new ReadableStream` runs before it returns.
@@ -15,14 +18,13 @@ function readFlightPayload() {
15
18
  start: (c) => void (controller = c),
16
19
  });
17
20
  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`.
21
+ // Payload scripts interleave with the document: the ones that already ran are in the array, the rest
22
+ // arrive through `push`.
20
23
  const data = (self.__FLIGHT_DATA ??= []);
21
24
  for (const chunk of data)
22
25
  enqueue(chunk);
23
26
  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.
27
+ // The last payload script lands before parsing finishes, so that is what closes the stream.
26
28
  if (document.readyState === 'loading') {
27
29
  document.addEventListener('DOMContentLoaded', () => controller.close(), { once: true });
28
30
  }
@@ -33,10 +35,7 @@ function readFlightPayload() {
33
35
  }
34
36
  /** Created at module evaluation, not inside `main()`, so no chunk can be pushed before it is watching. */
35
37
  const flightStream = readFlightPayload();
36
- /**
37
- * Guarantees somewhere to attach the fatal overlay. React's root container is the whole `document`,
38
- * so by the time an uncaught error has torn the tree down, `<body>` — or even `<html>` — may be gone.
39
- */
38
+ /** Guarantees somewhere to attach the fatal overlay: the root container is `document`, so a teardown can take `<body>` with it. */
40
39
  function overlayHost() {
41
40
  if (!document.documentElement)
42
41
  document.appendChild(document.createElement('html'));
@@ -45,25 +44,20 @@ function overlayHost() {
45
44
  return document.body;
46
45
  }
47
46
  /**
48
- * Replaces the white screen of death with something readable.
47
+ * Paints the reason for an uncaught render error over the blank page it leaves behind — the full stack in
48
+ * dev, a generic notice and a reload button in production.
49
49
  *
50
- * Because the root container is `document`, an uncaught render error leaves a genuinely blank page
51
- * with the reason only in the console — so this paints the reason over it instead. In development
52
- * that's the full stack; in production it's a generic notice plus a reload button, since the tree is
53
- * unrecoverable and reloading is the only way forward.
54
- *
55
- * Written with DOM calls rather than React (the renderer is what just failed) and `textContent`
56
- * rather than `innerHTML` (an error message is untrusted input).
50
+ * DOM calls rather than React (the renderer is what just failed), and `textContent` rather than
51
+ * `innerHTML` (an error message is untrusted input).
57
52
  */
58
53
  function showFatal(error, componentStack) {
59
- // Queued rather than run inline: React's teardown happens after this callback returns, and would
60
- // remove a node appended synchronously along with the rest of the tree.
54
+ // Queued: React's teardown runs after this callback returns and would remove a node appended inline.
61
55
  setTimeout(() => {
62
56
  const host = overlayHost();
63
57
  host.querySelector('[data-rshono-fatal]')?.remove();
64
58
  const box = document.createElement('div');
65
59
  box.setAttribute('data-rshono-fatal', '');
66
- box.setAttribute('role', 'alert'); // the page is gone; announce it rather than leaving silence
60
+ box.setAttribute('role', 'alert');
67
61
  box.style.cssText =
68
62
  'position:fixed;inset:0;z-index:2147483647;overflow:auto;padding:1.5rem;background:#18181b;color:#f4f4f5;' +
69
63
  'font:14px/1.6 ui-monospace,SFMono-Regular,Menlo,monospace;text-align:left';
@@ -95,22 +89,22 @@ function showFatal(error, componentStack) {
95
89
  }, 0);
96
90
  }
97
91
  /**
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.
92
+ * Asks a URL for its flight payload. Deliberately uncached — a payload can never be staler than the click
93
+ * that wanted it, and the browser's own HTTP cache is what makes a repeat visit cheap.
103
94
  */
104
95
  function requestPayload(href) {
105
96
  return createFromFetch(fetch(createRscRequest(new URL(href, location.href).href)));
106
97
  }
107
98
  async function main() {
99
+ // The assertion is load-bearing under the compiler that builds this: TypeScript 7 declares `nonce` on
100
+ // HTMLElement, 6 declares it on Element. ESLint runs the older lib — where the narrowing is redundant —
101
+ // so it reports an assertion that `tsc` requires. Believe `typecheck`, not the rule.
102
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
108
103
  const cspMeta = document.querySelector('meta[property="csp-nonce"]');
109
104
  if (cspMeta?.nonce)
110
105
  __webpack_nonce__ = cspMeta.nonce;
111
- // Both are replaced by BrowserRoot's own on mount. The defaults matter: `setServerCallback` is
112
- // registered before hydration, so an action or refresh firing in that window would otherwise call
113
- // an unassigned binding. Until there's a root to update, a full reload is the honest fallback.
106
+ // Both are replaced by BrowserRoot's own on mount. The defaults cover the window before hydration, where
107
+ // `setServerCallback` is already registered but there is no root to update — a reload is the honest answer.
114
108
  let setPayload = () => {
115
109
  window.location.reload();
116
110
  };
@@ -135,8 +129,7 @@ async function main() {
135
129
  }
136
130
  window.history.replaceState(null, '', target.href);
137
131
  }
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.
132
+ // A refresh keeps the URL, so it can't ride the history patch like push/replace and drives the re-fetch itself.
140
133
  const refresh = () => startNav(async () => {
141
134
  try {
142
135
  await fetchRscPayload();
@@ -147,12 +140,10 @@ async function main() {
147
140
  });
148
141
  /**
149
142
  * Turns a control-signal digest — how `redirect()` / `notFound()` reach the browser — into a real
150
- * navigation. Returns false for anything else, so callers can fall through to their own handling.
143
+ * navigation. Returns false for anything else, so callers fall through to their own handling.
151
144
  *
152
- * `hard` forces a full document load, for signals that surfaced *through React* (a nested
153
- * component's redirect, reported via the root error handlers). React unmounts the root on an
154
- * uncaught error, so there is no live tree left to soft-navigate with. A signal caught earlier —
155
- * a top-level payload rejection — still swaps the payload in place.
145
+ * `hard` forces a full document load, for signals that surfaced *through React*: it unmounts the root on
146
+ * an uncaught error, leaving no live tree to soft-navigate with.
156
147
  */
157
148
  function handleControlDigest(error, { hard = false } = {}) {
158
149
  const digest = error?.digest;
@@ -194,11 +185,8 @@ async function main() {
194
185
  startNav = (run) => startTransition(run);
195
186
  }, [startTransition]);
196
187
  /**
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.
188
+ * Scrolls where the navigation asked, once React has put its payload in the DOM — a `#hash` target does
189
+ * not exist until the new tree does. A layout effect, so the pre-scroll position is never painted.
202
190
  */
203
191
  React.useLayoutEffect(() => {
204
192
  const scroll = pendingScroll.current;
@@ -251,27 +239,23 @@ async function main() {
251
239
  throw result.error;
252
240
  return result.value;
253
241
  });
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.
242
+ // A `redirect()` / `notFound()` from a component below the page root reaches us through React: it rides the
243
+ // flight payload as an error, and boundaries re-throw it so it lands here rather than in a fallback.
257
244
  //
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.
245
+ // Installing these hooks opts out of React's own defaults, so everything that isn't a control signal has to
246
+ // be put back by hand — `reportError` rather than a bare log, so error-reporting tools still see it.
261
247
  hydrateRoot(document, _jsx(BrowserRoot, {}), {
262
248
  formState: initialPayload.formState,
263
249
  onCaughtError: (error, errorInfo) => {
264
250
  if (handleControlDigest(error, { hard: true }))
265
251
  return;
266
- // A boundary handled this and the tree is intact, so no overlay: whatever fallback the app
267
- // chose is the right thing to have on screen.
252
+ // A boundary handled it and the tree is intact, so no overlay over the app's own fallback.
268
253
  console.error(error, errorInfo.componentStack ?? '');
269
254
  },
270
255
  onUncaughtError: (error, errorInfo) => {
271
256
  if (handleControlDigest(error, { hard: true }))
272
257
  return;
273
- // Nothing caught it, so React tears the root down — and the root is `document`. This is the
274
- // white screen; paint the reason over it.
258
+ // Nothing caught it, so React tears the root down — and the root is `document`.
275
259
  globalThis.reportError(error);
276
260
  showFatal(error, errorInfo.componentStack);
277
261
  },
@@ -280,10 +264,7 @@ async function main() {
280
264
  initDevRefresh(fetchRscPayload);
281
265
  }
282
266
  }
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
- */
267
+ /** Runs teardown in reverse and empties the list, so a second call is a no-op. */
287
268
  function disposeAll(undo) {
288
269
  for (const dispose of undo.splice(0).reverse())
289
270
  dispose();
@@ -298,10 +279,8 @@ function isRouterLink(link) {
298
279
  !link.hasAttribute('data-native'));
299
280
  }
300
281
  /**
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.
282
+ * Upgrades the app's anchors: a plain left-click becomes a soft navigation. It shares no state with
283
+ * `listenNavigation` — a click only calls `history.pushState`, which is where that picks the navigation up.
305
284
  */
306
285
  function listenLinks() {
307
286
  const undo = [];
@@ -327,11 +306,8 @@ function listenLinks() {
327
306
  return () => disposeAll(undo);
328
307
  }
329
308
  /**
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.
309
+ * The element the current `#fragment` names, if it is on the page. A fragment is percent-encoded and an `id`
310
+ * is not, so it is decoded first — and taken literally when a hand-written `%` makes that throw.
335
311
  */
336
312
  function fragmentTarget() {
337
313
  const fragment = location.hash.slice(1);
@@ -341,37 +317,36 @@ function fragmentTarget() {
341
317
  try {
342
318
  id = decodeURIComponent(fragment);
343
319
  }
344
- catch { }
320
+ catch {
321
+ // Malformed escape — the literal fragment is the better guess at the id than nothing.
322
+ }
345
323
  return document.getElementById(id);
346
324
  }
347
325
  function listenNavigation(onNavigation) {
348
326
  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
327
+ // Set explicitly as a statement of intent: the browser remembers a traversal's offset, and nothing here
351
328
  // tracks one.
352
329
  const prevRestoration = window.history.scrollRestoration;
353
330
  try {
354
331
  window.history.scrollRestoration = 'auto';
355
332
  }
356
- catch { }
333
+ catch {
334
+ // Not settable in every browser, and only a preference — the navigation still works without it.
335
+ }
357
336
  undo.push(() => {
358
337
  try {
359
338
  window.history.scrollRestoration = prevRestoration;
360
339
  }
361
- catch { }
340
+ catch {
341
+ // As above: if it could not be set, it cannot be put back either.
342
+ }
362
343
  });
363
344
  /**
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.
345
+ * A push is not a real navigation to the browser, so nothing resets the scroll offset. A `#hash` names
346
+ * where to land instead; `replace` keeps its position, and a traversal is the browser's to restore.
368
347
  *
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`.
348
+ * `scrollIntoView` is the algorithm a browser's own fragment jump uses, so `scroll-padding-top` still
349
+ * applies. Neither call passes a `behavior`, leaving `scroll-behavior: smooth` the app's to ask for.
375
350
  */
376
351
  const afterRenderFor = (type) => () => {
377
352
  if (type !== 'push')
@@ -383,16 +358,12 @@ function listenNavigation(onNavigation) {
383
358
  window.scrollTo(0, 0);
384
359
  };
385
360
  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.
361
+ // What the payload on screen was rendered for. The document part only: the server never sees the fragment.
388
362
  let renderedUrl = documentUrl();
389
363
  /**
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.
364
+ * A navigation that moves only the fragment leaves the document unchanged, so the payload on screen is
365
+ * already the right one — fetching another would re-render the page out from under the jump.
366
+ * `router.refresh()` is unaffected, and remains the way to ask for fresh data at an unchanged URL.
396
367
  */
397
368
  const notify = (type) => {
398
369
  const afterRender = afterRenderFor(type);
@@ -406,6 +377,9 @@ function listenNavigation(onNavigation) {
406
377
  const onPopState = () => notify('pop');
407
378
  window.addEventListener('popstate', onPopState);
408
379
  undo.push(() => window.removeEventListener('popstate', onPopState));
380
+ // Saved unbound on purpose, and called back with `.call(this, …)` below — patching `history` is the only
381
+ // way to see a navigation the app makes itself, and the receiver is restored at every call site.
382
+ // eslint-disable-next-line @typescript-eslint/unbound-method
409
383
  const oldPushState = window.history.pushState;
410
384
  window.history.pushState = function (state, unused, url) {
411
385
  const res = oldPushState.call(this, state, unused, url);
@@ -415,6 +389,7 @@ function listenNavigation(onNavigation) {
415
389
  undo.push(() => {
416
390
  window.history.pushState = oldPushState;
417
391
  });
392
+ // eslint-disable-next-line @typescript-eslint/unbound-method -- as with `pushState` above.
418
393
  const oldReplaceState = window.history.replaceState;
419
394
  window.history.replaceState = function (state, unused, url) {
420
395
  const res = oldReplaceState.call(this, state, unused, url);
@@ -427,61 +402,58 @@ function listenNavigation(onNavigation) {
427
402
  return () => disposeAll(undo);
428
403
  }
429
404
  /**
430
- * Dev-only refresh client (stripped from prod bundles: the whole call is
431
- * guarded by import.meta.webpackHot). Listens to the CLI's SSE endpoint:
405
+ * Dev-only refresh client, listening to the CLI's SSE endpoint:
432
406
  *
433
- * client-built → hot-apply the waiting updates (react-refresh keeps
434
- * component state); any failure falls back to reload.
435
- * rsc-update → server component code changed: re-fetch the flight
436
- * payload for the current URL, state preserved.
437
- * hello → sent on (re)connect with the latest build hash; a
438
- * mismatch means events were missed — resync.
407
+ * client-built → hot-apply the waiting updates; anything the page can't be patched up to reloads.
408
+ * rsc-update → server component code changed: re-fetch the flight payload, state preserved.
409
+ * hello → sent on (re)connect with the latest build hash; a mismatch means a missed event.
439
410
  */
440
411
  function initDevRefresh(fetchRscPayload) {
412
+ const hot = import.meta.webpackHot;
441
413
  let connectedOnce = false;
442
- async function applyClientUpdate(hash) {
443
- const hot = import.meta.webpackHot;
444
- if (hash === __webpack_hash__)
445
- return;
446
- if (hot.status() !== 'idle') {
447
- window.location.reload();
448
- return;
449
- }
450
- try {
451
- await hot.check(true);
452
- if (hash !== __webpack_hash__)
453
- await applyClientUpdate(hash);
454
- }
455
- catch (error) {
456
- console.warn('[rshono] hot update failed, reloading:', error);
457
- window.location.reload();
458
- }
414
+ /** The newest build the dev server has announced — what {@link applyClientUpdate} walks towards. */
415
+ let targetHash;
416
+ function reload(reason, error) {
417
+ console.warn(`[rshono] ${reason} — reloading`, ...(error === undefined ? [] : [error]));
418
+ window.location.reload();
459
419
  }
460
- const source = new EventSource('/_rshono/hmr');
461
- source.onmessage = async (event) => {
462
- const message = JSON.parse(event.data);
420
+ async function applyClientUpdate() {
421
+ const giveUp = await walkHotUpdates(hot, () => __webpack_hash__, () => targetHash);
422
+ if (giveUp)
423
+ reload(giveUp.reason, giveUp.error);
424
+ }
425
+ async function handle(message) {
463
426
  switch (message.type) {
464
427
  case 'hello':
428
+ targetHash = message.hash ?? targetHash;
465
429
  if (connectedOnce) {
466
- if (message.hash && message.hash !== __webpack_hash__)
467
- await applyClientUpdate(message.hash);
430
+ await applyClientUpdate();
468
431
  await fetchRscPayload().catch(() => window.location.reload());
469
432
  }
470
433
  connectedOnce = true;
471
434
  break;
472
435
  case 'client-built':
473
- if (message.hash)
474
- await applyClientUpdate(message.hash);
436
+ targetHash = message.hash;
437
+ await applyClientUpdate();
475
438
  break;
476
439
  case 'rsc-update':
477
440
  console.log('[rshono] server components updated');
478
441
  await fetchRscPayload().catch(() => window.location.reload());
479
442
  break;
480
443
  }
444
+ }
445
+ const source = new EventSource('/_rshono/hmr');
446
+ // Chained rather than handled as they arrive: `hot.check` may only run from `idle`, and a burst of saves
447
+ // puts several frames on the wire inside the time one takes. Queueing drops nothing, because `targetHash`
448
+ // is shared — whichever handler runs next walks to the newest build.
449
+ let queue = Promise.resolve();
450
+ source.onmessage = (event) => {
451
+ const message = JSON.parse(event.data);
452
+ queue = queue.then(() => handle(message)).catch((error) => reload('the dev client failed', error));
481
453
  };
482
454
  }
483
- // Bootstrap failures (a truncated or malformed initial flight payload, most likely) would otherwise
484
- // be an unhandled rejection: nothing hydrates, nothing is reported, and the page just sits there.
455
+ // A bootstrap failure — a truncated initial payload, most likely — would otherwise be an unhandled
456
+ // rejection: nothing hydrates, nothing is reported, and the page just sits there.
485
457
  main().catch((error) => {
486
458
  console.error('[rshono] the client runtime failed to start:', error);
487
459
  showFatal(error);
@@ -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 { 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
+ {"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';\n// Dev-only: its one caller sits behind `import.meta.webpackHot`, which a production build compiles to\n// `false` — so this module is dropped there.\nimport { walkHotUpdates } from './hot-update.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`. */\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: the ones that already ran are in the array, the rest\n // arrive 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 parsing finishes, so that is what closes the stream.\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/** Guarantees somewhere to attach the fatal overlay: the root container is `document`, so a teardown can take `<body>` with it. */\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 * Paints the reason for an uncaught render error over the blank page it leaves behind — the full stack in\n * dev, a generic notice and a reload button in production.\n *\n * DOM calls rather than React (the renderer is what just failed), and `textContent` rather than\n * `innerHTML` (an error message is untrusted input).\n */\nfunction showFatal(error: unknown, componentStack?: string | null): void {\n // Queued: React's teardown runs after this callback returns and would remove a node appended inline.\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');\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. Deliberately uncached — a payload can never be staler than the click\n * that wanted it, and the browser's own HTTP cache is what makes a 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 // The assertion is load-bearing under the compiler that builds this: TypeScript 7 declares `nonce` on\n // HTMLElement, 6 declares it on Element. ESLint runs the older lib — where the narrowing is redundant —\n // so it reports an assertion that `tsc` requires. Believe `typecheck`, not the rule.\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion\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 cover the window before hydration, where\n // `setServerCallback` is already registered but there is no root to update — a reload is the honest answer.\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 and drives the re-fetch itself.\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 fall through to their own handling.\n *\n * `hard` forces a full document load, for signals that surfaced *through React*: it unmounts the root on\n * an uncaught error, leaving no live tree to soft-navigate with.\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 — a `#hash` target does\n * not exist until the new tree does. A layout effect, so the pre-scroll position is never painted.\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 rides the\n // flight payload as an error, and boundaries re-throw it so it lands here rather than in a fallback.\n //\n // Installing these hooks opts out of React's own defaults, so everything that isn't a control signal has to\n // be put back by hand — `reportError` rather than a bare log, so error-reporting tools still see it.\n hydrateRoot(document, <BrowserRoot />, {\n formState: initialPayload.formState,\n onCaughtError: (error, errorInfo) => {\n if (handleControlDigest(error, { hard: true })) return;\n // A boundary handled it and the tree is intact, so no overlay over the app's own fallback.\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`.\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/** Runs teardown in reverse and empties the list, so a second call is a no-op. */\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. It shares no state with\n * `listenNavigation` — a click only calls `history.pushState`, which is where that 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. A fragment is percent-encoded and an `id`\n * is not, so it is decoded first — and taken literally when a hand-written `%` makes that throw.\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 // Malformed escape — the literal fragment is the better guess at the id than nothing.\n }\n return document.getElementById(id);\n}\n\nfunction listenNavigation(onNavigation: (afterRender: () => void) => void): () => void {\n const undo: Array<() => void> = [];\n\n // Set explicitly as a statement of intent: the browser remembers a traversal's offset, and nothing here\n // tracks one.\n const prevRestoration = window.history.scrollRestoration;\n try {\n window.history.scrollRestoration = 'auto';\n } catch {\n // Not settable in every browser, and only a preference — the navigation still works without it.\n }\n undo.push(() => {\n try {\n window.history.scrollRestoration = prevRestoration;\n } catch {\n // As above: if it could not be set, it cannot be put back either.\n }\n });\n\n /**\n * A push is not a real navigation to the browser, so nothing resets the scroll offset. A `#hash` names\n * where to land instead; `replace` keeps its position, and a traversal is the browser's to restore.\n *\n * `scrollIntoView` is the algorithm a browser's own fragment jump uses, so `scroll-padding-top` still\n * applies. Neither call passes a `behavior`, leaving `scroll-behavior: smooth` the app's to ask for.\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. The document part only: the server never sees the fragment.\n let renderedUrl = documentUrl();\n\n /**\n * A navigation that moves only the fragment leaves the document unchanged, so the payload on screen is\n * already the right one — fetching another would re-render the page out from under the jump.\n * `router.refresh()` is unaffected, and 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 // Saved unbound on purpose, and called back with `.call(this, …)` below — patching `history` is the only\n // way to see a navigation the app makes itself, and the receiver is restored at every call site.\n // eslint-disable-next-line @typescript-eslint/unbound-method\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 // eslint-disable-next-line @typescript-eslint/unbound-method -- as with `pushState` above.\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, listening to the CLI's SSE endpoint:\n *\n * client-built → hot-apply the waiting updates; anything the page can't be patched up to reloads.\n * rsc-update → server component code changed: re-fetch the flight payload, state preserved.\n * hello → sent on (re)connect with the latest build hash; a mismatch means a missed event.\n */\nfunction initDevRefresh(fetchRscPayload: () => Promise<void>) {\n const hot = import.meta.webpackHot!;\n let connectedOnce = false;\n /** The newest build the dev server has announced — what {@link applyClientUpdate} walks towards. */\n let targetHash: string | undefined;\n\n function reload(reason: string, error?: unknown): void {\n console.warn(`[rshono] ${reason} — reloading`, ...(error === undefined ? [] : [error]));\n window.location.reload();\n }\n\n async function applyClientUpdate(): Promise<void> {\n const giveUp = await walkHotUpdates(\n hot,\n () => __webpack_hash__,\n () => targetHash,\n );\n if (giveUp) reload(giveUp.reason, giveUp.error);\n }\n\n async function handle(message: DevMessage): Promise<void> {\n switch (message.type) {\n case 'hello':\n targetHash = message.hash ?? targetHash;\n if (connectedOnce) {\n await applyClientUpdate();\n await fetchRscPayload().catch(() => window.location.reload());\n }\n connectedOnce = true;\n break;\n case 'client-built':\n targetHash = message.hash;\n await applyClientUpdate();\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 const source = new EventSource('/_rshono/hmr');\n // Chained rather than handled as they arrive: `hot.check` may only run from `idle`, and a burst of saves\n // puts several frames on the wire inside the time one takes. Queueing drops nothing, because `targetHash`\n // is shared — whichever handler runs next walks to the newest build.\n let queue: Promise<void> = Promise.resolve();\n source.onmessage = (event: MessageEvent<string>) => {\n const message = JSON.parse(event.data) as DevMessage;\n queue = queue.then(() => handle(message)).catch((error) => reload('the dev client failed', error));\n };\n}\n\n// A bootstrap failure — a truncated initial payload, most likely — would otherwise be an unhandled\n// 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"]}
@@ -3,7 +3,7 @@ import type React from 'react';
3
3
  import type { ReactFormState } from 'react-dom/client';
4
4
  import { type Route } from '../router.js';
5
5
  export declare const routes: readonly Route[];
6
- /** The result of a server action, as a discriminated union (a `Result<T, E>`) rather than an `ok` flag over one field. */
6
+ /** The result of a server action, as a `Result<T, E>` rather than an `ok` flag over one field. */
7
7
  export type ActionResult = {
8
8
  ok: true;
9
9
  value: unknown;
@@ -20,12 +20,11 @@ export type RscPayload = {
20
20
  };
21
21
  export declare const app: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
22
22
  /**
23
- * The app, handed to whatever is hosting it.
23
+ * The app, handed to whatever is hosting it: this binds a port and exports nothing where rshono owns the
24
+ * process, and *is* the export the platform looks for where the host owns it — so one entry serves both.
24
25
  *
25
- * On a platform where rshono owns the process this binds a port and the default export is nothing;
26
- * where the host owns it, this *is* the export the platform looks for — so the same entry serves
27
- * both without a per-platform entry file. `app` and `routes` stay named exports either way, because
28
- * `rshono build` imports them to prerender `render: 'static'` routes.
26
+ * `app` and `routes` stay named exports either way, because `rshono build` imports them to prerender
27
+ * `render: 'static'` routes.
29
28
  */
30
29
  declare const _default: unknown;
31
30
  export default _default;
@@ -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;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"}
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;AAK5B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAsBvD,OAAO,EAA0F,KAAK,KAAK,EAAoB,MAAM,cAAc,CAAC;AAwBpJ,eAAO,MAAM,MAAM,EAAE,SAAS,KAAK,EAAuB,CAAC;AAE3D,kGAAkG;AAClG,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;AAyYF,eAAO,MAAM,GAAG,4EAAa,CAAC;AAE9B;;;;;;GAMG"}