@bgub/fig-server 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.
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
- import { i as withContextValue, n as createStaticDispatcher, r as deferred, t as cloneContextValues } from "./shared-CQn6Dje6.js";
2
- import { Fragment, createElement } from "@bgub/fig";
3
- import { ACTIVITY_TEMPLATE_ATTRIBUTE, EARLY_EVENT_HANDLER_PROPERTY, EARLY_EVENT_QUEUE_PROPERTY, 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, assetResourceFromHostProps, assetResourceHostAttributes, assetResourceKey, collectChildren, createDataStore, invalidChildError, isActivity, isAssets, isClientReference, isContext, isErrorBoundary, isFigAssetResource, isPortal, isSuspense, isThenable, isValidElement, isViewTransition, readThenable, setCurrentDataStore, setCurrentDispatcher } from "@bgub/fig/internal";
1
+ import { i as escapeText, n as escapeScriptJson, t as escapeAttribute } from "./escaping-DAot8sFu.js";
2
+ import { a as deferred, c as streamHighWaterMark, i as createStaticDispatcher, l as withContextValue, n as cloneContextValues, o as nonceAttribute, r as componentStack, s as streamFlowBlocked, t as STREAMED_METADATA_ATTRIBUTE } from "./shared-Bna74_aZ.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 } from "@bgub/fig/internal";
4
5
  //#region src/html.ts
