@tanstack/redact 0.0.21 → 0.1.1

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 (254) hide show
  1. package/dist/core/attributes.js +2 -1
  2. package/dist/core/attributes.js.map +2 -2
  3. package/dist/core/browser.d.ts +9 -0
  4. package/dist/core/browser.js +35 -0
  5. package/dist/core/browser.js.map +7 -0
  6. package/dist/core/index.d.ts +2 -2
  7. package/dist/core/index.js +3 -3
  8. package/dist/core/internal.d.ts +31 -8
  9. package/dist/core/internal.js +3 -1
  10. package/dist/core/internal.js.map +2 -2
  11. package/dist/core/resource-hints.d.ts +7 -0
  12. package/dist/core/resource-hints.js +19 -0
  13. package/dist/core/resource-hints.js.map +7 -0
  14. package/dist/core/types.js +1 -1
  15. package/dist/dom/_all.d.ts +11 -16
  16. package/dist/dom/_all.js +9 -20
  17. package/dist/dom/_all.js.map +2 -2
  18. package/dist/dom/client.d.ts +4 -4
  19. package/dist/dom/client.js +4 -4
  20. package/dist/dom/commit.d.ts +23 -0
  21. package/dist/dom/commit.js +191 -0
  22. package/dist/dom/commit.js.map +7 -0
  23. package/dist/dom/dispatcher.d.ts +4 -22
  24. package/dist/dom/dispatcher.js +184 -126
  25. package/dist/dom/dispatcher.js.map +3 -3
  26. package/dist/dom/dom.d.ts +2 -0
  27. package/dist/dom/dom.js +72 -52
  28. package/dist/dom/dom.js.map +2 -2
  29. package/dist/dom/error-info.d.ts +2 -0
  30. package/dist/dom/error-info.js +16 -0
  31. package/dist/dom/error-info.js.map +7 -0
  32. package/dist/dom/event-replay.js +1 -1
  33. package/dist/dom/features/activity/full.d.ts +1 -0
  34. package/dist/dom/features/activity/full.js +162 -0
  35. package/dist/dom/features/activity/full.js.map +7 -0
  36. package/dist/dom/features/activity/index.d.ts +1 -0
  37. package/dist/dom/features/activity/index.js +3 -0
  38. package/dist/dom/features/activity/index.js.map +7 -0
  39. package/dist/dom/features/activity/stub.d.ts +1 -0
  40. package/dist/dom/features/activity/stub.js +12 -0
  41. package/dist/dom/features/activity/stub.js.map +7 -0
  42. package/dist/dom/features/class/full.js +87 -27
  43. package/dist/dom/features/class/full.js.map +2 -2
  44. package/dist/dom/features/class/index.d.ts +1 -1
  45. package/dist/dom/features/class/index.js +2 -2
  46. package/dist/dom/features/class/stub.js +3 -3
  47. package/dist/dom/features/context/full.d.ts +4 -1
  48. package/dist/dom/features/context/full.js +72 -15
  49. package/dist/dom/features/context/full.js.map +2 -2
  50. package/dist/dom/features/context/index.d.ts +1 -1
  51. package/dist/dom/features/context/index.js +2 -2
  52. package/dist/dom/features/context/stub.d.ts +4 -1
  53. package/dist/dom/features/context/stub.js +17 -8
  54. package/dist/dom/features/context/stub.js.map +2 -2
  55. package/dist/dom/features/forward-ref/full.js +12 -21
  56. package/dist/dom/features/forward-ref/full.js.map +2 -2
  57. package/dist/dom/features/forward-ref/index.d.ts +1 -1
  58. package/dist/dom/features/forward-ref/index.js +2 -2
  59. package/dist/dom/features/forward-ref/stub.js +4 -4
  60. package/dist/dom/features/fragment-refs/index.d.ts +1 -0
  61. package/dist/dom/features/fragment-refs/index.js +8 -0
  62. package/dist/dom/features/fragment-refs/index.js.map +7 -0
  63. package/dist/dom/features/fragment-refs/stub.d.ts +3 -0
  64. package/dist/dom/features/fragment-refs/stub.js +14 -0
  65. package/dist/dom/features/fragment-refs/stub.js.map +7 -0
  66. package/dist/dom/features/hydration/full.d.ts +11 -6
  67. package/dist/dom/features/hydration/full.js +76 -77
  68. package/dist/dom/features/hydration/full.js.map +2 -2
  69. package/dist/dom/features/hydration/index.d.ts +1 -1
  70. package/dist/dom/features/hydration/index.js +2 -2
  71. package/dist/dom/features/hydration/stub.d.ts +7 -2
  72. package/dist/dom/features/hydration/stub.js +1 -1
  73. package/dist/dom/features/hydration/stub.js.map +1 -1
  74. package/dist/dom/features/index.d.ts +8 -7
  75. package/dist/dom/features/index.js +9 -8
  76. package/dist/dom/features/index.js.map +2 -2
  77. package/dist/dom/features/lazy/full.js +4 -4
  78. package/dist/dom/features/lazy/index.d.ts +1 -1
  79. package/dist/dom/features/lazy/index.js +2 -2
  80. package/dist/dom/features/lazy/stub.js +4 -4
  81. package/dist/dom/features/memo/full.js +8 -6
  82. package/dist/dom/features/memo/full.js.map +2 -2
  83. package/dist/dom/features/memo/index.d.ts +1 -1
  84. package/dist/dom/features/memo/index.js +2 -2
  85. package/dist/dom/features/memo/stub.js +4 -4
  86. package/dist/dom/features/portal/full.js +4 -4
  87. package/dist/dom/features/portal/index.d.ts +1 -1
  88. package/dist/dom/features/portal/index.js +2 -2
  89. package/dist/dom/features/portal/stub.js +4 -4
  90. package/dist/dom/features/suspense/full.js +197 -52
  91. package/dist/dom/features/suspense/full.js.map +2 -2
  92. package/dist/dom/features/suspense/index.d.ts +1 -1
  93. package/dist/dom/features/suspense/index.js +2 -2
  94. package/dist/dom/features/suspense/stub.js +4 -4
  95. package/dist/dom/features/view-transition/full.d.ts +6 -0
  96. package/dist/dom/features/view-transition/full.js +280 -0
  97. package/dist/dom/features/view-transition/full.js.map +7 -0
  98. package/dist/dom/features/view-transition/index.d.ts +1 -0
  99. package/dist/dom/features/view-transition/index.js +3 -0
  100. package/dist/dom/features/view-transition/index.js.map +7 -0
  101. package/dist/dom/features/view-transition/resources.d.ts +11 -0
  102. package/dist/dom/features/view-transition/resources.js +108 -0
  103. package/dist/dom/features/view-transition/resources.js.map +7 -0
  104. package/dist/dom/features/view-transition/stub.d.ts +6 -0
  105. package/dist/dom/features/view-transition/stub.js +22 -0
  106. package/dist/dom/features/view-transition/stub.js.map +7 -0
  107. package/dist/dom/features/view-transition/visual.d.ts +14 -0
  108. package/dist/dom/features/view-transition/visual.js +356 -0
  109. package/dist/dom/features/view-transition/visual.js.map +7 -0
  110. package/dist/dom/fragment-instance.d.ts +40 -0
  111. package/dist/dom/fragment-instance.js +324 -0
  112. package/dist/dom/fragment-instance.js.map +7 -0
  113. package/dist/dom/index.d.ts +11 -11
  114. package/dist/dom/index.js +11 -18
  115. package/dist/dom/index.js.map +3 -3
  116. package/dist/dom/portal.d.ts +2 -2
  117. package/dist/dom/portal.js +2 -2
  118. package/dist/dom/portal.js.map +1 -1
  119. package/dist/dom/reconcile.d.ts +32 -3
  120. package/dist/dom/reconcile.js +689 -221
  121. package/dist/dom/reconcile.js.map +2 -2
  122. package/dist/dom/resource-hints.d.ts +6 -0
  123. package/dist/dom/resource-hints.js +115 -0
  124. package/dist/dom/resource-hints.js.map +7 -0
  125. package/dist/dom/resource-store.d.ts +13 -0
  126. package/dist/dom/resource-store.js +43 -0
  127. package/dist/dom/resource-store.js.map +7 -0
  128. package/dist/dom/resources.d.ts +1 -0
  129. package/dist/dom/resources.js +44 -0
  130. package/dist/dom/resources.js.map +7 -0
  131. package/dist/dom/retained-effects.d.ts +6 -0
  132. package/dist/dom/retained-effects.js +49 -0
  133. package/dist/dom/retained-effects.js.map +7 -0
  134. package/dist/dom/root-internal.d.ts +4 -4
  135. package/dist/dom/root-internal.js +2 -2
  136. package/dist/dom/root-internal.js.map +2 -2
  137. package/dist/dom/root.d.ts +5 -5
  138. package/dist/dom/root.js +11 -11
  139. package/dist/dom/root.js.map +2 -2
  140. package/dist/dom/test-utils.js +1 -1
  141. package/dist/react/activity.d.ts +7 -0
  142. package/dist/react/activity.js +8 -0
  143. package/dist/react/activity.js.map +7 -0
  144. package/dist/react/children.d.ts +1 -1
  145. package/dist/react/children.js +3 -3
  146. package/dist/react/children.js.map +1 -1
  147. package/dist/react/class.d.ts +1 -1
  148. package/dist/react/class.js +3 -3
  149. package/dist/react/class.js.map +1 -1
  150. package/dist/react/compiler-runtime.js +2 -2
  151. package/dist/react/context.d.ts +7 -2
  152. package/dist/react/context.js +3 -11
  153. package/dist/react/context.js.map +3 -3
  154. package/dist/react/element.d.ts +6 -3
  155. package/dist/react/element.js +7 -11
  156. package/dist/react/element.js.map +2 -2
  157. package/dist/react/hooks.d.ts +26 -7
  158. package/dist/react/hooks.js +13 -3
  159. package/dist/react/hooks.js.map +2 -2
  160. package/dist/react/index.d.ts +39 -24
  161. package/dist/react/index.js +39 -19
  162. package/dist/react/index.js.map +3 -3
  163. package/dist/react/jsx-runtime.d.ts +2 -2
  164. package/dist/react/jsx-runtime.js +3 -3
  165. package/dist/react/memo.d.ts +1 -1
  166. package/dist/react/memo.js +1 -1
  167. package/dist/react/portal.js +1 -1
  168. package/dist/react/shared-internals.d.ts +15 -5
  169. package/dist/react/shared-internals.js +2 -3
  170. package/dist/react/shared-internals.js.map +2 -2
  171. package/dist/react/suspense.js +1 -1
  172. package/dist/react/view-transition.d.ts +32 -0
  173. package/dist/react/view-transition.js +13 -0
  174. package/dist/react/view-transition.js.map +7 -0
  175. package/dist/scheduler/index.js +1 -1
  176. package/dist/server/bootstrap-script.d.ts +1 -23
  177. package/dist/server/bootstrap-script.js +7 -6
  178. package/dist/server/bootstrap-script.js.map +2 -2
  179. package/dist/server/dispatcher.d.ts +28 -6
  180. package/dist/server/dispatcher.js +33 -15
  181. package/dist/server/dispatcher.js.map +2 -2
  182. package/dist/server/escape.js +16 -15
  183. package/dist/server/escape.js.map +2 -2
  184. package/dist/server/index.d.ts +6 -6
  185. package/dist/server/index.js +7 -7
  186. package/dist/server/renderToString.d.ts +1 -1
  187. package/dist/server/renderToString.js +12 -8
  188. package/dist/server/renderToString.js.map +2 -2
  189. package/dist/server/resource-hints.d.ts +22 -0
  190. package/dist/server/resource-hints.js +148 -0
  191. package/dist/server/resource-hints.js.map +7 -0
  192. package/dist/server/stream.d.ts +15 -2
  193. package/dist/server/stream.js +155 -63
  194. package/dist/server/stream.js.map +2 -2
  195. package/dist/server/walk.d.ts +15 -2
  196. package/dist/server/walk.js +150 -110
  197. package/dist/server/walk.js.map +2 -2
  198. package/dist/vite/index.d.ts +6 -0
  199. package/dist/vite/index.js +22 -6
  200. package/dist/vite/index.js.map +2 -2
  201. package/package.json +1 -1
  202. package/src/core/attributes.ts +1 -0
  203. package/src/core/browser.ts +33 -0
  204. package/src/core/internal.ts +24 -6
  205. package/src/core/resource-hints.ts +36 -0
  206. package/src/dom/_all.ts +1 -7
  207. package/src/dom/commit.ts +186 -0
  208. package/src/dom/dispatcher.ts +190 -134
  209. package/src/dom/dom.ts +70 -54
  210. package/src/dom/error-info.ts +15 -0
  211. package/src/dom/features/activity/full.ts +166 -0
  212. package/src/dom/features/activity/index.ts +1 -0
  213. package/src/dom/features/activity/stub.ts +14 -0
  214. package/src/dom/features/class/full.ts +72 -28
  215. package/src/dom/features/context/full.ts +70 -13
  216. package/src/dom/features/context/stub.ts +10 -5
  217. package/src/dom/features/forward-ref/full.ts +9 -19
  218. package/src/dom/features/fragment-refs/index.ts +1 -0
  219. package/src/dom/features/fragment-refs/stub.ts +3 -0
  220. package/src/dom/features/hydration/full.ts +84 -85
  221. package/src/dom/features/hydration/stub.ts +1 -1
  222. package/src/dom/features/index.ts +1 -0
  223. package/src/dom/features/memo/full.ts +4 -3
  224. package/src/dom/features/suspense/full.ts +192 -55
  225. package/src/dom/features/view-transition/full.ts +288 -0
  226. package/src/dom/features/view-transition/index.ts +1 -0
  227. package/src/dom/features/view-transition/resources.ts +107 -0
  228. package/src/dom/features/view-transition/stub.ts +7 -0
  229. package/src/dom/features/view-transition/visual.ts +406 -0
  230. package/src/dom/fragment-instance.ts +337 -0
  231. package/src/dom/index.ts +6 -7
  232. package/src/dom/portal.ts +1 -1
  233. package/src/dom/reconcile.ts +695 -242
  234. package/src/dom/resource-hints.ts +115 -0
  235. package/src/dom/resource-store.ts +52 -0
  236. package/src/dom/resources.ts +39 -0
  237. package/src/dom/retained-effects.ts +38 -0
  238. package/src/dom/root-internal.ts +4 -4
  239. package/src/dom/root.ts +12 -14
  240. package/src/react/activity.ts +10 -0
  241. package/src/react/context.ts +4 -11
  242. package/src/react/element.ts +11 -12
  243. package/src/react/hooks.ts +12 -3
  244. package/src/react/index.ts +18 -0
  245. package/src/react/shared-internals.ts +3 -3
  246. package/src/react/view-transition.ts +41 -0
  247. package/src/server/bootstrap-script.ts +36 -5
  248. package/src/server/dispatcher.ts +35 -13
  249. package/src/server/escape.ts +15 -12
  250. package/src/server/renderToString.ts +7 -5
  251. package/src/server/resource-hints.ts +165 -0
  252. package/src/server/stream.ts +154 -62
  253. package/src/server/walk.ts +79 -26
  254. package/src/vite/index.ts +30 -13
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/server/stream.ts"],
4
- "sourcesContent": ["import type { ReactNode } from '../core'\nimport {\n beginSSR,\n endSSR,\n installSSRDispatcher,\n uninstallSSRDispatcher,\n applyContextSnapshot,\n} from './dispatcher'\nimport { walk, type SuspendedBoundary } from './walk'\nimport { BOUNDARY_REVEAL_RUNTIME, revealScript } from './bootstrap-script'\nimport { escapeScript } from './escape'\n\nexport interface StreamOptions {\n identifierPrefix?: string\n nonce?: string\n bootstrapScriptContent?: string | ReadonlyArray<string>\n bootstrapScripts?: ReadonlyArray<string | { src: string; async?: boolean; nonce?: string }>\n bootstrapModules?: ReadonlyArray<string | { src: string; nonce?: string }>\n onError?: (error: unknown) => string | void\n signal?: AbortSignal\n progressiveChunkSize?: number\n}\n\nexport interface ReadableStreamResult extends ReadableStream<Uint8Array> {\n allReady: Promise<void>\n}\n\nexport interface PipeableWritable {\n write(chunk: string): unknown\n end(): unknown\n}\n\nexport interface OrchestratorState {\n nextId: number\n pending: Set<Promise<void>>\n closed: boolean\n errored: unknown | null\n}\n\ntype Emit = (chunk: string) => void\n\nexport async function streamHtml(\n children: ReactNode,\n emit: Emit,\n options: StreamOptions,\n state: OrchestratorState,\n): Promise<void> {\n installSSRDispatcher()\n beginSSR(options.identifierPrefix)\n const nonce = options.nonce\n\n try {\n const boundaries: SuspendedBoundary[] = []\n\n // Buffer shell + bootstrap into a string[] and flush as a single emit.\n // Per-emit overhead in renderToReadableStream is TextEncoder.encode +\n // controller.enqueue \u2014 each walkHost normally fires 3+ emits (opening\n // tag, per-attribute, closing bracket), which for a ~30-component tree\n // is ~100 stream-controller round-trips. Batching collapses those into\n // one encode and one enqueue per shell \u2014 measured ~2-4% of total SSR\n // time on CPU profiles.\n const shellChunks: string[] = []\n const bufferedEmit: Emit = (chunk) => {\n shellChunks.push(chunk)\n }\n\n // 1. Render the shell. A root-level `use(promise)` has no Suspense\n // boundary to capture it, but App Router SSR commonly suspends at this\n // level while resolving the RSC stream. Wait and retry without leaking\n // partial shell chunks or boundary ids from the aborted attempt.\n let shellRendered = false\n let rootRetries = 0\n while (!shellRendered) {\n const chunkCount = shellChunks.length\n const boundaryCount = boundaries.length\n const nextId = state.nextId\n try {\n walk(children, {\n emit: bufferedEmit,\n onSuspend: (b) => boundaries.push(b),\n nextBoundaryId: () => state.nextId++,\n })\n shellRendered = true\n } catch (err) {\n shellChunks.length = chunkCount\n boundaries.length = boundaryCount\n state.nextId = nextId\n if (!isThenable(err)) throw err\n if (++rootRetries > 50) {\n throw new Error('renderToReadableStream exceeded 50 root suspension retries.')\n }\n await err\n }\n }\n\n // 2. Inject runtime + bootstrap scripts (once, after shell). Skip the\n // reveal/event-replay runtime when nothing needs it \u2014 no suspensions to\n // reveal and no bootstrap scripts to guard against early user input. That\n // keeps fully-static SSR responses byte-equivalent to a plain walk and\n // matches React's behavior where `renderToReadableStream` of a static\n // tree emits only the markup.\n const hasBootstrap =\n bootstrapScriptContentToArray(options.bootstrapScriptContent).length > 0 ||\n (options.bootstrapScripts?.length ?? 0) > 0 ||\n (options.bootstrapModules?.length ?? 0) > 0\n if (boundaries.length > 0 || hasBootstrap) {\n shellChunks.push(`<script${nonce ? ` nonce=\"${nonce}\"` : ''}>${BOUNDARY_REVEAL_RUNTIME}</script>`)\n for (const content of bootstrapScriptContentToArray(options.bootstrapScriptContent)) {\n shellChunks.push(inlineBootstrapTag(content, nonce))\n }\n for (const s of options.bootstrapScripts ?? []) {\n shellChunks.push(bootstrapTag(s, 'script', nonce))\n }\n for (const m of options.bootstrapModules ?? []) {\n shellChunks.push(bootstrapTag(m, 'module', nonce))\n }\n }\n\n if (shellChunks.length) emit(normalizeDocumentShell(shellChunks.join('')))\n\n // 3. Stream suspended boundaries as they resolve\n for (const b of boundaries) streamBoundary(b, emit, options, state)\n await drain(state)\n } catch (err) {\n state.errored = err\n if (options.onError) options.onError(err)\n throw err\n } finally {\n endSSR()\n uninstallSSRDispatcher()\n state.closed = true\n }\n}\n\nfunction streamBoundary(\n b: SuspendedBoundary,\n emit: Emit,\n options: StreamOptions,\n state: OrchestratorState,\n): void {\n const task = (async () => {\n try {\n await b.thenable\n } catch (err) {\n if (options.onError) options.onError(err)\n }\n if (state.closed) return\n\n // Re-render the boundary's children into a string, restoring the\n // provider stack from when the boundary first suspended.\n const parts: string[] = []\n const sub: SuspendedBoundary[] = []\n const restore = applyContextSnapshot(b.contextSnapshot)\n try {\n walk(b.children, {\n emit: (s) => parts.push(s),\n onSuspend: (n) => sub.push(n),\n nextBoundaryId: () => state.nextId++,\n })\n } catch (err) {\n if (options.onError) options.onError(err)\n restore()\n return\n }\n restore()\n\n emit(`<div hidden id=\"S:${b.id}\">${parts.join('')}</div>${revealScript(b.id, options.nonce)}`)\n\n // Recurse: any nested suspensions inside the now-revealed content\n for (const s of sub) streamBoundary(s, emit, options, state)\n })()\n state.pending.add(task)\n task.finally(() => state.pending.delete(task))\n}\n\nasync function drain(state: OrchestratorState): Promise<void> {\n while (state.pending.size > 0) {\n await Promise.race(state.pending)\n }\n}\n\nfunction isThenable(value: unknown): value is Promise<unknown> {\n return !!value && typeof (value as { then?: unknown }).then === 'function'\n}\n\nfunction bootstrapScriptContentToArray(\n content: StreamOptions['bootstrapScriptContent'],\n): string[] {\n if (content === undefined) return []\n return typeof content === 'string' ? [content] : [...content]\n}\n\nfunction inlineBootstrapTag(content: string, defaultNonce: string | undefined): string {\n const nAttr = defaultNonce ? ` nonce=\"${defaultNonce}\"` : ''\n return `<script${nAttr}>${escapeScript(content)}</script>`\n}\n\nfunction normalizeDocumentShell(html: string): string {\n const doctypeIndex = html.indexOf('<!DOCTYPE html><html')\n if (doctypeIndex <= 0) return html\n\n const headPrefix = html.slice(0, doctypeIndex)\n if (!isHeadPrefix(headPrefix)) return html\n\n const documentHtml = html.slice(doctypeIndex)\n const headOpen = documentHtml.match(/<head(?:\\s[^>]*)?>/)\n if (!headOpen || headOpen.index === undefined) return html\n\n const insertAt = headOpen.index + headOpen[0].length\n return documentHtml.slice(0, insertAt) + headPrefix + documentHtml.slice(insertAt)\n}\n\nfunction isHeadPrefix(value: string): boolean {\n if (!value) return false\n return stripLeadingHeadTags(value).trim() === ''\n}\n\nfunction stripLeadingHeadTags(value: string): string {\n let rest = value\n let changed = true\n while (changed) {\n changed = false\n const next = rest.replace(\n /^\\s*(?:<meta\\b[^>]*>|<link\\b[^>]*>|<base\\b[^>]*>|<title\\b[^>]*>[\\s\\S]*?<\\/title>|<style\\b[^>]*>[\\s\\S]*?<\\/style>|<script\\b[^>]*>[\\s\\S]*?<\\/script>)/i,\n '',\n )\n if (next !== rest) {\n rest = next\n changed = true\n }\n }\n return rest\n}\n\nfunction bootstrapTag(\n entry: string | { src: string; async?: boolean; nonce?: string },\n kind: 'script' | 'module',\n defaultNonce: string | undefined,\n): string {\n const src = typeof entry === 'string' ? entry : entry.src\n const nonce = typeof entry === 'string' ? defaultNonce : entry.nonce ?? defaultNonce\n const nAttr = nonce ? ` nonce=\"${nonce}\"` : ''\n if (kind === 'module') return `<script type=\"module\"${nAttr} src=\"${src}\"></script>`\n return `<script async${nAttr} src=\"${src}\"></script>`\n}\n\n// ---------------------------------------------------------------------------\n// Web Streams: renderToReadableStream\n// ---------------------------------------------------------------------------\n\nexport function renderToReadableStream(\n children: ReactNode,\n options: StreamOptions = {},\n): Promise<ReadableStreamResult> {\n const state: OrchestratorState = {\n nextId: 0,\n pending: new Set(),\n closed: false,\n errored: null,\n }\n const encoder = new TextEncoder()\n\n let allReadyResolve!: () => void\n let allReadyReject!: (e: unknown) => void\n const allReady = new Promise<void>((r, rej) => {\n allReadyResolve = r\n allReadyReject = rej\n })\n\n const stream = new ReadableStream<Uint8Array>({\n start(controller) {\n const emit = (chunk: string) => {\n try {\n controller.enqueue(encoder.encode(chunk))\n } catch {}\n }\n\n streamHtml(children, emit, options, state).then(\n () => {\n try {\n controller.close()\n } catch {}\n allReadyResolve()\n },\n (err) => {\n try {\n controller.error(err)\n } catch {}\n allReadyReject(err)\n },\n )\n\n options.signal?.addEventListener('abort', () => {\n state.closed = true\n try {\n controller.close()\n } catch {}\n })\n },\n })\n\n return Promise.resolve(Object.assign(stream, { allReady }))\n}\n\n// ---------------------------------------------------------------------------\n// Node Streams: renderToPipeableStream\n// ---------------------------------------------------------------------------\n\nexport interface PipeableHandle {\n pipe<T extends PipeableWritable>(dest: T): T\n abort(reason?: unknown): void\n}\n\nexport interface PipeableOptions extends StreamOptions {\n onShellReady?: () => void\n onShellError?: (err: unknown) => void\n onAllReady?: () => void\n}\n\nexport function renderToPipeableStream(\n children: ReactNode,\n options: PipeableOptions = {},\n): PipeableHandle {\n const state: OrchestratorState = {\n nextId: 0,\n pending: new Set(),\n closed: false,\n errored: null,\n }\n\n const buffers: string[] = []\n let dest: PipeableWritable | null = null\n let shellReady = false\n let finished = false\n let aborted = false\n\n const flushTo = (w: PipeableWritable) => {\n if (!buffers.length) return\n for (const b of buffers) w.write(b)\n buffers.length = 0\n }\n\n const emit: Emit = (chunk) => {\n if (aborted || finished) return\n if (dest) dest.write(chunk)\n else buffers.push(chunk)\n }\n\n // Kick off rendering\n streamHtml(children, emit, options, state).then(\n () => {\n finished = true\n if (dest) dest.end()\n options.onAllReady?.()\n },\n (err) => {\n if (!shellReady) {\n options.onShellError?.(err)\n } else {\n options.onError?.(err)\n if (dest) dest.end()\n }\n },\n )\n\n // We call onShellReady once the first synchronous emit has landed.\n // streamHtml above runs the shell synchronously before the first await in drain(),\n // so we can schedule onShellReady right after the first microtask.\n queueMicrotask(() => {\n if (aborted || finished) return\n shellReady = true\n options.onShellReady?.()\n })\n\n return {\n pipe<T extends PipeableWritable>(target: T): T {\n dest = target\n flushTo(target)\n if (finished) target.end()\n return target\n },\n abort(_reason?: unknown) {\n aborted = true\n state.closed = true\n if (dest) dest.end()\n },\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { ReactNode } from '../core'\nimport {\n beginSSR,\n endSSR,\n applyContextSnapshot,\n currentSSRFrame,\n type SSRFrame,\n} from './dispatcher'\nimport { walk, type SuspendedBoundary, type BrowserBailoutCallback } from './walk'\nimport { browserError, isBrowserToken, isBrowserError } from '../core/browser'\nimport { BOUNDARY_REVEAL_RUNTIME, revealScript } from './bootstrap-script'\nimport { escapeAttr, escapeScript } from './escape'\nimport { resourceURL } from '../core/resource-hints'\nimport type { ResourceScope } from './resource-hints'\n\nexport interface StreamOptions {\n identifierPrefix?: string\n nonce?: string | { script?: string; style?: string }\n bootstrapScriptContent?: string | ReadonlyArray<string>\n bootstrapScripts?: ReadonlyArray<string | { src: string; async?: boolean; nonce?: string }>\n bootstrapModules?: ReadonlyArray<string | { src: string; nonce?: string }>\n onError?: (error: unknown) => string | void\n onBrowserBailout?: BrowserBailoutCallback\n signal?: AbortSignal\n progressiveChunkSize?: number\n}\n\nexport interface ReadableStreamResult extends ReadableStream<Uint8Array> {\n allReady: Promise<void>\n}\n\nexport interface PipeableWritable {\n write(chunk: string): unknown\n end(): unknown\n destroy?(error?: unknown): unknown\n}\n\nexport interface OrchestratorState {\n nextId: number\n pending: Set<Promise<void>>\n closed: boolean\n errored: unknown | null\n aborted: boolean\n reason: unknown\n abort: (reason?: unknown) => void\n cancelled: Promise<void>\n onShellReady?: () => void\n frame?: SSRFrame\n}\n\nfunction createState(): OrchestratorState {\n let wake!: () => void\n const state: OrchestratorState = {\n nextId: 0, pending: new Set(), closed: false, errored: null,\n aborted: false, reason: undefined,\n cancelled: new Promise<void>((resolve) => { wake = resolve }),\n abort(reason) {\n if (state.closed || state.aborted) return\n state.aborted = true\n state.reason = isBrowserToken(reason) ? browserError(reason) : reason ?? new Error('The render was aborted by the server without a reason.')\n wake()\n },\n }\n return state\n}\n\ntype Emit = (chunk: string) => void\n\nexport async function streamHtml(\n children: ReactNode,\n emit: Emit,\n options: StreamOptions,\n state: OrchestratorState,\n): Promise<void> {\n const nonce = scriptNonce(options)\n\n try {\n const boundaries: SuspendedBoundary[] = []\n\n // Buffer shell + bootstrap into a string[] and flush as a single emit.\n // Per-emit overhead in renderToReadableStream is TextEncoder.encode +\n // controller.enqueue \u2014 each walkHost normally fires 3+ emits (opening\n // tag, per-attribute, closing bracket), which for a ~30-component tree\n // is ~100 stream-controller round-trips. Batching collapses those into\n // one encode and one enqueue per shell \u2014 measured ~2-4% of total SSR\n // time on CPU profiles.\n const shellChunks: string[] = []\n let head = 0\n const bufferedEmit: Emit = (chunk) => {\n shellChunks.push(chunk)\n }\n\n // 1. Render the shell. A root-level `use(promise)` has no Suspense\n // boundary to capture it, but App Router SSR commonly suspends at this\n // level while resolving the RSC stream. Wait and retry without leaking\n // partial shell chunks or boundary ids from the aborted attempt.\n let shellRendered = false\n let rootRetries = 0\n let resources: SSRFrame['resources']\n while (!shellRendered) {\n const chunkCount = shellChunks.length\n const boundaryCount = boundaries.length\n const nextId = state.nextId\n head = 0\n const previous = beginSSR(options.identifierPrefix)\n currentSSRFrame().styleNonce = typeof options.nonce === 'object' ? options.nonce?.style : undefined\n if (resources) currentSSRFrame().resources = resources\n let suspended: Promise<unknown> | undefined\n try {\n if (state.aborted) throw state.reason\n walk(children, {\n emit: bufferedEmit,\n onSuspend: (b) => boundaries.push(b),\n nextBoundaryId: () => state.nextId++,\n onBrowserBailout: options.onBrowserBailout,\n onHead: () => { head = shellChunks.length },\n })\n shellRendered = true\n state.frame = currentSSRFrame()\n } catch (err) {\n shellChunks.length = chunkCount\n boundaries.length = boundaryCount\n state.nextId = nextId\n if (!isThenable(err)) throw err\n if (++rootRetries > 50) {\n throw new Error('renderToReadableStream exceeded 50 root suspension retries.')\n }\n suspended = err\n } finally {\n resources = currentSSRFrame().resources\n endSSR(previous)\n }\n if (suspended) await Promise.race([suspended, state.cancelled])\n }\n\n const hints = state.frame?.resources?.drain()\n if (hints) shellChunks.splice(head, 0, hints)\n if (state.frame) state.frame.shellFlushed = true\n\n // 2. Inject runtime + bootstrap scripts (once, after shell). Skip the\n // reveal/event-replay runtime when nothing needs it \u2014 no suspensions to\n // reveal and no bootstrap scripts to guard against early user input. That\n // keeps fully-static SSR responses byte-equivalent to a plain walk and\n // matches React's behavior where `renderToReadableStream` of a static\n // tree emits only the markup.\n const hasBootstrap =\n bootstrapScriptContentToArray(options.bootstrapScriptContent).length > 0 ||\n (options.bootstrapScripts?.length ?? 0) > 0 ||\n (options.bootstrapModules?.length ?? 0) > 0\n if (boundaries.length > 0 || hasBootstrap) {\n shellChunks.push(`<script${nonce ? ` nonce=\"${escapeAttr(nonce)}\"` : ''}>${BOUNDARY_REVEAL_RUNTIME}</script>`)\n for (const content of bootstrapScriptContentToArray(options.bootstrapScriptContent)) {\n shellChunks.push(inlineBootstrapTag(content, nonce))\n }\n for (const s of options.bootstrapScripts ?? []) {\n shellChunks.push(bootstrapTag(s, 'script', nonce))\n }\n for (const m of options.bootstrapModules ?? []) {\n shellChunks.push(bootstrapTag(m, 'module', nonce))\n }\n }\n\n if (shellChunks.length) emit(normalizeDocumentShell(shellChunks.join('')))\n state.onShellReady?.()\n\n // 3. Stream suspended boundaries as they resolve\n for (const b of boundaries) streamBoundary(b, emit, options, state)\n await drain(state)\n } catch (err) {\n if (isBrowserError(err)) {\n err = new Error('The server render could not complete because client rendering was requested outside a Suspense boundary.',\n Object.hasOwn(err, 'cause') ? { cause: err.cause } : undefined)\n }\n state.errored = err\n if (options.onError) options.onError(err)\n throw err\n } finally {\n state.closed = true\n }\n}\n\nfunction streamBoundary(\n b: SuspendedBoundary,\n emit: Emit,\n options: StreamOptions,\n state: OrchestratorState,\n): void {\n const nonce = scriptNonce(options)\n const task = (async () => {\n try {\n await Promise.race([b.thenable, state.cancelled])\n } catch {}\n if (state.closed) return\n\n const defer = (error: unknown) => {\n if (isBrowserError(error)) options.onBrowserBailout?.(error, { componentStack: (error as any).componentStack || b.componentStack })\n else options.onError?.(error)\n emit(`<script${nonce ? ` nonce=\"${escapeAttr(nonce)}\"` : ''}>$RB(${b.id}${isBrowserError(error) ? '' : ',1'})</script>`)\n }\n if (state.aborted) { defer(state.reason); return }\n\n // Re-render the boundary's children into a string, restoring the\n // provider stack from when the boundary first suspended.\n const parts: string[] = []\n const sub: SuspendedBoundary[] = []\n const resourceScope: ResourceScope = {}\n let styles: string[][] | undefined\n const previous = beginSSR(options.identifierPrefix, state.frame)\n state.frame?.resources?.takeStylesheets()\n const restore = applyContextSnapshot(b.contextSnapshot)\n try {\n walk(b.children, {\n emit: (s) => parts.push(s),\n onSuspend: (n) => sub.push(n),\n nextBoundaryId: () => state.nextId++,\n onBrowserBailout: options.onBrowserBailout,\n componentStack: b.componentStack,\n resourceScope,\n })\n state.frame?.resources?.mergeScope(resourceScope)\n } catch (err) {\n if (isThenable(err)) {\n streamBoundary({ ...b, thenable: err }, emit, options, state)\n } else defer(err)\n return\n } finally {\n restore()\n endSSR(previous)\n const hints = state.frame?.resources?.drain()\n styles = state.frame?.resources?.takeStylesheets()\n if (hints) emit(hints)\n }\n\n emit(`<div hidden id=\"S:${b.id}\">${parts.join('')}</div>${revealScript(b.id, nonce, styles)}`)\n\n // Recurse: any nested suspensions inside the now-revealed content\n for (const s of sub) streamBoundary(s, emit, options, state)\n })()\n state.pending.add(task)\n task.then(() => state.pending.delete(task), () => state.pending.delete(task))\n}\n\nasync function drain(state: OrchestratorState): Promise<void> {\n while (state.pending.size > 0) {\n await Promise.race(state.pending)\n }\n}\n\nfunction isThenable(value: unknown): value is Promise<unknown> {\n return !!value && typeof (value as { then?: unknown }).then === 'function'\n}\n\nfunction scriptNonce(options: StreamOptions): string | undefined {\n return typeof options.nonce === 'string' ? options.nonce : options.nonce?.script\n}\n\nfunction bootstrapScriptContentToArray(\n content: StreamOptions['bootstrapScriptContent'],\n): string[] {\n if (content === undefined) return []\n return typeof content === 'string' ? [content] : [...content]\n}\n\nfunction inlineBootstrapTag(content: string, defaultNonce: string | undefined): string {\n const nAttr = defaultNonce ? ` nonce=\"${escapeAttr(defaultNonce)}\"` : ''\n return `<script${nAttr}>${escapeScript(content)}</script>`\n}\n\nfunction normalizeDocumentShell(html: string): string {\n const doctypeIndex = html.indexOf('<!DOCTYPE html><html')\n if (doctypeIndex <= 0) return html\n\n const headPrefix = html.slice(0, doctypeIndex)\n if (!isHeadPrefix(headPrefix)) return html\n\n const documentHtml = html.slice(doctypeIndex)\n const headOpen = documentHtml.match(/<head(?:\\s[^>]*)?>/)\n if (!headOpen || headOpen.index === undefined) return html\n\n const insertAt = headOpen.index + headOpen[0].length\n return documentHtml.slice(0, insertAt) + headPrefix + documentHtml.slice(insertAt)\n}\n\nfunction isHeadPrefix(value: string): boolean {\n if (!value) return false\n return stripLeadingHeadTags(value).trim() === ''\n}\n\nfunction stripLeadingHeadTags(value: string): string {\n let rest = value\n let changed = true\n while (changed) {\n changed = false\n const next = rest.replace(\n /^\\s*(?:<meta\\b[^>]*>|<link\\b[^>]*>|<base\\b[^>]*>|<title\\b[^>]*>[\\s\\S]*?<\\/title>|<style\\b[^>]*>[\\s\\S]*?<\\/style>|<script\\b[^>]*>[\\s\\S]*?<\\/script>)/i,\n '',\n )\n if (next !== rest) {\n rest = next\n changed = true\n }\n }\n return rest\n}\n\nfunction bootstrapTag(\n entry: string | { src: string; async?: boolean; nonce?: string },\n kind: 'script' | 'module',\n defaultNonce: string | undefined,\n): string {\n const src = escapeAttr(resourceURL(typeof entry === 'string' ? entry : entry.src))\n const nonce = typeof entry === 'string' ? defaultNonce : entry.nonce ?? defaultNonce\n const nAttr = nonce ? ` nonce=\"${escapeAttr(nonce)}\"` : ''\n if (kind === 'module') return `<script type=\"module\"${nAttr} src=\"${src}\"></script>`\n return `<script async${nAttr} src=\"${src}\"></script>`\n}\n\n// ---------------------------------------------------------------------------\n// Web Streams: renderToReadableStream\n// ---------------------------------------------------------------------------\n\nexport function renderToReadableStream(\n children: ReactNode,\n options: StreamOptions = {},\n): Promise<ReadableStreamResult> {\n const state = createState()\n const encoder = new TextEncoder()\n let abortListener: (() => void) | undefined\n const detachAbortListener = () => {\n if (abortListener) {\n options.signal?.removeEventListener('abort', abortListener)\n abortListener = undefined\n }\n }\n\n let allReadyResolve!: () => void\n let allReadyReject!: (e: unknown) => void\n const allReady = new Promise<void>((r, rej) => {\n allReadyResolve = r\n allReadyReject = rej\n })\n // Shell failures reject the outer promise before callers receive allReady.\n allReady.catch(() => {})\n let shellResolve!: (stream: ReadableStreamResult) => void\n let shellReject!: (error: unknown) => void\n const shell = new Promise<ReadableStreamResult>((resolve, reject) => {\n shellResolve = resolve\n shellReject = reject\n })\n state.onShellReady = () => queueMicrotask(() => shellResolve(Object.assign(stream, { allReady })))\n\n const stream = new ReadableStream<Uint8Array>({\n start(controller) {\n const emit = (chunk: string) => {\n try {\n controller.enqueue(encoder.encode(chunk))\n } catch {}\n }\n\n if (options.signal) {\n abortListener = () => {\n detachAbortListener()\n state.abort(options.signal!.reason)\n }\n options.signal.addEventListener('abort', abortListener)\n if (options.signal.aborted) abortListener()\n }\n\n streamHtml(children, emit, options, state).then(\n () => {\n detachAbortListener()\n try {\n controller.close()\n } catch {}\n allReadyResolve()\n },\n (err) => {\n detachAbortListener()\n try {\n controller.error(err)\n } catch {}\n allReadyReject(err)\n shellReject(err)\n },\n )\n\n },\n cancel(reason) {\n state.abort(reason)\n detachAbortListener()\n },\n })\n\n return shell\n}\n\n// ---------------------------------------------------------------------------\n// Node Streams: renderToPipeableStream\n// ---------------------------------------------------------------------------\n\nexport interface PipeableHandle {\n pipe<T extends PipeableWritable>(dest: T): T\n abort(reason?: unknown): void\n}\n\nexport interface PipeableOptions extends StreamOptions {\n onShellReady?: () => void\n onShellError?: (err: unknown) => void\n onAllReady?: () => void\n}\n\nexport function renderToPipeableStream(\n children: ReactNode,\n options: PipeableOptions = {},\n): PipeableHandle {\n const state = createState()\n\n const buffers: string[] = []\n let dest: PipeableWritable | null = null\n let shellReady = false\n let shellFailed = false\n let finished = false\n let failed = false\n let failure: unknown\n\n const finishDestination = (target: PipeableWritable) => {\n if (failed && target.destroy) target.destroy(failure)\n else target.end()\n }\n\n const flushTo = (w: PipeableWritable) => {\n if (!buffers.length) return\n for (const b of buffers) w.write(b)\n buffers.length = 0\n }\n\n const emit: Emit = (chunk) => {\n if (finished) return\n if (dest) dest.write(chunk)\n else buffers.push(chunk)\n }\n\n state.onShellReady = () => queueMicrotask(() => {\n if (shellFailed) return\n shellReady = true\n options.onShellReady?.()\n })\n\n // Kick off rendering\n streamHtml(children, emit, options, state).then(\n () => {\n finished = true\n if (dest) dest.end()\n options.onAllReady?.()\n },\n (err) => {\n finished = true\n failed = true\n failure = err\n if (!shellReady) {\n shellFailed = true\n options.onShellError?.(err)\n } else {\n if (dest) finishDestination(dest)\n }\n },\n )\n\n return {\n pipe<T extends PipeableWritable>(target: T): T {\n dest = target\n if (!failed) flushTo(target)\n if (finished) finishDestination(target)\n return target\n },\n abort(reason?: unknown) {\n state.abort(reason)\n },\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,19 +1,32 @@
1
- import { type ReactNode } from '../core';
2
- import { type ContextSnapshot } from './dispatcher';
1
+ import { type ReactNode } from "../core/index.js";
2
+ import { type ContextSnapshot } from "./dispatcher.js";
3
+ import type { ResourceScope } from "./resource-hints.js";
4
+ export interface ServerErrorInfo {
5
+ componentStack: string;
6
+ }
7
+ export type BrowserBailoutCallback = (error: Error, errorInfo: ServerErrorInfo) => void;
3
8
  export interface SuspendedBoundary {
4
9
  id: number;
5
10
  fallbackHTML: string;
6
11
  children: ReactNode;
7
12
  thenable: Promise<any>;
8
13
  contextSnapshot: ContextSnapshot;
14
+ componentStack: string;
9
15
  }
10
16
  export interface WalkOptions {
11
17
  emit: (chunk: string) => void;
18
+ onHead?: () => void;
12
19
  onSuspend?: ((boundary: SuspendedBoundary) => void) | undefined;
20
+ onBrowserBailout?: BrowserBailoutCallback | undefined;
21
+ componentStack?: string | undefined;
22
+ thrownInfo?: {
23
+ componentStack?: string | undefined;
24
+ };
13
25
  nextBoundaryId: () => number;
14
26
  bootstrapped?: boolean | undefined;
15
27
  isBoundaryResolution?: boolean | undefined;
16
28
  isSvg?: boolean | undefined;
29
+ resourceScope?: ResourceScope | undefined;
17
30
  /**
18
31
  * Tracks whether the most recent emission within the *current text flow*
19
32
  * ended with a text node. When the next emission is also text, we emit a
@@ -1,11 +1,12 @@
1
- // packages/redact/src/server/walk.ts
1
+ // src/server/walk.ts
2
2
  import {
3
3
  REACT_ELEMENT_TYPE,
4
4
  REACT_LEGACY_ELEMENT_TYPE,
5
5
  REACT_FRAGMENT_TYPE
6
- } from "../core";
6
+ } from "../core/index.js";
7
7
  import {
8
8
  REACT_SUSPENSE_TYPE,
9
+ REACT_CONTEXT_TYPE,
9
10
  REACT_PROVIDER_TYPE,
10
11
  REACT_CONSUMER_TYPE,
11
12
  REACT_FORWARD_REF_TYPE,
@@ -13,20 +14,26 @@ import {
13
14
  REACT_LAZY_TYPE,
14
15
  REACT_STRICT_MODE_TYPE,
15
16
  REACT_PROFILER_TYPE,
16
- REACT_PORTAL_TYPE
17
- } from "../react";
17
+ REACT_PORTAL_TYPE,
18
+ REACT_ACTIVITY_TYPE,
19
+ REACT_VIEW_TRANSITION_TYPE
20
+ } from "../react/index.js";
18
21
  import {
19
22
  attrToHtml,
20
23
  escapeText,
21
24
  escapeScript,
22
25
  VOID_ELEMENTS,
23
26
  RAW_TEXT_ELEMENTS
24
- } from "./escape";
27
+ } from "./escape.js";
25
28
  import {
26
29
  pushContext,
27
30
  popContext,
28
- snapshotContexts
29
- } from "./dispatcher";
31
+ snapshotContexts,
32
+ recordHostResource,
33
+ currentSSRFrame
34
+ } from "./dispatcher.js";
35
+ import { isBrowserError } from "../core/browser.js";
36
+ import { resourceKind } from "../core/resource-hints.js";
30
37
  function walk(node, opts) {
31
38
  if (!opts.textState) opts = { ...opts, textState: { lastWasText: false } };
32
39
  walkNode(node, opts);
@@ -86,6 +93,10 @@ function walkNode(node, opts) {
86
93
  function walkElement(el, opts) {
87
94
  const type = el.type;
88
95
  const props = el.props ?? {};
96
+ if (typeof type === "string") {
97
+ walkHost(type, props, opts);
98
+ return;
99
+ }
89
100
  if (type === REACT_FRAGMENT_TYPE || type === REACT_STRICT_MODE_TYPE || type === REACT_PROFILER_TYPE) {
90
101
  walkNode(props.children, opts);
91
102
  return;
@@ -94,15 +105,19 @@ function walkElement(el, opts) {
94
105
  walkSuspense(props, opts);
95
106
  return;
96
107
  }
97
- if (typeof type === "string") {
98
- walkHost(type, props, opts);
108
+ if (type === REACT_ACTIVITY_TYPE) {
109
+ if (props.mode !== "hidden") walkNode(props.children, opts);
110
+ return;
111
+ }
112
+ if (type === REACT_VIEW_TRANSITION_TYPE) {
113
+ walkNode(props.children, opts);
99
114
  return;
100
115
  }
101
116
  const marker = type?.$$typeof;
102
117
  if (marker === REACT_PORTAL_TYPE) {
103
118
  return;
104
119
  }
105
- if (marker === REACT_PROVIDER_TYPE) {
120
+ if (marker === REACT_CONTEXT_TYPE || marker === REACT_PROVIDER_TYPE) {
106
121
  const ctx = type._context;
107
122
  pushContext(ctx, props.value);
108
123
  try {
@@ -113,10 +128,9 @@ function walkElement(el, opts) {
113
128
  return;
114
129
  }
115
130
  if (marker === REACT_CONSUMER_TYPE) {
116
- const ctx = type._context;
117
131
  const render = props.children;
118
132
  if (typeof render === "function") {
119
- walkNode(render(ctx._currentValue), opts);
133
+ walkNode(render(type._context._currentValue), opts);
120
134
  }
121
135
  return;
122
136
  }
@@ -124,8 +138,7 @@ function walkElement(el, opts) {
124
138
  const render = type.render;
125
139
  const ref = props.ref ?? null;
126
140
  const { ref: _omit, ...rest } = props;
127
- const rendered = render(rest, ref);
128
- walkNode(rendered, opts);
141
+ walkComponent(render, rest, opts, ref);
129
142
  return;
130
143
  }
131
144
  if (marker === REACT_MEMO_TYPE) {
@@ -135,15 +148,8 @@ function walkElement(el, opts) {
135
148
  }
136
149
  if (marker === REACT_LAZY_TYPE) {
137
150
  const { _payload, _init } = type;
138
- try {
139
- const resolved = _init(_payload);
140
- walkElement({ ...el, type: resolved }, opts);
141
- } catch (thenable) {
142
- if (isThenable(thenable)) {
143
- throw thenable;
144
- }
145
- throw thenable;
146
- }
151
+ const resolved = _init(_payload);
152
+ walkElement({ ...el, type: resolved }, opts);
147
153
  return;
148
154
  }
149
155
  if (typeof type === "function") {
@@ -153,6 +159,7 @@ function walkElement(el, opts) {
153
159
  }
154
160
  function walkHost(tag, props, opts) {
155
161
  const isSvg = opts.isSvg || tag === "svg";
162
+ if (!isSvg && resourceKind(tag, props) && recordHostResource(tag, props, opts.resourceScope)) return;
156
163
  const isTextarea = tag === "textarea";
157
164
  const textareaValue = isTextarea ? props.value != null ? props.value : props.defaultValue : void 0;
158
165
  const isInput = tag === "input";
@@ -164,76 +171,82 @@ function walkHost(tag, props, opts) {
164
171
  pushSelectContext(val);
165
172
  }
166
173
  const isOption = tag === "option";
167
- if (tag === "html") opts.emit("<!DOCTYPE html>");
168
- opts.emit("<" + tag);
169
- for (const k in props) {
170
- if (isTextarea && (k === "value" || k === "defaultValue")) continue;
171
- if (isInput && (k === "defaultValue" || k === "defaultChecked")) continue;
172
- if (isSelect && (k === "value" || k === "defaultValue")) continue;
173
- if (isOption && k === "selected") continue;
174
- opts.emit(attrToHtml(k, props[k], isSvg));
175
- }
176
- if (inputValueAttr !== void 0) {
177
- opts.emit(attrToHtml("value", inputValueAttr, isSvg));
178
- }
179
- if (inputCheckedAttr !== void 0) {
180
- opts.emit(attrToHtml("checked", inputCheckedAttr, isSvg));
181
- }
182
- if (isOption) {
183
- const selectVal = currentSelectValue();
184
- if (selectVal !== void 0) {
185
- const optionValue = props.value != null ? props.value : optionChildText(props.children);
186
- const matches = Array.isArray(selectVal) ? selectVal.some((v) => "" + v === "" + optionValue) : "" + selectVal === "" + optionValue;
187
- if (matches) opts.emit(' selected=""');
188
- } else if (props.selected) {
189
- opts.emit(' selected=""');
174
+ try {
175
+ if (tag === "html") opts.emit("<!DOCTYPE html>");
176
+ opts.emit("<" + tag);
177
+ for (const k in props) {
178
+ if (isTextarea && (k === "value" || k === "defaultValue")) continue;
179
+ if (isInput && (k === "defaultValue" || k === "defaultChecked")) continue;
180
+ if (isSelect && (k === "value" || k === "defaultValue")) continue;
181
+ if (isOption && k === "selected") continue;
182
+ opts.emit(attrToHtml(k, props[k], isSvg));
183
+ }
184
+ if (inputValueAttr !== void 0) {
185
+ opts.emit(attrToHtml("value", inputValueAttr, isSvg));
186
+ }
187
+ if (inputCheckedAttr !== void 0) {
188
+ opts.emit(attrToHtml("checked", inputCheckedAttr, isSvg));
189
+ }
190
+ if (isOption) {
191
+ const selectVal = currentSelectValue();
192
+ if (selectVal !== void 0) {
193
+ const optionValue = props.value != null ? props.value : optionChildText(props.children);
194
+ const matches = Array.isArray(selectVal) ? selectVal.some((v) => "" + v === "" + optionValue) : "" + selectVal === "" + optionValue;
195
+ if (matches) opts.emit(' selected=""');
196
+ } else if (props.selected) {
197
+ opts.emit(' selected=""');
198
+ }
199
+ }
200
+ if (VOID_ELEMENTS.has(tag)) {
201
+ opts.emit("/>");
202
+ if (opts.textState) opts.textState.lastWasText = false;
203
+ return;
204
+ }
205
+ opts.emit(">");
206
+ if (tag === "head") opts.onHead?.();
207
+ const parentTextState = opts.textState;
208
+ const childOpts = {
209
+ ...opts,
210
+ isSvg: isSvg && tag !== "foreignObject",
211
+ textState: { lastWasText: false }
212
+ };
213
+ if (tag === "html" && !hasHeadChild(props.children)) {
214
+ opts.emit("<head>");
215
+ opts.onHead?.();
216
+ opts.emit("</head>");
217
+ }
218
+ const dangerouslyHtml = props.dangerouslySetInnerHTML?.__html;
219
+ if (isTextarea && textareaValue != null) {
220
+ opts.emit(escapeText(String(textareaValue)));
221
+ opts.emit(`</${tag}>`);
222
+ if (parentTextState) parentTextState.lastWasText = false;
223
+ return;
224
+ }
225
+ if (RAW_TEXT_ELEMENTS.has(tag)) {
226
+ if (dangerouslyHtml != null) {
227
+ opts.emit(escapeScript(String(dangerouslyHtml)));
228
+ } else {
229
+ const children = props.children;
230
+ if (typeof children === "string" || typeof children === "number") {
231
+ opts.emit(escapeScript(String(children)));
232
+ } else if (Array.isArray(children)) {
233
+ opts.emit(escapeScript(children.filter((c) => c != null).join("")));
234
+ }
235
+ }
236
+ opts.emit(`</${tag}>`);
237
+ if (parentTextState) parentTextState.lastWasText = false;
238
+ return;
190
239
  }
191
- }
192
- if (VOID_ELEMENTS.has(tag)) {
193
- opts.emit("/>");
194
- if (opts.textState) opts.textState.lastWasText = false;
195
- return;
196
- }
197
- opts.emit(">");
198
- const parentTextState = opts.textState;
199
- const childOpts = {
200
- ...opts,
201
- isSvg: isSvg && tag !== "foreignObject",
202
- textState: { lastWasText: false }
203
- };
204
- if (tag === "html" && !hasHeadChild(props.children)) {
205
- opts.emit("<head></head>");
206
- }
207
- const dangerouslyHtml = props.dangerouslySetInnerHTML?.__html;
208
- if (isTextarea && textareaValue != null) {
209
- opts.emit(escapeText(String(textareaValue)));
210
- opts.emit(`</${tag}>`);
211
- if (parentTextState) parentTextState.lastWasText = false;
212
- return;
213
- }
214
- if (RAW_TEXT_ELEMENTS.has(tag)) {
215
240
  if (dangerouslyHtml != null) {
216
- opts.emit(escapeScript(String(dangerouslyHtml)));
241
+ opts.emit(String(dangerouslyHtml));
217
242
  } else {
218
- const children = props.children;
219
- if (typeof children === "string" || typeof children === "number") {
220
- opts.emit(escapeScript(String(children)));
221
- } else if (Array.isArray(children)) {
222
- opts.emit(escapeScript(children.filter((c) => c != null).join("")));
223
- }
243
+ walkNode(props.children, childOpts);
224
244
  }
225
245
  opts.emit(`</${tag}>`);
226
246
  if (parentTextState) parentTextState.lastWasText = false;
227
- return;
247
+ } finally {
248
+ if (isSelect) popSelectContext();
228
249
  }
229
- if (dangerouslyHtml != null) {
230
- opts.emit(String(dangerouslyHtml));
231
- } else {
232
- walkNode(props.children, childOpts);
233
- }
234
- opts.emit(`</${tag}>`);
235
- if (isSelect) popSelectContext();
236
- if (parentTextState) parentTextState.lastWasText = false;
237
250
  }
238
251
  function hasHeadChild(children) {
239
252
  if (children == null || typeof children === "boolean") return false;
@@ -253,62 +266,89 @@ function isElementOfType(value, type) {
253
266
  function isIterable(value) {
254
267
  return !!value && typeof value[Symbol.iterator] === "function";
255
268
  }
256
- function walkComponent(fn, props, opts) {
257
- if (fn.prototype?.isReactComponent) {
258
- const ctxType = fn.contextType;
259
- const ctxValue = ctxType ? ctxType._currentValue : void 0;
260
- const instance = new fn(props, ctxValue);
261
- instance.props = props;
262
- instance.context = ctxValue;
263
- if (fn.getDerivedStateFromProps) {
264
- const d = fn.getDerivedStateFromProps(props, instance.state);
265
- if (d) instance.state = { ...instance.state, ...d };
269
+ function walkComponent(fn, props, opts, ref) {
270
+ if (opts.onBrowserBailout) {
271
+ opts = { ...opts, componentStack: `
272
+ at ${fn.displayName || fn.name || "Anonymous"}${opts.componentStack || ""}` };
273
+ }
274
+ try {
275
+ if (fn.prototype?.isReactComponent) {
276
+ const ctxType = fn.contextType;
277
+ const ctxValue = ctxType ? ctxType._currentValue : void 0;
278
+ const instance = new fn(props, ctxValue);
279
+ instance.props = props;
280
+ instance.context = ctxValue;
281
+ if (fn.getDerivedStateFromProps) {
282
+ const d = fn.getDerivedStateFromProps(props, instance.state);
283
+ if (d) instance.state = { ...instance.state, ...d };
284
+ }
285
+ walkNode(instance.render(), opts);
286
+ return;
266
287
  }
267
- walkNode(instance.render(), opts);
268
- return;
288
+ const rendered = fn(props, ref);
289
+ walkNode(rendered, opts);
290
+ } catch (error) {
291
+ if (opts.thrownInfo && !opts.thrownInfo.componentStack) opts.thrownInfo.componentStack = opts.componentStack;
292
+ if (isBrowserError(error) && !error.componentStack) {
293
+ Object.defineProperty(error, "componentStack", { value: opts.componentStack });
294
+ }
295
+ throw error;
269
296
  }
270
- const rendered = fn(props);
271
- walkNode(rendered, opts);
272
297
  }
273
298
  function walkSuspense(props, opts) {
274
299
  const id = opts.nextBoundaryId();
275
300
  const contextSnapshot = snapshotContexts();
276
301
  const childParts = [];
302
+ const nested = [];
303
+ const thrownInfo = {};
277
304
  const childEmit = (s) => childParts.push(s);
305
+ const resourceScope = currentSSRFrame().shellFlushed ? {} : void 0;
278
306
  try {
279
307
  walkNode(props.children, {
308
+ ...opts,
309
+ resourceScope,
310
+ thrownInfo,
280
311
  emit: childEmit,
281
- onSuspend: opts.onSuspend,
312
+ onSuspend: opts.onSuspend ? (boundary) => nested.push(boundary) : void 0,
282
313
  nextBoundaryId: opts.nextBoundaryId
283
314
  });
284
315
  } catch (thenable) {
285
- if (isThenable(thenable)) {
316
+ nested.length = 0;
317
+ if (isThenable(thenable) || isBrowserError(thenable)) {
286
318
  const fallbackParts = [];
287
- try {
288
- walkNode(props.fallback, {
289
- emit: (s) => fallbackParts.push(s),
290
- onSuspend: opts.onSuspend,
291
- nextBoundaryId: opts.nextBoundaryId
292
- });
293
- } catch {
319
+ walkNode(props.fallback, {
320
+ ...opts,
321
+ emit: (s) => fallbackParts.push(s),
322
+ onSuspend: opts.onSuspend ? (boundary) => nested.push(boundary) : void 0,
323
+ nextBoundaryId: opts.nextBoundaryId
324
+ });
325
+ if (isBrowserError(thenable)) {
326
+ opts.onBrowserBailout?.(thenable, { componentStack: thenable.componentStack || opts.componentStack || "" });
327
+ opts.emit(`<!--$!${id}-->${fallbackParts.join("")}<!--/$-->`);
328
+ for (const boundary of nested) opts.onSuspend?.(boundary);
329
+ return;
294
330
  }
295
331
  emitBoundary(opts, id, fallbackParts.join(""));
332
+ for (const boundary of nested) opts.onSuspend?.(boundary);
296
333
  if (opts.onSuspend) {
297
334
  opts.onSuspend({
298
335
  id,
299
336
  fallbackHTML: fallbackParts.join(""),
300
337
  children: props.children,
301
338
  thenable,
302
- contextSnapshot
339
+ contextSnapshot,
340
+ componentStack: thrownInfo.componentStack || opts.componentStack || ""
303
341
  });
304
342
  }
305
343
  return;
306
344
  }
307
345
  throw thenable;
308
346
  }
347
+ if (resourceScope) currentSSRFrame().resources?.mergeScope(resourceScope, opts.resourceScope);
309
348
  opts.emit(`<!--$${id}-->`);
310
349
  opts.emit(childParts.join(""));
311
350
  opts.emit(`<!--/$-->`);
351
+ for (const boundary of nested) opts.onSuspend?.(boundary);
312
352
  }
313
353
  function emitBoundary(opts, id, fallbackHTML) {
314
354
  opts.emit(`<!--$?${id}--><div id="B:${id}">`);