@bgub/fig 0.1.0-alpha.0 → 0.1.0-alpha.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 (40) hide show
  1. package/CHANGELOG.md +495 -0
  2. package/README.md +50 -19
  3. package/dist/element-BZ7r9ncY.d.ts +342 -0
  4. package/dist/element-DmbzNH0T.js +299 -0
  5. package/dist/element-DmbzNH0T.js.map +1 -0
  6. package/dist/hooks-QDRabULx.d.ts +158 -0
  7. package/dist/index.d.ts +3 -5
  8. package/dist/index.js +4 -4
  9. package/dist/internal.d.ts +212 -6
  10. package/dist/internal.js +14 -43
  11. package/dist/internal.js.map +1 -1
  12. package/dist/jsx-runtime.d.ts +1 -1
  13. package/dist/jsx-runtime.js +3 -3
  14. package/dist/jsx-runtime.js.map +1 -1
  15. package/dist/payload-format-KTNaSI4h.js +366 -0
  16. package/dist/payload-format-KTNaSI4h.js.map +1 -0
  17. package/dist/payload.d.ts +92 -0
  18. package/dist/payload.js +429 -0
  19. package/dist/payload.js.map +1 -0
  20. package/dist/{transition-DEqcImne.js → resource-kXeIR52S.js} +121 -71
  21. package/dist/resource-kXeIR52S.js.map +1 -0
  22. package/dist/{data-store-CRnNAT9-.js → transition-CC4kjjrU.js} +165 -54
  23. package/dist/transition-CC4kjjrU.js.map +1 -0
  24. package/package.json +5 -6
  25. package/dist/data-CHJh_xU9.d.ts +0 -79
  26. package/dist/data-h46EcMnE.js +0 -37
  27. package/dist/data-h46EcMnE.js.map +0 -1
  28. package/dist/data-store-CRnNAT9-.js.map +0 -1
  29. package/dist/data-store-EQOLQsW4.d.ts +0 -32
  30. package/dist/element-Bh_k9c3N.js +0 -179
  31. package/dist/element-Bh_k9c3N.js.map +0 -1
  32. package/dist/element-CCOOi4Ka.d.ts +0 -209
  33. package/dist/server.browser.d.ts +0 -9
  34. package/dist/server.browser.js +0 -8
  35. package/dist/server.browser.js.map +0 -1
  36. package/dist/server.d.ts +0 -9
  37. package/dist/server.js +0 -9
  38. package/dist/server.js.map +0 -1
  39. package/dist/transition-Cl6mAPcx.d.ts +0 -96
  40. package/dist/transition-DEqcImne.js.map +0 -1
package/dist/internal.js CHANGED
@@ -1,7 +1,7 @@
1
- import { a as assetResourceFromHostProps, d as isFigAssetResource, i as assetResourceFromHostAttributes, l as clientReferenceAssets, o as assetResourceHostAttributes, r as assetResourceDestination, s as assetResourceKey, t as setTransitionHandler, x as isContext, y as FigContextSymbol } from "./transition-DEqcImne.js";
2
- import { i as setCurrentDataStore, n as markDataResourceError, r as resolveCurrentDataStore, t as dataResourceKeysForError } from "./data-h46EcMnE.js";
3
- import { c as normalizeDataResourceKey, d as runWithDataStore, n as currentDataStore, t as createDataStore } from "./data-store-CRnNAT9-.js";
4
- import { C as isSuspense, S as isPortal, T as isViewTransition, a as FigAssetsSymbol, b as isClientReference, c as FigErrorBoundarySymbol, d as FigViewTransitionSymbol, i as FigActivitySymbol, j as setCurrentDispatcher, l as FigPortalSymbol, n as Assets, o as FigClientReferenceSymbol, s as FigElementSymbol, u as FigSuspenseSymbol, v as isActivity, w as isValidElement, x as isErrorBoundary, y as isAssets } from "./element-Bh_k9c3N.js";
1
+ import { _ as runWithDataStore, a as createRendererDataStore, b as isContext, i as createDataStore, m as normalizeDataResourceKey, o as currentDataStore, p as isDataStoreController, r as attachDataStore, t as setTransitionHandler, v as FigContextSymbol } from "./transition-CC4kjjrU.js";
2
+ import { $ as loadContextCapabilities, A as markClientOnlyHostBehavior, C as isSuspense, D as FigMixinSymbol, L as setCurrentDispatcher, M as resolveHostMix, O as clientOnlyHostBehavior, S as isPortal, T as isViewTransition, X as dataResourceKeysForError, Z as defineLoadContextCapabilities, _ as createPortalNode, a as FigAssetsSymbol, b as isClientReference, c as FigErrorBoundarySymbol, d as FigViewTransitionSymbol, et as markDataResourceError, i as FigActivitySymbol, j as mixinSlot, l as FigPortalSymbol, n as Assets, nt as setCurrentDataStore, o as FigClientReferenceSymbol, s as FigElementSymbol, tt as resolveCurrentDataStore, u as FigSuspenseSymbol, v as isActivity, w as isValidElement, x as isErrorBoundary, y as isAssets } from "./element-DmbzNH0T.js";
3
+ import { a as assetResourceKey, b as trackThenable, i as assetResourceHostAttributes, l as isFigAssetResource, m as preventAssetResourceHoist, n as assetResourceFromHostAttributes, r as assetResourceFromHostProps, s as clientReferenceAssets, t as assetResourceDestination, v as isThenable, y as readThenable } from "./resource-kXeIR52S.js";
4
+ import { _ as serializePayloadArray, b as serializePayloadSet, c as definePayloadGraphElement, d as encodePayloadValueWithGraph, g as rollbackPayloadGraph, h as jsonPayloadCodec, i as decodePayloadDataEntries, l as encodePayloadDataEntries, m as isPlainPayloadValue, n as checkpointPayloadGraph, o as decodePayloadValue, p as isPayloadSpecialModel, r as createPayloadGraphEncodeContext, t as assertPayloadCodecMatches, u as encodePayloadValue, v as serializePayloadMap, y as serializePayloadPlainObject } from "./payload-format-KTNaSI4h.js";
5
5
  //#region src/children.ts
6
6
  function collectChildren(node) {
7
7
  const children = [];
@@ -22,6 +22,10 @@ function collectChild(node, children) {
22
22
  children.push(node);
23
23
  return;
24
24
  }
25
+ if (isThenable(node)) {
26
+ children.push(node);
27
+ return;
28
+ }
25
29
  throw invalidChildError(node);
26
30
  }