5
6
  const voidElements = /* @__PURE__ */ new Set([
6
7
  "area",
@@ -23,9 +24,7 @@ function writeText(value, sink) {
23
24
  }
24
25
  function writeElementStart(type, props, sink, inheritedProps = {}) {
25
26
  validateTagName(type);
26
- sink.write(`<${type}`);
27
- writeAttributes(type, props, inheritedProps, sink);
28
- sink.write(">");
27
+ sink.write(`<${type}${serializeAttributes(type, props, inheritedProps)}>`);
29
28
  }
30
29
  function writeElementEnd(type, sink) {
31
30
  sink.write(`</${type}>`);
@@ -48,46 +47,39 @@ function unsafeHTMLContent(props) {
48
47
  if (typeof value === "string") return value;
49
48
  throw new Error("The unsafeHTML prop must be a string during server render.");
50
49
  }
51
- function writeAttributes(type, props, inheritedProps, sink) {
52
- for (const [name, value] of Object.entries(props)) {
50
+ function serializeAttributes(type, props, inheritedProps) {
51
+ let attributes = "";
52
+ for (const name of Object.keys(props)) {
53
+ const value = props[name];
53
54
  if (reservedProp(name)) continue;
54
55
  if (name === "value" && props.defaultValue !== void 0) continue;
55
56
  if (name === "checked" && props.defaultChecked !== void 0) continue;
56
57
  if (name === "style") {
57
58
  const style = serializeStyle(value);
58
- if (style !== "") writeAttribute(sink, "style", style);
59
+ if (style !== "") attributes += serializeAttribute("style", style);
59
60
  continue;
60
61
  }
61
- const attribute = formAttribute(type, name, value);
62
- if (attribute === null) continue;
63
- const [attributeNameValue, attributeValue] = attribute;
64
- validateAttributeName(attributeNameValue);
65
- if (attributeValue === true) {
66
- sink.write(` ${attributeNameValue}`);
67
- continue;
68
- }
69
- if (serializableAttributeValue(attributeValue)) {
70
- writeAttribute(sink, attributeNameValue, String(attributeValue));
71
- continue;
72
- }
73
- throw new Error(`Cannot serialize prop "${name}" to HTML.`);
74
- }
75
- if (type === "option" && props.selected === void 0 && optionSelected(optionValue(props), inheritedProps)) sink.write(" selected");
76
- }
77
- function formAttribute(type, name, value) {
78
- if ((type === "textarea" || type === "select") && valueProp(name)) return null;
79
- if (valueProp(name)) return valueAttribute(value);
80
- if (name === "defaultChecked") return value === true ? ["checked", true] : null;
81
- if (type === "option" && name === "selected") return value === true ? ["selected", true] : null;
82
- return attributeValue(name, value);
83
- }
84
- function attributeValue(name, value) {
85
- return emptyValue(value) ? null : [name, value];
86
- }
87
- function valueAttribute(value) {
88
- if (emptyValue(value)) return null;
89
- if (serializableAttributeValue(value)) return ["value", String(value)];
90
- return ["value", value];
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.`);
91
83
  }
92
84
  function optionSelected(value, selectProps) {
93
85
  const selectValue = selectProps.value !== void 0 ? selectProps.value : selectProps.defaultValue;
@@ -129,22 +121,23 @@ function emptyValue(value) {
129
121
  function emptyChild(value) {
130
122
  return value === null || value === void 0 || typeof value === "boolean";
131
123
  }
132
- function writeAttribute(sink, name, value) {
133
- sink.write(` ${name}="${escapeAttribute(value)}"`);
124
+ function serializeAttribute(name, value) {
125
+ return ` ${name}="${escapeAttribute(value)}"`;
134
126
  }
135
127
  function serializeStyle(value) {
136
128
  if (emptyValue(value)) return "";
137
129
  if (typeof value !== "object" || value === null) throw new Error("The style prop must be an object during server render.");
138
- const declarations = [];
130
+ let serialized = "";
139
131
  for (const [name, item] of Object.entries(value)) {
140
132
  if (emptyValue(item)) continue;
141
133
  if (typeof item !== "string" && typeof item !== "number" && typeof item !== "bigint") throw new Error(`Cannot serialize style property "${name}" to HTML.`);
142
- declarations.push(`${styleName(name)}:${String(item)}`);
134
+ if (serialized !== "") serialized += ";";
135
+ serialized += `${styleName(name)}:${String(item)}`;
143
136
  }
144
- return declarations.join(";");
137
+ return serialized;
145
138
  }
146
139
  function reservedProp(name) {
147
- return name === "children" || name === "key" || name === "events" || name === "bind" || name === "suppressHydrationWarning" || name === "unsafeHTML" || /^on[A-Z]/.test(name);
140
+ return name === "children" || name === "key" || name === "mix" || name === "bind" || name === "suppressHydrationWarning" || name === "unsafeHTML" || /^on[A-Z]/.test(name);
148
141
  }
149
142
  function valueProp(name) {
150
143
  return name === "value" || name === "defaultValue";
@@ -159,79 +152,240 @@ function validateTagName(name) {
159
152
  function validateAttributeName(name) {
160
153
  if (/[\s"'<>/=]/.test(name)) throw new Error(`Invalid HTML attribute name "${name}".`);
161
154
  }
162
- function escapeText(value) {
163
- return value.replace(/[&<>]/g, (character) => {
164
- if (character === "&") return "&amp;";
165
- if (character === "<") return "&lt;";
166
- return "&gt;";
167
- });
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) {
162
+ const preconnects = [];
163
+ const criticalPreloads = [];
164
+ const stylesheets = [];
165
+ const remaining = [];
166
+ for (const resource of resources) {
167
+ if (resource.kind === "script") 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")) 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
+ ]);
218
+ case "modulepreload": return serializeLink(resource.href, [
219
+ ["rel", "modulepreload"],
220
+ ["as", "script"],
221
+ ["crossorigin", resource.crossorigin],
222
+ ["fetchpriority", resource.fetchpriority]
223
+ ]);
224
+ case "font": return serializeLink(resource.href, [
225
+ ["rel", "preload"],
226
+ ["as", "font"],
227
+ ["crossorigin", resource.crossorigin ?? "anonymous"],
228
+ ["type", resource.type],
229
+ ["fetchpriority", resource.fetchpriority]
230
+ ]);
231
+ case "preconnect": return serializeLink(resource.href, [["rel", "preconnect"], ["crossorigin", resource.crossorigin]]);
232
+ }
233
+ }
234
+ function serializeLink(target, parameters) {
235
+ const encodedTarget = encodeLinkTarget(target);
236
+ if (encodedTarget === null) return null;
237
+ const parts = [`<${encodedTarget}>`];
238
+ for (const [name, value] of parameters) {
239
+ if (value === void 0) continue;
240
+ const parameter = serializeParameter(name, value);
241
+ if (parameter === null) return null;
242
+ parts.push(parameter);
243
+ }
244
+ return parts.join("; ");
245
+ }
246
+ function serializeParameter(name, value) {
247
+ if (value === "") return name;
248
+ if (hasInvalidParameterCharacter(value)) return null;
249
+ if (PARAMETER_TOKEN.test(value)) return `${name}=${value}`;
250
+ return `${name}="${value.replaceAll("\\", "\\\\").replaceAll("\"", "\\\"")}"`;
251
+ }
252
+ function encodeLinkTarget(value) {
253
+ if (value === "") return null;
254
+ let encoded = "";
255
+ for (let index = 0; index < value.length; index += 1) {
256
+ const code = value.charCodeAt(index);
257
+ if (code <= 32 || code === 127) return null;
258
+ const character = value[index];
259
+ if (character === "%" && HEX_ESCAPE.test(value.slice(index + 1, index + 3))) {
260
+ encoded += value.slice(index, index + 3);
261
+ index += 2;
262
+ continue;
263
+ }
264
+ if (code >= 48 && code <= 57 || code >= 65 && code <= 90 || code >= 97 && code <= 122 || URI_REFERENCE_PUNCTUATION.includes(character)) {
265
+ encoded += character;
266
+ continue;
267
+ }
268
+ const codePoint = value.codePointAt(index);
269
+ if (codePoint === void 0) return null;
270
+ const symbol = String.fromCodePoint(codePoint);
271
+ if (symbol.length === 2) index += 1;
272
+ try {
273
+ encoded += encodeURIComponent(symbol);
274
+ } catch {
275
+ return null;
276
+ }
277
+ }
278
+ return encoded;
168
279
  }
169
- function escapeAttribute(value) {
170
- return value.replace(/[&"<>]/g, (character) => {
171
- if (character === "&") return "&amp;";
172
- if (character === "\"") return "&quot;";
173
- if (character === "<") return "&lt;";
174
- return "&gt;";
175
- });
280
+ function hasInvalidParameterCharacter(value) {
281
+ for (let index = 0; index < value.length; index += 1) {
282
+ const code = value.charCodeAt(index);
283
+ if (code < 32 || code === 127 || code > 255) return true;
284
+ }
285
+ return false;
286
+ }
287
+ function normalizedLength(value) {
288
+ if (value === void 0 || Number.isNaN(value)) return DEFAULT_LENGTH;
289
+ return Math.max(0, Math.floor(value));
176
290
  }
177
291
  //#endregion
178
292
  //#region src/asset-registry.ts
179
293
  var AssetResourceRegistry = class {
180
294
  identifierPrefix;
181
295
  emittedResources = /* @__PURE__ */ new Set();
182
- resources = /* @__PURE__ */ new Map();
296
+ deliveryResources = /* @__PURE__ */ new Map();
297
+ metadataByOwner = /* @__PURE__ */ new Map();
183
298
  stylesheetIds = /* @__PURE__ */ new Map();
184
299
  nextStylesheetId = 0;
185
300
  constructor(identifierPrefix) {
186
301
  this.identifierPrefix = identifierPrefix;
187
302
  }
188
303
  register(resource) {
189
- return this.canonical(resource).added;
304
+ if (isMetadataResource(resource)) return;
305
+ this.canonical(resource);
306
+ }
307
+ activateMetadata(owner, resources) {
308
+ const metadata = resources.filter(isMetadataResource);
309
+ if (metadata.length === 0) {
310
+ this.metadataByOwner.delete(owner);
311
+ return;
312
+ }
313
+ this.metadataByOwner.set(owner, metadata);
314
+ }
315
+ releaseMetadata(owner) {
316
+ this.metadataByOwner.delete(owner);
190
317
  }
191
318
  write(resource, sink) {
319
+ if (isMetadataResource(resource)) return null;
192
320
  const { key, resource: current } = this.canonical(resource);
193
321
  const id = this.revealBlockerId(key, current);
194
- if (assetResourceDestination(current) === "head") return id;
195
322
  if (this.emittedResources.has(key)) return id;
196
323
  this.emittedResources.add(key);
197
324
  writeAssetTag(sink, current, id);
198
325
  return id;
199
326
  }
200
- headHtml(nonce) {
201
- let html = "";
202
- const sink = {
203
- nonce,
204
- write(chunk) {
205
- html += chunk;
206
- }
327
+ headHtml(nonce, streamMetadata = false) {
328
+ const { preamble, metadata } = this.headMetadataHtml(nonce, streamMetadata);
329
+ return preamble + metadata;
330
+ }
331
+ headMetadataHtml(nonce, streamMetadata = false) {
332
+ const buckets = {
333
+ charset: [],
334
+ parser: [],
335
+ viewport: [],
336
+ metadata: []
337
+ };
338
+ for (const resource of this.visibleMetadata().values()) {
339
+ const bucket = buckets[metadataPhase(resource)];
340
+ writeAssetTag({
341
+ nonce,
342
+ streamMetadata,
343
+ write: (chunk) => bucket.push(chunk)
344
+ }, resource, null);
345
+ }
346
+ return {
347
+ preamble: [
348
+ ...buckets.charset,
349
+ ...buckets.parser,
350
+ ...buckets.viewport
351
+ ].join(""),
352
+ metadata: buckets.metadata.join("")
207
353
  };
208
- for (const resource of this.resources.values()) if (assetResourceDestination(resource) === "head") writeAssetTag(sink, resource, null);
209
- return html;
354
+ }
355
+ metadataSnapshot() {
356
+ const snapshot = [];
357
+ for (const [key, resource] of this.visibleMetadata()) if (resource.kind === "title") snapshot.push([
358
+ key,
359
+ resource.kind,
360
+ resource.value
361
+ ]);
362
+ else snapshot.push([
363
+ key,
364
+ resource.kind,
365
+ metadataAttributes(resource)
366
+ ]);
367
+ return snapshot;
368
+ }
369
+ preloadHeaderEntries() {
370
+ return createPreloadHeaderEntries(this.deliveryResources.values());
371
+ }
372
+ visibleMetadata() {
373
+ const visible = /* @__PURE__ */ new Map();
374
+ for (const metadata of this.metadataByOwner.values()) for (const resource of metadata) visible.set(assetResourceKey(resource), resource);
375
+ return visible;
210
376
  }
211
377
  canonical(resource) {
212
378
  const key = assetResourceKey(resource);
213
- const current = this.resources.get(key);
379
+ const current = this.deliveryResources.get(key);
214
380
  if (current !== void 0) {
215
- if (assetSignature(current) !== assetSignature(resource)) {
216
- if (resource.kind === "title") {
217
- this.resources.set(key, resource);
218
- return {
219
- added: false,
220
- key,
221
- resource
222
- };
223
- }
224
- throw new AssetResourceConflictError(key, current, resource);
225
- }
381
+ if (assetSignature(current) !== assetSignature(resource)) throw new AssetResourceConflictError(key, current, resource);
226
382
  return {
227
- added: false,
228
383
  key,
229
384
  resource: current
230
385
  };
231
386
  }
232
- this.resources.set(key, resource);
387
+ this.deliveryResources.set(key, resource);
233
388
  return {
234
- added: true,
235
389
  key,
236
390
  resource
237
391
  };
@@ -258,7 +412,10 @@ var AssetResourceConflictError = class extends Error {
258
412
  function writeAssetTag(sink, resource, id) {
259
413
  switch (resource.kind) {
260
414
  case "title":
261
- writeElementStart("title", {}, sink);
415
+ writeElementStart("title", {
416
+ [HYDRATION_SKIP_ATTRIBUTE]: true,
417
+ [STREAMED_METADATA_ATTRIBUTE]: sink.streamMetadata ? assetResourceKey(resource) : void 0
418
+ }, sink);
262
419
  writeText(resource.value, sink);
263
420
  writeElementEnd("title", sink);
264
421
  return;
@@ -267,13 +424,18 @@ function writeAssetTag(sink, resource, id) {
267
424
  charset: resource.charset,
268
425
  name: resource.name,
269
426
  property: resource.property,
270
- "http-equiv": resource.httpEquiv,
427
+ "http-equiv": resource["http-equiv"],
271
428
  content: resource.content,
429
+ [HYDRATION_SKIP_ATTRIBUTE]: true,
430
+ [STREAMED_METADATA_ATTRIBUTE]: sink.streamMetadata ? assetResourceKey(resource) : void 0,
272
431
  "data-fig-resource-key": resource.key
273
432
  }, sink);
274
433
  return;
275
434
  default: {
276
- const props = Object.fromEntries(assetResourceHostAttributes(resource));
435
+ const props = {
436
+ [HYDRATION_SKIP_ATTRIBUTE]: true,
437
+ ...Object.fromEntries(assetResourceHostAttributes(resource))
438
+ };
277
439
  if (resource.kind === "stylesheet" && id !== null) props.id = id;
278
440
  const tag = resource.kind === "script" ? "script" : "link";
279
441
  writeElementStart(tag, withNonce(sink, props), sink);
@@ -281,6 +443,29 @@ function writeAssetTag(sink, resource, id) {
281
443
  }
282
444
  }
283
445
  }
446
+ function isMetadataResource(resource) {
447
+ return resource.kind === "title" || resource.kind === "meta";
448
+ }
449
+ function metadataPhase(resource) {
450
+ if (resource.kind === "title") return "metadata";
451
+ if (resource.charset !== void 0) return "charset";
452
+ if (normalizedMetadataName(resource["http-equiv"]) === "content-security-policy") return "parser";
453
+ if (normalizedMetadataName(resource.name) === "viewport") return "viewport";
454
+ return "metadata";
455
+ }
456
+ function normalizedMetadataName(value) {
457
+ return value?.trim().toLowerCase();
458
+ }
459
+ function metadataAttributes(resource) {
460
+ return [
461
+ ["charset", resource.charset],
462
+ ["name", resource.name],
463
+ ["property", resource.property],
464
+ ["http-equiv", resource["http-equiv"]],
465
+ ["content", resource.content],
466
+ ["data-fig-resource-key", resource.key]
467
+ ].filter((entry) => entry[1] !== void 0);
468
+ }
284
469
  function withNonce(sink, props) {
285
470
  return sink.nonce === void 0 ? props : {
286
471
  ...props,
@@ -289,14 +474,14 @@ function withNonce(sink, props) {
289
474
  }
290
475
  function assetSignature(resource) {
291
476
  switch (resource.kind) {
292
- case "stylesheet": return signature(resource.kind, resource.href, resource.media ?? "", resource.precedence ?? "", resource.crossOrigin ?? "", resource.blocking ?? "reveal");
293
- case "preload": return signature(resource.kind, resource.href, resource.as, resource.type ?? "", resource.crossOrigin ?? "", resource.fetchPriority ?? "");
294
- case "modulepreload": return signature(resource.kind, resource.href, resource.crossOrigin ?? "", resource.fetchPriority ?? "");
295
- case "font": return signature("preload", resource.href, "font", resource.type, resource.crossOrigin ?? "anonymous", resource.fetchPriority ?? "");
296
- case "preconnect": return signature(resource.kind, resource.href, resource.crossOrigin ?? "");
297
- case "script": return signature(resource.kind, resource.src, resource.module === true, resource.async !== false, resource.defer === true, resource.crossOrigin ?? "");
477
+ case "stylesheet": return signature(resource.kind, resource.href, resource.media ?? "", resource.precedence ?? "", resource.crossorigin ?? "", resource.blocking ?? "reveal");
478
+ case "preload": return signature(resource.kind, resource.href, resource.as, resource.type ?? "", resource.crossorigin ?? "", resource.fetchpriority ?? "");
479
+ case "modulepreload": return signature(resource.kind, resource.href, resource.crossorigin ?? "", resource.fetchpriority ?? "");
480
+ case "font": return signature("preload", resource.href, "font", resource.type, resource.crossorigin ?? "anonymous", resource.fetchpriority ?? "");
481
+ case "preconnect": return signature(resource.kind, resource.href, resource.crossorigin ?? "");
482
+ case "script": return signature(resource.kind, resource.src, resource.module === true, resource.async !== false, resource.defer === true, resource.crossorigin ?? "");
298
483
  case "title": return signature(resource.kind, resource.value);
299
- case "meta": return signature(resource.kind, resource.charset ?? "", resource.name ?? "", resource.property ?? "", resource.httpEquiv ?? "", resource.content ?? "");
484
+ case "meta": return signature(resource.kind, resource.charset ?? "", resource.name ?? "", resource.property ?? "", resource["http-equiv"] ?? "", resource.content ?? "");
300
485
  }
301
486
  return unsupportedAssetResource(resource);
302
487
  }
@@ -309,7 +494,7 @@ function signature(...values) {
309
494
  //#endregion
310
495
  //#region src/protocol.ts
311
496
  function serverRuntimeCodeFor(runtimeName) {
312
- 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 g=()=>this.v(b,s,f);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()}},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){let x=document.getElementById(b),y=document.getElementById(s);this.v(x,y,r=>this.o(x,y,r))},o(b,s,l){if(!b||!s)return;let a=b.previousSibling||b,p=a.parentNode,c=s.content||s;if(!p)return;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}';let r=a.__figRetry;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){let x=this.b(t,b),y=document.getElementById(s);this.v(x,y,r=>this.o(x,y,r))},ax(t,b,d,m){this.y(this.b(t,b),d,m)}}`;
497
+ 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)}}`;
313
498
  }
314
499
  function writeRuntime$1(request, write) {
315
500
  if (request.runtimeWritten) return;
@@ -317,17 +502,13 @@ function writeRuntime$1(request, write) {
317
502
  writeScript$1(request, serverRuntimeCodeFor(request.runtimeName), write);
318
503
  }
319
504
  function writeScript$1(request, code, write) {
320
- write(`<script${request.nonce === void 0 ? "" : ` nonce="${escapeAttribute(request.nonce)}"`}>${code}<\/script>`);
505
+ write(`<script ${HYDRATION_SKIP_ATTRIBUTE}=""${nonceAttribute(request.nonce)}>${code}<\/script>`);
321
506
  }
322
507
  function earlyEventCaptureCode() {
323
508
  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)`;
324
509
  }
325
510
  function earlyEventCaptureMarkup(request) {
326
- let markup = "";
327
- writeScript$1(request, earlyEventCaptureCode(), (chunk) => {
328
- markup += chunk;
329
- });
330
- return markup;
511
+ return `<script ${HYDRATION_SKIP_ATTRIBUTE}=""${nonceAttribute(request.nonce)}>${earlyEventCaptureCode()}<\/script>`;
331
512
  }
332
513
  function placeholderMarkup(request, id) {
333
514
  return templateMarkup(placeholderId(request, id));
@@ -354,18 +535,281 @@ function boundaryId(request, id) {
354
535
  return prefixedId(request, "b", id);
355
536
  }
356
537
  function jsString(value) {
357
- return JSON.stringify(value).replace(/</g, "\\u003C");
538
+ return escapeScriptJson(value);
358
539
  }
359
540
  function prefixedId(request, kind, id) {
360
541
  return request.identifierPrefix === "" ? `${kind}-${id}` : `${request.identifierPrefix}-${kind}-${id}`;
361
542
  }
362
543
  //#endregion
363
- //#region src/renderer.ts
364
- const errorStacks = /* @__PURE__ */ new WeakMap();
365
- const textEncoder = new TextEncoder();
544
+ //#region src/renderer-flush.ts
366
545
  const documentHeadMarker = Symbol("fig.document-head");
546
+ const leadingNewlineStartMarker = Symbol("fig.leading-newline-start");
547
+ const leadingNewlineEndMarker = Symbol("fig.leading-newline-end");
367
548
  const RUNTIME_REF = "__figSSR";
368
- const TEXT_SEPARATOR = "<!--,-->";
549
+ const textEncoder = new TextEncoder();
550
+ function flushCompletedQueues(request) {
551
+ if (request.controller === null || request.status === "closed") return;
552
+ if (request.pendingRootTasks > 0) return;
553
+ if (request.prerender && request.pendingTasks > 0) return;
554
+ if (request.flushing) return;
555
+ request.flushing = true;
556
+ try {
557
+ sealHead(request);
558
+ if (request.completedRootSegment !== null) {
559
+ flushSegment(request, request.completedRootSegment);
560
+ request.completedRootSegment = null;
561
+ flushWriteBuffer(request);
562
+ }
563
+ if (!drainBoundaryQueue(request, request.clientRenderedBoundaries, flushClientRenderedBoundary) && !drainBoundaryQueue(request, request.completedBoundaries, flushCompletedBoundary)) drainBoundaryQueue(request, request.partialBoundaries, flushPartialBoundary);
564
+ flushWriteBuffer(request);
565
+ } finally {
566
+ request.flushing = false;
567
+ }
568
+ if (request.pendingTasks === 0 && request.completedBoundaries.size === 0 && request.clientRenderedBoundaries.size === 0 && request.partialBoundaries.size === 0) {
569
+ request.cleanupAbortListener();
570
+ request.status = "closed";
571
+ request.dataStore.dispose();
572
+ request.controller.close();
573
+ }
574
+ }
575
+ function sealHead(request) {
576
+ if (request.headSnapshot !== null) return;
577
+ activateVisibleMetadata(request, request.rootSegment);
578
+ const metadata = request.assetRegistry.headMetadataHtml(request.nonce, !request.prerender && request.pendingTasks > 0);
579
+ request.headSnapshot = {
580
+ ...metadata,
581
+ preloadHeaderEntries: request.assetRegistry.preloadHeaderEntries()
582
+ };
583
+ request.headReady.resolve(metadata.preamble + metadata.metadata);
584
+ }
585
+ function flushSegment(request, segment) {
586
+ if (segment.status === "flushed") return;
587
+ if (segment.boundary !== null) {
588
+ flushSuspenseBoundary(request, segment, segment.boundary);
589
+ return;
590
+ }
591
+ flushSubtree(request, segment);
592
+ }
593
+ function flushSubtree(request, segment) {
594
+ segment.parentFlushed = true;
595
+ if (segment.status === "pending" || segment.status === "rendering") {
596
+ request.write(placeholderMarkup(request, ensureSegmentId(request, segment)));
597
+ return;
598
+ }
599
+ if (segment.status === "flushed") return;
600
+ segment.status = "flushed";
601
+ if (request.document === null || segment !== request.rootSegment) flushSegmentAssets(request, segment);
602
+ let chunkIndex = 0;
603
+ for (const child of segment.children) {
604
+ for (; chunkIndex < child.index; chunkIndex += 1) writeChunk(request, segment.chunks[chunkIndex], segment);
605
+ flushSegment(request, child);
606
+ }
607
+ for (; chunkIndex < segment.chunks.length; chunkIndex += 1) writeChunk(request, segment.chunks[chunkIndex], segment);
608
+ }
609
+ function flushSuspenseBoundary(request, segment, boundary) {
610
+ boundary.parentFlushed = true;
611
+ if (boundary.status === "completed") {
612
+ request.write(`<!--${SUSPENSE_COMPLETED_MARKER}-->`);
613
+ flushBoundaryContent(request, boundary);
614
+ request.write(`<!--${SUSPENSE_END_MARKER}-->`);
615
+ segment.status = "flushed";
616
+ return;
617
+ }
618
+ if (request.prerender && boundary.status === "client-rendered") {
619
+ request.write(`<!--${SUSPENSE_CLIENT_MARKER}-->`);
620
+ request.write(clientRenderedBoundaryPlaceholderMarkup(request, boundary));
621
+ flushSubtree(request, segment);
622
+ request.write(`<!--${SUSPENSE_END_MARKER}-->`);
623
+ return;
624
+ }
625
+ const boundaryIdValue = ensureBoundaryId(request, boundary);
626
+ flushSegmentAssets(request, boundary.contentSegment);
627
+ request.write(`<!--${SUSPENSE_PENDING_PREFIX}${boundaryIdValue}-->`);
628
+ request.write(boundaryPlaceholderMarkup(request, boundaryIdValue));
629
+ flushSubtree(request, segment);
630
+ request.write(`<!--${SUSPENSE_END_MARKER}-->`);
631
+ if (boundary.status === "client-rendered") request.clientRenderedBoundaries.add(boundary);
632
+ else if (boundary.completedSegments.length > 0) request.partialBoundaries.add(boundary);
633
+ }
634
+ function flushBoundaryContent(request, boundary) {
635
+ for (const segment of boundary.completedSegments) flushSegment(request, segment);
636
+ boundary.completedSegments = [];
637
+ }
638
+ function clientRenderedBoundaryPlaceholderMarkup(request, boundary) {
639
+ const id = escapeAttribute(boundaryId(request, ensureBoundaryId(request, boundary)));
640
+ const digest = boundary.error?.digest;
641
+ const message = boundary.error?.message;
642
+ return `<template id="${id}"${digest === void 0 || digest === "" ? "" : ` data-dgst="${escapeAttribute(digest)}"`}${message === void 0 || message === "" ? "" : ` data-msg="${escapeAttribute(message)}"`}></template>`;
643
+ }
644
+ function flushCompletedBoundary(request, boundary) {
645
+ flushPartialBoundary(request, boundary);
646
+ writeBoundaryRevealScript(request, boundary);
647
+ }
648
+ function flushPartialBoundary(request, boundary) {
649
+ for (const segment of boundary.completedSegments) flushBoundarySegment(request, boundary, segment);
650
+ boundary.completedSegments = [];
651
+ }
652
+ function flushBoundarySegment(request, boundary, segment) {
653
+ ensureBoundaryId(request, boundary);
654
+ const blockingIds = flushSegmentContainer(request, segment);
655
+ if (segment !== boundary.contentSegment) writeSegmentRevealScript(request, segment, blockingIds);
656
+ }
657
+ function writeSegmentRevealScript(request, segment, blockingIds) {
658
+ const id = ensureSegmentId(request, segment);
659
+ writeRuntime(request);
660
+ writeScript(request, withAssetGate(blockingIds, `${RUNTIME_REF}.s(${jsString(placeholderId(request, id))},${jsString(segmentId(request, id))})`));
661
+ }
662
+ function writeBoundaryRevealScript(request, boundary) {
663
+ const blockingIds = flushSegmentAssets(request, boundary.contentSegment);
664
+ const metadata = switchBoundaryMetadata(request, boundary);
665
+ const metadataArgument = metadata === null ? "" : `,${metadata}`;
666
+ writeRuntime(request);
667
+ const boundaryRef = jsString(boundaryId(request, ensureBoundaryId(request, boundary)));
668
+ const contentRef = jsString(segmentId(request, ensureSegmentId(request, boundary.contentSegment)));
669
+ writeScript(request, withAssetGate(blockingIds, boundary.activityId === null ? `${RUNTIME_REF}.c(${boundaryRef},${contentRef}${metadataArgument})` : `${RUNTIME_REF}.ac(${jsString(boundary.activityId)},${boundaryRef},${contentRef}${metadataArgument})`));
670
+ }
671
+ function switchBoundaryMetadata(request, boundary) {
672
+ if (!boundary.metadataVisible) return null;
673
+ const before = escapeScriptJson(request.assetRegistry.metadataSnapshot());
674
+ const fallback = boundary.fallbackSegment;
675
+ if (fallback !== null) {
676
+ request.assetRegistry.releaseMetadata(fallback);
677
+ for (const child of fallback.children) deactivateMetadataTree(request, child);
678
+ }
679
+ activateVisibleMetadata(request, boundary.contentSegment);
680
+ const after = escapeScriptJson(request.assetRegistry.metadataSnapshot());
681
+ return before === after ? null : after;
682
+ }
683
+ function activateVisibleMetadata(request, segment) {
684
+ if (segment.status === "pending" || segment.status === "rendering") return;
685
+ const boundary = segment.boundary;
686
+ if (boundary !== null) {
687
+ boundary.metadataVisible = true;
688
+ if (boundary.status === "completed") {
689
+ activateVisibleMetadata(request, boundary.contentSegment);
690
+ return;
691
+ }
692
+ }
693
+ request.assetRegistry.activateMetadata(segment, segment.assetResources);
694
+ for (const child of segment.children) activateVisibleMetadata(request, child);
695
+ }
696
+ function deactivateMetadataTree(request, segment) {
697
+ request.assetRegistry.releaseMetadata(segment);
698
+ for (const child of segment.children) deactivateMetadataTree(request, child);
699
+ const boundary = segment.boundary;
700
+ if (boundary === null) return;
701
+ boundary.metadataVisible = false;
702
+ deactivateMetadataTree(request, boundary.contentSegment);
703
+ }
704
+ function flushSegmentContainer(request, segment) {
705
+ if (segment.status === "flushed") return [];
706
+ const blockingIds = flushSegmentAssets(request, segment);
707
+ request.write(segmentContainerStartMarkup(request, ensureSegmentId(request, segment)));
708
+ flushSegment(request, segment);
709
+ request.write("</div>");
710
+ return blockingIds;
711
+ }
712
+ function flushSegmentAssets(request, segment) {
713
+ const blockingIds = /* @__PURE__ */ new Set();
714
+ collectSegmentAssets(request, segment, blockingIds);
715
+ return [...blockingIds];
716
+ }
717
+ function collectSegmentAssets(request, segment, blockingIds) {
718
+ if (segment.status !== "pending" && segment.status !== "rendering") flushAssetList(request, segment.assetResources, blockingIds);
719
+ for (const child of segment.children) collectSegmentAssets(request, child, blockingIds);
720
+ }
721
+ function flushAssetList(request, resources, blockingIds) {
722
+ for (const resource of resources) {
723
+ const id = request.assetRegistry.write(resource, request);
724
+ if (id !== null) blockingIds.add(id);
725
+ }
726
+ }
727
+ function withAssetGate(blockingIds, call) {
728
+ if (blockingIds.length === 0) return call;
729
+ return `${RUNTIME_REF}.r([${blockingIds.map(jsString).join(",")}],()=>{${call}})`;
730
+ }
731
+ function flushClientRenderedBoundary(request, boundary) {
732
+ if (boundary.id === null) return;
733
+ writeRuntime(request);
734
+ const boundaryRef = jsString(boundaryId(request, boundary.id));
735
+ const digest = jsString(boundary.error?.digest ?? "");
736
+ const message = jsString(boundary.error?.message ?? "");
737
+ writeScript(request, boundary.activityId === null ? `${RUNTIME_REF}.x(${boundaryRef},${digest},${message})` : `${RUNTIME_REF}.ax(${jsString(boundary.activityId)},${boundaryRef},${digest},${message})`);
738
+ }
739
+ function drainBoundaryQueue(request, queue, flush) {
740
+ for (;;) {
741
+ if (streamFlowBlocked(request.controller)) return true;
742
+ const first = queue.values().next();
743
+ if (first.done === true) return false;
744
+ flush(request, first.value);
745
+ queue.delete(first.value);
746
+ flushWriteBuffer(request);
747
+ }
748
+ }
749
+ function writeRuntime(request) {
750
+ writeRuntime$1(request, (chunk) => request.write(chunk));
751
+ }
752
+ function writeScript(request, code) {
753
+ writeScript$1(request, `(__figSSR=>{${code}})(globalThis[${jsString(request.runtimeName)}])`, (chunk) => request.write(chunk));
754
+ }
755
+ function writeChunk(request, chunk, segment) {
756
+ if (chunk === leadingNewlineStartMarker) {
757
+ request.leadingNewlineStack.push(false);
758
+ return;
759
+ }
760
+ if (chunk === leadingNewlineEndMarker) {
761
+ request.leadingNewlineStack.pop();
762
+ return;
763
+ }
764
+ if (typeof chunk === "object") {
765
+ request.write(request.leadingNewlineStack.at(-1) === false && chunk.value.startsWith("\n") ? `\n${chunk.value}` : chunk.value);
766
+ return;
767
+ }
768
+ if (chunk !== documentHeadMarker) {
769
+ request.write(chunk);
770
+ return;
771
+ }
772
+ if (request.document === null) return;
773
+ const metadata = request.headSnapshot ?? request.assetRegistry.headMetadataHtml(request.nonce);
774
+ const [beforeMetadata, afterMetadata] = partitionHeadAssets(segment.assetResources);
775
+ const blockingIds = /* @__PURE__ */ new Set();
776
+ request.write(metadata.preamble);
777
+ flushAssetList(request, beforeMetadata, blockingIds);
778
+ request.write(metadata.metadata);
779
+ flushAssetList(request, afterMetadata, blockingIds);
780
+ }
781
+ function partitionHeadAssets(resources) {
782
+ const preconnects = [];
783
+ const criticalPreloads = [];
784
+ const stylesheets = [];
785
+ const afterMetadata = [];
786
+ for (const resource of resources) if (resource.kind === "preconnect") preconnects.push(resource);
787
+ else if (resource.kind === "font" || resource.kind === "preload" && (resource.as === "font" || resource.as === "image" && resource.fetchpriority === "high")) criticalPreloads.push(resource);
788
+ else if (resource.kind === "stylesheet") stylesheets.push(resource);
789
+ else afterMetadata.push(resource);
790
+ return [[
791
+ ...preconnects,
792
+ ...criticalPreloads,
793
+ ...stylesheets
794
+ ], afterMetadata];
795
+ }
796
+ function flushWriteBuffer(request) {
797
+ if (request.writeBuffer.length === 0 || request.controller === null) return;
798
+ request.controller.enqueue(textEncoder.encode(request.writeBuffer.join("")));
799
+ request.writeBuffer = [];
800
+ }
801
+ function ensureSegmentId(request, segment) {
802
+ segment.id ??= request.nextSegmentId++;
803
+ return segment.id;
804
+ }
805
+ function ensureBoundaryId(request, boundary) {
806
+ boundary.id ??= request.nextBoundaryId++;
807
+ return boundary.id;
808
+ }
809
+ //#endregion
810
+ //#region src/renderer.ts
811
+ const errorStacks = /* @__PURE__ */ new WeakMap();
812
+ const TEXT_SEPARATOR = `<!--${TEXT_SEPARATOR_DATA}-->`;
369
813
  let nextRuntimeId = 0;
370
814
  function createServerRenderRequest(node, options = {}, mode = {}) {
371
815
  throwIfAborted(options.signal);
@@ -376,40 +820,39 @@ function createServerRenderRequest(node, options = {}, mode = {}) {
376
820
  headReady.promise.catch(() => void 0);
377
821
  allReady.promise.catch(() => void 0);
378
822
  const rootSegment = createSegment(0, null);
823
+ const dataStoreHost = {
824
+ getLane: () => null,
825
+ partition: options.dataPartition,
826
+ schedule: () => void 0
827
+ };
828
+ const dataStore = options.dataStore === void 0 ? createRendererDataStore(dataStoreHost) : attachDataStore(options.dataStore, dataStoreHost, options.initialData);
379
829
  const request = {
380
830
  abortableTasks: /* @__PURE__ */ new Set(),
381
- abortListener: null,
382
- abortSignal: options.signal ?? null,
383
831
  allReady,
832
+ cleanupAbortListener: () => void 0,
384
833
  completedBoundaries: /* @__PURE__ */ new Set(),
385
834
  completedRootSegment: null,
386
835
  controller: null,
387
- dataStore: createDataStore({
388
- getLane: () => null,
389
- partition: options.dataPartition,
390
- schedule: () => void 0
391
- }),
836
+ dataStore,
392
837
  fatalError: null,
393
838
  identifierPrefix: options.identifierPrefix ?? "",
839
+ leadingNewlineStack: [],
394
840
  nextBoundaryId: 0,
395
841
  nextSegmentId: 0,
396
842
  nextActivityId: 0,
397
843
  nextViewTransitionId: 0,
398
844
  nonce: options.nonce,
399
845
  onError: options.onError,
400
- onAssetError: options.onAssetError,
401
846
  pendingRootTasks: 0,
402
847
  pendingTasks: 0,
403
848
  pingedTasks: [],
404
- assetSink: null,
405
849
  rootSegment,
406
850
  runtimeName: createRuntimeName(options.identifierPrefix),
407
851
  runtimeWritten: false,
408
852
  headReady,
409
853
  headSnapshot: null,
410
854
  shellReady,
411
- status: "opening",
412
- stream: null,
855
+ status: "open",
413
856
  clientRenderedBoundaries: /* @__PURE__ */ new Set(),
414
857
  clientReferenceFallback: options.clientReferenceFallback,
415
858
  partialBoundaries: /* @__PURE__ */ new Set(),
@@ -419,22 +862,14 @@ function createServerRenderRequest(node, options = {}, mode = {}) {
419
862
  assetRegistry: new AssetResourceRegistry(options.identifierPrefix ?? ""),
420
863
  resolveAssetKey: options.resolveAssetKey,
421
864
  workScheduled: false,
422
- writeBuffer: []
423
- };
424
- request.assetSink = {
425
- nonce: options.nonce,
426
- write: (chunk) => write(request, chunk)
427
- };
428
- const stream = new ReadableStream({
429
- start(streamController) {
430
- request.controller = streamController;
431
- flushCompletedQueues(request);
432
- },
433
- cancel(reason) {
434
- abort(request, reason);
865
+ flushing: false,
866
+ writeBuffer: [],
867
+ write(chunk) {
868
+ if (chunk !== "" && this.leadingNewlineStack.length > 0) this.leadingNewlineStack[this.leadingNewlineStack.length - 1] = true;
869
+ this.writeBuffer.push(chunk);
435
870
  }
436
- });
437
- request.stream = stream;
871
+ };
872
+ if (options.dataStore === void 0 && options.initialData !== void 0) request.dataStore.hydrate(options.initialData);
438
873
  rootSegment.parentFlushed = true;
439
874
  const rootTask = createTask(request, node, rootSegment, {
440
875
  abortSet: request.abortableTasks,
@@ -442,17 +877,38 @@ function createServerRenderRequest(node, options = {}, mode = {}) {
442
877
  contextValues: /* @__PURE__ */ new Map(),
443
878
  hiddenActivityId: null,
444
879
  hostAncestors: [],
880
+ hostNamespace: "html",
445
881
  idPath: "",
882
+ pendingLeadingNewline: false,
446
883
  selectProps: null,
447
884
  stack: null,
448
885
  treeParent: options.renderTree?.tree ?? null,
449
886
  viewTransition: null
450
887
  });
451
888
  request.pingedTasks.push(rootTask);
889
+ const stream = new ReadableStream({
890
+ start(streamController) {
891
+ request.controller = streamController;
892
+ flushCompletedQueues(request);
893
+ },
894
+ pull() {
895
+ flushCompletedQueues(request);
896
+ },
897
+ cancel(reason) {
898
+ request.controller = null;
899
+ request.writeBuffer = [];
900
+ abort(request, reason);
901
+ request.status = "closed";
902
+ }
903
+ }, new ByteLengthQueuingStrategy({ highWaterMark: streamHighWaterMark(options.highWaterMark) }));
452
904
  if (options.signal !== void 0) {
453
- const abortListener = () => abort(request, options.signal?.reason);
454
- request.abortListener = abortListener;
455
- options.signal.addEventListener("abort", abortListener, { once: true });
905
+ const signal = options.signal;
906
+ const abortListener = () => abort(request, signal.reason);
907
+ signal.addEventListener("abort", abortListener, { once: true });
908
+ request.cleanupAbortListener = () => {
909
+ signal.removeEventListener("abort", abortListener);
910
+ request.cleanupAbortListener = () => void 0;
911
+ };
456
912
  }
457
913
  request.workScheduled = true;
458
914
  queueMicrotask(() => {
@@ -463,8 +919,13 @@ function createServerRenderRequest(node, options = {}, mode = {}) {
463
919
  abort: (reason) => abort(request, reason),
464
920
  allReady: allReady.promise,
465
921
  contentType: "text/html; charset=utf-8",
922
+ data: request.dataStore,
466
923
  getData: () => request.dataStore.snapshot(),
467
- getHead: () => request.headSnapshot ?? request.assetRegistry.headHtml(request.nonce),
924
+ getPreloadHeader: (headerOptions) => request.headSnapshot === null ? void 0 : formatPreloadHeader(request.headSnapshot.preloadHeaderEntries, headerOptions),
925
+ getHead: () => {
926
+ const snapshot = request.headSnapshot;
927
+ return snapshot === null ? request.assetRegistry.headHtml(request.nonce) : snapshot.preamble + snapshot.metadata;
928
+ },
468
929
  headReady: headReady.promise,
469
930
  shellReady: shellReady.promise,
470
931
  stream
@@ -491,7 +952,9 @@ function forkScope(scope) {
491
952
  contextValues: cloneContextValues(scope.contextValues),
492
953
  hiddenActivityId: scope.hiddenActivityId,
493
954
  hostAncestors: scope.hostAncestors,
955
+ hostNamespace: scope.hostNamespace,
494
956
  idPath: scope.idPath,
957
+ pendingLeadingNewline: scope.pendingLeadingNewline,
495
958
  selectProps: scope.selectProps,
496
959
  stack: scope.stack,
497
960
  treeParent: scope.treeParent,
@@ -525,16 +988,17 @@ function createBoundary(fallbackAbortableTasks, contentSegment) {
525
988
  completedSegments: [],
526
989
  contentSegment,
527
990
  error: null,
991
+ fallbackSegment: null,
528
992
  fallbackAbortableTasks,
529
993
  id: null,
530
994
  parentFlushed: false,
531
995
  pendingTasks: 0,
532
- status: "pending"
996
+ status: "pending",
997
+ metadataVisible: false
533
998
  };
534
999
  }
535
1000
  function performWork(request) {
536
1001
  if (request.status === "closed") return;
537
- if (request.status === "opening") request.status = "open";
538
1002
  const tasks = request.pingedTasks;
539
1003
  request.pingedTasks = [];
540
1004
  for (const task of tasks) retryTask(request, task);
@@ -549,7 +1013,7 @@ function retryTask(request, task) {
549
1013
  completeSegmentText(task.segment);
550
1014
  task.segment.status = "completed";
551
1015
  detachTask(request, task);
552
- finishedTask(request, task, task.segment);
1016
+ finishedTask(request, task);
553
1017
  } catch (error) {
554
1018
  detachTask(request, task);
555
1019
  task.segment.status = "completed";
@@ -557,16 +1021,13 @@ function retryTask(request, task) {
557
1021
  }
558
1022
  }
559
1023
  function createRenderFrame(request, segment, scope) {
560
- const frame = {
1024
+ return {
561
1025
  ...scope,
562
1026
  dispatcher: null,
563
1027
  localIdCounter: 0,
564
- pendingLeadingNewlineHost: null,
565
1028
  request,
566
1029
  segment
567
1030
  };
568
- frame.dispatcher = createServerDispatcher(frame);
569
- return frame;
570
1031
  }
571
1032
  function createServerDispatcher(frame) {
572
1033
  return createStaticDispatcher({
@@ -611,29 +1072,39 @@ function renderNode(node, frame) {
611
1072
  name: "#text",
612
1073
  props: { nodeValue: text }
613
1074
  });
614
- const output = consumePendingLeadingNewline(frame) ? preserveParserStrippedLeadingNewline(text) : text;
615
1075
  if (frame.segment.lastPushedText) frame.segment.write(TEXT_SEPARATOR);
616
- writeText(output, frame.segment);
1076
+ if (consumePendingLeadingNewline(frame)) writeLeadingNewlineText(text, frame.segment);
1077
+ else writeText(text, frame.segment);
617
1078
  frame.segment.lastPushedText = true;
618
1079
  }
619
1080
  return;
620
1081
  }
621
1082
  if (isPortal(node)) return;
622
- if (!isValidElement(node)) throw invalidChildError(node);
623
- renderElement(node, frame);
1083
+ if (isValidElement(node)) {
1084
+ renderElement(node, frame);
1085
+ return;
1086
+ }
1087
+ if (isThenable(node)) {
1088
+ renderChildren(readThenable(node), frame);
1089
+ return;
1090
+ }
1091
+ throw invalidChildError(node);
624
1092
  }
625
1093
  function renderChildren(node, frame) {
626
1094
  renderChildSequence(collectChildren(node), frame);
627
1095
  }
628
1096
  function renderChildSequence(children, frame, indexBase = 0) {
629
- for (let index = 0; index < children.length; index += 1) try {
630
- withIdSegment(frame, indexBase + index, () => renderNode(children[index], frame));
631
- } catch (error) {
632
- if (isThenable(error)) {
633
- spawnSuspendedTask(frame, children[index], error, indexBase + index);
634
- continue;
1097
+ for (let index = 0; index < children.length; index += 1) {
1098
+ const child = children[index];
1099
+ try {
1100
+ withIdSegment(frame, indexBase + index, () => renderNode(child, frame));
1101
+ } catch (error) {
1102
+ if (isThenable(error)) {
1103
+ spawnSuspendedTask(frame, child, error, indexBase + index);
1104
+ continue;
1105
+ }
1106
+ throw error;
635
1107
  }
636
- throw error;
637
1108
  }
638
1109
  }
639
1110
  function completeSegmentText(segment) {
@@ -678,20 +1149,13 @@ function collectedTreeNode(element) {
678
1149
  function collectedNameAndKind(type) {
679
1150
  if (typeof type === "string") return [type, "host"];
680
1151
  if (type === Fragment) return ["Fragment", "fragment"];
681
- if (isContext(type)) {
682
- const named = type;
683
- return [`${typeof named.displayName === "string" && named.displayName !== "" ? named.displayName : "Context"}.Provider`, "context-provider"];
684
- }
1152
+ if (isContext(type)) return ["Context.Provider", "context-provider"];
685
1153
  if (isAssets(type)) return ["Assets", "assets"];
686
1154
  if (isSuspense(type)) return ["Suspense", "suspense"];
687
1155
  if (isErrorBoundary(type)) return ["ErrorBoundary", "error-boundary"];
688
1156
  if (isActivity(type)) return ["Activity", "activity"];
689
1157
  if (isViewTransition(type)) return ["ViewTransition", "view-transition"];
690
- if (isClientReference(type)) {
691
- const id = type.id;
692
- const exportName = id.slice(id.lastIndexOf("#") + 1);
693
- return [exportName === "" ? "ClientReference" : exportName, "client-reference"];
694
- }
1158
+ if (isClientReference(type)) return [type.id.slice(type.id.lastIndexOf("#") + 1) || "ClientReference", "client-reference"];
695
1159
  if (typeof type === "function") return [type.name === "" ? "Anonymous" : type.name, "function"];
696
1160
  return ["Anonymous", "function"];
697
1161
  }
@@ -740,6 +1204,7 @@ function renderElementKind(element, frame) {
740
1204
  throw new Error(`Unsupported Fig element type: ${describeElementType(type)}.`);
741
1205
  }
742
1206
  function renderFunctionComponent(type, props, frame) {
1207
+ frame.dispatcher ??= createServerDispatcher(frame);
743
1208
  const previousDispatcher = setCurrentDispatcher(frame.dispatcher);
744
1209
  const previousDataStore = setCurrentDataStore(frame.request.dataStore);
745
1210
  const previousStack = frame.stack;
@@ -792,7 +1257,7 @@ function renderAssetValue(value, frame) {
792
1257
  for (const resource of Array.isArray(value) ? value : [value]) {
793
1258
  if (!isFigAssetResource(resource)) throw new Error("The assets prop must contain Fig asset resources.");
794
1259
  try {
795
- if (frame.request.assetRegistry.register(resource)) reportLateHeadAsset(frame.request, resource, frame.stack);
1260
+ frame.request.assetRegistry.register(resource);
796
1261
  } catch (error) {
797
1262
  recordErrorStack(error, frame.stack);
798
1263
  throw error;
@@ -800,19 +1265,6 @@ function renderAssetValue(value, frame) {
800
1265
  frame.segment.assetResources.push(resource);
801
1266
  }
802
1267
  }
803
- function reportLateHeadAsset(request, resource, stack) {
804
- if (request.headSnapshot === null || assetResourceDestination(resource) !== "head") return;
805
- const key = assetResourceKey(resource);
806
- const error = /* @__PURE__ */ new Error(`Fig head resource "${key}" was discovered after headReady. Move required metadata outside pending Suspense boundaries, or wait for allReady before reading getHead().`);
807
- try {
808
- request.onAssetError?.(error, {
809
- componentStack: componentStack(stack),
810
- destination: "head",
811
- key,
812
- resource
813
- });
814
- } catch {}
815
- }
816
1268
  function renderSuspense(props, frame) {
817
1269
  consumePendingLeadingNewline(frame);
818
1270
  const fallbackAbortableTasks = /* @__PURE__ */ new Set();
@@ -821,6 +1273,7 @@ function renderSuspense(props, frame) {
821
1273
  boundary.activityId = frame.hiddenActivityId;
822
1274
  const parentSegment = frame.segment;
823
1275
  const boundarySegment = createSegment(parentSegment.chunks.length, boundary);
1276
+ boundary.fallbackSegment = boundarySegment;
824
1277
  parentSegment.children.push(boundarySegment);
825
1278
  parentSegment.lastPushedText = false;
826
1279
  contentSegment.parentFlushed = true;
@@ -894,14 +1347,15 @@ function renderActivity(props, frame) {
894
1347
  frame.segment.write("</template>");
895
1348
  }
896
1349
  function renderHostElement(type, props, frame) {
897
- if (renderHostAsset(type, props, frame)) return;
1350
+ const namespace = hostElementNamespace(type, frame.hostNamespace);
1351
+ if (namespace === "html" && renderHostAsset(type, props, frame)) return;
898
1352
  const document = frame.request.document;
899
1353
  if (document !== null && !document.hasHead) {
900
1354
  if (type !== "html" && type !== "head") throw invalidDocumentShellError();
901
1355
  }
902
1356
  if (document !== null && type === "html") frame.segment.write("<!doctype html>");
903
1357
  if (document !== null && type === "head") document.hasHead = true;
904
- const isVoid = isVoidElement(type);
1358
+ const isVoid = namespace === "html" && isVoidElement(type);
905
1359
  const unsafeHTML = unsafeHTMLContent(props);
906
1360
  if (isVoid && hasRenderableChild(props.children)) throw new Error(`Void element <${type}> cannot have children.`);
907
1361
  if (isVoid && unsafeHTML !== null) throw new Error(`Void element <${type}> cannot have unsafeHTML.`);
@@ -911,37 +1365,52 @@ function renderHostElement(type, props, frame) {
911
1365
  writeElementStart(type, viewTransition === null ? props : viewTransitionHostProps(props, viewTransition), frame.segment, frame.selectProps ?? {});
912
1366
  if (document !== null && type === "head") frame.segment.write(earlyEventCaptureMarkup(frame.request));
913
1367
  if (isVoid) return;
914
- const previousPendingLeadingNewlineHost = frame.pendingLeadingNewlineHost;
915
- frame.pendingLeadingNewlineHost = leadingNewlineStrippedHost(type) ? type : null;
1368
+ const previousPendingLeadingNewline = frame.pendingLeadingNewline;
1369
+ const tracksLeadingNewline = leadingNewlineStrippedHost(type);
1370
+ frame.pendingLeadingNewline = tracksLeadingNewline;
916
1371
  if (unsafeHTML !== null) {
917
1372
  frame.segment.write(consumePendingLeadingNewline(frame) ? preserveParserStrippedLeadingNewline(unsafeHTML) : unsafeHTML);
918
- frame.pendingLeadingNewlineHost = previousPendingLeadingNewlineHost;
1373
+ frame.pendingLeadingNewline = previousPendingLeadingNewline;
919
1374
  writeElementEnd(type, frame.segment);
920
1375
  return;
921
1376
  }
922
- const formText = formTextContent(type, props);
1377
+ const formText = namespace === "html" ? formTextContent(type, props) : null;
923
1378
  if (formText !== null) {
924
1379
  writeText(consumePendingLeadingNewline(frame) ? preserveParserStrippedLeadingNewline(formText) : formText, frame.segment);
925
- frame.pendingLeadingNewlineHost = previousPendingLeadingNewlineHost;
1380
+ frame.pendingLeadingNewline = previousPendingLeadingNewline;
926
1381
  writeElementEnd(type, frame.segment);
927
1382
  return;
928
1383
  }
929
1384
  const previousSelectProps = frame.selectProps;
930
- if (type === "select") frame.selectProps = props;
1385
+ if (namespace === "html" && type === "select") frame.selectProps = props;
931
1386
  const previousHostAncestors = frame.hostAncestors;
1387
+ const previousHostNamespace = frame.hostNamespace;
932
1388
  const previousViewTransition = frame.viewTransition;
933
1389
  if (viewTransition !== null) frame.viewTransition = null;
1390
+ frame.hostNamespace = childHostNamespace(type, namespace);
1391
+ if (tracksLeadingNewline) frame.segment.chunks.push(leadingNewlineStartMarker);
934
1392
  try {
935
1393
  renderChildren(props.children, frame);
936
1394
  } finally {
937
1395
  frame.selectProps = previousSelectProps;
938
1396
  frame.hostAncestors = previousHostAncestors;
1397
+ frame.hostNamespace = previousHostNamespace;
939
1398
  frame.viewTransition = previousViewTransition;
940
- frame.pendingLeadingNewlineHost = previousPendingLeadingNewlineHost;
1399
+ frame.pendingLeadingNewline = previousPendingLeadingNewline;
941
1400
  }
1401
+ if (tracksLeadingNewline) frame.segment.chunks.push(leadingNewlineEndMarker);
942
1402
  if (document !== null && type === "head") writeDocumentHeadMarker(frame.segment);
943
1403
  writeElementEnd(type, frame.segment);
944
1404
  }
1405
+ function hostElementNamespace(type, parent) {
1406
+ const normalizedType = type.toLowerCase();
1407
+ if (normalizedType === "svg") return "svg";
1408
+ if (normalizedType === "math") return "mathml";
1409
+ return parent;
1410
+ }
1411
+ function childHostNamespace(type, namespace) {
1412
+ return namespace === "svg" && type.toLowerCase() === "foreignobject" ? "html" : namespace;
1413
+ }
945
1414
  function renderHostAsset(type, props, frame) {
946
1415
  const resource = assetResourceFromHostProps(type, props);
947
1416
  if (resource === null) return false;
@@ -979,16 +1448,16 @@ function pingTask(request, task) {
979
1448
  performWork(request);
980
1449
  });
981
1450
  }
982
- function finishedTask(request, task, segment) {
1451
+ function finishedTask(request, task) {
983
1452
  request.pendingTasks -= 1;
984
1453
  const boundary = task.boundary;
985
1454
  if (boundary === null) {
986
1455
  request.pendingRootTasks -= 1;
987
- if (segment === request.rootSegment || request.completedRootSegment === null) request.completedRootSegment = request.rootSegment;
1456
+ if (task.segment === request.rootSegment || request.completedRootSegment === null) request.completedRootSegment = request.rootSegment;
988
1457
  if (request.pendingRootTasks === 0) finishRootShell(request);
989
1458
  } else {
990
1459
  boundary.pendingTasks -= 1;
991
- if (segment.parentFlushed) enqueueUnique(boundary.completedSegments, segment);
1460
+ if (task.segment.parentFlushed) enqueueUnique(boundary.completedSegments, task.segment);
992
1461
  if (!completeBoundaryIfReady(request, boundary) && boundary.parentFlushed) request.partialBoundaries.add(boundary);
993
1462
  }
994
1463
  if (request.pendingTasks === 0) request.allReady.resolve(void 0);
@@ -1048,7 +1517,7 @@ function markBoundaryClientRendered(request, boundary, error, stack, payload) {
1048
1517
  }
1049
1518
  function abort(request, reason) {
1050
1519
  if (request.status === "closed") return;
1051
- cleanupAbortListener(request);
1520
+ request.cleanupAbortListener();
1052
1521
  request.status = "aborting";
1053
1522
  request.dataStore.dispose();
1054
1523
  const error = abortError(reason);
@@ -1068,7 +1537,7 @@ function abort(request, reason) {
1068
1537
  }
1069
1538
  function fatalError(request, error) {
1070
1539
  if (request.status === "closed") return;
1071
- cleanupAbortListener(request);
1540
+ request.cleanupAbortListener();
1072
1541
  request.status = "closed";
1073
1542
  request.dataStore.dispose();
1074
1543
  request.fatalError = error;
@@ -1085,164 +1554,6 @@ function finishRootShell(request) {
1085
1554
  if (!request.prerender) sealHead(request);
1086
1555
  request.shellReady.resolve(void 0);
1087
1556
  }
1088
- function flushCompletedQueues(request) {
1089
- if (request.controller === null || request.status === "closed") return;
1090
- if (request.status === "opening") return;
1091
- if (request.pendingRootTasks > 0) return;
1092
- if (request.prerender && request.pendingTasks > 0) return;
1093
- sealHead(request);
1094
- if (request.completedRootSegment !== null) {
1095
- flushSegment(request, request.completedRootSegment);
1096
- request.completedRootSegment = null;
1097
- flushWriteBuffer(request);
1098
- }
1099
- drainBoundaryQueue(request, request.clientRenderedBoundaries, flushClientRenderedBoundary);
1100
- drainBoundaryQueue(request, request.completedBoundaries, flushCompletedBoundary);
1101
- drainBoundaryQueue(request, request.partialBoundaries, flushPartialBoundary);
1102
- flushWriteBuffer(request);
1103
- if (request.pendingTasks === 0 && request.completedBoundaries.size === 0 && request.clientRenderedBoundaries.size === 0 && request.partialBoundaries.size === 0) {
1104
- cleanupAbortListener(request);
1105
- request.status = "closed";
1106
- request.dataStore.dispose();
1107
- request.controller.close();
1108
- }
1109
- }
1110
- function flushSegment(request, segment) {
1111
- if (segment.boundary !== null) {
1112
- flushSuspenseBoundary(request, segment, segment.boundary);
1113
- return;
1114
- }
1115
- flushSubtree(request, segment);
1116
- }
1117
- function flushSubtree(request, segment) {
1118
- segment.parentFlushed = true;
1119
- if (segment.status === "pending" || segment.status === "rendering") {
1120
- write(request, placeholderMarkup(request, ensureSegmentId(request, segment)));
1121
- return;
1122
- }
1123
- if (segment.status === "flushed") return;
1124
- segment.status = "flushed";
1125
- if (request.document === null || segment !== request.rootSegment) flushSegmentAssets(request, segment);
1126
- let chunkIndex = 0;
1127
- for (const child of segment.children) {
1128
- for (; chunkIndex < child.index; chunkIndex += 1) writeChunk(request, segment.chunks[chunkIndex], segment);
1129
- flushSegment(request, child);
1130
- }
1131
- for (; chunkIndex < segment.chunks.length; chunkIndex += 1) writeChunk(request, segment.chunks[chunkIndex], segment);
1132
- }
1133
- function flushSuspenseBoundary(request, segment, boundary) {
1134
- segment.boundary = null;
1135
- boundary.parentFlushed = true;
1136
- if (boundary.status === "completed") {
1137
- write(request, `<!--${SUSPENSE_COMPLETED_MARKER}-->`);
1138
- flushBoundaryContent(request, boundary);
1139
- write(request, `<!--${SUSPENSE_END_MARKER}-->`);
1140
- return;
1141
- }
1142
- if (request.prerender && boundary.status === "client-rendered") {
1143
- write(request, `<!--${SUSPENSE_CLIENT_MARKER}-->`);
1144
- write(request, clientRenderedBoundaryPlaceholderMarkup(request, boundary));
1145
- flushSubtree(request, segment);
1146
- write(request, `<!--${SUSPENSE_END_MARKER}-->`);
1147
- return;
1148
- }
1149
- const boundaryIdValue = ensureBoundaryId(request, boundary);
1150
- flushSegmentAssets(request, boundary.contentSegment);
1151
- write(request, `<!--${SUSPENSE_PENDING_PREFIX}${boundaryIdValue}-->`);
1152
- write(request, boundaryPlaceholderMarkup(request, boundaryIdValue));
1153
- flushSubtree(request, segment);
1154
- write(request, `<!--${SUSPENSE_END_MARKER}-->`);
1155
- if (boundary.status === "client-rendered") request.clientRenderedBoundaries.add(boundary);
1156
- else if (boundary.completedSegments.length > 0) request.partialBoundaries.add(boundary);
1157
- }
1158
- function flushBoundaryContent(request, boundary) {
1159
- for (const segment of boundary.completedSegments) flushSegment(request, segment);
1160
- boundary.completedSegments = [];
1161
- }
1162
- function clientRenderedBoundaryPlaceholderMarkup(request, boundary) {
1163
- const id = escapeAttribute(boundaryId(request, ensureBoundaryId(request, boundary)));
1164
- const digest = boundary.error?.digest;
1165
- const message = boundary.error?.message;
1166
- return `<template id="${id}"${digest === void 0 || digest === "" ? "" : ` data-dgst="${escapeAttribute(digest)}"`}${message === void 0 || message === "" ? "" : ` data-msg="${escapeAttribute(message)}"`}></template>`;
1167
- }
1168
- function sealHead(request) {
1169
- if (request.headSnapshot !== null) return;
1170
- const head = request.assetRegistry.headHtml(request.nonce);
1171
- request.headSnapshot = head;
1172
- request.headReady.resolve(head);
1173
- }
1174
- function flushCompletedBoundary(request, boundary) {
1175
- flushPartialBoundary(request, boundary);
1176
- writeBoundaryRevealScript(request, boundary);
1177
- }
1178
- function flushPartialBoundary(request, boundary) {
1179
- for (const segment of boundary.completedSegments) flushBoundarySegment(request, boundary, segment);
1180
- boundary.completedSegments = [];
1181
- }
1182
- function flushBoundarySegment(request, boundary, segment) {
1183
- ensureBoundaryId(request, boundary);
1184
- ensureSegmentId(request, segment);
1185
- const blockingIds = flushSegmentContainer(request, segment);
1186
- if (segment !== boundary.contentSegment) writeSegmentRevealScript(request, segment, blockingIds);
1187
- }
1188
- function writeSegmentRevealScript(request, segment, blockingIds) {
1189
- const id = ensureSegmentId(request, segment);
1190
- writeRuntime(request);
1191
- writeScript(request, withAssetGate(request, blockingIds, `${RUNTIME_REF}.s(${jsString(placeholderId(request, id))},${jsString(segmentId(request, id))})`));
1192
- }
1193
- function writeBoundaryRevealScript(request, boundary) {
1194
- const blockingIds = flushSegmentAssets(request, boundary.contentSegment);
1195
- writeRuntime(request);
1196
- const boundaryRef = jsString(boundaryId(request, ensureBoundaryId(request, boundary)));
1197
- const contentRef = jsString(segmentId(request, ensureSegmentId(request, boundary.contentSegment)));
1198
- const runtime = RUNTIME_REF;
1199
- writeScript(request, withAssetGate(request, blockingIds, boundary.activityId === null ? `${runtime}.c(${boundaryRef},${contentRef})` : `${runtime}.ac(${jsString(boundary.activityId)},${boundaryRef},${contentRef})`));
1200
- }
1201
- function flushSegmentContainer(request, segment) {
1202
- if (segment.status === "flushed") return [];
1203
- const blockingIds = flushSegmentAssets(request, segment);
1204
- write(request, segmentContainerStartMarkup(request, ensureSegmentId(request, segment)));
1205
- flushSegment(request, segment);
1206
- write(request, "</div>");
1207
- return blockingIds;
1208
- }
1209
- function flushSegmentAssets(request, segment) {
1210
- const blockingIds = /* @__PURE__ */ new Set();
1211
- collectSegmentAssets(request, segment, request.assetSink, blockingIds);
1212
- return [...blockingIds];
1213
- }
1214
- function collectSegmentAssets(request, segment, sink, blockingIds) {
1215
- if (segment.status !== "pending" && segment.status !== "rendering") flushAssetList(request, segment.assetResources, sink, blockingIds);
1216
- for (const child of segment.children) collectSegmentAssets(request, child, sink, blockingIds);
1217
- }
1218
- function flushAssetList(request, resources, sink, blockingIds) {
1219
- for (const resource of resources) {
1220
- const id = request.assetRegistry.write(resource, sink);
1221
- if (id !== null) blockingIds.add(id);
1222
- }
1223
- }
1224
- function withAssetGate(request, blockingIds, call) {
1225
- if (blockingIds.length === 0) return call;
1226
- return `${RUNTIME_REF}.r([${blockingIds.map(jsString).join(",")}],()=>{${call}})`;
1227
- }
1228
- function flushClientRenderedBoundary(request, boundary) {
1229
- if (boundary.id === null) return;
1230
- writeRuntime(request);
1231
- const boundaryRef = jsString(boundaryId(request, boundary.id));
1232
- const digest = jsString(boundary.error?.digest ?? "");
1233
- const message = jsString(boundary.error?.message ?? "");
1234
- const runtime = RUNTIME_REF;
1235
- writeScript(request, boundary.activityId === null ? `${runtime}.x(${boundaryRef},${digest},${message})` : `${runtime}.ax(${jsString(boundary.activityId)},${boundaryRef},${digest},${message})`);
1236
- }
1237
- function drainBoundaryQueue(request, queue, flush) {
1238
- for (;;) {
1239
- const first = queue.values().next();
1240
- if (first.done === true) return;
1241
- flush(request, first.value);
1242
- queue.delete(first.value);
1243
- flushWriteBuffer(request);
1244
- }
1245
- }
1246
1557
  function enqueueUnique(queue, item) {
1247
1558
  if (!queue.includes(item)) queue.push(item);
1248
1559
  }
@@ -1265,72 +1576,35 @@ function stackForError(error, fallback) {
1265
1576
  if (typeof error !== "object" && typeof error !== "function" || error === null) return fallback;
1266
1577
  return errorStacks.get(error) ?? fallback;
1267
1578
  }
1268
- function writeRuntime(request) {
1269
- writeRuntime$1(request, (chunk) => write(request, chunk));
1270
- }
1271
- function writeScript(request, code) {
1272
- writeScript$1(request, `(__figSSR=>{${code}})(globalThis[${jsString(request.runtimeName)}])`, (chunk) => write(request, chunk));
1273
- }
1274
1579
  function createRuntimeName(identifierPrefix) {
1275
1580
  const id = nextRuntimeId.toString(36);
1276
1581
  nextRuntimeId += 1;
1277
1582
  const prefix = identifierPrefix?.replace(/[^A-Za-z0-9_$]/g, "_") ?? "";
1278
1583
  return prefix === "" ? `__figSSR_${id}` : `__figSSR_${prefix}_${id}`;
1279
1584
  }
1280
- function writeChunk(request, chunk, segment) {
1281
- if (chunk !== documentHeadMarker) {
1282
- write(request, chunk);
1283
- return;
1284
- }
1285
- if (request.document === null) return;
1286
- write(request, request.assetRegistry.headHtml(request.nonce));
1287
- flushAssetList(request, segment.assetResources, request.assetSink, /* @__PURE__ */ new Set());
1288
- }
1289
- function write(request, chunk) {
1290
- request.writeBuffer.push(chunk);
1291
- }
1292
1585
  function writeDocumentHeadMarker(segment) {
1293
1586
  segment.lastPushedText = false;
1294
1587
  segment.chunks.push(documentHeadMarker);
1295
1588
  }
1296
1589
  function consumePendingLeadingNewline(frame) {
1297
- const pending = frame.pendingLeadingNewlineHost !== null;
1298
- frame.pendingLeadingNewlineHost = null;
1590
+ const pending = frame.pendingLeadingNewline;
1591
+ frame.pendingLeadingNewline = false;
1299
1592
  return pending;
1300
1593
  }
1301
1594
  function leadingNewlineStrippedHost(type) {
1302
1595
  return type === "pre" || type === "textarea";
1303
1596
  }
1597
+ function writeLeadingNewlineText(text, segment) {
1598
+ writeText(text, { write(value) {
1599
+ segment.write({ value });
1600
+ } });
1601
+ }
1304
1602
  function preserveParserStrippedLeadingNewline(text) {
1305
1603
  return text.startsWith("\n") ? `\n${text}` : text;
1306
1604
  }
1307
- function cleanupAbortListener(request) {
1308
- if (request.abortListener === null || request.abortSignal === null) return;
1309
- request.abortSignal.removeEventListener("abort", request.abortListener);
1310
- request.abortListener = null;
1311
- request.abortSignal = null;
1312
- }
1313
- function flushWriteBuffer(request) {
1314
- if (request.writeBuffer.length === 0 || request.controller === null) return;
1315
- request.controller.enqueue(textEncoder.encode(request.writeBuffer.join("")));
1316
- request.writeBuffer = [];
1317
- }
1318
1605
  function invalidDocumentShellError() {
1319
1606
  return /* @__PURE__ */ new Error("renderToDocumentStream requires the root to render an <html> document with a <head>.");
1320
1607
  }
1321
- function ensureSegmentId(request, segment) {
1322
- segment.id ??= request.nextSegmentId++;
1323
- return segment.id;
1324
- }
1325
- function ensureBoundaryId(request, boundary) {
1326
- boundary.id ??= request.nextBoundaryId++;
1327
- return boundary.id;
1328
- }
1329
- function componentStack(stack) {
1330
- const frames = [];
1331
- for (let frame = stack; frame !== null; frame = frame.parent) frames.push(` at ${frame.name}`);
1332
- return frames.length === 0 ? "" : `\n${frames.join("\n")}`;
1333
- }
1334
1608
  function throwIfAborted(signal) {
1335
1609
  if (signal?.aborted === true) throw abortReason(signal.reason);
1336
1610
  }
@@ -1371,7 +1645,9 @@ function renderToDocumentStream(node, options = {}) {
1371
1645
  abort: (reason) => request.abort(reason),
1372
1646
  allReady: request.allReady,
1373
1647
  contentType: request.contentType,
1648
+ data: request.data,
1374
1649
  getData: () => request.getData(),
1650
+ getPreloadHeader: (headerOptions) => request.getPreloadHeader(headerOptions),
1375
1651
  shellReady: request.shellReady,
1376
1652
  stream: request.stream
1377
1653
  };
@@ -1424,6 +1700,6 @@ async function readStreamToString(stream) {
1424
1700
  }
1425
1701
  }
1426
1702
  //#endregion
1427
- export { createRenderTreeCollector, escapeAttribute, escapeText, prerender, renderToDocumentHtml, renderToDocumentStream, renderToHtml, renderToStream };
1703
+ export { createRenderTreeCollector, prerender, renderToDocumentHtml, renderToDocumentStream, renderToHtml, renderToStream };
1428
1704
 
1429
1705
  //# sourceMappingURL=index.js.map