@bgub/fig-server 0.1.0-alpha.2 → 0.1.0-alpha.3

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.
@@ -0,0 +1,1764 @@
1
+ import { i as escapeText, n as escapeScriptJson, t as escapeAttribute } from "./escaping-DAot8sFu.js";
2
+ import { a as componentStack, c as errorMessage, d as streamHighWaterMark, f as withContextValue, i as cloneContextValues, l as nonceAttribute, n as suppressesImagePreloads, o as createStaticDispatcher, r as STREAMED_METADATA_ATTRIBUTE, s as deferred, t as imagePreloadFromHostProps, u as streamFlowBlocked } from "./image-preloads-D3OBEaWp.js";
3
+ import { Fragment, createElement, isValidElement } from "@bgub/fig";
4
+ import { ACTIVITY_TEMPLATE_ATTRIBUTE, EARLY_EVENT_HANDLER_PROPERTY, EARLY_EVENT_QUEUE_PROPERTY, 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, assetResourceFromHostProps, assetResourceHostAttributes, assetResourceKey, attachDataStore, collectChildren, createRendererDataStore, invalidChildError, isActivity, isAssets, isClientReference, isContext, isErrorBoundary, isFigAssetResource, isPortal, isSuspense, isThenable, isViewTransition, readThenable, setCurrentDataStore, setCurrentDispatcher, validateInstanceNesting, validateTextNesting } from "@bgub/fig/internal";
5
+ //#region src/html.ts
6
+ const voidElements = /* @__PURE__ */ new Set([
7
+ "area",
8
+ "base",
9
+ "br",
10
+ "col",
11
+ "embed",
12
+ "hr",
13
+ "img",
14
+ "input",
15
+ "link",
16
+ "meta",
17
+ "param",
18
+ "source",
19
+ "track",
20
+ "wbr"
21
+ ]);
22
+ function writeText(value, sink) {
23
+ sink.write(escapeText(value));
24
+ }
25
+ function writeElementStart(type, props, sink, inheritedProps = {}) {
26
+ validateTagName(type);
27
+ sink.write(`<${type}${serializeAttributes(type, props, inheritedProps)}>`);
28
+ }
29
+ function writeElementEnd(type, sink) {
30
+ sink.write(`</${type}>`);
31
+ }
32
+ function isVoidElement(type) {
33
+ return voidElements.has(type);
34
+ }
35
+ function hasRenderableChild(node) {
36
+ if (Array.isArray(node)) return node.some(hasRenderableChild);
37
+ if (isPortal(node)) return false;
38
+ return !emptyChild(node);
39
+ }
40
+ function formTextContent(type, props) {
41
+ if (type !== "textarea") return null;
42
+ return formString(props.value !== void 0 ? props.value : props.defaultValue);
43
+ }
44
+ function unsafeHTMLContent(props) {
45
+ const value = props.unsafeHTML;
46
+ if (emptyValue(value)) return null;
47
+ if (typeof value === "string") return value;
48
+ throw new Error("The unsafeHTML prop must be a string during server render.");
49
+ }
50
+ function serializeAttributes(type, props, inheritedProps) {
51
+ let attributes = "";
52
+ for (const name of Object.keys(props)) {
53
+ const value = props[name];
54
+ if (reservedProp(name)) continue;
55
+ if (name === "value" && props.defaultValue !== void 0) continue;
56
+ if (name === "checked" && props.defaultChecked !== void 0) continue;
57
+ if (name === "style") {
58
+ const style = serializeStyle(value);
59
+ if (style !== "") attributes += serializeAttribute("style", style);
60
+ continue;
61
+ }
62
+ attributes += serializeProp(type, name, value);
63
+ }
64
+ if (type === "option" && props.selected === void 0 && optionSelected(optionValue(props), inheritedProps)) attributes += " selected";
65
+ return attributes;
66
+ }
67
+ function serializeProp(type, name, value) {
68
+ if ((type === "textarea" || type === "select") && valueProp(name)) return "";
69
+ let attributeName = name;
70
+ let attributeValue = value;
71
+ if (valueProp(name)) {
72
+ attributeName = "value";
73
+ if (serializableAttributeValue(value)) attributeValue = String(value);
74
+ } else if (name === "defaultChecked") {
75
+ attributeName = "checked";
76
+ attributeValue = value === true ? true : null;
77
+ } else if (type === "option" && name === "selected") attributeValue = value === true ? true : null;
78
+ if (emptyValue(attributeValue)) return "";
79
+ validateAttributeName(attributeName);
80
+ if (attributeValue === true) return ` ${attributeName}`;
81
+ if (serializableAttributeValue(attributeValue)) return serializeAttribute(attributeName, String(attributeValue));
82
+ throw new Error(`Cannot serialize prop "${name}" to HTML.`);
83
+ }
84
+ function optionSelected(value, selectProps) {
85
+ const selectValue = selectProps.value !== void 0 ? selectProps.value : selectProps.defaultValue;
86
+ if (emptyValue(selectValue)) return false;
87
+ const optionValue = formString(value);
88
+ if (optionValue === null) return false;
89
+ return selectedValueSet(selectValue).has(optionValue);
90
+ }
91
+ function optionValue(props) {
92
+ return props.value === void 0 ? optionTextValue(props.children) : formString(props.value);
93
+ }
94
+ function optionTextValue(node) {
95
+ if (typeof node === "string" || typeof node === "number") return String(node);
96
+ if (Array.isArray(node)) {
97
+ let text = "";
98
+ for (const child of node) {
99
+ const childText = optionTextValue(child);
100
+ if (childText === null) return null;
101
+ text += childText;
102
+ }
103
+ return text;
104
+ }
105
+ return null;
106
+ }
107
+ function formString(value) {
108
+ if (emptyValue(value)) return null;
109
+ if (serializableAttributeValue(value)) return String(value);
110
+ return null;
111
+ }
112
+ function selectedValueSet(value) {
113
+ return new Set(Array.isArray(value) ? value.map(String) : [String(value)]);
114
+ }
115
+ function serializableAttributeValue(value) {
116
+ return value === true || typeof value === "string" || typeof value === "number" || typeof value === "bigint";
117
+ }
118
+ function emptyValue(value) {
119
+ return value === null || value === void 0 || value === false;
120
+ }
121
+ function emptyChild(value) {
122
+ return value === null || value === void 0 || typeof value === "boolean";
123
+ }
124
+ function serializeAttribute(name, value) {
125
+ return ` ${name}="${escapeAttribute(value)}"`;
126
+ }
127
+ function serializeStyle(value) {
128
+ if (emptyValue(value)) return "";
129
+ if (typeof value !== "object" || value === null) throw new Error("The style prop must be an object during server render.");
130
+ let serialized = "";
131
+ for (const [name, item] of Object.entries(value)) {
132
+ if (emptyValue(item)) continue;
133
+ if (typeof item !== "string" && typeof item !== "number" && typeof item !== "bigint") throw new Error(`Cannot serialize style property "${name}" to HTML.`);
134
+ if (serialized !== "") serialized += ";";
135
+ serialized += `${styleName(name)}:${String(item)}`;
136
+ }
137
+ return serialized;
138
+ }
139
+ function reservedProp(name) {
140
+ return name === "children" || name === "key" || name === "mix" || name === "bind" || name === "suppressHydrationWarning" || name === "unsafeHTML" || /^on[A-Z]/.test(name);
141
+ }
142
+ function valueProp(name) {
143
+ return name === "value" || name === "defaultValue";
144
+ }
145
+ function styleName(name) {
146
+ if (name.startsWith("--")) return name;
147
+ return name.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
148
+ }
149
+ function validateTagName(name) {
150
+ if (!/^[A-Za-z][A-Za-z0-9:._-]*$/.test(name)) throw new Error(`Invalid HTML tag name "${name}".`);
151
+ }
152
+ function validateAttributeName(name) {
153
+ if (/[\s"'<>/=]/.test(name)) throw new Error(`Invalid HTML attribute name "${name}".`);
154
+ }
155
+ //#endregion
156
+ //#region src/preload-header.ts
157
+ const DEFAULT_LENGTH = 2e3;
158
+ const HEX_ESCAPE = /^[0-9A-Fa-f]{2}$/;
159
+ const PARAMETER_TOKEN = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
160
+ const URI_REFERENCE_PUNCTUATION = "-._~:/?#[]@!$&'()*+,;=";
161
+ function createPreloadHeaderEntries(resources, isEarlyImage) {
162
+ const preconnects = [];
163
+ const criticalPreloads = [];
164
+ const stylesheets = [];
165
+ const remaining = [];
166
+ for (const resource of resources) {
167
+ if (!isServerPreloadHeaderResource(resource)) continue;
168
+ const value = preloadHeaderValue(resource);
169
+ if (value === null) continue;
170
+ const entry = {
171
+ resource,
172
+ value
173
+ };
174
+ if (resource.kind === "preconnect") preconnects.push(entry);
175
+ else if (resource.kind === "font" || resource.kind === "preload" && (resource.as === "font" || resource.as === "image" && (resource.fetchpriority === "high" || isEarlyImage?.(resource) === true))) criticalPreloads.push(entry);
176
+ else if (resource.kind === "stylesheet") stylesheets.push(entry);
177
+ else remaining.push(entry);
178
+ }
179
+ return [
180
+ ...preconnects,
181
+ ...criticalPreloads,
182
+ ...stylesheets,
183
+ ...remaining
184
+ ];
185
+ }
186
+ function formatPreloadHeader(entries, options = {}) {
187
+ const maxLength = normalizedLength(options.maxLength);
188
+ if (maxLength === 0) return void 0;
189
+ const seen = /* @__PURE__ */ new Set();
190
+ const values = [];
191
+ let length = 0;
192
+ for (const entry of entries) {
193
+ if (options.filter !== void 0 && !options.filter(entry.resource)) continue;
194
+ if (seen.has(entry.value)) continue;
195
+ const addedLength = entry.value.length + (values.length === 0 ? 0 : 2);
196
+ if (length + addedLength > maxLength) continue;
197
+ seen.add(entry.value);
198
+ values.push(entry.value);
199
+ length += addedLength;
200
+ }
201
+ return values.length === 0 ? void 0 : values.join(", ");
202
+ }
203
+ function preloadHeaderValue(resource) {
204
+ switch (resource.kind) {
205
+ case "stylesheet": return serializeLink(resource.href, [
206
+ ["rel", "preload"],
207
+ ["as", "style"],
208
+ ["crossorigin", resource.crossorigin],
209
+ ["media", resource.media]
210
+ ]);
211
+ case "preload": return serializeLink(resource.href, [
212
+ ["rel", "preload"],
213
+ ["as", resource.as],
214
+ ["crossorigin", resource.crossorigin],
215
+ ["type", resource.type],
216
+ ["fetchpriority", resource.fetchpriority],
217
+ ["referrerpolicy", resource.referrerpolicy]
218
+ ]);
219
+ case "modulepreload": return serializeLink(resource.href, [
220
+ ["rel", "modulepreload"],
221
+ ["as", "script"],
222
+ ["crossorigin", resource.crossorigin],
223
+ ["fetchpriority", resource.fetchpriority]
224
+ ]);
225
+ case "font": return serializeLink(resource.href, [
226
+ ["rel", "preload"],
227
+ ["as", "font"],
228
+ ["crossorigin", resource.crossorigin ?? "anonymous"],
229
+ ["type", resource.type],
230
+ ["fetchpriority", resource.fetchpriority]
231
+ ]);
232
+ case "preconnect": return serializeLink(resource.href, [["rel", "preconnect"], ["crossorigin", resource.crossorigin]]);
233
+ }
234
+ }
235
+ function isServerPreloadHeaderResource(resource) {
236
+ if (resource.kind === "script") return false;
237
+ return resource.kind !== "preload" || resource.href !== void 0 && (resource.as !== "image" || !resource.imagesrcset);
238
+ }
239
+ function serializeLink(target, parameters) {
240
+ const encodedTarget = encodeLinkTarget(target);
241
+ if (encodedTarget === null) return null;
242
+ const parts = [`<${encodedTarget}>`];
243
+ for (const [name, value] of parameters) {
244
+ if (value === void 0) continue;
245
+ const parameter = serializeParameter(name, value);
246
+ if (parameter === null) return null;
247
+ parts.push(parameter);
248
+ }
249
+ return parts.join("; ");
250
+ }
251
+ function serializeParameter(name, value) {
252
+ if (value === "") return name;
253
+ if (hasInvalidParameterCharacter(value)) return null;
254
+ if (PARAMETER_TOKEN.test(value)) return `${name}=${value}`;
255
+ return `${name}="${value.replaceAll("\\", "\\\\").replaceAll("\"", "\\\"")}"`;
256
+ }
257
+ function encodeLinkTarget(value) {
258
+ if (value === "") return null;
259
+ let encoded = "";
260
+ for (let index = 0; index < value.length; index += 1) {
261
+ const code = value.charCodeAt(index);
262
+ if (code <= 32 || code === 127) return null;
263
+ const character = value[index];
264
+ if (character === "%" && HEX_ESCAPE.test(value.slice(index + 1, index + 3))) {
265
+ encoded += value.slice(index, index + 3);
266
+ index += 2;
267
+ continue;
268
+ }
269
+ if (code >= 48 && code <= 57 || code >= 65 && code <= 90 || code >= 97 && code <= 122 || URI_REFERENCE_PUNCTUATION.includes(character)) {
270
+ encoded += character;
271
+ continue;
272
+ }
273
+ const codePoint = value.codePointAt(index);
274
+ if (codePoint === void 0) return null;
275
+ const symbol = String.fromCodePoint(codePoint);
276
+ if (symbol.length === 2) index += 1;
277
+ try {
278
+ encoded += encodeURIComponent(symbol);
279
+ } catch {
280
+ return null;
281
+ }
282
+ }
283
+ return encoded;
284
+ }
285
+ function hasInvalidParameterCharacter(value) {
286
+ for (let index = 0; index < value.length; index += 1) {
287
+ const code = value.charCodeAt(index);
288
+ if (code < 32 || code === 127 || code > 255) return true;
289
+ }
290
+ return false;
291
+ }
292
+ function normalizedLength(value) {
293
+ if (value === void 0 || Number.isNaN(value)) return DEFAULT_LENGTH;
294
+ return Math.max(0, Math.floor(value));
295
+ }
296
+ //#endregion
297
+ //#region src/asset-registry.ts
298
+ var AssetResourceRegistry = class {
299
+ identifierPrefix;
300
+ earlyImageKeys = /* @__PURE__ */ new Set();
301
+ emittedResources = /* @__PURE__ */ new Set();
302
+ deliveryResources = /* @__PURE__ */ new Map();
303
+ metadataByOwner = /* @__PURE__ */ new Map();
304
+ stylesheetIds = /* @__PURE__ */ new Map();
305
+ nextStylesheetId = 0;
306
+ constructor(identifierPrefix) {
307
+ this.identifierPrefix = identifierPrefix;
308
+ }
309
+ register(resource) {
310
+ if (isMetadataResource(resource)) return;
311
+ this.canonical(resource);
312
+ }
313
+ registerAutomaticImage(resource) {
314
+ const { key, resource: current } = this.canonical(resource);
315
+ if (this.earlyImageKeys.size < 10 || current.kind === "preload" && current.as === "image" && current.fetchpriority === "high") this.earlyImageKeys.add(key);
316
+ }
317
+ isEarlyImage(resource) {
318
+ return this.earlyImageKeys.has(assetResourceKey(resource));
319
+ }
320
+ activateMetadata(owner, resources) {
321
+ const metadata = resources.filter(isMetadataResource);
322
+ if (metadata.length === 0) {
323
+ this.metadataByOwner.delete(owner);
324
+ return;
325
+ }
326
+ this.metadataByOwner.set(owner, metadata);
327
+ }
328
+ releaseMetadata(owner) {
329
+ this.metadataByOwner.delete(owner);
330
+ }
331
+ write(resource, sink) {
332
+ if (isMetadataResource(resource)) return null;
333
+ const { key, resource: current } = this.canonical(resource);
334
+ const id = this.revealBlockerId(key, current);
335
+ if (this.emittedResources.has(key)) return id;
336
+ this.emittedResources.add(key);
337
+ writeAssetTag(sink, current, id);
338
+ return id;
339
+ }
340
+ headHtml(nonce, streamMetadata = false) {
341
+ const { preamble, metadata } = this.headMetadataHtml(nonce, streamMetadata);
342
+ return preamble + metadata;
343
+ }
344
+ headMetadataHtml(nonce, streamMetadata = false) {
345
+ const buckets = {
346
+ charset: [],
347
+ parser: [],
348
+ viewport: [],
349
+ metadata: []
350
+ };
351
+ for (const resource of this.visibleMetadata().values()) {
352
+ const bucket = buckets[metadataPhase(resource)];
353
+ writeAssetTag({
354
+ nonce,
355
+ streamMetadata,
356
+ write: (chunk) => bucket.push(chunk)
357
+ }, resource, null);
358
+ }
359
+ return {
360
+ preamble: [
361
+ ...buckets.charset,
362
+ ...buckets.parser,
363
+ ...buckets.viewport
364
+ ].join(""),
365
+ metadata: buckets.metadata.join("")
366
+ };
367
+ }
368
+ metadataSnapshot() {
369
+ const snapshot = [];
370
+ for (const [key, resource] of this.visibleMetadata()) if (resource.kind === "title") snapshot.push([
371
+ key,
372
+ resource.kind,
373
+ resource.value
374
+ ]);
375
+ else snapshot.push([
376
+ key,
377
+ resource.kind,
378
+ metadataAttributes(resource)
379
+ ]);
380
+ return snapshot;
381
+ }
382
+ preloadHeaderEntries() {
383
+ return createPreloadHeaderEntries(this.deliveryResources.values(), (resource) => this.isEarlyImage(resource));
384
+ }
385
+ visibleMetadata() {
386
+ const visible = /* @__PURE__ */ new Map();
387
+ for (const metadata of this.metadataByOwner.values()) for (const resource of metadata) visible.set(assetResourceKey(resource), resource);
388
+ return visible;
389
+ }
390
+ canonical(resource) {
391
+ const key = assetResourceKey(resource);
392
+ const current = this.deliveryResources.get(key);
393
+ if (current !== void 0) {
394
+ if (assetSignature(current) !== assetSignature(resource)) {
395
+ const promoted = promoteCompatibleImagePreload(current, resource);
396
+ if (promoted === null) throw new AssetResourceConflictError(key, current, resource);
397
+ this.deliveryResources.set(key, promoted);
398
+ return {
399
+ key,
400
+ resource: promoted
401
+ };
402
+ }
403
+ return {
404
+ key,
405
+ resource: current
406
+ };
407
+ }
408
+ this.deliveryResources.set(key, resource);
409
+ return {
410
+ key,
411
+ resource
412
+ };
413
+ }
414
+ revealBlockerId(key, resource) {
415
+ if (resource.kind !== "stylesheet") return null;
416
+ if (resource.blocking === "none") return null;
417
+ return this.stylesheetIdFor(key);
418
+ }
419
+ stylesheetIdFor(key) {
420
+ const current = this.stylesheetIds.get(key);
421
+ if (current !== void 0) return current;
422
+ const id = this.identifierPrefix === "" ? `r-${this.nextStylesheetId}` : `${this.identifierPrefix}-r-${this.nextStylesheetId}`;
423
+ this.nextStylesheetId += 1;
424
+ this.stylesheetIds.set(key, id);
425
+ return id;
426
+ }
427
+ };
428
+ var AssetResourceConflictError = class extends Error {
429
+ constructor(key, current, incoming) {
430
+ super(`Conflicting Fig resource for key "${key}". Existing: ${JSON.stringify(current)}. Incoming: ${JSON.stringify(incoming)}.`);
431
+ }
432
+ };
433
+ function writeAssetTag(sink, resource, id) {
434
+ switch (resource.kind) {
435
+ case "title":
436
+ writeElementStart("title", {
437
+ [HYDRATION_SKIP_ATTRIBUTE]: true,
438
+ [STREAMED_METADATA_ATTRIBUTE]: sink.streamMetadata ? assetResourceKey(resource) : void 0
439
+ }, sink);
440
+ writeText(resource.value, sink);
441
+ writeElementEnd("title", sink);
442
+ return;
443
+ case "meta":
444
+ writeElementStart("meta", {
445
+ charset: resource.charset,
446
+ name: resource.name,
447
+ property: resource.property,
448
+ "http-equiv": resource["http-equiv"],
449
+ content: resource.content,
450
+ [HYDRATION_SKIP_ATTRIBUTE]: true,
451
+ [STREAMED_METADATA_ATTRIBUTE]: sink.streamMetadata ? assetResourceKey(resource) : void 0,
452
+ "data-fig-resource-key": resource.key
453
+ }, sink);
454
+ return;
455
+ default: {
456
+ const props = {
457
+ [HYDRATION_SKIP_ATTRIBUTE]: true,
458
+ ...Object.fromEntries(assetResourceHostAttributes(resource))
459
+ };
460
+ if (resource.kind === "stylesheet" && id !== null) props.id = id;
461
+ const tag = resource.kind === "script" ? "script" : "link";
462
+ writeElementStart(tag, withNonce(sink, props), sink);
463
+ if (tag === "script") writeElementEnd("script", sink);
464
+ }
465
+ }
466
+ }
467
+ function isMetadataResource(resource) {
468
+ return resource.kind === "title" || resource.kind === "meta";
469
+ }
470
+ function metadataPhase(resource) {
471
+ if (resource.kind === "title") return "metadata";
472
+ if (resource.charset !== void 0) return "charset";
473
+ if (normalizedMetadataName(resource["http-equiv"]) === "content-security-policy") return "parser";
474
+ if (normalizedMetadataName(resource.name) === "viewport") return "viewport";
475
+ return "metadata";
476
+ }
477
+ function normalizedMetadataName(value) {
478
+ return value?.trim().toLowerCase();
479
+ }
480
+ function metadataAttributes(resource) {
481
+ return [
482
+ ["charset", resource.charset],
483
+ ["name", resource.name],
484
+ ["property", resource.property],
485
+ ["http-equiv", resource["http-equiv"]],
486
+ ["content", resource.content],
487
+ ["data-fig-resource-key", resource.key]
488
+ ].filter((entry) => entry[1] !== void 0);
489
+ }
490
+ function withNonce(sink, props) {
491
+ return sink.nonce === void 0 ? props : {
492
+ ...props,
493
+ nonce: sink.nonce
494
+ };
495
+ }
496
+ function assetSignature(resource) {
497
+ switch (resource.kind) {
498
+ case "stylesheet": return signature(resource.kind, resource.href, resource.media ?? "", resource.precedence ?? "", resource.crossorigin ?? "", resource.blocking ?? "reveal");
499
+ case "preload": {
500
+ const imagesrcset = resource.as === "image" ? resource.imagesrcset || void 0 : void 0;
501
+ return signature(resource.kind, imagesrcset === void 0 ? resource.href ?? "" : "", resource.as, resource.type ?? "", resource.crossorigin ?? "", resource.fetchpriority ?? "", imagesrcset ?? "", imagesrcset === void 0 ? "" : resource.imagesizes ?? "", resource.referrerpolicy ?? "");
502
+ }
503
+ case "modulepreload": return signature(resource.kind, resource.href, resource.crossorigin ?? "", resource.fetchpriority ?? "");
504
+ case "font": return signature("preload", resource.href, "font", resource.type, resource.crossorigin ?? "anonymous", resource.fetchpriority ?? "", "", "", "");
505
+ case "preconnect": return signature(resource.kind, resource.href, resource.crossorigin ?? "");
506
+ case "script": return signature(resource.kind, resource.src, resource.module === true, resource.async !== false, resource.defer === true, resource.crossorigin ?? "");
507
+ case "title": return signature(resource.kind, resource.value);
508
+ case "meta": return signature(resource.kind, resource.charset ?? "", resource.name ?? "", resource.property ?? "", resource["http-equiv"] ?? "", resource.content ?? "");
509
+ }
510
+ return unsupportedAssetResource(resource);
511
+ }
512
+ function promoteCompatibleImagePreload(current, incoming) {
513
+ if (current.kind !== "preload" || incoming.kind !== "preload" || current.as !== "image" || incoming.as !== "image" || assetSignature({
514
+ ...current,
515
+ fetchpriority: incoming.fetchpriority
516
+ }) !== assetSignature(incoming)) return null;
517
+ const currentPriority = current.fetchpriority === "auto" ? void 0 : current.fetchpriority;
518
+ const incomingPriority = incoming.fetchpriority === "auto" ? void 0 : incoming.fetchpriority;
519
+ if (currentPriority === incomingPriority) return current;
520
+ if (currentPriority === "low" || incomingPriority === "low") return null;
521
+ return currentPriority === "high" ? current : {
522
+ ...current,
523
+ fetchpriority: "high"
524
+ };
525
+ }
526
+ function unsupportedAssetResource(resource) {
527
+ throw new Error(`Unsupported asset resource kind: ${resource.kind}`);
528
+ }
529
+ function signature(...values) {
530
+ return JSON.stringify(values);
531
+ }
532
+ //#endregion
533
+ //#region src/protocol.ts
534
+ function serverRuntimeCodeFor(runtimeName) {
535
+ return `globalThis[${jsString(runtimeName)}]??={r(a,f){let n=0,d=()=>{--n||f()};for(let i of a){let e=document.getElementById(i);if(e&&e.tagName==='LINK'&&e.rel==='stylesheet'&&!e.sheet){n++;e.addEventListener('load',d,{once:true});e.addEventListener('error',d,{once:true})}}n||f()},q(e,a){if(e&&e.nodeType===1){if(e.hasAttribute&&e.hasAttribute('${VIEW_TRANSITION_NAME_ATTRIBUTE}'))a.push([e,e.getAttribute('${VIEW_TRANSITION_NAME_ATTRIBUTE}'),e.getAttribute('${VIEW_TRANSITION_CLASS_ATTRIBUTE}')]);if(e.querySelectorAll)for(let x of e.querySelectorAll('[${VIEW_TRANSITION_NAME_ATTRIBUTE}]'))a.push([x,x.getAttribute('${VIEW_TRANSITION_NAME_ATTRIBUTE}'),x.getAttribute('${VIEW_TRANSITION_CLASS_ATTRIBUTE}')])}},g(r){let a=[];this.q(r,a);return a},h(b){let a=[],d=0;for(let e=b;e;){if(e.nodeType===8){if(e.data.indexOf('${SUSPENSE_MARKER_PREFIX}')===0)d++;else if(e.data==='${SUSPENSE_END_MARKER}'){if(d===0)break;d--}}else this.q(e,a);e=e.nextSibling}return a},a(l){for(let x of l){let e=x[0],s=e.style;x[3]=s.viewTransitionName;x[4]=s.viewTransitionClass;s.viewTransitionName=x[1];if(x[2])s.viewTransitionClass=x[2]}},u(l){for(let x of l){let e=x[0],s=e.style;s.viewTransitionName=x[3]||'';s.viewTransitionClass=x[4]||'';!(e.getAttribute&&e.getAttribute('style'))&&e.removeAttribute&&e.removeAttribute('style')}},z(l){for(let f of l)f()},j(t,r){let p=t&&(t.ready||t.finished);p&&p.then?p.then(r,()=>{let f=t&&t.finished;f&&f.then?f.then(r,r):r()}):r()},v(b,s,f){let o=this.h(b),n=this.g(s);if(!o.length&&!n.length){f();return}let d=document,w=d.startViewTransition;if(typeof w!='function'){f();return}let p=d.${VIEW_TRANSITION_PENDING_PROPERTY},pw=p&&(p.finished||p.ready);if(pw&&pw.then){let q=0,i,g=()=>{if(q)return;q=1;clearTimeout(i);d.${VIEW_TRANSITION_PENDING_PROPERTY}===p&&(d.${VIEW_TRANSITION_PENDING_PROPERTY}=null);this.v(b,s,f)};i=setTimeout(g,${VIEW_TRANSITION_TIMEOUT_MS});pw.then(g,g);return}this.a(o);let m=0,l=[],r=()=>{this.u(o);this.u(n);this.z(l)};try{let t=w.call(d,()=>{m=1;f(l);this.a(n)});if(t){d.${VIEW_TRANSITION_PENDING_PROPERTY}=t;let c=()=>{d.${VIEW_TRANSITION_PENDING_PROPERTY}===t&&(d.${VIEW_TRANSITION_PENDING_PROPERTY}=null)},cw=t.finished||t.ready;cw&&cw.then?cw.then(c,c):c()}this.j(t,r)}catch(e){r();if(m)throw e;f()}},m(a){let h=document.head,e=new Map;for(let n of h.querySelectorAll('[${STREAMED_METADATA_ATTRIBUTE}]'))e.set(n.getAttribute('${STREAMED_METADATA_ATTRIBUTE}'),n);for(let d of a){let k=d[0],t=d[1],v=d[2],n=e.get(k);if(!n||n.tagName.toLowerCase()!==t){n&&n.remove();n=document.createElement(t);n.setAttribute('${STREAMED_METADATA_ATTRIBUTE}',k);n.setAttribute('${HYDRATION_SKIP_ATTRIBUTE}','');h.appendChild(n)}e.delete(k);if(t==='title')n.textContent=v;else{for(let x of Array.from(n.attributes))if(x.name!=='${STREAMED_METADATA_ATTRIBUTE}'&&x.name!=='${HYDRATION_SKIP_ATTRIBUTE}')n.removeAttribute(x.name);for(let x of v)n.setAttribute(x[0],x[1])}}for(let n of e.values())n.remove()},s(p,s){p=document.getElementById(p);s=document.getElementById(s);if(!p||!s)return;this.v(p,s,()=>{while(s.firstChild)p.parentNode.insertBefore(s.firstChild,p);p.remove();s.remove()})},f(r,i){if(!r)return null;if(r.id===i)return r;for(let e of r.querySelectorAll?r.querySelectorAll('[id]'):[])if(e.id===i)return e;return null},b(t,b){let e=document.getElementById(t),r=e&&(e.content||e);return this.f(r,b)||document.getElementById(b)},c(b,s,m){let x=document.getElementById(b),y=document.getElementById(s);this.v(x,y,r=>this.o(x,y,r,m))},o(b,s,l,m){if(!b||!s)return;let a=b.previousSibling||b,p=a.parentNode,c=s.content||s;if(!p)return;let r=a.nodeType===8&&a.__figRetry;if(!r&&m)this.m(m);while(c.firstChild)p.insertBefore(c.firstChild,b);for(let e=b,d=0;e;){if(e.nodeType===8){if(e.data.indexOf('${SUSPENSE_MARKER_PREFIX}')===0)d++;else if(e.data==='${SUSPENSE_END_MARKER}'){if(d===0)break;d--}}let x=e.nextSibling;e.remove();e=x}s.remove();if(a.nodeType===8){a.data='${SUSPENSE_COMPLETED_MARKER}';if(r){if(l)l.push(r);else r()}}},x(b,d,m){this.y(document.getElementById(b),d,m)},y(b,d,m){if(!b)return;let s=b.previousSibling;if(s&&s.nodeType===8){s.data='${SUSPENSE_CLIENT_MARKER}';if(d)b.dataset.dgst=d;if(m)b.dataset.msg=m;s.__figRetry&&s.__figRetry()}},ac(t,b,s,m){let x=this.b(t,b),y=document.getElementById(s);this.v(x,y,r=>this.o(x,y,r,m))},ax(t,b,d,m){this.y(this.b(t,b),d,m)}}`;
536
+ }
537
+ function writeRuntime$1(request, write) {
538
+ if (request.runtimeWritten) return;
539
+ request.runtimeWritten = true;
540
+ writeScript$1(request, serverRuntimeCodeFor(request.runtimeName), write);
541
+ }
542
+ function writeScript$1(request, code, write) {
543
+ write(`<script ${HYDRATION_SKIP_ATTRIBUTE}=""${nonceAttribute(request.nonce)}>${code}<\/script>`);
544
+ }
545
+ function earlyEventCaptureCode() {
546
+ return `(d=>{if(d.${EARLY_EVENT_QUEUE_PROPERTY})return;let q=d.${EARLY_EVENT_QUEUE_PROPERTY}=[],h=d.${EARLY_EVENT_HANDLER_PROPERTY}=e=>{q.push(e)};for(let t of [${REPLAYABLE_EVENT_TYPES.map((type) => `'${type}'`).join(",")}])d.addEventListener(t,h,!0)})(document)`;
547
+ }
548
+ function earlyEventCaptureMarkup(request) {
549
+ return `<script ${HYDRATION_SKIP_ATTRIBUTE}=""${nonceAttribute(request.nonce)}>${earlyEventCaptureCode()}<\/script>`;
550
+ }
551
+ function placeholderMarkup(request, id) {
552
+ return templateMarkup(placeholderId(request, id));
553
+ }
554
+ function boundaryPlaceholderMarkup(request, id) {
555
+ return templateMarkup(boundaryId(request, id));
556
+ }
557
+ function templateMarkup(id) {
558
+ return `<template id="${escapeAttribute(id)}"></template>`;
559
+ }
560
+ function segmentContainerStartMarkup(request, id) {
561
+ return `<div hidden id="${escapeAttribute(segmentId(request, id))}">`;
562
+ }
563
+ function activityId(request, id) {
564
+ return prefixedId(request, "a", id);
565
+ }
566
+ function placeholderId(request, id) {
567
+ return prefixedId(request, "p", id);
568
+ }
569
+ function segmentId(request, id) {
570
+ return prefixedId(request, "s", id);
571
+ }
572
+ function boundaryId(request, id) {
573
+ return prefixedId(request, "b", id);
574
+ }
575
+ function jsString(value) {
576
+ return escapeScriptJson(value);
577
+ }
578
+ function prefixedId(request, kind, id) {
579
+ return request.identifierPrefix === "" ? `${kind}-${id}` : `${request.identifierPrefix}-${kind}-${id}`;
580
+ }
581
+ //#endregion
582
+ //#region src/renderer-flush.ts
583
+ const documentHeadMarker = Symbol("fig.document-head");
584
+ const leadingNewlineStartMarker = Symbol("fig.leading-newline-start");
585
+ const leadingNewlineEndMarker = Symbol("fig.leading-newline-end");
586
+ const RUNTIME_REF = "__figSSR";
587
+ const textEncoder = new TextEncoder();
588
+ function flushCompletedQueues(request) {
589
+ if (request.controller === null || request.status === "closed") return;
590
+ if (request.pendingRootTasks > 0) return;
591
+ if (request.prerender && request.pendingTasks > 0) return;
592
+ if (request.flushing) return;
593
+ request.flushing = true;
594
+ try {
595
+ sealHead(request);
596
+ if (request.completedRootSegment !== null) {
597
+ flushSegment(request, request.completedRootSegment);
598
+ request.completedRootSegment = null;
599
+ flushWriteBuffer(request);
600
+ }
601
+ if (!drainBoundaryQueue(request, request.clientRenderedBoundaries, flushClientRenderedBoundary) && !drainBoundaryQueue(request, request.completedBoundaries, flushCompletedBoundary)) drainBoundaryQueue(request, request.partialBoundaries, flushPartialBoundary);
602
+ flushWriteBuffer(request);
603
+ } finally {
604
+ request.flushing = false;
605
+ }
606
+ if (request.pendingTasks === 0 && request.completedBoundaries.size === 0 && request.clientRenderedBoundaries.size === 0 && request.partialBoundaries.size === 0) {
607
+ request.cleanupAbortListener();
608
+ request.status = "closed";
609
+ request.dataStore.dispose();
610
+ request.controller.close();
611
+ }
612
+ }
613
+ function sealHead(request) {
614
+ if (request.headSnapshot !== null) return;
615
+ activateVisibleMetadata(request, request.rootSegment);
616
+ const metadata = request.assetRegistry.headMetadataHtml(request.nonce, !request.prerender && request.pendingTasks > 0);
617
+ request.headSnapshot = {
618
+ ...metadata,
619
+ preloadHeaderEntries: request.assetRegistry.preloadHeaderEntries()
620
+ };
621
+ request.headReady.resolve(metadata.preamble + metadata.metadata);
622
+ }
623
+ function flushSegment(request, segment) {
624
+ if (segment.status === "flushed") return;
625
+ if (segment.boundary !== null) {
626
+ flushSuspenseBoundary(request, segment, segment.boundary);
627
+ return;
628
+ }
629
+ flushSubtree(request, segment);
630
+ }
631
+ function flushSubtree(request, segment) {
632
+ segment.parentFlushed = true;
633
+ if (segment.status === "pending" || segment.status === "rendering") {
634
+ request.write(placeholderMarkup(request, ensureSegmentId(request, segment)));
635
+ return;
636
+ }
637
+ if (segment.status === "flushed") return;
638
+ segment.status = "flushed";
639
+ if (request.document === null || segment !== request.rootSegment) flushSegmentAssets(request, segment);
640
+ let chunkIndex = 0;
641
+ for (const child of segment.children) {
642
+ for (; chunkIndex < child.index; chunkIndex += 1) writeChunk(request, segment.chunks[chunkIndex], segment);
643
+ flushSegment(request, child);
644
+ }
645
+ for (; chunkIndex < segment.chunks.length; chunkIndex += 1) writeChunk(request, segment.chunks[chunkIndex], segment);
646
+ }
647
+ function flushSuspenseBoundary(request, segment, boundary) {
648
+ boundary.parentFlushed = true;
649
+ if (boundary.status === "completed") {
650
+ request.write(`<!--${SUSPENSE_COMPLETED_MARKER}-->`);
651
+ flushBoundaryContent(request, boundary);
652
+ request.write(`<!--${SUSPENSE_END_MARKER}-->`);
653
+ segment.status = "flushed";
654
+ return;
655
+ }
656
+ if (request.prerender && boundary.status === "client-rendered") {
657
+ request.write(`<!--${SUSPENSE_CLIENT_MARKER}-->`);
658
+ request.write(clientRenderedBoundaryPlaceholderMarkup(request, boundary));
659
+ flushSubtree(request, segment);
660
+ request.write(`<!--${SUSPENSE_END_MARKER}-->`);
661
+ return;
662
+ }
663
+ const boundaryIdValue = ensureBoundaryId(request, boundary);
664
+ flushSegmentAssets(request, boundary.contentSegment);
665
+ request.write(`<!--${SUSPENSE_PENDING_PREFIX}${boundaryIdValue}-->`);
666
+ request.write(boundaryPlaceholderMarkup(request, boundaryIdValue));
667
+ flushSubtree(request, segment);
668
+ request.write(`<!--${SUSPENSE_END_MARKER}-->`);
669
+ if (boundary.status === "client-rendered") request.clientRenderedBoundaries.add(boundary);
670
+ else if (boundary.completedSegments.length > 0) request.partialBoundaries.add(boundary);
671
+ }
672
+ function flushBoundaryContent(request, boundary) {
673
+ for (const segment of boundary.completedSegments) flushSegment(request, segment);
674
+ boundary.completedSegments = [];
675
+ }
676
+ function clientRenderedBoundaryPlaceholderMarkup(request, boundary) {
677
+ const id = escapeAttribute(boundaryId(request, ensureBoundaryId(request, boundary)));
678
+ const digest = boundary.error?.digest;
679
+ const message = boundary.error?.message;
680
+ return `<template id="${id}"${digest === void 0 || digest === "" ? "" : ` data-dgst="${escapeAttribute(digest)}"`}${message === void 0 || message === "" ? "" : ` data-msg="${escapeAttribute(message)}"`}></template>`;
681
+ }
682
+ function flushCompletedBoundary(request, boundary) {
683
+ flushPartialBoundary(request, boundary);
684
+ writeBoundaryRevealScript(request, boundary);
685
+ }
686
+ function flushPartialBoundary(request, boundary) {
687
+ for (const segment of boundary.completedSegments) flushBoundarySegment(request, boundary, segment);
688
+ boundary.completedSegments = [];
689
+ }
690
+ function flushBoundarySegment(request, boundary, segment) {
691
+ ensureBoundaryId(request, boundary);
692
+ const blockingIds = flushSegmentContainer(request, segment);
693
+ if (segment !== boundary.contentSegment) writeSegmentRevealScript(request, segment, blockingIds);
694
+ }
695
+ function writeSegmentRevealScript(request, segment, blockingIds) {
696
+ const id = ensureSegmentId(request, segment);
697
+ writeRuntime(request);
698
+ writeScript(request, withAssetGate(blockingIds, `${RUNTIME_REF}.s(${jsString(placeholderId(request, id))},${jsString(segmentId(request, id))})`));
699
+ }
700
+ function writeBoundaryRevealScript(request, boundary) {
701
+ const blockingIds = flushSegmentAssets(request, boundary.contentSegment);
702
+ const metadata = switchBoundaryMetadata(request, boundary);
703
+ const metadataArgument = metadata === null ? "" : `,${metadata}`;
704
+ writeRuntime(request);
705
+ const boundaryRef = jsString(boundaryId(request, ensureBoundaryId(request, boundary)));
706
+ const contentRef = jsString(segmentId(request, ensureSegmentId(request, boundary.contentSegment)));
707
+ writeScript(request, withAssetGate(blockingIds, boundary.activityId === null ? `${RUNTIME_REF}.c(${boundaryRef},${contentRef}${metadataArgument})` : `${RUNTIME_REF}.ac(${jsString(boundary.activityId)},${boundaryRef},${contentRef}${metadataArgument})`));
708
+ }
709
+ function switchBoundaryMetadata(request, boundary) {
710
+ if (!boundary.metadataVisible) return null;
711
+ const before = escapeScriptJson(request.assetRegistry.metadataSnapshot());
712
+ const fallback = boundary.fallbackSegment;
713
+ if (fallback !== null) {
714
+ request.assetRegistry.releaseMetadata(fallback);
715
+ for (const child of fallback.children) deactivateMetadataTree(request, child);
716
+ }
717
+ activateVisibleMetadata(request, boundary.contentSegment);
718
+ const after = escapeScriptJson(request.assetRegistry.metadataSnapshot());
719
+ return before === after ? null : after;
720
+ }
721
+ function activateVisibleMetadata(request, segment) {
722
+ if (segment.status === "pending" || segment.status === "rendering") return;
723
+ const boundary = segment.boundary;
724
+ if (boundary !== null) {
725
+ boundary.metadataVisible = true;
726
+ if (boundary.status === "completed") {
727
+ activateVisibleMetadata(request, boundary.contentSegment);
728
+ return;
729
+ }
730
+ }
731
+ request.assetRegistry.activateMetadata(segment, segment.assetResources);
732
+ for (const child of segment.children) activateVisibleMetadata(request, child);
733
+ }
734
+ function deactivateMetadataTree(request, segment) {
735
+ request.assetRegistry.releaseMetadata(segment);
736
+ for (const child of segment.children) deactivateMetadataTree(request, child);
737
+ const boundary = segment.boundary;
738
+ if (boundary === null) return;
739
+ boundary.metadataVisible = false;
740
+ deactivateMetadataTree(request, boundary.contentSegment);
741
+ }
742
+ function flushSegmentContainer(request, segment) {
743
+ if (segment.status === "flushed") return [];
744
+ const blockingIds = flushSegmentAssets(request, segment);
745
+ request.write(segmentContainerStartMarkup(request, ensureSegmentId(request, segment)));
746
+ flushSegment(request, segment);
747
+ request.write("</div>");
748
+ return blockingIds;
749
+ }
750
+ function flushSegmentAssets(request, segment) {
751
+ const blockingIds = /* @__PURE__ */ new Set();
752
+ collectSegmentAssets(request, segment, blockingIds);
753
+ return [...blockingIds];
754
+ }
755
+ function collectSegmentAssets(request, segment, blockingIds) {
756
+ if (segment.status !== "pending" && segment.status !== "rendering") flushAssetList(request, segment.assetResources, blockingIds);
757
+ for (const child of segment.children) collectSegmentAssets(request, child, blockingIds);
758
+ }
759
+ function flushAssetList(request, resources, blockingIds) {
760
+ for (const resource of resources) {
761
+ const id = request.assetRegistry.write(resource, request);
762
+ if (id !== null) blockingIds.add(id);
763
+ }
764
+ }
765
+ function withAssetGate(blockingIds, call) {
766
+ if (blockingIds.length === 0) return call;
767
+ return `${RUNTIME_REF}.r([${blockingIds.map(jsString).join(",")}],()=>{${call}})`;
768
+ }
769
+ function flushClientRenderedBoundary(request, boundary) {
770
+ if (boundary.id === null) return;
771
+ writeRuntime(request);
772
+ const boundaryRef = jsString(boundaryId(request, boundary.id));
773
+ const digest = jsString(boundary.error?.digest ?? "");
774
+ const message = jsString(boundary.error?.message ?? "");
775
+ writeScript(request, boundary.activityId === null ? `${RUNTIME_REF}.x(${boundaryRef},${digest},${message})` : `${RUNTIME_REF}.ax(${jsString(boundary.activityId)},${boundaryRef},${digest},${message})`);
776
+ }
777
+ function drainBoundaryQueue(request, queue, flush) {
778
+ for (;;) {
779
+ if (streamFlowBlocked(request.controller)) return true;
780
+ const first = queue.values().next();
781
+ if (first.done === true) return false;
782
+ flush(request, first.value);
783
+ queue.delete(first.value);
784
+ flushWriteBuffer(request);
785
+ }
786
+ }
787
+ function writeRuntime(request) {
788
+ writeRuntime$1(request, (chunk) => request.write(chunk));
789
+ }
790
+ function writeScript(request, code) {
791
+ writeScript$1(request, `(__figSSR=>{${code}})(globalThis[${jsString(request.runtimeName)}])`, (chunk) => request.write(chunk));
792
+ }
793
+ function writeChunk(request, chunk, segment) {
794
+ if (chunk === leadingNewlineStartMarker) {
795
+ request.leadingNewlineStack.push(false);
796
+ return;
797
+ }
798
+ if (chunk === leadingNewlineEndMarker) {
799
+ request.leadingNewlineStack.pop();
800
+ return;
801
+ }
802
+ if (typeof chunk === "object") {
803
+ request.write(request.leadingNewlineStack.at(-1) === false && chunk.value.startsWith("\n") ? `\n${chunk.value}` : chunk.value);
804
+ return;
805
+ }
806
+ if (chunk !== documentHeadMarker) {
807
+ request.write(chunk);
808
+ return;
809
+ }
810
+ if (request.document === null) return;
811
+ const metadata = request.headSnapshot ?? request.assetRegistry.headMetadataHtml(request.nonce);
812
+ const [beforeMetadata, afterMetadata] = partitionHeadAssets(request, segment.assetResources);
813
+ const blockingIds = /* @__PURE__ */ new Set();
814
+ request.write(metadata.preamble);
815
+ flushAssetList(request, beforeMetadata, blockingIds);
816
+ request.write(metadata.metadata);
817
+ flushAssetList(request, afterMetadata, blockingIds);
818
+ }
819
+ function partitionHeadAssets(request, resources) {
820
+ const preconnects = [];
821
+ const criticalPreloads = [];
822
+ const stylesheets = [];
823
+ const afterMetadata = [];
824
+ for (const resource of resources) if (resource.kind === "preconnect") preconnects.push(resource);
825
+ else if (resource.kind === "font" || resource.kind === "preload" && (resource.as === "font" || resource.as === "image" && (resource.fetchpriority === "high" || request.assetRegistry.isEarlyImage(resource)))) criticalPreloads.push(resource);
826
+ else if (resource.kind === "stylesheet") stylesheets.push(resource);
827
+ else afterMetadata.push(resource);
828
+ return [[
829
+ ...preconnects,
830
+ ...criticalPreloads,
831
+ ...stylesheets
832
+ ], afterMetadata];
833
+ }
834
+ function flushWriteBuffer(request) {
835
+ if (request.writeBuffer.length === 0 || request.controller === null) return;
836
+ request.controller.enqueue(textEncoder.encode(request.writeBuffer.join("")));
837
+ request.writeBuffer = [];
838
+ }
839
+ function ensureSegmentId(request, segment) {
840
+ segment.id ??= request.nextSegmentId++;
841
+ return segment.id;
842
+ }
843
+ function ensureBoundaryId(request, boundary) {
844
+ boundary.id ??= request.nextBoundaryId++;
845
+ return boundary.id;
846
+ }
847
+ //#endregion
848
+ //#region src/renderer.ts
849
+ const errorStacks = /* @__PURE__ */ new WeakMap();
850
+ const TEXT_SEPARATOR = `<!--${TEXT_SEPARATOR_DATA}-->`;
851
+ let nextRuntimeId = 0;
852
+ function createServerRenderRequest(node, options = {}, mode = {}) {
853
+ throwIfAborted(options.signal);
854
+ const shellReady = deferred();
855
+ const headReady = deferred();
856
+ const allReady = deferred();
857
+ shellReady.promise.catch(() => void 0);
858
+ headReady.promise.catch(() => void 0);
859
+ allReady.promise.catch(() => void 0);
860
+ const rootSegment = createSegment(0, null);
861
+ const dataStoreHost = {
862
+ getLane: () => null,
863
+ partition: options.dataPartition,
864
+ schedule: () => void 0
865
+ };
866
+ const dataStore = options.dataStore === void 0 ? createRendererDataStore(dataStoreHost) : attachDataStore(options.dataStore, dataStoreHost, options.initialData);
867
+ const request = {
868
+ abortableTasks: /* @__PURE__ */ new Set(),
869
+ allReady,
870
+ cleanupAbortListener: () => void 0,
871
+ completedBoundaries: /* @__PURE__ */ new Set(),
872
+ completedRootSegment: null,
873
+ controller: null,
874
+ dataStore,
875
+ fatalError: null,
876
+ identifierPrefix: options.identifierPrefix ?? "",
877
+ leadingNewlineStack: [],
878
+ nextBoundaryId: 0,
879
+ nextSegmentId: 0,
880
+ nextActivityId: 0,
881
+ nextViewTransitionId: 0,
882
+ nonce: options.nonce,
883
+ onError: options.onError,
884
+ pendingRootTasks: 0,
885
+ pendingTasks: 0,
886
+ pingedTasks: [],
887
+ rootSegment,
888
+ runtimeName: createRuntimeName(options.identifierPrefix),
889
+ runtimeWritten: false,
890
+ headReady,
891
+ headSnapshot: null,
892
+ shellReady,
893
+ status: "open",
894
+ clientRenderedBoundaries: /* @__PURE__ */ new Set(),
895
+ clientReferenceFallback: options.clientReferenceFallback,
896
+ partialBoundaries: /* @__PURE__ */ new Set(),
897
+ prerender: mode.prerender === true,
898
+ componentAssets: options.assets,
899
+ document: mode.document === true ? { hasHead: false } : null,
900
+ assetRegistry: new AssetResourceRegistry(options.identifierPrefix ?? ""),
901
+ resolveAssetKey: options.resolveAssetKey,
902
+ workScheduled: false,
903
+ flushing: false,
904
+ writeBuffer: [],
905
+ write(chunk) {
906
+ if (chunk !== "" && this.leadingNewlineStack.length > 0) this.leadingNewlineStack[this.leadingNewlineStack.length - 1] = true;
907
+ this.writeBuffer.push(chunk);
908
+ }
909
+ };
910
+ if (options.dataStore === void 0 && options.initialData !== void 0) request.dataStore.hydrate(options.initialData);
911
+ rootSegment.parentFlushed = true;
912
+ const rootTask = createTask(request, node, rootSegment, {
913
+ abortSet: request.abortableTasks,
914
+ boundary: null,
915
+ contextValues: /* @__PURE__ */ new Map(),
916
+ hiddenActivityId: null,
917
+ hostAncestors: [],
918
+ hostNamespace: "html",
919
+ imagePreloadsSuppressed: false,
920
+ idPath: "",
921
+ pendingLeadingNewline: false,
922
+ selectProps: null,
923
+ stack: null,
924
+ treeParent: options.renderTree?.tree ?? null,
925
+ viewTransition: null
926
+ });
927
+ request.pingedTasks.push(rootTask);
928
+ const stream = new ReadableStream({
929
+ start(streamController) {
930
+ request.controller = streamController;
931
+ flushCompletedQueues(request);
932
+ },
933
+ pull() {
934
+ flushCompletedQueues(request);
935
+ },
936
+ cancel(reason) {
937
+ request.controller = null;
938
+ request.writeBuffer = [];
939
+ abort(request, reason);
940
+ request.status = "closed";
941
+ }
942
+ }, new ByteLengthQueuingStrategy({ highWaterMark: streamHighWaterMark(options.highWaterMark) }));
943
+ if (options.signal !== void 0) {
944
+ const signal = options.signal;
945
+ const abortListener = () => abort(request, signal.reason);
946
+ signal.addEventListener("abort", abortListener, { once: true });
947
+ request.cleanupAbortListener = () => {
948
+ signal.removeEventListener("abort", abortListener);
949
+ request.cleanupAbortListener = () => void 0;
950
+ };
951
+ }
952
+ request.workScheduled = true;
953
+ queueMicrotask(() => {
954
+ request.workScheduled = false;
955
+ performWork(request);
956
+ });
957
+ return {
958
+ abort: (reason) => abort(request, reason),
959
+ allReady: allReady.promise,
960
+ contentType: "text/html; charset=utf-8",
961
+ data: request.dataStore,
962
+ getData: () => request.dataStore.snapshot(),
963
+ getPreloadHeader: (headerOptions) => request.headSnapshot === null ? void 0 : formatPreloadHeader(request.headSnapshot.preloadHeaderEntries, headerOptions),
964
+ getHead: () => {
965
+ const snapshot = request.headSnapshot;
966
+ return snapshot === null ? request.assetRegistry.headHtml(request.nonce) : snapshot.preamble + snapshot.metadata;
967
+ },
968
+ headReady: headReady.promise,
969
+ shellReady: shellReady.promise,
970
+ stream
971
+ };
972
+ }
973
+ function createTask(request, node, segment, scope, childIndexBase = 0) {
974
+ request.pendingTasks += 1;
975
+ if (scope.boundary === null) request.pendingRootTasks += 1;
976
+ else scope.boundary.pendingTasks += 1;
977
+ const task = {
978
+ ...scope,
979
+ childIndexBase,
980
+ node,
981
+ segment
982
+ };
983
+ request.abortableTasks.add(task);
984
+ scope.abortSet.add(task);
985
+ return task;
986
+ }
987
+ function forkScope(scope) {
988
+ return {
989
+ abortSet: scope.abortSet,
990
+ boundary: scope.boundary,
991
+ contextValues: cloneContextValues(scope.contextValues),
992
+ hiddenActivityId: scope.hiddenActivityId,
993
+ hostAncestors: scope.hostAncestors,
994
+ hostNamespace: scope.hostNamespace,
995
+ imagePreloadsSuppressed: scope.imagePreloadsSuppressed,
996
+ idPath: scope.idPath,
997
+ pendingLeadingNewline: scope.pendingLeadingNewline,
998
+ selectProps: scope.selectProps,
999
+ stack: scope.stack,
1000
+ treeParent: scope.treeParent,
1001
+ viewTransition: scope.viewTransition === null ? null : { ...scope.viewTransition }
1002
+ };
1003
+ }
1004
+ function createSegment(index, boundary, textSeams = {
1005
+ lastPushedText: false,
1006
+ textEmbedded: false
1007
+ }) {
1008
+ return {
1009
+ boundary,
1010
+ children: [],
1011
+ chunks: [],
1012
+ id: null,
1013
+ index,
1014
+ lastPushedText: textSeams.lastPushedText,
1015
+ parentFlushed: false,
1016
+ assetResources: [],
1017
+ status: "pending",
1018
+ textEmbedded: textSeams.textEmbedded,
1019
+ write(chunk) {
1020
+ this.lastPushedText = false;
1021
+ this.chunks.push(chunk);
1022
+ }
1023
+ };
1024
+ }
1025
+ function createBoundary(fallbackAbortableTasks, contentSegment) {
1026
+ return {
1027
+ activityId: null,
1028
+ completedSegments: [],
1029
+ contentSegment,
1030
+ error: null,
1031
+ fallbackSegment: null,
1032
+ fallbackAbortableTasks,
1033
+ id: null,
1034
+ parentFlushed: false,
1035
+ pendingTasks: 0,
1036
+ status: "pending",
1037
+ metadataVisible: false
1038
+ };
1039
+ }
1040
+ function performWork(request) {
1041
+ if (request.status === "closed") return;
1042
+ const tasks = request.pingedTasks;
1043
+ request.pingedTasks = [];
1044
+ for (const task of tasks) retryTask(request, task);
1045
+ flushCompletedQueues(request);
1046
+ }
1047
+ function retryTask(request, task) {
1048
+ if (task.segment.status !== "pending") return;
1049
+ task.segment.status = "rendering";
1050
+ const frame = createRenderFrame(request, task.segment, forkScope(task));
1051
+ try {
1052
+ renderChildSequence(collectChildren(task.node), frame, task.childIndexBase);
1053
+ completeSegmentText(task.segment);
1054
+ task.segment.status = "completed";
1055
+ detachTask(request, task);
1056
+ finishedTask(request, task);
1057
+ } catch (error) {
1058
+ detachTask(request, task);
1059
+ task.segment.status = "completed";
1060
+ erroredTask(request, task, error);
1061
+ }
1062
+ }
1063
+ function createRenderFrame(request, segment, scope) {
1064
+ return {
1065
+ ...scope,
1066
+ dispatcher: null,
1067
+ localIdCounter: 0,
1068
+ request,
1069
+ segment
1070
+ };
1071
+ }
1072
+ function createServerDispatcher(frame) {
1073
+ return createStaticDispatcher({
1074
+ contextValues: frame.contextValues,
1075
+ externalStoreError: "useSyncExternalStore requires getServerSnapshot during server render.",
1076
+ readPromise(promise) {
1077
+ throwIfAborting(frame.request);
1078
+ return readThenable(promise);
1079
+ },
1080
+ readData(resource, args) {
1081
+ throwIfAborting(frame.request);
1082
+ return frame.request.dataStore.readData(resource, args, frame);
1083
+ },
1084
+ preloadData(resource, args) {
1085
+ throwIfAborting(frame.request);
1086
+ frame.request.dataStore.preloadData(resource, ...args);
1087
+ },
1088
+ useId() {
1089
+ const id = `${frame.request.identifierPrefix}fig-${frame.idPath}-${frame.localIdCounter.toString(32)}`;
1090
+ frame.localIdCounter += 1;
1091
+ return id;
1092
+ },
1093
+ updateError: "State updates are not allowed during server render."
1094
+ });
1095
+ }
1096
+ function renderNode(node, frame) {
1097
+ if (Array.isArray(node)) {
1098
+ renderChildren(node, frame);
1099
+ return;
1100
+ }
1101
+ if (node === null || node === void 0 || typeof node === "boolean") return;
1102
+ if (typeof node === "string" || typeof node === "number") {
1103
+ const text = String(node);
1104
+ if (frame.request.document !== null && !frame.request.document.hasHead) {
1105
+ if (text.trim() !== "") throw invalidDocumentShellError();
1106
+ }
1107
+ if (frame.hostNamespace === "html") validateTextNesting(text, frame.hostAncestors);
1108
+ if (text !== "") {
1109
+ if (frame.treeParent !== null) frame.treeParent.children.push({
1110
+ children: [],
1111
+ key: null,
1112
+ kind: "text",
1113
+ name: "#text",
1114
+ props: { nodeValue: text }
1115
+ });
1116
+ if (frame.segment.lastPushedText) frame.segment.write(TEXT_SEPARATOR);
1117
+ if (consumePendingLeadingNewline(frame)) writeLeadingNewlineText(text, frame.segment);
1118
+ else writeText(text, frame.segment);
1119
+ frame.segment.lastPushedText = true;
1120
+ }
1121
+ return;
1122
+ }
1123
+ if (isPortal(node)) return;
1124
+ if (isValidElement(node)) {
1125
+ renderElement(node, frame);
1126
+ return;
1127
+ }
1128
+ if (isThenable(node)) {
1129
+ renderChildren(readThenable(node), frame);
1130
+ return;
1131
+ }
1132
+ throw invalidChildError(node);
1133
+ }
1134
+ function renderChildren(node, frame) {
1135
+ renderChildSequence(collectChildren(node), frame);
1136
+ }
1137
+ function renderChildSequence(children, frame, indexBase = 0) {
1138
+ for (let index = 0; index < children.length; index += 1) {
1139
+ const child = children[index];
1140
+ try {
1141
+ withIdSegment(frame, indexBase + index, () => renderNode(child, frame));
1142
+ } catch (error) {
1143
+ if (isThenable(error)) {
1144
+ spawnSuspendedTask(frame, child, error, indexBase + index);
1145
+ continue;
1146
+ }
1147
+ throw error;
1148
+ }
1149
+ }
1150
+ }
1151
+ function completeSegmentText(segment) {
1152
+ if (segment.textEmbedded && segment.lastPushedText) segment.write(TEXT_SEPARATOR);
1153
+ }
1154
+ function withIdSegment(frame, index, callback) {
1155
+ const previousIdPath = frame.idPath;
1156
+ const segment = index.toString(32);
1157
+ frame.idPath = previousIdPath === "" ? segment : `${previousIdPath}-${segment}`;
1158
+ try {
1159
+ return callback();
1160
+ } finally {
1161
+ frame.idPath = previousIdPath;
1162
+ }
1163
+ }
1164
+ function renderElement(element, frame) {
1165
+ if (frame.treeParent === null) {
1166
+ renderElementKind(element, frame);
1167
+ return;
1168
+ }
1169
+ const treeNode = collectedTreeNode(element);
1170
+ frame.treeParent.children.push(treeNode);
1171
+ const previousTreeParent = frame.treeParent;
1172
+ frame.treeParent = treeNode;
1173
+ try {
1174
+ renderElementKind(element, frame);
1175
+ } finally {
1176
+ frame.treeParent = previousTreeParent;
1177
+ }
1178
+ }
1179
+ function collectedTreeNode(element) {
1180
+ const { children: _children, ...ownProps } = element.props;
1181
+ const [name, kind] = collectedNameAndKind(element.type);
1182
+ return {
1183
+ children: [],
1184
+ key: element.key ?? null,
1185
+ kind,
1186
+ name,
1187
+ props: ownProps
1188
+ };
1189
+ }
1190
+ function collectedNameAndKind(type) {
1191
+ if (typeof type === "string") return [type, "host"];
1192
+ if (type === Fragment) return ["Fragment", "fragment"];
1193
+ if (isContext(type)) return ["Context.Provider", "context-provider"];
1194
+ if (isAssets(type)) return ["Assets", "assets"];
1195
+ if (isSuspense(type)) return ["Suspense", "suspense"];
1196
+ if (isErrorBoundary(type)) return ["ErrorBoundary", "error-boundary"];
1197
+ if (isActivity(type)) return ["Activity", "activity"];
1198
+ if (isViewTransition(type)) return ["ViewTransition", "view-transition"];
1199
+ if (isClientReference(type)) return [type.id.slice(type.id.lastIndexOf("#") + 1) || "ClientReference", "client-reference"];
1200
+ if (typeof type === "function") return [type.name === "" ? "Anonymous" : type.name, "function"];
1201
+ return ["Anonymous", "function"];
1202
+ }
1203
+ function renderElementKind(element, frame) {
1204
+ const type = element.type;
1205
+ if (typeof type === "string") {
1206
+ renderHostElement(type, element.props, frame);
1207
+ return;
1208
+ }
1209
+ if (type === Fragment) {
1210
+ renderChildren(element.props.children, frame);
1211
+ return;
1212
+ }
1213
+ if (isContext(type)) {
1214
+ renderContextProvider(type, element.props, frame);
1215
+ return;
1216
+ }
1217
+ if (isAssets(type)) {
1218
+ renderAssets(element.props, frame);
1219
+ return;
1220
+ }
1221
+ if (isSuspense(type)) {
1222
+ renderSuspense(element.props, frame);
1223
+ return;
1224
+ }
1225
+ if (isErrorBoundary(type)) {
1226
+ renderChildren(element.props.children, frame);
1227
+ return;
1228
+ }
1229
+ if (isClientReference(type)) {
1230
+ renderClientReference(type, element.props, frame);
1231
+ return;
1232
+ }
1233
+ if (isActivity(type)) {
1234
+ renderActivity(element.props, frame);
1235
+ return;
1236
+ }
1237
+ if (isViewTransition(type)) {
1238
+ renderViewTransition(element.props, frame);
1239
+ return;
1240
+ }
1241
+ if (typeof type === "function") {
1242
+ renderFunctionComponent(type, element.props, frame);
1243
+ return;
1244
+ }
1245
+ throw new Error(`Unsupported Fig element type: ${describeElementType(type)}.`);
1246
+ }
1247
+ function renderFunctionComponent(type, props, frame) {
1248
+ frame.dispatcher ??= createServerDispatcher(frame);
1249
+ const previousDispatcher = setCurrentDispatcher(frame.dispatcher);
1250
+ const previousDataStore = setCurrentDataStore(frame.request.dataStore);
1251
+ const previousStack = frame.stack;
1252
+ const previousLocalIdCounter = frame.localIdCounter;
1253
+ frame.stack = {
1254
+ name: type.name || "Anonymous",
1255
+ parent: previousStack
1256
+ };
1257
+ frame.localIdCounter = 0;
1258
+ try {
1259
+ renderComponentAssets(type, frame);
1260
+ renderChildren(type(props), frame);
1261
+ } catch (error) {
1262
+ recordErrorStack(error, frame.stack);
1263
+ throw error;
1264
+ } finally {
1265
+ frame.stack = previousStack;
1266
+ frame.localIdCounter = previousLocalIdCounter;
1267
+ setCurrentDataStore(previousDataStore);
1268
+ setCurrentDispatcher(previousDispatcher);
1269
+ }
1270
+ }
1271
+ function renderClientReference(type, props, frame) {
1272
+ if (type.ssr !== void 0) {
1273
+ renderComponentAssets(type, frame);
1274
+ renderElement(createElement(type.ssr, props), frame);
1275
+ return;
1276
+ }
1277
+ const fallback = frame.request.clientReferenceFallback;
1278
+ if (fallback === void 0) {
1279
+ renderFunctionComponent(type, props, frame);
1280
+ return;
1281
+ }
1282
+ renderComponentAssets(type, frame);
1283
+ renderChildren(fallback(type, props), frame);
1284
+ }
1285
+ function renderComponentAssets(type, frame) {
1286
+ const key = isClientReference(type) ? type.id : frame.request.resolveAssetKey?.(type);
1287
+ if (key !== void 0) renderAssetValue(frame.request.componentAssets?.[key], frame);
1288
+ }
1289
+ function renderContextProvider(context, props, frame) {
1290
+ withContextValue(frame.contextValues, context, props.value, () => renderChildren(props.children, frame));
1291
+ }
1292
+ function renderAssets(props, frame) {
1293
+ renderAssetValue(props.assets, frame);
1294
+ renderChildren(props.children, frame);
1295
+ }
1296
+ function renderAssetValue(value, frame) {
1297
+ if (value === void 0 || value === null || value === false) return;
1298
+ for (const resource of Array.isArray(value) ? value : [value]) {
1299
+ if (!isFigAssetResource(resource)) throw new Error("The assets prop must contain Fig asset resources.");
1300
+ try {
1301
+ frame.request.assetRegistry.register(resource);
1302
+ } catch (error) {
1303
+ recordErrorStack(error, frame.stack);
1304
+ throw error;
1305
+ }
1306
+ frame.segment.assetResources.push(resource);
1307
+ }
1308
+ }
1309
+ function renderAutomaticImagePreload(resource, frame) {
1310
+ try {
1311
+ frame.request.assetRegistry.registerAutomaticImage(resource);
1312
+ } catch (error) {
1313
+ recordErrorStack(error, frame.stack);
1314
+ throw error;
1315
+ }
1316
+ frame.segment.assetResources.push(resource);
1317
+ }
1318
+ function renderSuspense(props, frame) {
1319
+ consumePendingLeadingNewline(frame);
1320
+ const fallbackAbortableTasks = /* @__PURE__ */ new Set();
1321
+ const contentSegment = createSegment(0, null);
1322
+ const boundary = createBoundary(fallbackAbortableTasks, contentSegment);
1323
+ boundary.activityId = frame.hiddenActivityId;
1324
+ const parentSegment = frame.segment;
1325
+ const boundarySegment = createSegment(parentSegment.chunks.length, boundary);
1326
+ boundary.fallbackSegment = boundarySegment;
1327
+ parentSegment.children.push(boundarySegment);
1328
+ parentSegment.lastPushedText = false;
1329
+ contentSegment.parentFlushed = true;
1330
+ const contentFrame = createRenderFrame(frame.request, contentSegment, {
1331
+ ...forkScope(frame),
1332
+ boundary
1333
+ });
1334
+ try {
1335
+ renderChildren(props.children, contentFrame);
1336
+ contentSegment.status = "completed";
1337
+ boundary.completedSegments.push(contentSegment);
1338
+ if (boundary.pendingTasks === 0) boundary.status = "completed";
1339
+ } catch (error) {
1340
+ contentSegment.status = "completed";
1341
+ markBoundaryClientRendered(frame.request, boundary, error, frame.stack);
1342
+ }
1343
+ const advanceSurfaceWatermark = (branch) => {
1344
+ if (frame.viewTransition !== null && branch.viewTransition !== null) frame.viewTransition.index = Math.max(frame.viewTransition.index, branch.viewTransition.index);
1345
+ };
1346
+ advanceSurfaceWatermark(contentFrame);
1347
+ if (boundary.status === "completed") return;
1348
+ const fallbackFrame = createRenderFrame(frame.request, boundarySegment, {
1349
+ ...forkScope(frame),
1350
+ abortSet: fallbackAbortableTasks
1351
+ });
1352
+ try {
1353
+ renderChildren(props.fallback, fallbackFrame);
1354
+ boundarySegment.status = "completed";
1355
+ } catch (error) {
1356
+ if (boundary.pendingTasks > 0) for (const task of Array.from(boundary.fallbackAbortableTasks)) abortTask(frame.request, task);
1357
+ throw error;
1358
+ } finally {
1359
+ advanceSurfaceWatermark(fallbackFrame);
1360
+ }
1361
+ }
1362
+ function renderViewTransition(props, frame) {
1363
+ const previousViewTransition = frame.viewTransition;
1364
+ frame.viewTransition = createServerViewTransition(props, frame.request);
1365
+ try {
1366
+ renderChildren(props.children, frame);
1367
+ } finally {
1368
+ frame.viewTransition = previousViewTransition;
1369
+ }
1370
+ }
1371
+ function createServerViewTransition(props, request) {
1372
+ return {
1373
+ className: serverViewTransitionClass(props),
1374
+ index: 0,
1375
+ name: props.name === void 0 || props.name === "auto" ? `fig-vt-${request.nextViewTransitionId++}` : props.name
1376
+ };
1377
+ }
1378
+ function serverViewTransitionClass(props) {
1379
+ const className = props.default;
1380
+ if (className === void 0 || className === "auto" || className === "none") return null;
1381
+ return className;
1382
+ }
1383
+ function renderActivity(props, frame) {
1384
+ if (props.mode !== "hidden") {
1385
+ renderChildren(props.children, frame);
1386
+ return;
1387
+ }
1388
+ const id = activityId(frame.request, frame.request.nextActivityId++);
1389
+ frame.segment.write(`<template ${ACTIVITY_TEMPLATE_ATTRIBUTE}="" id="${escapeAttribute(id)}">`);
1390
+ const previousHiddenActivityId = frame.hiddenActivityId;
1391
+ frame.hiddenActivityId = id;
1392
+ try {
1393
+ renderChildren(props.children, frame);
1394
+ } finally {
1395
+ frame.hiddenActivityId = previousHiddenActivityId;
1396
+ }
1397
+ frame.segment.write("</template>");
1398
+ }
1399
+ function renderHostElement(type, props, frame) {
1400
+ const namespace = hostElementNamespace(type, frame.hostNamespace);
1401
+ if (namespace === "html" && renderHostAsset(type, props, frame)) return;
1402
+ if (namespace === "html") validateInstanceNesting(type, frame.hostAncestors);
1403
+ const document = frame.request.document;
1404
+ if (document !== null && !document.hasHead) {
1405
+ if (type !== "html" && type !== "head") throw invalidDocumentShellError();
1406
+ }
1407
+ if (document !== null && type === "html") frame.segment.write("<!doctype html>");
1408
+ if (document !== null && type === "head") document.hasHead = true;
1409
+ const isVoid = namespace === "html" && isVoidElement(type);
1410
+ const unsafeHTML = unsafeHTMLContent(props);
1411
+ if (isVoid && hasRenderableChild(props.children)) throw new Error(`Void element <${type}> cannot have children.`);
1412
+ if (isVoid && unsafeHTML !== null) throw new Error(`Void element <${type}> cannot have unsafeHTML.`);
1413
+ if (unsafeHTML !== null && hasRenderableChild(props.children)) throw new Error("Host elements cannot have both unsafeHTML and children.");
1414
+ if (namespace === "html") {
1415
+ const imagePreload = imagePreloadFromHostProps(type, props, frame.imagePreloadsSuppressed);
1416
+ if (imagePreload !== null) renderAutomaticImagePreload(imagePreload, frame);
1417
+ }
1418
+ consumePendingLeadingNewline(frame);
1419
+ const viewTransition = frame.viewTransition;
1420
+ writeElementStart(type, viewTransition === null ? props : viewTransitionHostProps(props, viewTransition), frame.segment, frame.selectProps ?? {});
1421
+ if (document !== null && type === "head") frame.segment.write(earlyEventCaptureMarkup(frame.request));
1422
+ if (isVoid) return;
1423
+ const previousPendingLeadingNewline = frame.pendingLeadingNewline;
1424
+ const tracksLeadingNewline = leadingNewlineStrippedHost(type);
1425
+ frame.pendingLeadingNewline = tracksLeadingNewline;
1426
+ if (unsafeHTML !== null) {
1427
+ frame.segment.write(consumePendingLeadingNewline(frame) ? preserveParserStrippedLeadingNewline(unsafeHTML) : unsafeHTML);
1428
+ frame.pendingLeadingNewline = previousPendingLeadingNewline;
1429
+ writeElementEnd(type, frame.segment);
1430
+ return;
1431
+ }
1432
+ const formText = namespace === "html" ? formTextContent(type, props) : null;
1433
+ if (formText !== null) {
1434
+ writeText(consumePendingLeadingNewline(frame) ? preserveParserStrippedLeadingNewline(formText) : formText, frame.segment);
1435
+ frame.pendingLeadingNewline = previousPendingLeadingNewline;
1436
+ writeElementEnd(type, frame.segment);
1437
+ return;
1438
+ }
1439
+ const previousSelectProps = frame.selectProps;
1440
+ if (namespace === "html" && type === "select") frame.selectProps = props;
1441
+ const previousHostAncestors = frame.hostAncestors;
1442
+ const previousHostNamespace = frame.hostNamespace;
1443
+ const previousImagePreloadsSuppressed = frame.imagePreloadsSuppressed;
1444
+ const previousViewTransition = frame.viewTransition;
1445
+ if (viewTransition !== null) frame.viewTransition = null;
1446
+ frame.hostAncestors = [type, ...previousHostAncestors];
1447
+ frame.hostNamespace = childHostNamespace(type, namespace);
1448
+ frame.imagePreloadsSuppressed = previousImagePreloadsSuppressed || namespace === "html" && suppressesImagePreloads(type);
1449
+ if (tracksLeadingNewline) frame.segment.chunks.push(leadingNewlineStartMarker);
1450
+ try {
1451
+ renderChildren(props.children, frame);
1452
+ } finally {
1453
+ frame.selectProps = previousSelectProps;
1454
+ frame.hostAncestors = previousHostAncestors;
1455
+ frame.hostNamespace = previousHostNamespace;
1456
+ frame.imagePreloadsSuppressed = previousImagePreloadsSuppressed;
1457
+ frame.viewTransition = previousViewTransition;
1458
+ frame.pendingLeadingNewline = previousPendingLeadingNewline;
1459
+ }
1460
+ if (tracksLeadingNewline) frame.segment.chunks.push(leadingNewlineEndMarker);
1461
+ if (document !== null && type === "head") writeDocumentHeadMarker(frame.segment);
1462
+ writeElementEnd(type, frame.segment);
1463
+ }
1464
+ function hostElementNamespace(type, parent) {
1465
+ const normalizedType = type.toLowerCase();
1466
+ if (normalizedType === "svg") return "svg";
1467
+ if (normalizedType === "math") return "mathml";
1468
+ return parent;
1469
+ }
1470
+ function childHostNamespace(type, namespace) {
1471
+ return namespace === "svg" && type.toLowerCase() === "foreignobject" ? "html" : namespace;
1472
+ }
1473
+ function renderHostAsset(type, props, frame) {
1474
+ const resource = assetResourceFromHostProps(type, props);
1475
+ if (resource === null) return false;
1476
+ renderAssetValue(resource, frame);
1477
+ return true;
1478
+ }
1479
+ function viewTransitionHostProps(props, viewTransition) {
1480
+ const index = viewTransition.index++;
1481
+ const name = index === 0 ? viewTransition.name : `${viewTransition.name}_${index}`;
1482
+ const nextProps = {
1483
+ ...props,
1484
+ [VIEW_TRANSITION_NAME_ATTRIBUTE]: name
1485
+ };
1486
+ if (viewTransition.className !== null) nextProps[VIEW_TRANSITION_CLASS_ATTRIBUTE] = viewTransition.className;
1487
+ return nextProps;
1488
+ }
1489
+ function spawnSuspendedTask(frame, node, thenable, childIndexBase) {
1490
+ const request = frame.request;
1491
+ const segment = createSegment(frame.segment.chunks.length, null, {
1492
+ lastPushedText: frame.segment.lastPushedText,
1493
+ textEmbedded: true
1494
+ });
1495
+ frame.segment.lastPushedText = false;
1496
+ frame.segment.children.push(segment);
1497
+ const task = createTask(request, node, segment, forkScope(frame), childIndexBase);
1498
+ thenable.then(() => pingTask(request, task), () => pingTask(request, task));
1499
+ }
1500
+ function pingTask(request, task) {
1501
+ if (request.status === "closed" || request.status === "aborting") return;
1502
+ request.pingedTasks.push(task);
1503
+ if (request.workScheduled) return;
1504
+ request.workScheduled = true;
1505
+ queueMicrotask(() => {
1506
+ request.workScheduled = false;
1507
+ performWork(request);
1508
+ });
1509
+ }
1510
+ function finishedTask(request, task) {
1511
+ request.pendingTasks -= 1;
1512
+ const boundary = task.boundary;
1513
+ if (boundary === null) {
1514
+ request.pendingRootTasks -= 1;
1515
+ if (task.segment === request.rootSegment || request.completedRootSegment === null) request.completedRootSegment = request.rootSegment;
1516
+ if (request.pendingRootTasks === 0) finishRootShell(request);
1517
+ } else {
1518
+ boundary.pendingTasks -= 1;
1519
+ if (task.segment.parentFlushed) enqueueUnique(boundary.completedSegments, task.segment);
1520
+ if (!completeBoundaryIfReady(request, boundary) && boundary.parentFlushed) request.partialBoundaries.add(boundary);
1521
+ }
1522
+ if (request.pendingTasks === 0) request.allReady.resolve(void 0);
1523
+ }
1524
+ function erroredTask(request, task, error) {
1525
+ request.pendingTasks -= 1;
1526
+ const boundary = task.boundary;
1527
+ if (boundary === null) {
1528
+ request.pendingRootTasks -= 1;
1529
+ fatalError(request, error);
1530
+ return;
1531
+ }
1532
+ boundary.pendingTasks -= 1;
1533
+ markBoundaryClientRendered(request, boundary, error, task.stack);
1534
+ if (request.pendingTasks === 0) request.allReady.resolve(void 0);
1535
+ }
1536
+ function detachTask(request, task) {
1537
+ task.abortSet.delete(task);
1538
+ request.abortableTasks.delete(task);
1539
+ }
1540
+ function abortTask(request, task) {
1541
+ if (!request.abortableTasks.delete(task)) return;
1542
+ task.segment.status = "completed";
1543
+ task.abortSet.delete(task);
1544
+ request.pendingTasks -= 1;
1545
+ const boundary = task.boundary;
1546
+ if (boundary === null) {
1547
+ request.pendingRootTasks -= 1;
1548
+ if (request.pendingRootTasks === 0) finishRootShell(request);
1549
+ } else {
1550
+ boundary.pendingTasks -= 1;
1551
+ completeBoundaryIfReady(request, boundary);
1552
+ }
1553
+ if (request.pendingTasks === 0) request.allReady.resolve(void 0);
1554
+ }
1555
+ function completeBoundaryIfReady(request, boundary) {
1556
+ if (boundary.pendingTasks !== 0 || boundary.status !== "pending") return false;
1557
+ boundary.status = "completed";
1558
+ abortFallbackTasks(request, boundary);
1559
+ if (boundary.parentFlushed) request.completedBoundaries.add(boundary);
1560
+ return true;
1561
+ }
1562
+ function abortFallbackTasks(request, boundary) {
1563
+ for (const fallbackTask of Array.from(boundary.fallbackAbortableTasks)) abortTask(request, fallbackTask);
1564
+ }
1565
+ function markBoundaryClientRendered(request, boundary, error, stack, payload) {
1566
+ if (boundary.status !== "client-rendered") {
1567
+ boundary.status = "client-rendered";
1568
+ boundary.error = payload ?? reportBoundaryError(request, error, stack);
1569
+ }
1570
+ boundary.completedSegments = [];
1571
+ request.completedBoundaries.delete(boundary);
1572
+ request.partialBoundaries.delete(boundary);
1573
+ for (const task of Array.from(request.abortableTasks)) if (task.boundary === boundary) abortTask(request, task);
1574
+ for (const task of Array.from(boundary.fallbackAbortableTasks)) abortTask(request, task);
1575
+ if (boundary.parentFlushed) request.clientRenderedBoundaries.add(boundary);
1576
+ }
1577
+ function abort(request, reason) {
1578
+ if (request.status === "closed") return;
1579
+ request.cleanupAbortListener();
1580
+ request.status = "aborting";
1581
+ request.dataStore.dispose();
1582
+ const error = abortError(reason);
1583
+ request.fatalError = error;
1584
+ if (request.pendingRootTasks > 0) {
1585
+ fatalError(request, error);
1586
+ return;
1587
+ }
1588
+ for (const task of Array.from(request.abortableTasks)) {
1589
+ const boundary = task.boundary;
1590
+ if (boundary !== null) markBoundaryClientRendered(request, boundary, error, task.stack, {});
1591
+ }
1592
+ request.abortableTasks.clear();
1593
+ request.pendingTasks = 0;
1594
+ request.allReady.resolve(void 0);
1595
+ flushCompletedQueues(request);
1596
+ }
1597
+ function fatalError(request, error) {
1598
+ if (request.status === "closed") return;
1599
+ request.cleanupAbortListener();
1600
+ request.status = "closed";
1601
+ request.dataStore.dispose();
1602
+ request.fatalError = error;
1603
+ request.headReady.reject(error);
1604
+ request.shellReady.reject(error);
1605
+ request.allReady.reject(error);
1606
+ request.controller?.error(error);
1607
+ }
1608
+ function finishRootShell(request) {
1609
+ if (request.document !== null && !request.document.hasHead) {
1610
+ fatalError(request, invalidDocumentShellError());
1611
+ return;
1612
+ }
1613
+ if (!request.prerender) sealHead(request);
1614
+ request.shellReady.resolve(void 0);
1615
+ }
1616
+ function enqueueUnique(queue, item) {
1617
+ if (!queue.includes(item)) queue.push(item);
1618
+ }
1619
+ function reportBoundaryError(request, error, stack) {
1620
+ const info = { componentStack: componentStack(stackForError(error, stack)) };
1621
+ if (request.onError === void 0) return { message: errorMessage(error) };
1622
+ try {
1623
+ return request.onError(error, info) ?? {};
1624
+ } catch {
1625
+ return {};
1626
+ }
1627
+ }
1628
+ function recordErrorStack(error, stack) {
1629
+ if (stack === null) return;
1630
+ if (typeof error !== "object" && typeof error !== "function") return;
1631
+ if (error === null || isThenable(error)) return;
1632
+ if (!errorStacks.has(error)) errorStacks.set(error, stack);
1633
+ }
1634
+ function stackForError(error, fallback) {
1635
+ if (typeof error !== "object" && typeof error !== "function" || error === null) return fallback;
1636
+ return errorStacks.get(error) ?? fallback;
1637
+ }
1638
+ function createRuntimeName(identifierPrefix) {
1639
+ const id = nextRuntimeId.toString(36);
1640
+ nextRuntimeId += 1;
1641
+ const prefix = identifierPrefix?.replace(/[^A-Za-z0-9_$]/g, "_") ?? "";
1642
+ return prefix === "" ? `__figSSR_${id}` : `__figSSR_${prefix}_${id}`;
1643
+ }
1644
+ function writeDocumentHeadMarker(segment) {
1645
+ segment.lastPushedText = false;
1646
+ segment.chunks.push(documentHeadMarker);
1647
+ }
1648
+ function consumePendingLeadingNewline(frame) {
1649
+ const pending = frame.pendingLeadingNewline;
1650
+ frame.pendingLeadingNewline = false;
1651
+ return pending;
1652
+ }
1653
+ function leadingNewlineStrippedHost(type) {
1654
+ return type === "pre" || type === "textarea";
1655
+ }
1656
+ function writeLeadingNewlineText(text, segment) {
1657
+ writeText(text, { write(value) {
1658
+ segment.write({ value });
1659
+ } });
1660
+ }
1661
+ function preserveParserStrippedLeadingNewline(text) {
1662
+ return text.startsWith("\n") ? `\n${text}` : text;
1663
+ }
1664
+ function invalidDocumentShellError() {
1665
+ return /* @__PURE__ */ new Error("renderToDocumentStream requires the root to render an <html> document with a <head>.");
1666
+ }
1667
+ function throwIfAborted(signal) {
1668
+ if (signal?.aborted === true) throw abortReason(signal.reason);
1669
+ }
1670
+ function throwIfAborting(request) {
1671
+ if (request.status === "aborting") throw abortReason(request.fatalError);
1672
+ }
1673
+ function abortError(reason) {
1674
+ if (reason instanceof Error) return reason;
1675
+ return new Error(typeof reason === "string" ? reason : "Server render was aborted.");
1676
+ }
1677
+ function abortReason(reason) {
1678
+ return reason ?? /* @__PURE__ */ new Error("Server render was aborted.");
1679
+ }
1680
+ function describeElementType(type) {
1681
+ if (typeof type === "symbol") return String(type);
1682
+ if (typeof type === "function") return type.name || "anonymous function";
1683
+ return typeof type;
1684
+ }
1685
+ //#endregion
1686
+ //#region src/render-tree.ts
1687
+ function createRenderTreeCollector() {
1688
+ return { tree: {
1689
+ children: [],
1690
+ key: null,
1691
+ kind: "root",
1692
+ name: "Root",
1693
+ props: {}
1694
+ } };
1695
+ }
1696
+ //#endregion
1697
+ //#region src/index.ts
1698
+ function renderToStream(node, options = {}) {
1699
+ return createServerRenderRequest(node, options);
1700
+ }
1701
+ function renderToDocumentStream(node, options = {}) {
1702
+ const request = createServerRenderRequest(node, options, { document: true });
1703
+ return {
1704
+ abort: (reason) => request.abort(reason),
1705
+ allReady: request.allReady,
1706
+ contentType: request.contentType,
1707
+ data: request.data,
1708
+ getData: () => request.getData(),
1709
+ getPreloadHeader: (headerOptions) => request.getPreloadHeader(headerOptions),
1710
+ shellReady: request.shellReady,
1711
+ stream: request.stream
1712
+ };
1713
+ }
1714
+ /**
1715
+ * The streamed output, buffered: awaits `allReady` and concatenates exactly
1716
+ * the bytes a streaming client would have received — including the inline
1717
+ * streaming runtime and boundary-reveal scripts when the tree suspends past
1718
+ * the shell. Right for caching responses and snapshotting wire output; it is
1719
+ * NOT React's `renderToString` (use `prerender` for settled, script-free
1720
+ * static markup).
1721
+ */
1722
+ async function renderToHtml(node, options = {}) {
1723
+ const result = renderToStream(node, options);
1724
+ await result.allReady;
1725
+ return readStreamToString(result.stream);
1726
+ }
1727
+ /** Document-mode {@link renderToHtml}: the streamed document, buffered. */
1728
+ async function renderToDocumentHtml(node, options = {}) {
1729
+ const result = renderToDocumentStream(node, options);
1730
+ await result.allReady;
1731
+ return readStreamToString(result.stream);
1732
+ }
1733
+ /**
1734
+ * Settled static HTML: waits for all async work before flushing, so completed
1735
+ * Suspense content is emitted in logical position without streaming scripts.
1736
+ */
1737
+ async function prerender(node, options = {}) {
1738
+ const { document = false, ...renderOptions } = options;
1739
+ const result = createServerRenderRequest(node, renderOptions, {
1740
+ document,
1741
+ prerender: true
1742
+ });
1743
+ await result.allReady;
1744
+ const html = await readStreamToString(result.stream);
1745
+ return {
1746
+ data: result.getData(),
1747
+ head: document ? "" : result.getHead(),
1748
+ html
1749
+ };
1750
+ }
1751
+ async function readStreamToString(stream) {
1752
+ const reader = stream.getReader();
1753
+ const textDecoder = new TextDecoder();
1754
+ let output = "";
1755
+ for (;;) {
1756
+ const { done, value } = await reader.read();
1757
+ if (done) return output + textDecoder.decode();
1758
+ output += textDecoder.decode(value, { stream: true });
1759
+ }
1760
+ }
1761
+ //#endregion
1762
+ export { createRenderTreeCollector, prerender, renderToDocumentHtml, renderToDocumentStream, renderToHtml, renderToStream };
1763
+
1764
+ //# sourceMappingURL=index.js.map