27
31
  function appendTextChild(children, text) {
@@ -30,7 +34,7 @@ function appendTextChild(children, text) {
30
34
  else children.push(text);
31
35
  }
32
36
  function invalidChildError(value) {
33
- return /* @__PURE__ */ new Error(`Invalid Fig child: ${describeInvalidChild(value)}. Render a string, number, element, array, boolean, null, or undefined.`);
37
+ return /* @__PURE__ */ new Error(`Invalid Fig child: ${describeInvalidChild(value)}. Render a string, number, element, promise, array, boolean, null, or undefined.`);
34
38
  }
35
39
  function describeInvalidChild(value) {
36
40
  if (typeof value !== "object" || value === null) return typeof value;
@@ -68,7 +72,7 @@ function validWithParent(child, parent) {
68
72
  case "tfoot": return child === "tr" || scriptLike(child);
69
73
  case "colgroup": return child === "col" || child === "template";
70
74
  case "table": return child === "caption" || child === "colgroup" || child === "tbody" || child === "tfoot" || child === "thead" || scriptLike(child);
71
- case "head": return headChild(child);
75
+ case "head": return tagIn(headChildren, child);
72
76
  case "html": return child === "head" || child === "body";
73
77
  case "frameset": return child === "frame";
74
78
  }
@@ -128,9 +132,6 @@ function normalizedTag(type) {
128
132
  function scriptLike(tag) {
129
133
  return tag === "script" || tag === "style" || tag === "template";
130
134
  }
131
- function headChild(tag) {
132
- return tagIn(headChildren, tag);
133
- }
134
135
  function hintFor(child, parent) {
135
136
  if (parent === "table" && child === "tr") return " Add a <tbody>, <thead>, or <tfoot>.";
136
137
  return "";
@@ -148,10 +149,13 @@ const SUSPENSE_COMPLETED_MARKER = "fig:suspense:completed";
148
149
  const SUSPENSE_CLIENT_MARKER = "fig:suspense:client";
149
150
  const SUSPENSE_PENDING_PREFIX = "fig:suspense:pending:";
150
151
  const SUSPENSE_END_MARKER = "/fig:suspense";
152
+ const TEXT_SEPARATOR_DATA = ",";
151
153
  const ACTIVITY_TEMPLATE_ATTRIBUTE = "data-fig-activity";
152
154
  const VIEW_TRANSITION_NAME_ATTRIBUTE = "data-fig-vt-name";
153
155
  const VIEW_TRANSITION_CLASS_ATTRIBUTE = "data-fig-vt-class";
154
156
  const VIEW_TRANSITION_PENDING_PROPERTY = "__figViewTransition";
157
+ const VIEW_TRANSITION_TIMEOUT_MS = 6e4;
158
+ const HYDRATION_SKIP_ATTRIBUTE = "data-fig-hydration-skip";
155
159
  const EARLY_EVENT_QUEUE_PROPERTY = "__figEarlyEvents";
156
160
  const EARLY_EVENT_HANDLER_PROPERTY = "__figEarlyEventHandler";
157
161
  const REPLAYABLE_EVENT_TYPES = [
@@ -162,39 +166,6 @@ const REPLAYABLE_EVENT_TYPES = [
162
166
  "pointerup"
163
167
  ];
164
168
  //#endregion
165
- //#region src/thenables.ts
166
- const thenableRecords = /* @__PURE__ */ new WeakMap();
167
- function recordFor(thenable) {
168
- const key = thenable;
169
- let record = thenableRecords.get(key);
170
- if (record === void 0) {
171
- const pendingRecord = { status: "pending" };
172
- record = pendingRecord;
173
- thenableRecords.set(key, pendingRecord);
174
- thenable.then((value) => {
175
- pendingRecord.status = "fulfilled";
176
- pendingRecord.value = value;
177
- }, (reason) => {
178
- pendingRecord.status = "rejected";
179
- pendingRecord.reason = reason;
180
- });
181
- }
182
- return record;
183
- }
184
- function trackThenable(thenable) {
185
- recordFor(thenable);
186
- }
187
- function readThenable(thenable) {
188
- const record = recordFor(thenable);
189
- if (record.status === "fulfilled") return record.value;
190
- if (record.status === "rejected") throw record.reason;
191
- throw thenable;
192
- }
193
- function isThenable(value) {
194
- if (typeof value !== "object" && typeof value !== "function" || value === null) return false;
195
- return typeof value.then === "function";
196
- }
197
- //#endregion
198
- export { ACTIVITY_TEMPLATE_ATTRIBUTE, Assets, EARLY_EVENT_HANDLER_PROPERTY, EARLY_EVENT_QUEUE_PROPERTY, FigActivitySymbol, FigAssetsSymbol, FigClientReferenceSymbol, FigContextSymbol, FigElementSymbol, FigErrorBoundarySymbol, FigPortalSymbol, FigSuspenseSymbol, FigViewTransitionSymbol, REPLAYABLE_EVENT_TYPES, SUSPENSE_CLIENT_MARKER, SUSPENSE_COMPLETED_MARKER, SUSPENSE_END_MARKER, SUSPENSE_MARKER_PREFIX, SUSPENSE_PENDING_PREFIX, VIEW_TRANSITION_CLASS_ATTRIBUTE, VIEW_TRANSITION_NAME_ATTRIBUTE, VIEW_TRANSITION_PENDING_PROPERTY, assetResourceDestination, assetResourceFromHostAttributes, assetResourceFromHostProps, assetResourceHostAttributes, assetResourceKey, clientReferenceAssets, collectChildren, createDataStore, currentDataStore, dataResourceKeysForError, describeInvalidChild, invalidChildError, isActivity, isAssets, isClientReference, isContext, isErrorBoundary, isFigAssetResource, isPortal, isSuspense, isThenable, isValidElement, isViewTransition, markDataResourceError, normalizeDataResourceKey, readThenable, resolveCurrentDataStore, runWithDataStore, setCurrentDataStore, setCurrentDispatcher, setTransitionHandler, trackThenable, validateInstanceNesting, validateTextNesting };
169
+ export { ACTIVITY_TEMPLATE_ATTRIBUTE, Assets, EARLY_EVENT_HANDLER_PROPERTY, EARLY_EVENT_QUEUE_PROPERTY, FigActivitySymbol, FigAssetsSymbol, FigClientReferenceSymbol, FigContextSymbol, FigElementSymbol, FigErrorBoundarySymbol, FigMixinSymbol, FigPortalSymbol, FigSuspenseSymbol, FigViewTransitionSymbol, HYDRATION_SKIP_ATTRIBUTE, REPLAYABLE_EVENT_TYPES, SUSPENSE_CLIENT_MARKER, SUSPENSE_COMPLETED_MARKER, SUSPENSE_END_MARKER, SUSPENSE_MARKER_PREFIX, SUSPENSE_PENDING_PREFIX, TEXT_SEPARATOR_DATA, VIEW_TRANSITION_CLASS_ATTRIBUTE, VIEW_TRANSITION_NAME_ATTRIBUTE, VIEW_TRANSITION_PENDING_PROPERTY, VIEW_TRANSITION_TIMEOUT_MS, assertPayloadCodecMatches, assetResourceDestination, assetResourceFromHostAttributes, assetResourceFromHostProps, assetResourceHostAttributes, assetResourceKey, attachDataStore, checkpointPayloadGraph, clientOnlyHostBehavior, clientReferenceAssets, collectChildren, createDataStore, createPayloadGraphEncodeContext, createPortalNode, createRendererDataStore, currentDataStore, dataResourceKeysForError, decodePayloadDataEntries, decodePayloadValue, defineLoadContextCapabilities, definePayloadGraphElement, describeInvalidChild, encodePayloadDataEntries, encodePayloadValue, encodePayloadValueWithGraph, invalidChildError, isActivity, isAssets, isClientReference, isContext, isDataStoreController, isErrorBoundary, isFigAssetResource, isPayloadSpecialModel, isPlainPayloadValue, isPortal, isSuspense, isThenable, isViewTransition, jsonPayloadCodec, loadContextCapabilities, markClientOnlyHostBehavior, markDataResourceError, mixinSlot, normalizeDataResourceKey, preventAssetResourceHoist, readThenable, resolveCurrentDataStore, resolveHostMix, rollbackPayloadGraph, runWithDataStore, serializePayloadArray, serializePayloadMap, serializePayloadPlainObject, serializePayloadSet, setCurrentDataStore, setCurrentDispatcher, setTransitionHandler, trackThenable, validateInstanceNesting, validateTextNesting };
199
170
 
200
171
  //# sourceMappingURL=internal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"internal.js","names":[],"sources":["../src/children.ts","../src/dom-nesting.ts","../src/suspense-protocol.ts","../src/thenables.ts"],"sourcesContent":["import {\n type FigElement,\n type FigNode,\n type FigPortal,\n isPortal,\n isValidElement,\n} from \"./element.ts\";\n\n// What normalization leaves behind: arrays are flattened, null/undefined/\n// booleans are dropped, and numbers are stringified into (merged) text.\nexport type NormalizedChild = FigElement<any> | FigPortal<any> | string;\n\n// Child normalization shared by the reconciler and the server renderer.\n// Adjacent text merging here MUST match on both sides: the server emits\n// merged text nodes into HTML, and hydration matches them against the\n// client's fiber children — divergence is a hydration mismatch.\nexport function collectChildren(node: FigNode): NormalizedChild[] {\n const children: NormalizedChild[] = [];\n collectChild(node, children);\n return children;\n}\n\nfunction collectChild(node: FigNode, children: NormalizedChild[]): void {\n if (Array.isArray(node)) {\n for (const child of node) collectChild(child, children);\n return;\n }\n\n if (node === null || node === undefined || typeof node === \"boolean\") return;\n\n if (typeof node === \"string\" || typeof node === \"number\") {\n appendTextChild(children, String(node));\n return;\n }\n\n if (isValidElement(node) || isPortal(node)) {\n children.push(node);\n return;\n }\n\n throw invalidChildError(node);\n}\n\nfunction appendTextChild(children: NormalizedChild[], text: string): void {\n const previous = children.at(-1);\n\n if (typeof previous === \"string\") {\n children[children.length - 1] = `${previous}${text}`;\n } else {\n children.push(text);\n }\n}\n\nexport function invalidChildError(value: unknown): Error {\n return new Error(\n `Invalid Fig child: ${describeInvalidChild(value)}. Render a string, number, element, array, boolean, null, or undefined.`,\n );\n}\n\nexport function describeInvalidChild(value: unknown): string {\n if (typeof value !== \"object\" || value === null) return typeof value;\n\n const keys = Object.keys(value);\n return keys.length === 0 ? \"object\" : `object with keys ${keys.join(\", \")}`;\n}\n","const phrasingContainers = \"|a|button|p|\";\n\n// HTML parser auto-close rules are scoped: these tags reset the \"is there an\n// open <a>/<button>/<p>?\" checks, so e.g. <a><table><td><a> and\n// <p><button><div> parse without re-parenting and must not be flagged.\n// <button> additionally terminates button scope (the <p> auto-close check).\nconst scopeTerminators =\n \"|applet|caption|desc|foreignobject|html|marquee|object|table|td|template|th|title|\";\n\nconst pAutoClosingTags =\n \"|address|article|aside|blockquote|center|details|dialog|dir|div|dl|fieldset|figcaption|figure|footer|form|h1|h2|h3|h4|h5|h6|header|hgroup|hr|main|menu|nav|ol|p|pre|section|table|ul|\";\n\nconst headChildren =\n \"|base|basefont|bgsound|link|meta|title|noscript|noframes|script|style|template|\";\n\nconst specialTags =\n \"|address|applet|area|article|aside|base|basefont|bgsound|blockquote|body|br|button|caption|center|col|colgroup|dd|details|dir|div|dl|dt|embed|fieldset|figcaption|figure|footer|form|frame|frameset|h1|h2|h3|h4|h5|h6|head|header|hgroup|hr|html|iframe|img|input|keygen|li|link|listing|main|marquee|menu|meta|nav|noembed|noframes|noscript|object|ol|p|param|plaintext|pre|script|section|select|source|style|summary|table|tbody|td|template|textarea|tfoot|th|thead|title|tr|track|ul|wbr|xmp|mi|mo|mn|ms|mtext|annotation-xml|foreignobject|desc|\";\n\nexport function validateInstanceNesting(\n type: string,\n ancestors: readonly string[],\n): void {\n const child = normalizedTag(type);\n const parent =\n ancestors[0] === undefined ? null : normalizedTag(ancestors[0]);\n\n if (parent !== null && !validWithParent(child, parent)) {\n throw invalidNestingError(\n `<${child}> cannot be a child of <${parent}>.${hintFor(child, parent)}`,\n );\n }\n\n const invalidAncestor = invalidAncestorFor(child, ancestors);\n if (invalidAncestor !== null) {\n throw invalidNestingError(\n `<${child}> cannot appear inside <${invalidAncestor}>.`,\n );\n }\n}\n\nexport function validateTextNesting(\n text: string,\n ancestors: readonly string[],\n): void {\n // Whitespace-only text is inserted in place even inside tables (\"in table\n // text\" mode only foster-parents non-whitespace), so it is harmless.\n if (!/[^ \\t\\n\\r\\f]/.test(text)) return;\n\n const parent =\n ancestors[0] === undefined ? null : normalizedTag(ancestors[0]);\n if (parent === null || validTextWithParent(parent)) return;\n\n throw invalidNestingError(`text cannot be a child of <${parent}>.`);\n}\n\nfunction validWithParent(child: string, parent: string): boolean {\n switch (parent) {\n case \"select\":\n return (\n child === \"hr\" ||\n child === \"option\" ||\n child === \"optgroup\" ||\n child === \"script\" ||\n child === \"template\"\n );\n case \"optgroup\":\n return child === \"option\";\n case \"option\":\n return false;\n case \"tr\":\n return child === \"th\" || child === \"td\" || scriptLike(child);\n case \"tbody\":\n case \"thead\":\n case \"tfoot\":\n return child === \"tr\" || scriptLike(child);\n case \"colgroup\":\n return child === \"col\" || child === \"template\";\n case \"table\":\n return (\n child === \"caption\" ||\n child === \"colgroup\" ||\n child === \"tbody\" ||\n child === \"tfoot\" ||\n child === \"thead\" ||\n scriptLike(child)\n );\n case \"head\":\n return headChild(child);\n case \"html\":\n return child === \"head\" || child === \"body\";\n case \"frameset\":\n return child === \"frame\";\n }\n\n switch (child) {\n case \"caption\":\n case \"col\":\n case \"colgroup\":\n case \"tbody\":\n case \"tfoot\":\n case \"thead\":\n case \"tr\":\n return parent === \"template\";\n case \"td\":\n case \"th\":\n return parent === \"tr\" || parent === \"template\";\n case \"option\":\n return parent === \"datalist\" || parent === \"template\";\n case \"optgroup\":\n return parent === \"template\";\n case \"head\":\n case \"body\":\n case \"frameset\":\n return parent === \"html\" || parent === \"template\";\n case \"frame\":\n return parent === \"template\";\n case \"html\":\n return false;\n }\n\n return true;\n}\n\nfunction validTextWithParent(parent: string): boolean {\n // <option>, <select>, and <optgroup> reject element children, but the\n // parser inserts character tokens into them in place, so text is legal.\n return (\n parent === \"option\" ||\n parent === \"select\" ||\n parent === \"optgroup\" ||\n validWithParent(\"#text\", parent)\n );\n}\n\nfunction invalidAncestorFor(\n child: string,\n ancestors: readonly string[],\n): string | null {\n let inScope = true;\n let inButtonScope = true;\n let inListScope = true;\n let inTemplate = false;\n\n for (const ancestorType of ancestors) {\n const ancestor = normalizedTag(ancestorType);\n\n if (child === ancestor && tagIn(phrasingContainers, child)) {\n if (child === \"p\" ? inButtonScope : inScope) return ancestor;\n }\n if (inButtonScope && ancestor === \"p\" && tagIn(pAutoClosingTags, child)) {\n return ancestor;\n }\n if (inListScope && listItemAncestor(child, ancestor)) return ancestor;\n // The parser's form element pointer ignores scope but resets in templates.\n if (!inTemplate && ancestor === \"form\" && child === \"form\") return ancestor;\n\n if (tagIn(scopeTerminators, ancestor)) {\n if (ancestor === \"template\") inTemplate = true;\n inScope = false;\n inButtonScope = false;\n } else if (ancestor === \"button\") {\n inButtonScope = false;\n }\n // li/dd/dt auto-closing sees through phrasing/formatting wrappers and\n // address/div/p; other special elements terminate the parser walk.\n if (\n tagIn(specialTags, ancestor) &&\n ancestor !== \"address\" &&\n ancestor !== \"div\" &&\n ancestor !== \"p\"\n ) {\n inListScope = false;\n }\n }\n\n return null;\n}\n\nfunction listItemAncestor(child: string, ancestor: string): boolean {\n if (child === \"li\") return ancestor === \"li\";\n if (child === \"dd\" || child === \"dt\") {\n return ancestor === \"dd\" || ancestor === \"dt\";\n }\n return false;\n}\n\nfunction normalizedTag(type: string): string {\n return type.toLowerCase();\n}\n\nfunction scriptLike(tag: string): boolean {\n return tag === \"script\" || tag === \"style\" || tag === \"template\";\n}\n\nfunction headChild(tag: string): boolean {\n return tagIn(headChildren, tag);\n}\n\nfunction hintFor(child: string, parent: string): string {\n if (parent === \"table\" && child === \"tr\") {\n return \" Add a <tbody>, <thead>, or <tfoot>.\";\n }\n\n return \"\";\n}\n\nfunction invalidNestingError(message: string): Error {\n return new Error(`Invalid DOM nesting: ${message}`);\n}\n\nfunction tagIn(tags: string, tag: string): boolean {\n return tags.includes(`|${tag}|`);\n}\n","// The Suspense streaming wire format shared by the server renderer (which\n// emits these markers as HTML comments and interpolates them into the inline\n// reveal script) and fig-dom (which parses them into dehydrated boundaries).\n// Changing any value is a protocol change: server output and client parsing\n// must move together.\n\nexport const SUSPENSE_MARKER_PREFIX = \"fig:suspense:\";\nexport const SUSPENSE_COMPLETED_MARKER = \"fig:suspense:completed\";\nexport const SUSPENSE_CLIENT_MARKER = \"fig:suspense:client\";\nexport const SUSPENSE_PENDING_PREFIX = \"fig:suspense:pending:\";\nexport const SUSPENSE_END_MARKER = \"/fig:suspense\";\n\n// Hidden Activity content streams inside an inert template carrying this\n// attribute; the client treats such templates as dehydrated boundaries.\nexport const ACTIVITY_TEMPLATE_ATTRIBUTE = \"data-fig-activity\";\n\nexport const VIEW_TRANSITION_NAME_ATTRIBUTE = \"data-fig-vt-name\";\nexport const VIEW_TRANSITION_CLASS_ATTRIBUTE = \"data-fig-vt-class\";\n\n// Per-document mutex holding the currently running view transition. Client\n// commits and inline streaming reveals both check it and chain on the\n// previous transition's finished promise, so concurrent transitions never\n// skip each other's animations or clobber temporarily applied names.\nexport const VIEW_TRANSITION_PENDING_PROPERTY = \"__figViewTransition\";\n\n// Early-event capture: a tiny inline script at the top of a server-rendered\n// document queues replayable events that fire before the client bundle\n// executes. The first hydration root drains the queue, removes the capture\n// listeners, and replays claimed events through the standard replay path.\n// The event list must stay in sync with fig-dom's replayable set — a\n// discrete replay forces synchronous hydration of its target, which is what\n// makes pre-bundle clicks safe to honor.\nexport const EARLY_EVENT_QUEUE_PROPERTY = \"__figEarlyEvents\";\nexport const EARLY_EVENT_HANDLER_PROPERTY = \"__figEarlyEventHandler\";\nexport const REPLAYABLE_EVENT_TYPES = [\n \"click\",\n \"keydown\",\n \"keyup\",\n \"pointerdown\",\n \"pointerup\",\n] as const;\n","export type Thenable<T = unknown> = PromiseLike<T> & object;\n\ninterface ThenableRecord<T> {\n status: \"pending\" | \"fulfilled\" | \"rejected\";\n value?: T;\n reason?: unknown;\n}\n\n// One process-wide registry keyed by thenable identity: the reconciler's\n// readPromise, the server renderers' dispatchers, and preloaders all share\n// it, so suspend/settle semantics cannot drift between client and server.\nconst thenableRecords = new WeakMap<object, ThenableRecord<unknown>>();\n\nfunction recordFor<T>(thenable: PromiseLike<T>): ThenableRecord<T> {\n const key = thenable as Thenable<T>;\n let record = thenableRecords.get(key) as ThenableRecord<T> | undefined;\n\n if (record === undefined) {\n const pendingRecord: ThenableRecord<T> = { status: \"pending\" };\n record = pendingRecord;\n thenableRecords.set(key, pendingRecord);\n thenable.then(\n (value) => {\n pendingRecord.status = \"fulfilled\";\n pendingRecord.value = value;\n },\n (reason: unknown) => {\n pendingRecord.status = \"rejected\";\n pendingRecord.reason = reason;\n },\n );\n }\n\n return record;\n}\n\n// Starts tracking without reading. Preloaders call this when they begin a\n// load so that a thenable settled before its first render read resolves\n// synchronously instead of suspending for one retry beat.\nexport function trackThenable<T>(thenable: PromiseLike<T>): void {\n recordFor(thenable);\n}\n\nexport function readThenable<T>(thenable: PromiseLike<T>): T {\n const record = recordFor(thenable);\n if (record.status === \"fulfilled\") return record.value as T;\n if (record.status === \"rejected\") throw record.reason;\n throw thenable;\n}\n\nexport function isThenable(value: unknown): value is Thenable {\n if (\n (typeof value !== \"object\" && typeof value !== \"function\") ||\n value === null\n ) {\n return false;\n }\n\n return typeof (value as PromiseLike<unknown>).then === \"function\";\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"internal.js","names":[],"sources":["../src/children.ts","../src/dom-nesting.ts","../src/suspense-protocol.ts"],"sourcesContent":["import {\n type AwaitedFigNode,\n type FigElement,\n type FigNode,\n type FigPortal,\n isPortal,\n isValidElement,\n} from \"./element.ts\";\nimport { isThenable } from \"./thenables.ts\";\n\n// What normalization leaves behind: arrays are flattened, null/undefined/\n// booleans are dropped, and numbers are stringified into (merged) text.\nexport type NormalizedChild =\n | FigElement<any>\n | FigPortal<any>\n | PromiseLike<AwaitedFigNode>\n | string;\n\n// Child normalization shared by the reconciler and the server renderer.\n// Adjacent text merging here MUST match on both sides: the server emits\n// merged text nodes into HTML, and hydration matches them against the\n// client's fiber children — divergence is a hydration mismatch.\nexport function collectChildren(node: FigNode): NormalizedChild[] {\n const children: NormalizedChild[] = [];\n collectChild(node, children);\n return children;\n}\n\nfunction collectChild(node: FigNode, children: NormalizedChild[]): void {\n if (Array.isArray(node)) {\n for (const child of node) collectChild(child, children);\n return;\n }\n\n if (node === null || node === undefined || typeof node === \"boolean\") return;\n\n if (typeof node === \"string\" || typeof node === \"number\") {\n appendTextChild(children, String(node));\n return;\n }\n\n if (isValidElement(node) || isPortal(node)) {\n children.push(node);\n return;\n }\n\n if (isThenable(node)) {\n children.push(node);\n return;\n }\n\n throw invalidChildError(node);\n}\n\nfunction appendTextChild(children: NormalizedChild[], text: string): void {\n const previous = children.at(-1);\n\n if (typeof previous === \"string\") {\n children[children.length - 1] = `${previous}${text}`;\n } else {\n children.push(text);\n }\n}\n\nexport function invalidChildError(value: unknown): Error {\n return new Error(\n `Invalid Fig child: ${describeInvalidChild(value)}. Render a string, number, element, promise, array, boolean, null, or undefined.`,\n );\n}\n\nexport function describeInvalidChild(value: unknown): string {\n if (typeof value !== \"object\" || value === null) return typeof value;\n\n const keys = Object.keys(value);\n return keys.length === 0 ? \"object\" : `object with keys ${keys.join(\", \")}`;\n}\n","const phrasingContainers = \"|a|button|p|\";\n\n// HTML parser auto-close rules are scoped: these tags reset the \"is there an\n// open <a>/<button>/<p>?\" checks, so e.g. <a><table><td><a> and\n// <p><button><div> parse without re-parenting and must not be flagged.\n// <button> additionally terminates button scope (the <p> auto-close check).\nconst scopeTerminators =\n \"|applet|caption|desc|foreignobject|html|marquee|object|table|td|template|th|title|\";\n\nconst pAutoClosingTags =\n \"|address|article|aside|blockquote|center|details|dialog|dir|div|dl|fieldset|figcaption|figure|footer|form|h1|h2|h3|h4|h5|h6|header|hgroup|hr|main|menu|nav|ol|p|pre|section|table|ul|\";\n\nconst headChildren =\n \"|base|basefont|bgsound|link|meta|title|noscript|noframes|script|style|template|\";\n\nconst specialTags =\n \"|address|applet|area|article|aside|base|basefont|bgsound|blockquote|body|br|button|caption|center|col|colgroup|dd|details|dir|div|dl|dt|embed|fieldset|figcaption|figure|footer|form|frame|frameset|h1|h2|h3|h4|h5|h6|head|header|hgroup|hr|html|iframe|img|input|keygen|li|link|listing|main|marquee|menu|meta|nav|noembed|noframes|noscript|object|ol|p|param|plaintext|pre|script|section|select|source|style|summary|table|tbody|td|template|textarea|tfoot|th|thead|title|tr|track|ul|wbr|xmp|mi|mo|mn|ms|mtext|annotation-xml|foreignobject|desc|\";\n\nexport function validateInstanceNesting(\n type: string,\n ancestors: readonly string[],\n): void {\n const child = normalizedTag(type);\n const parent =\n ancestors[0] === undefined ? null : normalizedTag(ancestors[0]);\n\n if (parent !== null && !validWithParent(child, parent)) {\n throw invalidNestingError(\n `<${child}> cannot be a child of <${parent}>.${hintFor(child, parent)}`,\n );\n }\n\n const invalidAncestor = invalidAncestorFor(child, ancestors);\n if (invalidAncestor !== null) {\n throw invalidNestingError(\n `<${child}> cannot appear inside <${invalidAncestor}>.`,\n );\n }\n}\n\nexport function validateTextNesting(\n text: string,\n ancestors: readonly string[],\n): void {\n // Whitespace-only text is inserted in place even inside tables (\"in table\n // text\" mode only foster-parents non-whitespace), so it is harmless.\n if (!/[^ \\t\\n\\r\\f]/.test(text)) return;\n\n const parent =\n ancestors[0] === undefined ? null : normalizedTag(ancestors[0]);\n if (parent === null || validTextWithParent(parent)) return;\n\n throw invalidNestingError(`text cannot be a child of <${parent}>.`);\n}\n\nfunction validWithParent(child: string, parent: string): boolean {\n switch (parent) {\n case \"select\":\n return (\n child === \"hr\" ||\n child === \"option\" ||\n child === \"optgroup\" ||\n child === \"script\" ||\n child === \"template\"\n );\n case \"optgroup\":\n return child === \"option\";\n case \"option\":\n return false;\n case \"tr\":\n return child === \"th\" || child === \"td\" || scriptLike(child);\n case \"tbody\":\n case \"thead\":\n case \"tfoot\":\n return child === \"tr\" || scriptLike(child);\n case \"colgroup\":\n return child === \"col\" || child === \"template\";\n case \"table\":\n return (\n child === \"caption\" ||\n child === \"colgroup\" ||\n child === \"tbody\" ||\n child === \"tfoot\" ||\n child === \"thead\" ||\n scriptLike(child)\n );\n case \"head\":\n return tagIn(headChildren, child);\n case \"html\":\n return child === \"head\" || child === \"body\";\n case \"frameset\":\n return child === \"frame\";\n }\n\n switch (child) {\n case \"caption\":\n case \"col\":\n case \"colgroup\":\n case \"tbody\":\n case \"tfoot\":\n case \"thead\":\n case \"tr\":\n return parent === \"template\";\n case \"td\":\n case \"th\":\n return parent === \"tr\" || parent === \"template\";\n case \"option\":\n return parent === \"datalist\" || parent === \"template\";\n case \"optgroup\":\n return parent === \"template\";\n case \"head\":\n case \"body\":\n case \"frameset\":\n return parent === \"html\" || parent === \"template\";\n case \"frame\":\n return parent === \"template\";\n case \"html\":\n return false;\n }\n\n return true;\n}\n\nfunction validTextWithParent(parent: string): boolean {\n // <option>, <select>, and <optgroup> reject element children, but the\n // parser inserts character tokens into them in place, so text is legal.\n return (\n parent === \"option\" ||\n parent === \"select\" ||\n parent === \"optgroup\" ||\n validWithParent(\"#text\", parent)\n );\n}\n\nfunction invalidAncestorFor(\n child: string,\n ancestors: readonly string[],\n): string | null {\n let inScope = true;\n let inButtonScope = true;\n let inListScope = true;\n let inTemplate = false;\n\n for (const ancestorType of ancestors) {\n const ancestor = normalizedTag(ancestorType);\n\n if (child === ancestor && tagIn(phrasingContainers, child)) {\n if (child === \"p\" ? inButtonScope : inScope) return ancestor;\n }\n if (inButtonScope && ancestor === \"p\" && tagIn(pAutoClosingTags, child)) {\n return ancestor;\n }\n if (inListScope && listItemAncestor(child, ancestor)) return ancestor;\n // The parser's form element pointer ignores scope but resets in templates.\n if (!inTemplate && ancestor === \"form\" && child === \"form\") return ancestor;\n\n if (tagIn(scopeTerminators, ancestor)) {\n if (ancestor === \"template\") inTemplate = true;\n inScope = false;\n inButtonScope = false;\n } else if (ancestor === \"button\") {\n inButtonScope = false;\n }\n // li/dd/dt auto-closing sees through phrasing/formatting wrappers and\n // address/div/p; other special elements terminate the parser walk.\n if (\n tagIn(specialTags, ancestor) &&\n ancestor !== \"address\" &&\n ancestor !== \"div\" &&\n ancestor !== \"p\"\n ) {\n inListScope = false;\n }\n }\n\n return null;\n}\n\nfunction listItemAncestor(child: string, ancestor: string): boolean {\n if (child === \"li\") return ancestor === \"li\";\n if (child === \"dd\" || child === \"dt\") {\n return ancestor === \"dd\" || ancestor === \"dt\";\n }\n return false;\n}\n\nfunction normalizedTag(type: string): string {\n return type.toLowerCase();\n}\n\nfunction scriptLike(tag: string): boolean {\n return tag === \"script\" || tag === \"style\" || tag === \"template\";\n}\n\nfunction hintFor(child: string, parent: string): string {\n if (parent === \"table\" && child === \"tr\") {\n return \" Add a <tbody>, <thead>, or <tfoot>.\";\n }\n\n return \"\";\n}\n\nfunction invalidNestingError(message: string): Error {\n return new Error(`Invalid DOM nesting: ${message}`);\n}\n\nfunction tagIn(tags: string, tag: string): boolean {\n return tags.includes(`|${tag}|`);\n}\n","// The Suspense streaming wire format shared by the server renderer (which\n// emits these markers as HTML comments and interpolates them into the inline\n// reveal script) and fig-dom (which parses them into dehydrated boundaries).\n// Changing any value is a protocol change: server output and client parsing\n// must move together.\n\nexport const SUSPENSE_MARKER_PREFIX = \"fig:suspense:\";\nexport const SUSPENSE_COMPLETED_MARKER = \"fig:suspense:completed\";\nexport const SUSPENSE_CLIENT_MARKER = \"fig:suspense:client\";\nexport const SUSPENSE_PENDING_PREFIX = \"fig:suspense:pending:\";\nexport const SUSPENSE_END_MARKER = \"/fig:suspense\";\n\n// The server emits a comment with exactly this data between adjacent text\n// writes that come from different normalized text children: the HTML parser\n// would otherwise merge them into one DOM text node while the client keeps\n// one text fiber each. fig-dom's hydration cursor skips only comments whose\n// data matches this value (fig:suspense markers use their own prefixes).\nexport const TEXT_SEPARATOR_DATA = \",\";\n\n// Hidden Activity content streams inside an inert template carrying this\n// attribute; the client treats such templates as dehydrated boundaries.\nexport const ACTIVITY_TEMPLATE_ATTRIBUTE = \"data-fig-activity\";\n\nexport const VIEW_TRANSITION_NAME_ATTRIBUTE = \"data-fig-vt-name\";\nexport const VIEW_TRANSITION_CLASS_ATTRIBUTE = \"data-fig-vt-class\";\n\n// Per-document mutex holding the currently running view transition. Client\n// commits and inline streaming reveals both wait on it before proceeding.\nexport const VIEW_TRANSITION_PENDING_PROPERTY = \"__figViewTransition\";\n// React's maximum suspended-commit wait, shared with streaming reveals so a\n// non-settling transition cannot hold either path indefinitely.\nexport const VIEW_TRANSITION_TIMEOUT_MS = 60_000;\n\n// Early-event capture: a tiny inline script at the top of a server-rendered\n// document queues replayable events that fire before the client bundle\n// executes. The first hydration root drains the queue, removes the capture\n// listeners, and replays claimed events through the standard replay path.\n// The event list must stay in sync with fig-dom's replayable set — a\n// discrete replay forces synchronous hydration of its target, which is what\n// makes pre-bundle clicks safe to honor.\nexport const HYDRATION_SKIP_ATTRIBUTE = \"data-fig-hydration-skip\";\nexport const EARLY_EVENT_QUEUE_PROPERTY = \"__figEarlyEvents\";\nexport const EARLY_EVENT_HANDLER_PROPERTY = \"__figEarlyEventHandler\";\nexport const REPLAYABLE_EVENT_TYPES = [\n \"click\",\n \"keydown\",\n \"keyup\",\n \"pointerdown\",\n \"pointerup\",\n] as const;\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { O as Fragment, b as FigNode, g as FigElement, k as Key, o as ElementType } from "./element-CCOOi4Ka.js";
1
+ import { A as Fragment, C as FigNode, j as Key, l as ElementType, y as FigElement } from "./element-BZ7r9ncY.js";
2
2
  //#region src/jsx-runtime.d.ts
3
3
  type JSXProps = Record<string, unknown>;
4
4
  declare function jsx(type: ElementType, props: JSXProps | null, key?: string | number): FigElement;
@@ -1,4 +1,4 @@
1
- import { f as Fragment, s as FigElementSymbol } from "./element-Bh_k9c3N.js";
1
+ import { M as resolveHostMix, f as Fragment, s as FigElementSymbol } from "./element-DmbzNH0T.js";
2
2
  //#region src/jsx-runtime.ts
3
3
  function jsx(type, props, key) {
4
4
  if (props !== null && "key" in props) {
@@ -7,14 +7,14 @@ function jsx(type, props, key) {
7
7
  $$typeof: FigElementSymbol,
8
8
  type,
9
9
  key: key ?? propsKey ?? null,
10
- props: rest
10
+ props: "mix" in rest && typeof type === "string" ? resolveHostMix(type, rest) : rest
11
11
  };
12
12
  }
13
13
  return {
14
14
  $$typeof: FigElementSymbol,
15
15
  type,
16
16
  key: key ?? null,
17
- props: props ?? {}
17
+ props: props !== null && "mix" in props && typeof type === "string" ? resolveHostMix(type, { ...props }) : props ?? {}
18
18
  };
19
19
  }
20
20
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"jsx-runtime.js","names":[],"sources":["../src/jsx-runtime.ts"],"sourcesContent":["import {\n type ElementType,\n type FigElement,\n FigElementSymbol,\n type FigNode,\n Fragment,\n type Key,\n} from \"./element.ts\";\n\ntype JSXProps = Record<string, unknown>;\n\nexport function jsx(\n type: ElementType,\n props: JSXProps | null,\n key?: string | number,\n): FigElement {\n if (props !== null && \"key\" in props) {\n const { key: propsKey, ...rest } = props;\n return {\n $$typeof: FigElementSymbol,\n type,\n key: key ?? (propsKey as Key | null | undefined) ?? null,\n props: rest,\n };\n }\n\n return {\n $$typeof: FigElementSymbol,\n type,\n key: key ?? null,\n props: props ?? {},\n };\n}\n\n// The automatic-runtime contract is exactly jsx/jsxs/jsxDEV/Fragment. jsxDEV\n// aliases jsx: the dev transform's extra arguments (isStaticChildren, source,\n// self) are ignored — Fig builds component stacks from fibers instead.\nexport { Fragment, jsx as jsxs, jsx as jsxDEV };\n\n// Core's JSX namespace is renderer-neutral. Host-prop vocabulary belongs to\n// renderer runtimes such as @bgub/fig-dom/jsx-runtime, so using core directly\n// as jsxImportSource rejects intrinsic tags.\nexport namespace JSX {\n // The type of a JSX expression, and what function components may return:\n // any renderable node (elements, strings, numbers, booleans, null, arrays).\n export type Element = FigNode;\n\n export interface ElementChildrenAttribute {\n children: unknown;\n }\n\n // Props every JSX element accepts beyond its own declared props.\n export interface IntrinsicAttributes {\n key?: Key | null;\n }\n\n export interface IntrinsicElements {}\n}\n"],"mappings":";;AAWA,SAAgB,IACd,MACA,OACA,KACY;CACZ,IAAI,UAAU,QAAQ,SAAS,OAAO;EACpC,MAAM,EAAE,KAAK,UAAU,GAAG,SAAS;EACnC,OAAO;GACL,UAAU;GACV;GACA,KAAK,OAAQ,YAAuC;GACpD,OAAO;EACT;CACF;CAEA,OAAO;EACL,UAAU;EACV;EACA,KAAK,OAAO;EACZ,OAAO,SAAS,CAAC;CACnB;AACF"}
1
+ {"version":3,"file":"jsx-runtime.js","names":[],"sources":["../src/jsx-runtime.ts"],"sourcesContent":["import {\n type ElementType,\n type FigElement,\n FigElementSymbol,\n type FigNode,\n Fragment,\n type Key,\n} from \"./element.ts\";\nimport { resolveHostMix } from \"./mixin.ts\";\n\ntype JSXProps = Record<string, unknown>;\n\nexport function jsx(\n type: ElementType,\n props: JSXProps | null,\n key?: string | number,\n): FigElement {\n if (props !== null && \"key\" in props) {\n const { key: propsKey, ...rest } = props;\n return {\n $$typeof: FigElementSymbol,\n type,\n key: key ?? (propsKey as Key | null | undefined) ?? null,\n props:\n \"mix\" in rest && typeof type === \"string\"\n ? resolveHostMix(type, rest)\n : rest,\n };\n }\n\n return {\n $$typeof: FigElementSymbol,\n type,\n key: key ?? null,\n props:\n props !== null && \"mix\" in props && typeof type === \"string\"\n ? resolveHostMix(type, { ...props })\n : (props ?? {}),\n };\n}\n\n// The automatic-runtime contract is exactly jsx/jsxs/jsxDEV/Fragment. jsxDEV\n// aliases jsx: the dev transform's extra arguments (isStaticChildren, source,\n// self) are ignored — Fig builds component stacks from fibers instead.\nexport { Fragment, jsx as jsxs, jsx as jsxDEV };\n\n// Core's JSX namespace is renderer-neutral. Host-prop vocabulary belongs to\n// renderer runtimes such as @bgub/fig-dom/jsx-runtime, so using core directly\n// as jsxImportSource rejects intrinsic tags.\nexport namespace JSX {\n // The type of a JSX expression, and what function components may return:\n // any renderable node (elements, strings, numbers, booleans, null, arrays).\n export type Element = FigNode;\n\n export interface ElementChildrenAttribute {\n children: unknown;\n }\n\n // Props every JSX element accepts beyond its own declared props.\n export interface IntrinsicAttributes {\n key?: Key | null;\n }\n\n export interface IntrinsicElements {}\n}\n"],"mappings":";;AAYA,SAAgB,IACd,MACA,OACA,KACY;CACZ,IAAI,UAAU,QAAQ,SAAS,OAAO;EACpC,MAAM,EAAE,KAAK,UAAU,GAAG,SAAS;EACnC,OAAO;GACL,UAAU;GACV;GACA,KAAK,OAAQ,YAAuC;GACpD,OACE,SAAS,QAAQ,OAAO,SAAS,WAC7B,eAAe,MAAM,IAAI,IACzB;EACR;CACF;CAEA,OAAO;EACL,UAAU;EACV;EACA,KAAK,OAAO;EACZ,OACE,UAAU,QAAQ,SAAS,SAAS,OAAO,SAAS,WAChD,eAAe,MAAM,EAAE,GAAG,MAAM,CAAC,IAChC,SAAS,CAAC;CACnB;AACF"}
@@ -0,0 +1,366 @@
1
+ //#region src/payload-format.ts
2
+ const textEncoder = new TextEncoder();
3
+ /**
4
+ * Readable development-oriented codec: one JSON payload row per newline.
5
+ */
6
+ const jsonPayloadCodec = {
7
+ id: "json",
8
+ contentType: "text/x-fig-payload; codec=json; charset=utf-8",
9
+ createDecoder(onRow) {
10
+ return createJsonPayloadDecoder(onRow);
11
+ },
12
+ encodeRow(row) {
13
+ return textEncoder.encode(`${JSON.stringify(row)}\n`);
14
+ }
15
+ };
16
+ function createJsonPayloadDecoder(onRow) {
17
+ const decoder = new TextDecoder();
18
+ let buffer = "";
19
+ let searchStart = 0;
20
+ function processBufferedLines() {
21
+ let lineStart = 0;
22
+ let firstError;
23
+ for (;;) {
24
+ const newlineIndex = buffer.indexOf("\n", searchStart);
25
+ if (newlineIndex === -1) {
26
+ searchStart = buffer.length;
27
+ break;
28
+ }
29
+ try {
30
+ processPayloadLine(buffer.slice(lineStart, newlineIndex), onRow);
31
+ } catch (error) {
32
+ firstError ??= error;
33
+ }
34
+ lineStart = newlineIndex + 1;
35
+ searchStart = lineStart;
36
+ }
37
+ if (firstError !== void 0) {
38
+ buffer = "";
39
+ searchStart = 0;
40
+ throw firstError;
41
+ }
42
+ if (lineStart > 0) {
43
+ buffer = buffer.slice(lineStart);
44
+ searchStart -= lineStart;
45
+ }
46
+ }
47
+ return {
48
+ decode(chunk) {
49
+ buffer += decoder.decode(chunk, { stream: true });
50
+ processBufferedLines();
51
+ },
52
+ flush() {
53
+ buffer += decoder.decode();
54
+ if (buffer.length > 0) {
55
+ const line = buffer;
56
+ buffer = "";
57
+ searchStart = 0;
58
+ processPayloadLine(line, onRow);
59
+ }
60
+ }
61
+ };
62
+ }
63
+ function processPayloadLine(line, onRow) {
64
+ if (line.length > 0) onRow(JSON.parse(line));
65
+ }
66
+ /**
67
+ * Extract the codec id from a payload content-type header, or null when the
68
+ * header carries no codec parameter.
69
+ */
70
+ function payloadCodecIdFromContentType(contentTypeHeader) {
71
+ const parts = contentTypeHeader.split(";").slice(1);
72
+ for (const part of parts) {
73
+ const [name, rawValue] = part.split("=");
74
+ if (name?.trim().toLowerCase() !== "codec") continue;
75
+ const value = rawValue?.trim();
76
+ if (value === void 0 || value.length === 0) return null;
77
+ return value.replace(/^"|"$/g, "");
78
+ }
79
+ return null;
80
+ }
81
+ /**
82
+ * Throw when a response content-type declares a codec other than the one this
83
+ * client decodes with. A missing header or codec parameter passes: transports
84
+ * that strip content types stay usable, and mismatches still fail fast when
85
+ * declared.
86
+ */
87
+ function assertPayloadCodecMatches(codec, contentTypeHeader) {
88
+ if (contentTypeHeader === null) return;
89
+ const received = payloadCodecIdFromContentType(contentTypeHeader);
90
+ if (received === null || received === codec.id) return;
91
+ throw new Error(`Payload codec mismatch: producer used "${received}" but this client expects "${codec.id}".`);
92
+ }
93
+ /** Decode an `error` row value into a digest-carrying Error. */
94
+ function errorFromPayloadValue(value) {
95
+ const error = new Error(value.message ?? "The server render failed.");
96
+ return value.digest === void 0 ? error : Object.assign(error, { digest: value.digest });
97
+ }
98
+ function createPayloadGraphDecodeContext() {
99
+ const refs = /* @__PURE__ */ new Map();
100
+ const context = {
101
+ decodeChild: (model) => decodeModelValue(model, context),
102
+ refs: {
103
+ define(id, create, fill) {
104
+ const value = create();
105
+ refs.set(id, value);
106
+ fill(value);
107
+ return value;
108
+ },
109
+ read(id) {
110
+ if (!refs.has(id)) throw new Error(`Payload referenced unknown object id ${id}.`);
111
+ return refs.get(id);
112
+ }
113
+ }
114
+ };
115
+ return context;
116
+ }
117
+ function createPayloadGraphEncodeContext() {
118
+ return {
119
+ defined: [],
120
+ ids: /* @__PURE__ */ new WeakMap()
121
+ };
122
+ }
123
+ function isPlainPayloadValue(value) {
124
+ return value === null || value === void 0 || typeof value === "string" || typeof value === "number" || typeof value === "boolean" || typeof value === "bigint" || typeof value === "symbol";
125
+ }
126
+ /**
127
+ * Encode ordinary data values into PayloadModel. Server component references
128
+ * such as Fig elements, promises, and client references are handled by the
129
+ * payload renderer before ordinary values reach this helper.
130
+ */
131
+ function encodePayloadValue(value) {
132
+ return encodePayloadValueWithGraph(value, createPayloadGraphEncodeContext());
133
+ }
134
+ function encodePayloadValueWithGraph(value, graph) {
135
+ if (value === null) return null;
136
+ if (value === void 0) return { $fig: "undefined" };
137
+ if (typeof value === "string" || typeof value === "boolean") return value;
138
+ if (typeof value === "number") return encodePayloadNumber(value);
139
+ if (typeof value === "bigint") return {
140
+ $fig: "bigint",
141
+ value: value.toString()
142
+ };
143
+ if (typeof value === "symbol") {
144
+ const key = Symbol.keyFor(value);
145
+ if (key === void 0) throw new Error("Only global Symbol.for symbols can be serialized.");
146
+ return {
147
+ $fig: "symbol",
148
+ key
149
+ };
150
+ }
151
+ if (typeof value === "function") throw new Error("Functions cannot be serialized into the payload.");
152
+ if (Array.isArray(value)) return serializePayloadArray(value, graph, () => value, (item) => encodePayloadValueWithGraph(item, graph));
153
+ if (value instanceof Date) {
154
+ const json = value.toJSON();
155
+ if (json === null) throw new Error("Invalid Date values cannot be serialized.");
156
+ return {
157
+ $fig: "date",
158
+ value: json
159
+ };
160
+ }
161
+ if (value instanceof Map) return serializePayloadMap(value, graph, ([key, item]) => [encodePayloadValueWithGraph(key, graph), encodePayloadValueWithGraph(item, graph)]);
162
+ if (value instanceof Set) return serializePayloadSet(value, graph, (item) => encodePayloadValueWithGraph(item, graph));
163
+ if (typeof value === "object" && value !== null) return serializePayloadPlainObject(value, graph, (child) => encodePayloadValueWithGraph(child, graph));
164
+ throw new Error(`Cannot serialize ${typeof value} into the payload.`);
165
+ }
166
+ function serializePayloadMap(value, graph, encodeEntry) {
167
+ const existing = payloadGraphReference(graph, value);
168
+ if (existing !== null) return existing;
169
+ const id = definePayloadGraphObject(graph, value);
170
+ const entries = [];
171
+ for (const entry of value) entries.push(encodeEntry(entry));
172
+ return {
173
+ $fig: "map",
174
+ id,
175
+ entries
176
+ };
177
+ }
178
+ function serializePayloadSet(value, graph, encodeItem) {
179
+ const existing = payloadGraphReference(graph, value);
180
+ if (existing !== null) return existing;
181
+ const id = definePayloadGraphObject(graph, value);
182
+ const values = [];
183
+ for (const item of value) values.push(encodeItem(item));
184
+ return {
185
+ $fig: "set",
186
+ id,
187
+ values
188
+ };
189
+ }
190
+ function payloadGraphReference(graph, value) {
191
+ const id = graph.ids.get(value);
192
+ return id === void 0 ? null : {
193
+ $fig: "ref",
194
+ id
195
+ };
196
+ }
197
+ function definePayloadGraphObject(graph, value) {
198
+ graph.defined.push(value);
199
+ const id = graph.defined.length;
200
+ graph.ids.set(value, id);
201
+ return id;
202
+ }
203
+ function checkpointPayloadGraph(graph) {
204
+ return graph.defined.length;
205
+ }
206
+ function rollbackPayloadGraph(graph, checkpoint) {
207
+ while (graph.defined.length > checkpoint) graph.ids.delete(graph.defined.pop());
208
+ }
209
+ function definePayloadGraphElement(graph, value) {
210
+ const existing = payloadGraphReference(graph, value);
211
+ if (existing !== null) return existing;
212
+ return definePayloadGraphObject(graph, value);
213
+ }
214
+ function serializePayloadArray(value, graph, entries, encodeChild) {
215
+ const existing = payloadGraphReference(graph, value);
216
+ if (existing !== null) return existing;
217
+ return {
218
+ $fig: "array",
219
+ id: definePayloadGraphObject(graph, value),
220
+ value: entries().map(encodeChild)
221
+ };
222
+ }
223
+ function serializePayloadPlainObject(value, graph, encodeChild) {
224
+ const existing = payloadGraphReference(graph, value);
225
+ if (existing !== null) return existing;
226
+ return {
227
+ $fig: "object",
228
+ id: definePayloadGraphObject(graph, value),
229
+ value: encodePayloadRecord(plainPayloadObject(value), encodeChild)
230
+ };
231
+ }
232
+ function plainPayloadObject(value) {
233
+ const prototype = Object.getPrototypeOf(value);
234
+ if (prototype !== Object.prototype && prototype !== null) throw new Error(`Cannot serialize ${prototype?.constructor?.name ?? "object"} into the payload.`);
235
+ return value;
236
+ }
237
+ function encodePayloadRecord(record, encodeChild) {
238
+ const encoded = {};
239
+ for (const [name, child] of Object.entries(record)) encoded[name] = encodeChild(child);
240
+ return encoded;
241
+ }
242
+ function encodePayloadNumber(value) {
243
+ if (Number.isNaN(value)) return {
244
+ $fig: "number",
245
+ value: "NaN"
246
+ };
247
+ if (value === Infinity) return {
248
+ $fig: "number",
249
+ value: "Infinity"
250
+ };
251
+ if (value === -Infinity) return {
252
+ $fig: "number",
253
+ value: "-Infinity"
254
+ };
255
+ if (Object.is(value, -0)) return {
256
+ $fig: "number",
257
+ value: "-0"
258
+ };
259
+ return value;
260
+ }
261
+ /** Decode values produced by encodePayloadValue. */
262
+ function decodePayloadValue(model) {
263
+ return decodeModelValue(model, createPayloadGraphDecodeContext());
264
+ }
265
+ function decodeModelValue(model, graph) {
266
+ if (model === null) return null;
267
+ if (Array.isArray(model)) return model.map((item) => decodeModelValue(item, graph));
268
+ if (typeof model !== "object") return model;
269
+ if (isPayloadValueSpecialModel(model)) return decodePayloadValueTag(model, graph.refs, graph.decodeChild);
270
+ return decodePayloadRecord(model, graph.decodeChild);
271
+ }
272
+ function isPayloadValueSpecialModel(model) {
273
+ if (!("$fig" in model)) return false;
274
+ const tag = model.$fig;
275
+ return tag === "bigint" || tag === "array" || tag === "date" || tag === "map" || tag === "number" || tag === "object" || tag === "ref" || tag === "set" || tag === "symbol" || tag === "undefined";
276
+ }
277
+ function decodePayloadValueTag(model, refs, decodeChild) {
278
+ switch (model.$fig) {
279
+ case "array": return refs.define(model.id, () => [], (value) => {
280
+ for (const item of model.value) value.push(decodeChild(item));
281
+ });
282
+ case "bigint": return BigInt(model.value);
283
+ case "date": return new Date(model.value);
284
+ case "map": return refs.define(model.id, () => /* @__PURE__ */ new Map(), (value) => {
285
+ for (const [key, item] of model.entries) value.set(decodeChild(key), decodeChild(item));
286
+ });
287
+ case "number": return decodePayloadNumber(model.value);
288
+ case "object":
289
+ if (model.id === void 0) return decodePayloadRecord(model.value, decodeChild);
290
+ return refs.define(model.id, () => ({}), (value) => {
291
+ for (const [name, child] of Object.entries(model.value)) definePayloadProperty(value, name, decodeChild(child));
292
+ });
293
+ case "ref": return refs.read(model.id);
294
+ case "set": return refs.define(model.id, () => /* @__PURE__ */ new Set(), (value) => {
295
+ for (const item of model.values) value.add(decodeChild(item));
296
+ });
297
+ case "symbol": return Symbol.for(model.key);
298
+ case "undefined": return;
299
+ }
300
+ }
301
+ function decodePayloadRecord(value, decodeChild) {
302
+ const decoded = {};
303
+ for (const [name, child] of Object.entries(value)) definePayloadProperty(decoded, name, decodeChild(child));
304
+ return decoded;
305
+ }
306
+ function definePayloadProperty(target, name, value) {
307
+ if (name === "__proto__") {
308
+ Object.defineProperty(target, name, {
309
+ configurable: true,
310
+ enumerable: true,
311
+ value,
312
+ writable: true
313
+ });
314
+ return;
315
+ }
316
+ target[name] = value;
317
+ }
318
+ function decodePayloadNumber(value) {
319
+ switch (value) {
320
+ case "Infinity": return Infinity;
321
+ case "-Infinity": return -Infinity;
322
+ case "-0": return -0;
323
+ case "NaN": return NaN;
324
+ }
325
+ }
326
+ function encodePayloadDataEntries(entries) {
327
+ const graph = createPayloadGraphEncodeContext();
328
+ return entries.map((entry) => ({
329
+ ...entry,
330
+ value: encodePayloadValueWithGraph(entry.value, graph)
331
+ }));
332
+ }
333
+ function decodePayloadDataEntries(entries) {
334
+ const graph = createPayloadGraphDecodeContext();
335
+ return entries.map((entry) => ({
336
+ ...entry,
337
+ value: decodeModelValue(entry.value, graph)
338
+ }));
339
+ }
340
+ function isPayloadSpecialModel(model) {
341
+ if (!("$fig" in model)) return false;
342
+ switch (model.$fig) {
343
+ case "array":
344
+ case "bigint":
345
+ case "client":
346
+ case "date":
347
+ case "element":
348
+ case "fragment":
349
+ case "lazy":
350
+ case "map":
351
+ case "number":
352
+ case "object":
353
+ case "promise":
354
+ case "ref":
355
+ case "set":
356
+ case "suspense":
357
+ case "symbol":
358
+ case "undefined":
359
+ case "view-transition": return true;
360
+ default: return false;
361
+ }
362
+ }
363
+ //#endregion
364
+ export { serializePayloadArray as _, decodePayloadRecord as a, serializePayloadSet as b, definePayloadGraphElement as c, encodePayloadValueWithGraph as d, errorFromPayloadValue as f, rollbackPayloadGraph as g, jsonPayloadCodec as h, decodePayloadDataEntries as i, encodePayloadDataEntries as l, isPlainPayloadValue as m, checkpointPayloadGraph as n, decodePayloadValue as o, isPayloadSpecialModel as p, createPayloadGraphEncodeContext as r, decodePayloadValueTag as s, assertPayloadCodecMatches as t, encodePayloadValue as u, serializePayloadMap as v, serializePayloadPlainObject as y };
365
+
366
+ //# sourceMappingURL=payload-format-KTNaSI4h.js.map