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

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/payload.js CHANGED
@@ -1,166 +1,36 @@
1
- import { i as withContextValue, n as createStaticDispatcher, r as deferred, t as cloneContextValues } from "./shared-CQn6Dje6.js";
2
- import { Fragment, Suspense, ViewTransition, clientReference, createElement, readPromise } from "@bgub/fig";
3
- import { FigElementSymbol, assetResourceDestination, assetResourceKey, clientReferenceAssets, createDataStore, describeInvalidChild, isActivity, isAssets, isClientReference, isContext, isErrorBoundary, isFigAssetResource, isPortal, isSuspense, isThenable, isValidElement, isViewTransition, normalizeDataResourceKey, readThenable, setCurrentDataStore, setCurrentDispatcher, trackThenable } from "@bgub/fig/internal";
1
+ import { a as componentStack, d as withContextValue, i as cloneContextValues, l as streamFlowBlocked, n as suppressesImagePreloads, o as createStaticDispatcher, s as deferred, t as imagePreloadFromHostProps, u as streamHighWaterMark } from "./image-preloads-BIFcrqm9.js";
2
+ import { Fragment, isValidElement } from "@bgub/fig";
3
+ import { assetResourceDestination, assetResourceKey, checkpointPayloadGraph, clientOnlyHostBehavior, clientReferenceAssets, createPayloadGraphEncodeContext, createRendererDataStore, definePayloadGraphElement, describeInvalidChild, encodePayloadDataEntries, encodePayloadValueWithGraph, isActivity, isAssets, isClientReference, isContext, isErrorBoundary, isFigAssetResource, isPlainPayloadValue, isPortal, isSuspense, isThenable, isViewTransition, jsonPayloadCodec, readThenable, rollbackPayloadGraph, serializePayloadArray, serializePayloadMap, serializePayloadPlainObject, serializePayloadSet, setCurrentDataStore, setCurrentDispatcher } from "@bgub/fig/internal";
4
4
  //#region src/payload.ts
5
- const PAYLOAD_BOUNDARY_HEADER = "x-fig-payload-boundary";
6
5
  var PayloadRequestCancelledError = class extends Error {
7
6
  constructor() {
8
7
  super("Payload request cancelled.");
9
8
  this.name = "PayloadRequestCancelledError";
10
9
  }
11
10
  };
12
- var PayloadFetchError = class extends Error {
13
- response;
14
- status;
15
- constructor(response) {
16
- super(`Payload request failed with status ${response.status}.`);
17
- this.name = "PayloadFetchError";
18
- this.response = response;
19
- this.status = response.status;
20
- }
21
- };
22
- const textEncoder = new TextEncoder();
23
- const PayloadBoundarySymbol = Symbol.for("fig.payload-boundary");
24
11
  const errorStacks = /* @__PURE__ */ new WeakMap();
25
12
  const childrenTreeProps = /* @__PURE__ */ new Set(["children"]);
26
13
  const emptyTreeProps = /* @__PURE__ */ new Set();
27
14
  const suspenseTreeProps = /* @__PURE__ */ new Set(["children", "fallback"]);
28
- function createPayloadGraphEncodeContext() {
29
- return {
30
- ids: /* @__PURE__ */ new WeakMap(),
31
- nextId: 1,
32
- objects: /* @__PURE__ */ new Map()
33
- };
34
- }
35
- function createPayloadGraphDecodeContext() {
36
- return { refs: /* @__PURE__ */ new Map() };
37
- }
38
- /**
39
- * Readable development-oriented codec: one JSON payload row per newline.
40
- */
41
- const jsonPayloadCodec = {
42
- id: "json",
43
- contentType: "text/x-fig-payload; codec=json; charset=utf-8",
44
- createDecoder(onRow) {
45
- return createJsonPayloadDecoder(onRow);
46
- },
47
- encodeRow(row) {
48
- return textEncoder.encode(`${JSON.stringify(row)}\n`);
49
- }
50
- };
51
- function createJsonPayloadDecoder(onRow) {
52
- const decoder = new TextDecoder();
53
- let buffer = "";
54
- let searchStart = 0;
55
- function processBufferedLines() {
56
- let lineStart = 0;
57
- let firstError;
58
- for (;;) {
59
- const newlineIndex = buffer.indexOf("\n", searchStart);
60
- if (newlineIndex === -1) {
61
- searchStart = buffer.length;
62
- break;
63
- }
64
- try {
65
- processPayloadLine(buffer.slice(lineStart, newlineIndex), onRow);
66
- } catch (error) {
67
- firstError ??= error;
68
- }
69
- lineStart = newlineIndex + 1;
70
- searchStart = lineStart;
71
- }
72
- if (firstError !== void 0) {
73
- buffer = "";
74
- searchStart = 0;
75
- throw firstError;
76
- }
77
- if (lineStart > 0) {
78
- buffer = buffer.slice(lineStart);
79
- searchStart -= lineStart;
80
- }
81
- }
82
- return {
83
- decode(chunk) {
84
- buffer += decoder.decode(chunk, { stream: true });
85
- processBufferedLines();
86
- },
87
- flush() {
88
- buffer += decoder.decode();
89
- if (buffer.length > 0) {
90
- const line = buffer;
91
- buffer = "";
92
- searchStart = 0;
93
- processPayloadLine(line, onRow);
94
- }
95
- }
96
- };
97
- }
98
- function processPayloadLine(line, onRow) {
99
- if (line.length > 0) onRow(JSON.parse(line));
100
- }
101
- function payloadCodecIdFromContentType(contentTypeHeader) {
102
- const parts = contentTypeHeader.split(";").slice(1);
103
- for (const part of parts) {
104
- const [name, rawValue] = part.split("=");
105
- if (name?.trim().toLowerCase() !== "codec") continue;
106
- const value = rawValue?.trim();
107
- if (value === void 0 || value.length === 0) return null;
108
- return value.replace(/^"|"$/g, "");
109
- }
110
- return null;
111
- }
112
- const PayloadBoundary = Object.assign((props) => props.children, { $$typeof: PayloadBoundarySymbol });
113
15
  function renderToPayloadStream(node, options = {}) {
114
- const request = createPayloadRequest(node, options);
16
+ const { request, stream } = createPayloadRequest(node, options);
115
17
  return {
116
- abort: (reason) => abortPayloadRequest(request, reason),
117
18
  allReady: request.allReady.promise,
118
- contentType: request.codec.contentType,
119
- stream: request.stream
19
+ contentType: jsonPayloadCodec.contentType,
20
+ stream
120
21
  };
121
22
  }
122
- function createPayloadResponse(options = {}) {
123
- return new PayloadResponseImpl(options);
124
- }
125
- async function processPayloadStream(response, stream, signal) {
126
- await response.processStream(stream, signal);
127
- }
128
- function isPayloadRequestCancelled(error) {
129
- return error instanceof PayloadRequestCancelledError || typeof DOMException !== "undefined" && error instanceof DOMException && error.name === "AbortError";
130
- }
131
- async function fetchPayload(response, input, options = {}) {
132
- const { fetch: fetchImpl = globalThis.fetch, headers, refreshBoundary, signal, ...init } = options;
133
- if (fetchImpl === void 0) throw new Error("fetchPayload requires a fetch implementation.");
134
- throwIfAborted(signal);
135
- const result = await fetchImpl(input, {
136
- ...init,
137
- headers: appendPayloadHeaders(response.codec, headers, refreshBoundary),
138
- signal
139
- });
140
- throwIfAborted(signal);
141
- if (!result.ok) {
142
- await result.body?.cancel().catch(() => void 0);
143
- throw new PayloadFetchError(result);
144
- }
145
- if (result.body === null) throw new Error("Payload response did not include a body.");
146
- assertPayloadCodecMatches(response.codec, result.headers.get("content-type"));
147
- if (refreshBoundary !== void 0) response.beginRefreshPayload();
148
- await processPayloadStream(response, result.body, signal);
149
- return result;
150
- }
151
23
  function createPayloadRequest(node, options) {
152
24
  throwIfAborted(options.signal);
153
25
  const pendingDataSnapshots = /* @__PURE__ */ new Map();
154
26
  const request = {
155
- abortListener: null,
156
- abortSignal: null,
157
27
  allReady: deferred(),
158
- boundaryIds: null,
28
+ cleanupAbortListener: () => void 0,
159
29
  clientReferenceRows: /* @__PURE__ */ new Map(),
160
30
  clientReferenceAssets: options.clientReferenceAssets,
161
- codec: options.codec ?? jsonPayloadCodec,
31
+ componentAssets: options.componentAssets,
162
32
  controller: null,
163
- dataStore: createDataStore({
33
+ dataStore: createRendererDataStore({
164
34
  getLane: () => null,
165
35
  onEntryChange: (entry) => {
166
36
  pendingDataSnapshots.set(entry.canonicalKey, entry);
@@ -178,459 +48,84 @@ function createPayloadRequest(node, options) {
178
48
  pendingTasks: 0,
179
49
  pingedTasks: [],
180
50
  queuedRows: [],
181
- refreshBoundary: options.refreshBoundary ?? null,
182
- status: "opening",
183
- stream: null,
51
+ flushingRows: false,
52
+ status: "open",
184
53
  workScheduled: false
185
54
  };
186
55
  request.allReady.promise.catch(() => void 0);
187
- request.stream = new ReadableStream({
56
+ request.pingedTasks.push(createTask(request, 0, {
57
+ kind: "node",
58
+ value: node
59
+ }, /* @__PURE__ */ new Map(), false, null));
60
+ const stream = new ReadableStream({
188
61
  start(controller) {
189
62
  request.controller = controller;
190
63
  flushRows(request);
191
64
  },
65
+ pull() {
66
+ flushRows(request);
67
+ },
192
68
  cancel(reason) {
193
69
  abortPayloadRequest(request, reason);
194
70
  }
195
- });
196
- if (options.signal !== void 0) {
197
- const abortListener = () => abortPayloadRequest(request, options.signal?.reason);
198
- request.abortListener = abortListener;
199
- request.abortSignal = options.signal;
200
- options.signal.addEventListener("abort", abortListener, { once: true });
201
- }
202
- request.pingedTasks.push(createTask(request, 0, "node", node, /* @__PURE__ */ new Map(), null));
203
- request.workScheduled = true;
204
- queueMicrotask(() => {
205
- request.workScheduled = false;
206
- performWork(request);
207
- });
208
- return request;
209
- }
210
- var PayloadResponseImpl = class {
211
- options;
212
- assetResources = /* @__PURE__ */ new Map();
213
- boundaries = /* @__PURE__ */ new Map();
214
- decodedBoundaries = /* @__PURE__ */ new Map();
215
- initialBoundaries = /* @__PURE__ */ new Map();
216
- clientReferences = /* @__PURE__ */ new Map();
217
- chunks = /* @__PURE__ */ new Map();
218
- clientReferenceEntries = /* @__PURE__ */ new Map();
219
- resolvedClientReferenceComponents = /* @__PURE__ */ new Map();
220
- listeners = /* @__PURE__ */ new Set();
221
- resolveRootReady = () => void 0;
222
- rootReady = new Promise((resolve) => {
223
- this.resolveRootReady = resolve;
224
- });
225
- maxRowId = 0;
226
- maxObjectId = 0;
227
- objectIdBase = 0;
228
- objectRefs = /* @__PURE__ */ new Map();
229
- pendingData = [];
230
- rootData = null;
231
- rowIdBase = 0;
232
- currentDecodeRevision = 0;
233
- stringDecoder;
234
- nextModelRevision = 1;
235
- maxObjectIdScanDirty = false;
236
- codec;
237
- constructor(options) {
238
- this.options = options;
239
- this.codec = options.codec ?? jsonPayloadCodec;
240
- this.stringDecoder = this.createDecoder(this.rowIdBase, this.objectIdBase);
241
- }
242
- beginRefreshPayload() {
243
- this.ensureMaxObjectIdScanned();
244
- this.rowIdBase = this.maxRowId;
245
- this.objectIdBase = this.maxObjectId;
246
- this.stringDecoder = this.createDecoder(this.rowIdBase, this.objectIdBase);
247
- }
248
- resetPayloadDecoder() {
249
- this.rowIdBase = 0;
250
- this.objectIdBase = 0;
251
- this.stringDecoder = this.createDecoder(this.rowIdBase, this.objectIdBase);
252
- }
253
- getAssetResources() {
254
- return [...this.assetResources.values()];
255
- }
256
- getClientReferences() {
257
- return [...this.clientReferences.values()];
258
- }
259
- recordAssetResources(assets) {
260
- if (assets === void 0) return;
261
- for (const resource of assets) {
262
- if (!isFigAssetResource(resource) || assetResourceDestination(resource) !== "stream") continue;
263
- const key = assetResourceKey(resource);
264
- if (!this.assetResources.has(key)) this.assetResources.set(key, resource);
265
- }
266
- }
267
- recordClientReference(value) {
268
- if (this.clientReferences.has(value.id)) return;
269
- const reference = { id: value.id };
270
- const assets = value.assets?.filter(isFigAssetResource);
271
- if (assets !== void 0) reference.assets = assets;
272
- if (value.exportName !== void 0) reference.exportName = value.exportName;
273
- if (value.ssr === true) reference.ssr = true;
274
- this.clientReferences.set(value.id, reference);
275
- const load = this.options.loadClientReference;
276
- if (load !== void 0) {
277
- const metadata = clientRowMetadata(value);
278
- if (this.options.resolveClientReference?.(metadata) === void 0) this.clientReferenceEntry(metadata, load);
279
- }
280
- }
281
- bindRoot(root) {
282
- this.rootData = root.data ?? null;
283
- this.hydratePendingData();
284
- const render = () => root.render(this.getRoot());
285
- const unsubscribe = this.subscribe(render);
286
- render();
287
- return unsubscribe;
288
- }
289
- getRoot() {
290
- return createElement(PayloadResponseRoot, { response: this });
291
- }
292
- createDecoder(rowIdBase, objectIdBase) {
293
- return this.codec.createDecoder((row) => this.processRow(row, rowIdBase, objectIdBase));
294
- }
295
- processRow(row, rowIdBase, objectIdBase) {
296
- if (rowIdBase > 0 || objectIdBase > 0) shiftRowIds(row, rowIdBase, objectIdBase);
297
- this.markMaxObjectIdScanDirty(row);
298
- if (row.tag === "data") {
299
- this.pendingData.push(...decodePayloadDataEntries(row.value));
300
- this.hydratePendingData();
301
- return;
302
- }
303
- if (row.tag === "assets") {
304
- this.recordAssetResources(row.value);
305
- this.notify();
306
- return;
307
- }
308
- if (row.tag === "refresh") {
309
- const revision = this.claimModelRevision();
310
- this.boundaries.set(row.boundary, {
311
- model: row.value,
312
- revision
313
- });
314
- this.invalidateDecodeCachesForBoundary(row.boundary);
315
- this.decodedBoundaries.set(row.boundary, this.decodeModelAtRevision(row.value, revision));
316
- const activeBoundaries = this.refreshRetainedChunks();
317
- this.pruneObjectRefs(activeBoundaries);
318
- this.notify();
319
- return;
320
- }
321
- if (row.tag === "refresh-error") {
322
- this.notify();
323
- throw errorFromPayload(row.value);
324
- }
325
- const revision = row.tag === "model" ? this.claimModelRevision() : 0;
326
- resolveDecodedRow(this, row, revision);
327
- if (row.id === 0) {
328
- if (row.tag === "model") {
329
- const activeBoundaries = this.refreshRetainedChunks();
330
- this.pruneObjectRefs(activeBoundaries);
331
- }
332
- this.resolveRootReady();
333
- this.notify();
334
- }
335
- }
336
- async processStream(stream, signal) {
337
- const decoder = this.createDecoder(this.rowIdBase, this.objectIdBase);
338
- try {
339
- await readByteStream(stream, (chunk) => decoder.decode(chunk), signal);
340
- decoder.flush();
341
- } finally {
342
- this.resetPayloadDecoder();
343
- }
344
- }
345
- processBytesChunk(chunk) {
346
- this.stringDecoder.decode(chunk);
347
- }
348
- processStringChunk(chunk) {
349
- this.processBytesChunk(textEncoder.encode(chunk));
350
- }
351
- subscribe(listener) {
352
- this.listeners.add(listener);
353
- return () => {
354
- this.listeners.delete(listener);
355
- };
356
- }
357
- invalidateDecodeCachesForBoundary(id) {
358
- for (const boundaryId of this.decodedBoundaries.keys()) {
359
- const entry = this.currentBoundaryEntry(boundaryId);
360
- if (boundaryId === id || entry !== void 0 && this.modelCanReachBoundary(entry.model, id)) this.decodedBoundaries.delete(boundaryId);
361
- }
362
- for (const chunk of this.chunks.values()) if (chunk.model !== null && this.modelCanReachBoundary(chunk.model, id)) {
363
- chunk.decoded = void 0;
364
- chunk.hasDecoded = false;
365
- }
366
- }
367
- defineObjectRef(id, create, fill) {
368
- const existing = this.objectRefs.get(id);
369
- if (existing !== void 0) return existing.value;
370
- const value = create();
371
- this.objectRefs.set(id, { value });
372
- if (id > this.maxObjectId) this.maxObjectId = id;
373
- try {
374
- fill(value);
375
- return value;
376
- } catch (error) {
377
- this.objectRefs.delete(id);
378
- throw error;
379
- }
380
- }
381
- readObjectRef(id) {
382
- const ref = this.objectRefs.get(id);
383
- if (ref === void 0) throw new Error(`Payload referenced unknown object id ${id}.`);
384
- return ref.value;
385
- }
386
- noteObjectId(id) {
387
- if (id > this.maxObjectId) this.maxObjectId = id;
388
- }
389
- prepareBoundaryInitial(id, initial) {
390
- const revision = this.currentDecodeRevision;
391
- const previous = this.initialBoundaries.get(id);
392
- this.initialBoundaries.set(id, {
393
- model: initial,
394
- revision
395
- });
396
- if (this.currentBoundaryEntry(id)?.model !== initial) return;
397
- if (previous?.model === initial && previous.revision === revision && this.decodedBoundaries.has(id)) return;
398
- const decoded = this.decodeModelAtRevision(initial, revision);
399
- this.decodedBoundaries.set(id, decoded);
400
- }
401
- pruneObjectRefs(activeBoundaries = this.activeBoundaryEntries()) {
402
- if ([...this.chunks.entries()].some(([id, chunk]) => id !== 0 && chunk.status === "pending")) return;
403
- const retained = /* @__PURE__ */ new Set();
404
- for (const chunk of this.chunks.values()) if (chunk.model !== null) collectObjectIds(chunk.model, retained);
405
- for (const entry of activeBoundaries) collectObjectIds(entry.model, retained);
406
- for (const id of this.objectRefs.keys()) if (!retained.has(id)) this.objectRefs.delete(id);
407
- }
408
- readBoundary(id, initial) {
409
- let decoded = this.decodedBoundaries.get(id);
410
- if (decoded === void 0) {
411
- const entry = this.currentBoundaryEntry(id);
412
- const model = entry?.model ?? initial;
413
- const revision = entry?.revision ?? this.currentDecodeRevision;
414
- decoded = this.decodeModelAtRevision(model, revision);
415
- this.decodedBoundaries.set(id, decoded);
416
- }
417
- return decoded;
418
- }
419
- readChunk(id) {
420
- const chunk = this.getChunk(id);
421
- if (chunk.status === "rejected") throw chunk.value;
422
- if (chunk.status === "pending") readPromise(chunk.promise);
423
- if (chunk.model === null) return chunk.value;
424
- if (!chunk.hasDecoded) {
425
- chunk.decoded = this.decodeModelAtRevision(chunk.model, chunk.revision);
426
- chunk.hasDecoded = true;
427
- }
428
- return chunk.decoded;
429
- }
430
- decodeClientReference(metadata) {
431
- const resolvedCached = this.resolvedClientReferenceComponents.get(metadata.id);
432
- if (resolvedCached !== void 0) return resolvedCached;
433
- const cached = this.clientReferenceEntries.get(metadata.id)?.component;
434
- if (cached !== void 0) return cached;
435
- const resolved = this.options.resolveClientReference?.(metadata);
436
- if (resolved !== void 0) {
437
- const component = function PayloadResolvedClientComponent(props) {
438
- return createElement(resolved, props);
439
- };
440
- this.resolvedClientReferenceComponents.set(metadata.id, component);
441
- return component;
442
- }
443
- const load = this.options.loadClientReference;
444
- if (load !== void 0) {
445
- const entry = this.clientReferenceEntry(metadata, load);
446
- let type = null;
447
- entry.component = function PayloadClientComponent(props) {
448
- if (type === null) type = resolveClientReferenceExport(readPromise(entry.load), metadata);
449
- return createElement(type, props);
450
- };
451
- return entry.component;
452
- }
453
- if (this.options.resolveClientReference !== void 0) return clientReference({
454
- id: metadata.id,
455
- load: () => Promise.resolve({})
456
- });
457
- return function PayloadUnresolvedClientComponent() {
458
- throw new Error(`Cannot render client reference "${metadata.id}" because createPayloadResponse was not configured with loadClientReference or a matching resolveClientReference.`);
459
- };
460
- }
461
- preloadClientReferences() {
462
- const loads = [...this.clientReferenceEntries.values()].map((entry) => entry.load);
463
- return Promise.allSettled(loads).then(() => void 0);
464
- }
465
- clientReferenceEntry(metadata, load) {
466
- let entry = this.clientReferenceEntries.get(metadata.id);
467
- if (entry === void 0) {
468
- entry = { load: load(metadata) };
469
- this.clientReferenceEntries.set(metadata.id, entry);
470
- trackThenable(entry.load);
471
- }
472
- return entry;
473
- }
474
- refreshRetainedChunks() {
475
- const rootModel = this.chunks.get(0)?.model;
476
- if (rootModel === void 0 || rootModel === null) return [];
477
- const nextRetained = referencedChunkClosure(rootModel, this.chunks);
478
- const activeBoundaries = this.activeBoundaryEntries();
479
- for (const entry of activeBoundaries) addChunkRefs(nextRetained, referencedChunkClosure(entry.model, this.chunks));
480
- if (![...this.chunks.entries()].some(([id, chunk]) => id !== 0 && chunk.status === "pending")) {
481
- for (const id of this.chunks.keys()) if (id !== 0 && !nextRetained.has(id)) this.chunks.delete(id);
482
- }
483
- const activeSources = new Map(activeBoundaries.map((entry) => [entry.id, entry.source]));
484
- for (const id of this.boundaries.keys()) if (activeSources.get(id) !== "refresh") this.boundaries.delete(id);
485
- for (const id of this.initialBoundaries.keys()) if (activeSources.get(id) !== "initial") this.initialBoundaries.delete(id);
486
- for (const id of this.decodedBoundaries.keys()) if (!activeSources.has(id)) this.decodedBoundaries.delete(id);
487
- return activeBoundaries;
488
- }
489
- markMaxObjectIdScanDirty(row) {
490
- if (row.tag === "model" || row.tag === "refresh") this.maxObjectIdScanDirty = true;
491
- }
492
- ensureMaxObjectIdScanned() {
493
- if (!this.maxObjectIdScanDirty) return;
494
- this.maxObjectIdScanDirty = false;
495
- for (const chunk of this.chunks.values()) if (chunk.model !== null) noteMaxObjectIds(this, chunk.model);
496
- for (const entry of this.boundaries.values()) noteMaxObjectIds(this, entry.model);
497
- for (const entry of this.initialBoundaries.values()) noteMaxObjectIds(this, entry.model);
498
- }
499
- modelCanReachBoundary(model, id) {
500
- const models = [model];
501
- const visitedBoundaries = /* @__PURE__ */ new Set();
502
- const visitedChunks = /* @__PURE__ */ new Set();
503
- for (let index = 0; index < models.length; index += 1) {
504
- const current = models[index];
505
- if (current === void 0) continue;
506
- const boundaryIds = /* @__PURE__ */ new Set();
507
- collectBoundaryIds(current, boundaryIds);
508
- if (boundaryIds.has(id)) return true;
509
- for (const boundaryId of boundaryIds) {
510
- if (visitedBoundaries.has(boundaryId)) continue;
511
- visitedBoundaries.add(boundaryId);
512
- const entry = this.currentBoundaryEntry(boundaryId);
513
- if (entry !== void 0) models.push(entry.model);
514
- }
515
- const chunkIds = /* @__PURE__ */ new Set();
516
- collectReferencedChunkIds(current, chunkIds);
517
- for (const chunkId of chunkIds) {
518
- if (visitedChunks.has(chunkId)) continue;
519
- visitedChunks.add(chunkId);
520
- const chunk = this.chunks.get(chunkId);
521
- if (chunk?.model !== null && chunk?.model !== void 0) models.push(chunk.model);
522
- }
523
- }
524
- return false;
525
- }
526
- activeBoundaryEntries() {
527
- const rootModel = this.chunks.get(0)?.model;
528
- if (rootModel === void 0 || rootModel === null) return [];
529
- const active = /* @__PURE__ */ new Set();
530
- const visitedChunks = /* @__PURE__ */ new Set();
531
- const models = [rootModel];
532
- const entries = [];
533
- for (let index = 0; index < models.length; index += 1) {
534
- const chunkIds = /* @__PURE__ */ new Set();
535
- collectReferencedChunkIds(models[index], chunkIds);
536
- for (const id of chunkIds) {
537
- if (visitedChunks.has(id)) continue;
538
- visitedChunks.add(id);
539
- const chunk = this.chunks.get(id);
540
- if (chunk?.model !== null && chunk?.model !== void 0) models.push(chunk.model);
541
- }
542
- const ids = /* @__PURE__ */ new Set();
543
- collectBoundaryIds(models[index], ids);
544
- for (const id of ids) {
545
- if (active.has(id)) continue;
546
- active.add(id);
547
- const entry = this.currentBoundaryEntry(id);
548
- if (entry === void 0) continue;
549
- entries.push({
550
- ...entry,
551
- id
552
- });
553
- models.push(entry.model);
554
- }
555
- }
556
- return entries;
557
- }
558
- currentBoundaryEntry(id) {
559
- const refreshed = this.boundaries.get(id);
560
- const initial = this.initialBoundaries.get(id);
561
- if (refreshed === void 0) return initial === void 0 ? void 0 : {
562
- ...initial,
563
- source: "initial"
564
- };
565
- if (initial === void 0) return {
566
- ...refreshed,
567
- source: "refresh"
568
- };
569
- return initial.revision > refreshed.revision ? {
570
- ...initial,
571
- source: "initial"
572
- } : {
573
- ...refreshed,
574
- source: "refresh"
71
+ }, new ByteLengthQueuingStrategy({ highWaterMark: streamHighWaterMark(options.highWaterMark) }));
72
+ const signal = options.signal;
73
+ if (signal !== void 0) {
74
+ const abortListener = () => abortPayloadRequest(request, signal.reason);
75
+ signal.addEventListener("abort", abortListener, { once: true });
76
+ request.cleanupAbortListener = () => {
77
+ signal.removeEventListener("abort", abortListener);
78
+ request.cleanupAbortListener = () => void 0;
575
79
  };
576
80
  }
577
- claimModelRevision() {
578
- const revision = this.nextModelRevision;
579
- this.nextModelRevision += 1;
580
- return revision;
581
- }
582
- decodeModelAtRevision(model, revision) {
583
- const previous = this.currentDecodeRevision;
584
- this.currentDecodeRevision = revision;
585
- try {
586
- return decodeModel(this, model);
587
- } finally {
588
- this.currentDecodeRevision = previous;
589
- }
590
- }
591
- getChunk(id) {
592
- if (id > this.maxRowId) this.maxRowId = id;
593
- return getOrCreateChunk(this.chunks, id);
594
- }
595
- notify() {
596
- for (const listener of this.listeners) listener();
597
- }
598
- hydratePendingData() {
599
- if (this.rootData === null || this.pendingData.length === 0) return;
600
- const entries = this.pendingData;
601
- this.pendingData = [];
602
- this.rootData.hydrate(entries);
603
- }
604
- };
605
- function createTask(request, id, kind, value, contextValues, stack) {
81
+ scheduleWork(request);
82
+ return {
83
+ request,
84
+ stream
85
+ };
86
+ }
87
+ function createTask(request, id, value, contextValues, imagePreloadsSuppressed, stack) {
606
88
  request.pendingTasks += 1;
607
89
  return {
608
90
  contextValues,
609
91
  id,
610
- kind,
92
+ imagePreloadsSuppressed,
611
93
  stack,
612
- value
94
+ ...value
613
95
  };
614
96
  }
615
97
  function performWork(request) {
616
98
  if (request.status === "closed") return;
617
- if (request.status === "opening") request.status = "open";
618
99
  const tasks = request.pingedTasks;
619
100
  request.pingedTasks = [];
620
101
  for (const task of tasks) retryTask(request, task);
621
102
  flushRows(request);
622
103
  }
623
104
  function retryTask(request, task) {
624
- const frame = createRenderFrame(request, cloneContextValues(task.contextValues), task.stack);
105
+ const frame = {
106
+ contextValues: cloneContextValues(task.contextValues),
107
+ dispatcher: null,
108
+ pendingAssets: [],
109
+ request,
110
+ imagePreloadsSuppressed: task.imagePreloadsSuppressed,
111
+ stack: task.stack
112
+ };
625
113
  try {
626
- const value = task.kind === "node" ? serializeNode(task.value, frame) : serializeValue(readThenable(task.value), frame);
114
+ let value;
115
+ switch (task.kind) {
116
+ case "node":
117
+ value = serializeNode(task.value, frame);
118
+ break;
119
+ case "node-promise":
120
+ value = serializeNode(readThenable(task.value), frame);
121
+ break;
122
+ case "promise":
123
+ value = serializeValue(readThenable(task.value), frame);
124
+ break;
125
+ }
126
+ flushFrameAssets(frame, task.id);
627
127
  emitDataRows(request);
628
- if (request.refreshBoundary !== null && task.id === 0) emitRow(request, {
629
- boundary: request.refreshBoundary,
630
- tag: "refresh",
631
- value
632
- });
633
- else emitRow(request, {
128
+ emitRow(request, {
634
129
  id: task.id,
635
130
  tag: "model",
636
131
  value
@@ -638,15 +133,12 @@ function retryTask(request, task) {
638
133
  finishTask(request);
639
134
  } catch (error) {
640
135
  if (isThenable(error)) {
136
+ flushFrameAssets(frame, task.id);
641
137
  error.then(() => pingTask(request, task), () => pingTask(request, task));
642
138
  return;
643
139
  }
644
- if (request.refreshBoundary !== null && task.id === 0) emitRow(request, {
645
- boundary: request.refreshBoundary,
646
- tag: "refresh-error",
647
- value: errorRowPayload(request, error, task.stack)
648
- });
649
- else emitRow(request, {
140
+ flushFrameAssets(frame, task.id);
141
+ emitRow(request, {
650
142
  id: task.id,
651
143
  tag: "error",
652
144
  value: errorRowPayload(request, error, task.stack)
@@ -662,7 +154,7 @@ function emitDataRows(request) {
662
154
  const entries = [];
663
155
  for (const snapshot of request.pendingDataSnapshots.values()) {
664
156
  if (!snapshot.hasValue || snapshot.status === "refreshing") continue;
665
- const key = normalizeDataResourceKey(snapshot.key);
157
+ const key = snapshot.canonicalKey;
666
158
  if (request.emittedDataKeys.has(key)) {
667
159
  request.pendingDataSnapshots.delete(snapshot.canonicalKey);
668
160
  continue;
@@ -679,13 +171,14 @@ function emitDataRows(request) {
679
171
  value: encodePayloadDataEntries(entries)
680
172
  });
681
173
  }
682
- function createRenderFrame(request, contextValues, stack) {
683
- return {
684
- contextValues,
685
- dispatcher: null,
686
- request,
687
- stack
688
- };
174
+ function flushFrameAssets(frame, rowId) {
175
+ if (frame.pendingAssets.length === 0) return;
176
+ const value = frame.pendingAssets.splice(0);
177
+ emitRow(frame.request, {
178
+ for: rowId,
179
+ tag: "assets",
180
+ value
181
+ });
689
182
  }
690
183
  function createPayloadDispatcher(frame) {
691
184
  return createStaticDispatcher({
@@ -711,42 +204,37 @@ function serializeNode(node, frame) {
711
204
  if (node === null || node === void 0 || typeof node === "boolean") return node === void 0 ? { $fig: "undefined" } : node;
712
205
  if (typeof node === "string" || typeof node === "number") return node;
713
206
  if (isPortal(node)) return null;
714
- if (!isValidElement(node)) throw invalidChildError$1(node);
715
- return serializeElement(node, frame, false);
207
+ if (isValidElement(node)) return serializeElement(node, frame, false);
208
+ if (isThenable(node)) return outlineTask(frame, {
209
+ kind: "node-promise",
210
+ value: node
211
+ }, "promise", node);
212
+ throw invalidChildError$1(node);
716
213
  }
717
214
  function serializeNodeOrLazy(node, frame, preserveElementIdentity = false) {
718
- const graphCheckpoint = checkpointGraph(frame.request.graph);
215
+ const graphCheckpoint = checkpointPayloadGraph(frame.request.graph);
216
+ const assetCheckpoint = frame.pendingAssets.length;
719
217
  try {
720
218
  if (!isValidElement(node)) return serializeNode(node, frame);
721
219
  return serializeElement(node, frame, preserveElementIdentity);
722
220
  } catch (error) {
723
- rollbackGraph(frame.request.graph, graphCheckpoint);
724
- if (isThenable(error)) return outlineTask(frame, "node", node, "lazy", error);
725
- return outlineError(frame, error, "lazy");
221
+ rollbackPayloadGraph(frame.request.graph, graphCheckpoint);
222
+ const scopedAssets = frame.pendingAssets.splice(assetCheckpoint);
223
+ if (isThenable(error)) return outlineTask(frame, {
224
+ kind: "node",
225
+ value: node
226
+ }, "lazy", error, scopedAssets);
227
+ return outlineError(frame, error, "lazy", scopedAssets);
726
228
  }
727
229
  }
728
230
  function serializeElement(element, frame, preserveIdentity) {
729
231
  const type = element.type;
730
- if (typeof type === "string") return serializeElementModel(element, type, frame, preserveIdentity, childrenTreeProps);
232
+ if (typeof type === "string") return serializeHostElement(element, type, frame, preserveIdentity);
731
233
  if (type === Fragment) return serializeElementModel(element, { $fig: "fragment" }, frame, preserveIdentity, childrenTreeProps);
732
234
  if (isClientReference(type)) return serializeElementModel(element, {
733
235
  $fig: "client",
734
236
  id: emitClientReference(frame.request, type)
735
237
  }, frame, preserveIdentity);
736
- if (isPayloadBoundary(type)) {
737
- const id = element.props.id;
738
- if (typeof id !== "string" || id.length === 0) throw new Error("Payload boundaries require a non-empty string id.");
739
- if (frame.request.refreshBoundary === id) throw new Error(`Refresh payload for boundary "${id}" must render that boundary's replacement content, not a nested PayloadBoundary with the same id.`);
740
- if (frame.request.boundaryIds !== null) {
741
- if (frame.request.boundaryIds.has(id)) throw new Error(`Duplicate payload boundary id "${id}".`);
742
- frame.request.boundaryIds.add(id);
743
- }
744
- return {
745
- $fig: "boundary",
746
- child: serializeTreeProp(element.props.children, frame),
747
- id
748
- };
749
- }
750
238
  if (isContext(type)) return serializeContextProvider(type, element.props, frame);
751
239
  if (isAssets(type)) return serializeAssets(element.props, frame);
752
240
  if (isSuspense(type)) return serializeElementModel(element, { $fig: "suspense" }, frame, preserveIdentity, suspenseTreeProps);
@@ -756,18 +244,32 @@ function serializeElement(element, frame, preserveIdentity) {
756
244
  if (typeof type === "function") return serializeFunctionComponent(type, element.props, frame);
757
245
  throw new Error("Unsupported Fig element type during payload render.");
758
246
  }
247
+ function serializeHostElement(element, type, frame, preserveIdentity) {
248
+ const preload = imagePreloadFromHostProps(type, element.props, frame.imagePreloadsSuppressed);
249
+ if (preload !== null) frame.pendingAssets.push(...serializeAssetResources(frame.request, preload));
250
+ const previousImagePreloadsSuppressed = frame.imagePreloadsSuppressed;
251
+ frame.imagePreloadsSuppressed = previousImagePreloadsSuppressed || suppressesImagePreloads(type);
252
+ try {
253
+ return serializeElementModel(element, type, frame, preserveIdentity, childrenTreeProps);
254
+ } finally {
255
+ frame.imagePreloadsSuppressed = previousImagePreloadsSuppressed;
256
+ }
257
+ }
759
258
  function serializeElementModel(element, type, frame, preserveIdentity, treeProps = emptyTreeProps) {
760
- const id = preserveIdentity ? defineGraphElement(frame.request.graph, element) : void 0;
259
+ const id = preserveIdentity ? definePayloadGraphElement(frame.request.graph, element) : void 0;
761
260
  if (typeof id === "object") return id;
762
- return {
261
+ const model = {
763
262
  $fig: "element",
764
- ...id === void 0 ? null : { id },
765
263
  key: element.key,
766
- props: serializeProps(element.props, frame, treeProps),
264
+ props: serializeProps(element.props, frame, treeProps, typeof type === "string"),
767
265
  type
768
266
  };
267
+ if (id !== void 0) model.id = id;
268
+ return model;
769
269
  }
770
270
  function serializeFunctionComponent(type, props, frame) {
271
+ const assetCheckpoint = frame.pendingAssets.length;
272
+ frame.pendingAssets.push(...serializeAssetResources(frame.request, frame.request.componentAssets?.(type)));
771
273
  frame.dispatcher ??= createPayloadDispatcher(frame);
772
274
  const previousDispatcher = setCurrentDispatcher(frame.dispatcher);
773
275
  const previousDataStore = setCurrentDataStore(frame.request.dataStore);
@@ -778,7 +280,14 @@ function serializeFunctionComponent(type, props, frame) {
778
280
  };
779
281
  try {
780
282
  const result = type(props);
781
- return serializeNode(isThenable(result) ? readThenable(result) : result, frame);
283
+ if (isThenable(result)) {
284
+ const scopedAssets = frame.pendingAssets.splice(assetCheckpoint);
285
+ return outlineTask(frame, {
286
+ kind: "node-promise",
287
+ value: result
288
+ }, "promise", result, scopedAssets);
289
+ }
290
+ return serializeNode(result, frame);
782
291
  } catch (error) {
783
292
  recordErrorStack(error, frame.stack);
784
293
  throw error;
@@ -792,16 +301,18 @@ function serializeContextProvider(context, props, frame) {
792
301
  return withContextValue(frame.contextValues, context, props.value, () => serializeNode(props.children, frame));
793
302
  }
794
303
  function serializeAssets(props, frame) {
795
- const serialized = serializeAssetResources(frame.request, props.assets);
796
- if (serialized.length > 0) emitRow(frame.request, {
797
- tag: "assets",
798
- value: serialized
799
- });
304
+ frame.pendingAssets.push(...serializeAssetResources(frame.request, props.assets));
800
305
  return serializeNode(props.children, frame);
801
306
  }
802
- function serializeProps(props, frame, treeProps) {
307
+ function serializeProps(props, frame, treeProps, hostElement = false) {
308
+ const clientOnlyBehavior = hostElement ? clientOnlyHostBehavior(props) : void 0;
309
+ if (clientOnlyBehavior !== void 0) throw new Error(`Client-only host behavior from ${clientOnlyBehavior} cannot be serialized in a payload; move it into a client reference.`);
803
310
  const value = {};
804
- for (const [name, child] of Object.entries(props)) value[name] = treeProps.has(name) ? serializeTreeProp(child, frame) : serializeValue(child, frame);
311
+ for (const name of Object.keys(props)) {
312
+ if (hostElement && name === "mix") continue;
313
+ const child = props[name];
314
+ value[name] = treeProps.has(name) ? serializeTreeProp(child, frame) : serializeValue(child, frame);
315
+ }
805
316
  return {
806
317
  $fig: "object",
807
318
  value
@@ -812,273 +323,50 @@ function serializeTreeProp(value, frame) {
812
323
  return serializeNodeOrLazy(value, frame);
813
324
  }
814
325
  function serializeValue(value, frame) {
815
- if (isPlainPayloadValue(value)) return encodePayloadValue(value);
816
- if (typeof value === "function") {
817
- if (isClientReference(value)) return {
818
- $fig: "client",
819
- id: emitClientReference(frame.request, value)
820
- };
821
- throw new Error("Functions cannot be passed to client references.");
822
- }
823
- if (isThenable(value)) return outlineTask(frame, "promise", value, "promise", value);
326
+ if (isPlainPayloadValue(value)) return encodePayloadValueWithGraph(value, frame.request.graph);
327
+ if (isClientReference(value)) return {
328
+ $fig: "client",
329
+ id: emitClientReference(frame.request, value)
330
+ };
824
331
  if (isValidElement(value)) return serializeNodeOrLazy(value, frame, true);
825
332
  if (isPortal(value)) return null;
333
+ if (isThenable(value)) return outlineTask(frame, {
334
+ kind: "promise",
335
+ value
336
+ }, "promise", value);
337
+ if (typeof value === "function") throw new Error("Functions cannot be passed to client references.");
826
338
  if (typeof value === "object" && value !== null) {
827
- if (value instanceof Date) return encodePayloadValueInternal(value, frame.request.graph);
828
- if (value instanceof Map) return serializeMap(value, frame.request.graph, ([key, item]) => [serializeValue(key, frame), serializeValue(item, frame)]);
829
- if (value instanceof Set) return serializeSet(value, frame.request.graph, (item) => serializeValue(item, frame));
830
- if (Array.isArray(value)) return serializeArray(value, frame.request.graph, () => value, (item) => serializeValue(item, frame));
831
- return serializePlainObject(value, frame.request.graph, (child) => serializeValue(child, frame));
832
- }
833
- throw new Error(`Cannot serialize ${typeof value} into the payload.`);
834
- }
835
- function isPlainPayloadValue(value) {
836
- return value === null || value === void 0 || typeof value === "string" || typeof value === "number" || typeof value === "boolean" || typeof value === "bigint" || typeof value === "symbol";
837
- }
838
- /**
839
- * Encode ordinary data values into PayloadModel. Server component references
840
- * such as Fig elements, promises, and client references are handled by the
841
- * payload renderer before ordinary values reach this helper.
842
- */
843
- function encodePayloadValue(value) {
844
- return encodePayloadValueInternal(value, createPayloadGraphEncodeContext());
845
- }
846
- function encodePayloadValueInternal(value, graph) {
847
- if (value === null) return null;
848
- if (value === void 0) return { $fig: "undefined" };
849
- if (typeof value === "string" || typeof value === "boolean") return value;
850
- if (typeof value === "number") return encodePayloadNumber(value);
851
- if (typeof value === "bigint") return {
852
- $fig: "bigint",
853
- value: value.toString()
854
- };
855
- if (typeof value === "symbol") {
856
- const key = Symbol.keyFor(value);
857
- if (key === void 0) throw new Error("Only global Symbol.for symbols can be serialized.");
858
- return {
859
- $fig: "symbol",
860
- key
861
- };
339
+ if (value instanceof Date) return encodePayloadValueWithGraph(value, frame.request.graph);
340
+ if (value instanceof Map) return serializePayloadMap(value, frame.request.graph, ([key, item]) => [serializeValue(key, frame), serializeValue(item, frame)]);
341
+ if (value instanceof Set) return serializePayloadSet(value, frame.request.graph, (item) => serializeValue(item, frame));
342
+ if (Array.isArray(value)) return serializePayloadArray(value, frame.request.graph, () => value, (item) => serializeValue(item, frame));
343
+ return serializePayloadPlainObject(value, frame.request.graph, (child) => serializeValue(child, frame));
862
344
  }
863
- if (typeof value === "function") throw new Error("Functions cannot be serialized into the payload.");
864
- if (Array.isArray(value)) return serializeArray(value, graph, () => value, (item) => encodePayloadValueInternal(item, graph));
865
- if (value instanceof Date) {
866
- const json = value.toJSON();
867
- if (json === null) throw new Error("Invalid Date values cannot be serialized.");
868
- return {
869
- $fig: "date",
870
- value: json
871
- };
872
- }
873
- if (value instanceof Map) return serializeMap(value, graph, ([key, item]) => [encodePayloadValueInternal(key, graph), encodePayloadValueInternal(item, graph)]);
874
- if (value instanceof Set) return serializeSet(value, graph, (item) => encodePayloadValueInternal(item, graph));
875
- if (typeof value === "object" && value !== null) return serializePlainObject(value, graph, (child) => encodePayloadValueInternal(child, graph));
876
345
  throw new Error(`Cannot serialize ${typeof value} into the payload.`);
877
346
  }
878
- function serializeMap(value, graph, encodeEntry) {
879
- const existing = graphReference(graph, value);
880
- if (existing !== null) return existing;
881
- return {
882
- $fig: "map",
883
- id: defineGraphObject(graph, value),
884
- entries: [...value.entries()].map(encodeEntry)
885
- };
886
- }
887
- function serializeSet(value, graph, encodeItem) {
888
- const existing = graphReference(graph, value);
889
- if (existing !== null) return existing;
890
- return {
891
- $fig: "set",
892
- id: defineGraphObject(graph, value),
893
- values: [...value.values()].map(encodeItem)
894
- };
895
- }
896
- function graphReference(graph, value) {
897
- const id = graph.ids.get(value);
898
- return id === void 0 ? null : {
899
- $fig: "ref",
900
- id
901
- };
902
- }
903
- function defineGraphObject(graph, value) {
904
- const id = graph.nextId;
905
- graph.nextId += 1;
906
- graph.ids.set(value, id);
907
- graph.objects.set(id, value);
908
- return id;
909
- }
910
- function checkpointGraph(graph) {
911
- return graph.nextId;
912
- }
913
- function rollbackGraph(graph, checkpoint) {
914
- for (let id = graph.nextId - 1; id >= checkpoint; id -= 1) {
915
- const value = graph.objects.get(id);
916
- if (value !== void 0) graph.ids.delete(value);
917
- graph.objects.delete(id);
918
- }
919
- graph.nextId = checkpoint;
920
- }
921
- function defineGraphElement(graph, value) {
922
- const existing = graphReference(graph, value);
923
- if (existing !== null) return existing;
924
- return defineGraphObject(graph, value);
925
- }
926
- function serializeArray(value, graph, entries, encodeChild) {
927
- const existing = graphReference(graph, value);
928
- if (existing !== null) return existing;
929
- return {
930
- $fig: "array",
931
- id: defineGraphObject(graph, value),
932
- value: entries().map(encodeChild)
933
- };
934
- }
935
- function serializePlainObject(value, graph, encodeChild) {
936
- const existing = graphReference(graph, value);
937
- if (existing !== null) return existing;
938
- return {
939
- $fig: "object",
940
- id: defineGraphObject(graph, value),
941
- value: encodePayloadRecord(plainPayloadObject(value), encodeChild)
942
- };
943
- }
944
- function plainPayloadObject(value) {
945
- const prototype = Object.getPrototypeOf(value);
946
- if (prototype !== Object.prototype && prototype !== null) throw new Error(`Cannot serialize ${prototype?.constructor?.name ?? "object"} into the payload.`);
947
- return value;
948
- }
949
- function encodePayloadRecord(record, encodeChild) {
950
- const encoded = {};
951
- for (const [name, child] of Object.entries(record)) encoded[name] = encodeChild(child);
952
- return encoded;
953
- }
954
- function encodePayloadNumber(value) {
955
- if (Number.isNaN(value)) return {
956
- $fig: "number",
957
- value: "NaN"
958
- };
959
- if (value === Infinity) return {
960
- $fig: "number",
961
- value: "Infinity"
962
- };
963
- if (value === -Infinity) return {
964
- $fig: "number",
965
- value: "-Infinity"
966
- };
967
- if (Object.is(value, -0)) return {
968
- $fig: "number",
969
- value: "-0"
970
- };
971
- return value;
972
- }
973
- /** Decode values produced by encodePayloadValue. */
974
- function decodePayloadValue(model) {
975
- return decodeModelValue(model, createPayloadGraphDecodeContext());
976
- }
977
- function decodeModelValue(model, graph) {
978
- if (model === null) return null;
979
- if (Array.isArray(model)) return model.map((item) => decodeModelValue(item, graph));
980
- if (typeof model !== "object") return model;
981
- if (isPayloadValueSpecialModel(model)) return decodePayloadSpecialValue(model, graph);
982
- return decodePayloadRecord(model, (child) => decodeModelValue(child, graph));
983
- }
984
- function isPayloadValueSpecialModel(model) {
985
- if (!("$fig" in model)) return false;
986
- const tag = model.$fig;
987
- return tag === "bigint" || tag === "array" || tag === "date" || tag === "map" || tag === "number" || tag === "object" || tag === "ref" || tag === "set" || tag === "symbol" || tag === "undefined";
988
- }
989
- function decodePayloadSpecialValue(model, graph) {
990
- switch (model.$fig) {
991
- case "array": {
992
- const value = [];
993
- graph.refs.set(model.id, value);
994
- value.push(...model.value.map((item) => decodeModelValue(item, graph)));
995
- return value;
996
- }
997
- case "bigint": return BigInt(model.value);
998
- case "date": return new Date(model.value);
999
- case "map": {
1000
- const value = /* @__PURE__ */ new Map();
1001
- graph.refs.set(model.id, value);
1002
- for (const [key, item] of model.entries) value.set(decodeModelValue(key, graph), decodeModelValue(item, graph));
1003
- return value;
1004
- }
1005
- case "number": return decodePayloadNumber(model.value);
1006
- case "object": return decodePayloadPlainObject(model, graph);
1007
- case "ref": return readGraphRef(graph, model.id);
1008
- case "set": {
1009
- const value = /* @__PURE__ */ new Set();
1010
- graph.refs.set(model.id, value);
1011
- for (const item of model.values) value.add(decodeModelValue(item, graph));
1012
- return value;
1013
- }
1014
- case "symbol": return Symbol.for(model.key);
1015
- case "undefined": return;
1016
- }
1017
- }
1018
- function decodePayloadPlainObject(model, graph) {
1019
- const decoded = {};
1020
- if (model.id !== void 0) graph.refs.set(model.id, decoded);
1021
- for (const [name, value] of Object.entries(model.value)) definePayloadProperty(decoded, name, decodeModelValue(value, graph));
1022
- return decoded;
1023
- }
1024
- function decodePayloadRecord(value, decodeChild) {
1025
- const decoded = {};
1026
- for (const [name, child] of Object.entries(value)) definePayloadProperty(decoded, name, decodeChild(child));
1027
- return decoded;
1028
- }
1029
- function definePayloadProperty(target, name, value) {
1030
- Object.defineProperty(target, name, {
1031
- configurable: true,
1032
- enumerable: true,
1033
- value,
1034
- writable: true
1035
- });
1036
- }
1037
- function readGraphRef(graph, id) {
1038
- if (!graph.refs.has(id)) throw new Error(`Payload referenced unknown object id ${id}.`);
1039
- return graph.refs.get(id);
1040
- }
1041
- function decodePayloadNumber(value) {
1042
- switch (value) {
1043
- case "Infinity": return Infinity;
1044
- case "-Infinity": return -Infinity;
1045
- case "-0": return -0;
1046
- case "NaN": return NaN;
1047
- }
1048
- }
1049
- function encodePayloadDataEntries(entries) {
1050
- const graph = createPayloadGraphEncodeContext();
1051
- return entries.map((entry) => encodePayloadDataEntryWithGraph(entry, graph));
1052
- }
1053
- function decodePayloadDataEntries(entries) {
1054
- const graph = createPayloadGraphDecodeContext();
1055
- return entries.map((entry) => decodePayloadDataEntryWithGraph(entry, graph));
1056
- }
1057
- function encodePayloadDataEntryWithGraph(entry, graph) {
1058
- return {
1059
- ...entry,
1060
- value: encodePayloadValueInternal(entry.value, graph)
1061
- };
1062
- }
1063
- function decodePayloadDataEntryWithGraph(entry, graph) {
1064
- return {
1065
- ...entry,
1066
- value: decodeModelValue(entry.value, graph)
1067
- };
1068
- }
1069
- function outlineTask(frame, kind, value, referenceKind, wakeable) {
347
+ function outlineTask(frame, value, referenceKind, wakeable, scopedAssets = []) {
1070
348
  const request = frame.request;
1071
349
  const id = request.nextRowId++;
1072
- const task = createTask(request, id, kind, value, cloneContextValues(frame.contextValues), stackForError(wakeable, frame.stack));
350
+ if (scopedAssets.length > 0) emitRow(request, {
351
+ for: id,
352
+ tag: "assets",
353
+ value: scopedAssets
354
+ });
355
+ const task = createTask(request, id, value, cloneContextValues(frame.contextValues), frame.imagePreloadsSuppressed, stackForError(wakeable, frame.stack));
1073
356
  wakeable.then(() => pingTask(request, task), () => pingTask(request, task));
1074
357
  return {
1075
358
  $fig: referenceKind,
1076
359
  id
1077
360
  };
1078
361
  }
1079
- function outlineError(frame, error, referenceKind) {
362
+ function outlineError(frame, error, referenceKind, scopedAssets) {
1080
363
  const request = frame.request;
1081
364
  const id = request.nextRowId++;
365
+ if (scopedAssets.length > 0) emitRow(request, {
366
+ for: id,
367
+ tag: "assets",
368
+ value: scopedAssets
369
+ });
1082
370
  emitRow(request, {
1083
371
  id,
1084
372
  tag: "error",
@@ -1107,27 +395,15 @@ function stackForError(error, fallback) {
1107
395
  if (typeof error !== "object" || error === null) return fallback;
1108
396
  return errorStacks.get(error) ?? fallback;
1109
397
  }
1110
- function componentStack(stack) {
1111
- const frames = [];
1112
- for (let frame = stack; frame !== null; frame = frame.parent) frames.push(` at ${frame.name}`);
1113
- return frames.length === 0 ? "" : `\n${frames.join("\n")}`;
1114
- }
1115
- function clientRowMetadata(value) {
1116
- const metadata = { id: value.id };
1117
- if (value.exportName !== void 0) metadata.exportName = value.exportName;
1118
- if (value.ssr === true) metadata.ssr = true;
1119
- return metadata;
1120
- }
1121
398
  function clientReferenceExportName(id) {
1122
399
  const hashIndex = id.lastIndexOf("#");
1123
400
  if (hashIndex === -1) return void 0;
1124
- const exportName = id.slice(hashIndex + 1);
1125
- return exportName === "" ? void 0 : exportName;
401
+ return id.slice(hashIndex + 1) || void 0;
1126
402
  }
1127
403
  function emitClientReference(request, reference) {
1128
404
  const existing = request.clientReferenceRows.get(reference.id);
1129
405
  if (existing !== void 0) return existing;
1130
- const assets = serializeClientReferenceAssets(request, reference);
406
+ const assets = serializeAssetResources(request, collectClientReferenceAssets(request, reference));
1131
407
  const value = { id: reference.id };
1132
408
  if (assets.length > 0) value.assets = assets;
1133
409
  const exportName = clientReferenceExportName(reference.id);
@@ -1142,18 +418,16 @@ function emitClientReference(request, reference) {
1142
418
  });
1143
419
  return id;
1144
420
  }
1145
- function serializeClientReferenceAssets(request, reference) {
1146
- return serializeAssetResources(request, collectClientReferenceAssets(request, reference));
1147
- }
1148
421
  function serializeAssetResources(request, value) {
1149
422
  const input = isFigAssetResource(value) ? [value] : Array.isArray(value) ? value : [];
1150
423
  const resources = [];
1151
424
  for (const resource of input) {
1152
425
  if (!isFigAssetResource(resource)) continue;
1153
- if (assetResourceDestination(resource) !== "stream") continue;
1154
- const key = assetResourceKey(resource);
1155
- if (request.emittedAssetKeys.has(key)) continue;
1156
- request.emittedAssetKeys.add(key);
426
+ if (assetResourceDestination(resource) === "stream") {
427
+ const key = assetResourceKey(resource);
428
+ if (request.emittedAssetKeys.has(key)) continue;
429
+ request.emittedAssetKeys.add(key);
430
+ }
1157
431
  resources.push(serializeAssetResource(resource));
1158
432
  }
1159
433
  return resources;
@@ -1167,62 +441,94 @@ function collectClientReferenceAssets(request, reference) {
1167
441
  }
1168
442
  function serializeAssetResource(resource) {
1169
443
  switch (resource.kind) {
1170
- case "stylesheet": return {
1171
- ...resource.crossOrigin === void 0 ? {} : { crossOrigin: resource.crossOrigin },
1172
- href: resource.href,
1173
- kind: resource.kind,
1174
- ...resource.media === void 0 ? {} : { media: resource.media },
1175
- ...resource.precedence === void 0 ? {} : { precedence: resource.precedence }
1176
- };
1177
- case "preload": return {
1178
- as: resource.as,
1179
- ...resource.crossOrigin === void 0 ? {} : { crossOrigin: resource.crossOrigin },
1180
- ...resource.fetchPriority === void 0 ? {} : { fetchPriority: resource.fetchPriority },
1181
- href: resource.href,
1182
- kind: resource.kind,
1183
- ...resource.type === void 0 ? {} : { type: resource.type }
1184
- };
1185
- case "modulepreload": return {
1186
- ...resource.crossOrigin === void 0 ? {} : { crossOrigin: resource.crossOrigin },
1187
- ...resource.fetchPriority === void 0 ? {} : { fetchPriority: resource.fetchPriority },
1188
- href: resource.href,
1189
- kind: resource.kind
1190
- };
1191
- case "script": return {
1192
- ...resource.async === void 0 ? {} : { async: resource.async },
1193
- ...resource.crossOrigin === void 0 ? {} : { crossOrigin: resource.crossOrigin },
1194
- ...resource.defer === void 0 ? {} : { defer: resource.defer },
1195
- kind: resource.kind,
1196
- ...resource.module === void 0 ? {} : { module: resource.module },
1197
- src: resource.src
1198
- };
1199
- case "font": return {
1200
- ...resource.crossOrigin === void 0 ? {} : { crossOrigin: resource.crossOrigin },
1201
- ...resource.fetchPriority === void 0 ? {} : { fetchPriority: resource.fetchPriority },
1202
- href: resource.href,
444
+ case "stylesheet": {
445
+ const model = {
446
+ href: resource.href,
447
+ kind: resource.kind
448
+ };
449
+ if (resource.crossorigin !== void 0) model.crossorigin = resource.crossorigin;
450
+ if (resource.media !== void 0) model.media = resource.media;
451
+ if (resource.precedence !== void 0) model.precedence = resource.precedence;
452
+ return model;
453
+ }
454
+ case "preload": {
455
+ const model = {
456
+ as: resource.as,
457
+ kind: resource.kind
458
+ };
459
+ if (resource.crossorigin !== void 0) model.crossorigin = resource.crossorigin;
460
+ if (resource.fetchpriority !== void 0) model.fetchpriority = resource.fetchpriority;
461
+ if (resource.href !== void 0) model.href = resource.href;
462
+ if (resource.imagesizes !== void 0) model.imagesizes = resource.imagesizes;
463
+ if (resource.imagesrcset !== void 0) model.imagesrcset = resource.imagesrcset;
464
+ if (resource.referrerpolicy !== void 0) model.referrerpolicy = resource.referrerpolicy;
465
+ if (resource.type !== void 0) model.type = resource.type;
466
+ return model;
467
+ }
468
+ case "modulepreload": {
469
+ const model = {
470
+ href: resource.href,
471
+ kind: resource.kind
472
+ };
473
+ if (resource.crossorigin !== void 0) model.crossorigin = resource.crossorigin;
474
+ if (resource.fetchpriority !== void 0) model.fetchpriority = resource.fetchpriority;
475
+ return model;
476
+ }
477
+ case "script": {
478
+ const model = {
479
+ kind: resource.kind,
480
+ src: resource.src
481
+ };
482
+ if (resource.async !== void 0) model.async = resource.async;
483
+ if (resource.crossorigin !== void 0) model.crossorigin = resource.crossorigin;
484
+ if (resource.defer !== void 0) model.defer = resource.defer;
485
+ if (resource.module !== void 0) model.module = resource.module;
486
+ return model;
487
+ }
488
+ case "font": {
489
+ const model = {
490
+ href: resource.href,
491
+ kind: resource.kind,
492
+ type: resource.type
493
+ };
494
+ if (resource.crossorigin !== void 0) model.crossorigin = resource.crossorigin;
495
+ if (resource.fetchpriority !== void 0) model.fetchpriority = resource.fetchpriority;
496
+ return model;
497
+ }
498
+ case "preconnect": {
499
+ const model = {
500
+ href: resource.href,
501
+ kind: resource.kind
502
+ };
503
+ if (resource.crossorigin !== void 0) model.crossorigin = resource.crossorigin;
504
+ return model;
505
+ }
506
+ case "title": return {
1203
507
  kind: resource.kind,
1204
- type: resource.type
1205
- };
1206
- case "preconnect": return {
1207
- ...resource.crossOrigin === void 0 ? {} : { crossOrigin: resource.crossOrigin },
1208
- href: resource.href,
1209
- kind: resource.kind
508
+ value: resource.value
1210
509
  };
1211
- case "title":
1212
- case "meta": throw new Error("Head-only resources cannot be serialized into the payload.");
510
+ case "meta": {
511
+ const model = { kind: resource.kind };
512
+ if (resource.charset !== void 0) model.charset = resource.charset;
513
+ if (resource.content !== void 0) model.content = resource.content;
514
+ if (resource["http-equiv"] !== void 0) model["http-equiv"] = resource["http-equiv"];
515
+ if (resource.key !== void 0) model.key = resource.key;
516
+ if (resource.name !== void 0) model.name = resource.name;
517
+ if (resource.property !== void 0) model.property = resource.property;
518
+ return model;
519
+ }
1213
520
  }
1214
- return unsupportedSerializedAssetResource(resource);
1215
- }
1216
- function unsupportedSerializedAssetResource(resource) {
1217
- throw new Error(`Unsupported asset resource kind: ${resource.kind}`);
1218
521
  }
1219
522
  function emitRow(request, row) {
1220
- request.queuedRows.push(request.codec.encodeRow(row));
523
+ request.queuedRows.push(jsonPayloadCodec.encodeRow(row));
1221
524
  flushRows(request);
1222
525
  }
1223
526
  function pingTask(request, task) {
1224
527
  if (request.status === "closed") return;
1225
528
  request.pingedTasks.push(task);
529
+ scheduleWork(request);
530
+ }
531
+ function scheduleWork(request) {
1226
532
  if (request.workScheduled) return;
1227
533
  request.workScheduled = true;
1228
534
  queueMicrotask(() => {
@@ -1232,21 +538,29 @@ function pingTask(request, task) {
1232
538
  }
1233
539
  function flushRows(request) {
1234
540
  if (request.controller === null || request.status === "closed") return;
1235
- if (request.status === "opening") return;
1236
- if (request.queuedRows.length > 0) {
1237
- for (const row of request.queuedRows) request.controller.enqueue(row);
1238
- request.queuedRows = [];
541
+ if (request.flushingRows) return;
542
+ request.flushingRows = true;
543
+ try {
544
+ let flushed = 0;
545
+ while (flushed < request.queuedRows.length && !streamFlowBlocked(request.controller)) {
546
+ request.controller.enqueue(request.queuedRows[flushed]);
547
+ flushed += 1;
548
+ }
549
+ if (flushed === request.queuedRows.length) request.queuedRows.length = 0;
550
+ else if (flushed > 0) request.queuedRows = request.queuedRows.slice(flushed);
551
+ } finally {
552
+ request.flushingRows = false;
1239
553
  }
1240
- if (request.pendingTasks === 0) {
554
+ if (request.pendingTasks === 0 && request.queuedRows.length === 0) {
1241
555
  request.status = "closed";
1242
- cleanupPayloadAbortListener(request);
556
+ request.cleanupAbortListener();
1243
557
  request.dataStore.dispose();
1244
558
  request.controller.close();
1245
559
  }
1246
560
  }
1247
561
  function closeWithError(request, error) {
1248
562
  if (request.status === "closed") return;
1249
- cleanupPayloadAbortListener(request);
563
+ request.cleanupAbortListener();
1250
564
  request.status = "closed";
1251
565
  request.dataStore.dispose();
1252
566
  request.allReady.reject(error);
@@ -1255,446 +569,20 @@ function closeWithError(request, error) {
1255
569
  function abortPayloadRequest(request, reason) {
1256
570
  closeWithError(request, reason ?? new PayloadRequestCancelledError());
1257
571
  }
1258
- function cleanupPayloadAbortListener(request) {
1259
- if (request.abortListener === null) return;
1260
- request.abortSignal?.removeEventListener("abort", request.abortListener);
1261
- request.abortListener = null;
1262
- request.abortSignal = null;
1263
- }
1264
572
  function flattenChildArrays(children) {
573
+ if (!children.some(Array.isArray)) return children;
1265
574
  const collected = [];
1266
- for (const child of children) if (Array.isArray(child)) collected.push(...flattenChildArrays(child));
575
+ for (const child of children) if (Array.isArray(child)) for (const nested of flattenChildArrays(child)) collected.push(nested);
1267
576
  else collected.push(child);
1268
577
  return collected;
1269
578
  }
1270
579
  function invalidChildError$1(value) {
1271
580
  return /* @__PURE__ */ new Error(`Invalid Fig child in payload render: ${describeInvalidChild(value)}.`);
1272
581
  }
1273
- async function readByteStream(stream, onChunk, signal) {
1274
- const reader = stream.getReader();
1275
- const abort = () => {
1276
- reader.cancel(signal?.reason).catch(() => void 0);
1277
- };
1278
- try {
1279
- signal?.addEventListener("abort", abort, { once: true });
1280
- while (true) {
1281
- throwIfAborted(signal);
1282
- const { done, value } = await reader.read();
1283
- throwIfAborted(signal);
1284
- if (done) return;
1285
- onChunk(value);
1286
- }
1287
- } catch (error) {
1288
- if (!signal?.aborted) await reader.cancel(error).catch(() => void 0);
1289
- throw error;
1290
- } finally {
1291
- signal?.removeEventListener("abort", abort);
1292
- reader.releaseLock();
1293
- throwIfAborted(signal);
1294
- }
1295
- }
1296
582
  function throwIfAborted(signal) {
1297
583
  if (signal?.aborted) throw new PayloadRequestCancelledError();
1298
584
  }
1299
- function resolveDecodedRow(response, row, revision) {
1300
- const chunk = response.getChunk(row.id);
1301
- if (row.tag === "error") {
1302
- const error = errorFromPayload(row.value);
1303
- chunk.model = null;
1304
- chunk.status = "rejected";
1305
- chunk.value = error;
1306
- chunk.reject(error);
1307
- chunk.promise.catch(() => void 0);
1308
- return;
1309
- }
1310
- let value;
1311
- if (row.tag === "client") {
1312
- response.recordClientReference(row.value);
1313
- response.recordAssetResources(row.value.assets);
1314
- value = response.decodeClientReference(clientRowMetadata(row.value));
1315
- } else value = response.decodeModelAtRevision(row.value, revision);
1316
- chunk.model = row.tag === "model" ? row.value : null;
1317
- chunk.revision = revision;
1318
- if (row.tag === "model") {
1319
- chunk.decoded = value;
1320
- chunk.hasDecoded = true;
1321
- }
1322
- chunk.status = "fulfilled";
1323
- chunk.value = value;
1324
- chunk.resolve(value);
1325
- }
1326
- function errorFromPayload(value) {
1327
- const error = new Error(value.message ?? "The server render failed.");
1328
- if (value.digest !== void 0) error.digest = value.digest;
1329
- return error;
1330
- }
1331
- function shiftRowIds(row, rowOffset, objectOffset) {
1332
- if (row.tag === "client" || row.tag === "error" || row.tag === "model") row.id += rowOffset;
1333
- if (row.tag === "model" || row.tag === "refresh") shiftModelIds(row.value, rowOffset, objectOffset);
1334
- if (row.tag === "data") for (const entry of row.value) shiftModelIds(entry.value, rowOffset, objectOffset);
1335
- }
1336
- function shiftModelIds(model, rowOffset, objectOffset) {
1337
- if (model === null || typeof model !== "object") return;
1338
- if (Array.isArray(model)) {
1339
- for (const item of model) shiftModelIds(item, rowOffset, objectOffset);
1340
- return;
1341
- }
1342
- if (isPayloadSpecialModel(model)) {
1343
- const special = model;
1344
- switch (special.$fig) {
1345
- case "array":
1346
- special.id += objectOffset;
1347
- for (const value of special.value) shiftModelIds(value, rowOffset, objectOffset);
1348
- return;
1349
- case "client":
1350
- case "lazy":
1351
- case "promise":
1352
- special.id += rowOffset;
1353
- return;
1354
- case "element":
1355
- if (special.id !== void 0) special.id += objectOffset;
1356
- shiftModelIds(special.type, rowOffset, objectOffset);
1357
- shiftModelIds(special.props, rowOffset, objectOffset);
1358
- return;
1359
- case "object":
1360
- if (special.id !== void 0) special.id += objectOffset;
1361
- for (const value of Object.values(special.value)) shiftModelIds(value, rowOffset, objectOffset);
1362
- return;
1363
- case "boundary":
1364
- shiftModelIds(special.child, rowOffset, objectOffset);
1365
- return;
1366
- case "map":
1367
- special.id += objectOffset;
1368
- for (const [key, value] of special.entries) {
1369
- shiftModelIds(key, rowOffset, objectOffset);
1370
- shiftModelIds(value, rowOffset, objectOffset);
1371
- }
1372
- return;
1373
- case "ref":
1374
- special.id += objectOffset;
1375
- return;
1376
- case "set":
1377
- special.id += objectOffset;
1378
- for (const value of special.values) shiftModelIds(value, rowOffset, objectOffset);
1379
- return;
1380
- default: return;
1381
- }
1382
- }
1383
- for (const value of Object.values(model)) shiftModelIds(value, rowOffset, objectOffset);
1384
- }
1385
- function noteMaxObjectIds(response, model) {
1386
- if (model === null || typeof model !== "object") return;
1387
- if (Array.isArray(model)) {
1388
- for (const item of model) noteMaxObjectIds(response, item);
1389
- return;
1390
- }
1391
- if (isPayloadSpecialModel(model)) switch (model.$fig) {
1392
- case "array":
1393
- response.noteObjectId(model.id);
1394
- for (const value of model.value) noteMaxObjectIds(response, value);
1395
- return;
1396
- case "element":
1397
- if (model.id !== void 0) response.noteObjectId(model.id);
1398
- noteMaxObjectIds(response, model.type);
1399
- noteMaxObjectIds(response, model.props);
1400
- return;
1401
- case "map":
1402
- response.noteObjectId(model.id);
1403
- for (const [key, value] of model.entries) {
1404
- noteMaxObjectIds(response, key);
1405
- noteMaxObjectIds(response, value);
1406
- }
1407
- return;
1408
- case "object":
1409
- if (model.id !== void 0) response.noteObjectId(model.id);
1410
- for (const value of Object.values(model.value)) noteMaxObjectIds(response, value);
1411
- return;
1412
- case "ref":
1413
- case "set":
1414
- response.noteObjectId(model.id);
1415
- if (model.$fig === "set") for (const value of model.values) noteMaxObjectIds(response, value);
1416
- return;
1417
- case "boundary":
1418
- noteMaxObjectIds(response, model.child);
1419
- return;
1420
- default: return;
1421
- }
1422
- for (const value of Object.values(model)) noteMaxObjectIds(response, value);
1423
- }
1424
- function collectObjectIds(model, ids) {
1425
- if (model === null || typeof model !== "object") return;
1426
- if (Array.isArray(model)) {
1427
- for (const item of model) collectObjectIds(item, ids);
1428
- return;
1429
- }
1430
- if (isPayloadSpecialModel(model)) switch (model.$fig) {
1431
- case "array":
1432
- ids.add(model.id);
1433
- for (const value of model.value) collectObjectIds(value, ids);
1434
- return;
1435
- case "element":
1436
- if (model.id !== void 0) ids.add(model.id);
1437
- collectObjectIds(model.type, ids);
1438
- collectObjectIds(model.props, ids);
1439
- return;
1440
- case "map":
1441
- ids.add(model.id);
1442
- for (const [key, value] of model.entries) {
1443
- collectObjectIds(key, ids);
1444
- collectObjectIds(value, ids);
1445
- }
1446
- return;
1447
- case "object":
1448
- if (model.id !== void 0) ids.add(model.id);
1449
- for (const value of Object.values(model.value)) collectObjectIds(value, ids);
1450
- return;
1451
- case "ref":
1452
- ids.add(model.id);
1453
- return;
1454
- case "set":
1455
- ids.add(model.id);
1456
- for (const value of model.values) collectObjectIds(value, ids);
1457
- return;
1458
- case "boundary": return;
1459
- default: return;
1460
- }
1461
- for (const value of Object.values(model)) collectObjectIds(value, ids);
1462
- }
1463
- function collectBoundaryIds(model, ids) {
1464
- if (model === null || typeof model !== "object") return;
1465
- if (Array.isArray(model)) {
1466
- for (const item of model) collectBoundaryIds(item, ids);
1467
- return;
1468
- }
1469
- if (isPayloadSpecialModel(model)) switch (model.$fig) {
1470
- case "array":
1471
- for (const value of model.value) collectBoundaryIds(value, ids);
1472
- return;
1473
- case "element":
1474
- collectBoundaryIds(model.type, ids);
1475
- collectBoundaryIds(model.props, ids);
1476
- return;
1477
- case "object":
1478
- for (const value of Object.values(model.value)) collectBoundaryIds(value, ids);
1479
- return;
1480
- case "boundary":
1481
- ids.add(model.id);
1482
- return;
1483
- case "map":
1484
- for (const [key, value] of model.entries) {
1485
- collectBoundaryIds(key, ids);
1486
- collectBoundaryIds(value, ids);
1487
- }
1488
- return;
1489
- case "set":
1490
- for (const value of model.values) collectBoundaryIds(value, ids);
1491
- return;
1492
- default: return;
1493
- }
1494
- for (const value of Object.values(model)) collectBoundaryIds(value, ids);
1495
- }
1496
- function referencedChunkClosure(model, chunks) {
1497
- const ids = /* @__PURE__ */ new Set();
1498
- const pending = [model];
1499
- for (let index = 0; index < pending.length; index += 1) {
1500
- const next = /* @__PURE__ */ new Set();
1501
- collectReferencedChunkIds(pending[index], next);
1502
- for (const id of next) {
1503
- if (ids.has(id)) continue;
1504
- ids.add(id);
1505
- const chunk = chunks.get(id);
1506
- if (chunk?.model !== null && chunk?.model !== void 0) pending.push(chunk.model);
1507
- }
1508
- }
1509
- return ids;
1510
- }
1511
- function collectReferencedChunkIds(model, ids) {
1512
- if (model === null || typeof model !== "object") return;
1513
- if (Array.isArray(model)) {
1514
- for (const item of model) collectReferencedChunkIds(item, ids);
1515
- return;
1516
- }
1517
- if (isPayloadSpecialModel(model)) switch (model.$fig) {
1518
- case "array":
1519
- for (const value of model.value) collectReferencedChunkIds(value, ids);
1520
- return;
1521
- case "client":
1522
- case "lazy":
1523
- case "promise":
1524
- ids.add(model.id);
1525
- return;
1526
- case "element":
1527
- collectReferencedChunkIds(model.type, ids);
1528
- collectReferencedChunkIds(model.props, ids);
1529
- return;
1530
- case "object":
1531
- for (const value of Object.values(model.value)) collectReferencedChunkIds(value, ids);
1532
- return;
1533
- case "ref": return;
1534
- case "boundary": return;
1535
- case "map":
1536
- for (const [key, value] of model.entries) {
1537
- collectReferencedChunkIds(key, ids);
1538
- collectReferencedChunkIds(value, ids);
1539
- }
1540
- return;
1541
- case "set":
1542
- for (const value of model.values) collectReferencedChunkIds(value, ids);
1543
- return;
1544
- default: return;
1545
- }
1546
- for (const value of Object.values(model)) collectReferencedChunkIds(value, ids);
1547
- }
1548
- function addChunkRefs(target, ids) {
1549
- for (const id of ids) target.add(id);
1550
- }
1551
- function isPayloadSpecialModel(model) {
1552
- if (!("$fig" in model)) return false;
1553
- switch (model.$fig) {
1554
- case "array":
1555
- case "bigint":
1556
- case "boundary":
1557
- case "client":
1558
- case "date":
1559
- case "element":
1560
- case "fragment":
1561
- case "lazy":
1562
- case "map":
1563
- case "number":
1564
- case "object":
1565
- case "promise":
1566
- case "ref":
1567
- case "set":
1568
- case "suspense":
1569
- case "symbol":
1570
- case "undefined":
1571
- case "view-transition": return true;
1572
- default: return false;
1573
- }
1574
- }
1575
- function decodeModel(response, model) {
1576
- if (model === null) return null;
1577
- if (Array.isArray(model)) return model.map((item) => decodeModel(response, item));
1578
- if (typeof model !== "object") return model;
1579
- if (isPayloadSpecialModel(model)) return decodeSpecialModel(response, model);
1580
- const decoded = {};
1581
- for (const [name, value] of Object.entries(model)) definePayloadProperty(decoded, name, decodeModel(response, value));
1582
- return decoded;
1583
- }
1584
- function decodeSpecialModel(response, model) {
1585
- switch (model.$fig) {
1586
- case "array": return response.defineObjectRef(model.id, () => [], (value) => {
1587
- value.push(...model.value.map((item) => decodeModel(response, item)));
1588
- });
1589
- case "bigint": return BigInt(model.value);
1590
- case "date": return new Date(model.value);
1591
- case "map": return response.defineObjectRef(model.id, () => /* @__PURE__ */ new Map(), (value) => {
1592
- for (const [key, item] of model.entries) value.set(decodeModel(response, key), decodeModel(response, item));
1593
- });
1594
- case "number": return decodePayloadNumber(model.value);
1595
- case "object":
1596
- if (model.id === void 0) {
1597
- const value = {};
1598
- for (const [name, child] of Object.entries(model.value)) definePayloadProperty(value, name, decodeModel(response, child));
1599
- return value;
1600
- }
1601
- return response.defineObjectRef(model.id, () => ({}), (value) => {
1602
- for (const [name, child] of Object.entries(model.value)) definePayloadProperty(value, name, decodeModel(response, child));
1603
- });
1604
- case "ref": return response.readObjectRef(model.id);
1605
- case "set": return response.defineObjectRef(model.id, () => /* @__PURE__ */ new Set(), (value) => {
1606
- for (const item of model.values) value.add(decodeModel(response, item));
1607
- });
1608
- case "symbol": return Symbol.for(model.key);
1609
- case "undefined": return;
1610
- case "boundary":
1611
- response.prepareBoundaryInitial(model.id, model.child);
1612
- return createElement(PayloadBoundarySlot, {
1613
- id: model.id,
1614
- initial: model.child,
1615
- response
1616
- });
1617
- case "element": {
1618
- if (model.id !== void 0) return response.defineObjectRef(model.id, () => ({
1619
- $$typeof: FigElementSymbol,
1620
- key: model.key,
1621
- props: {},
1622
- type: Fragment
1623
- }), (element) => {
1624
- element.type = decodeElementType(response, model.type);
1625
- element.props = decodeModel(response, model.props);
1626
- });
1627
- const type = decodeElementType(response, model.type);
1628
- const props = decodeModel(response, model.props);
1629
- if (model.key !== null) props.key = model.key;
1630
- return createElement(type, props);
1631
- }
1632
- case "client": return response.readChunk(model.id);
1633
- case "fragment": return Fragment;
1634
- case "lazy": return createElement(PayloadLazyNode, {
1635
- id: model.id,
1636
- response
1637
- });
1638
- case "promise": return response.getChunk(model.id).promise;
1639
- case "suspense": return Suspense;
1640
- case "view-transition": return ViewTransition;
1641
- }
1642
- }
1643
- function decodeElementType(response, type) {
1644
- if (typeof type === "string") return type;
1645
- return decodeSpecialModel(response, type);
1646
- }
1647
- function PayloadResponseRoot(props) {
1648
- return props.response.readChunk(0);
1649
- }
1650
- function PayloadBoundarySlot(props) {
1651
- return props.response.readBoundary(props.id, props.initial);
1652
- }
1653
- function PayloadLazyNode(props) {
1654
- return props.response.readChunk(props.id);
1655
- }
1656
- function resolveClientReferenceExport(moduleValue, metadata) {
1657
- if (typeof moduleValue === "function") return moduleValue;
1658
- if (typeof moduleValue === "object" && moduleValue !== null && metadata.exportName !== void 0) {
1659
- const candidate = moduleValue[metadata.exportName];
1660
- if (typeof candidate === "function") return candidate;
1661
- }
1662
- throw new Error(`Client reference "${metadata.id}" did not load a component.`);
1663
- }
1664
- function appendPayloadHeaders(codec, headers, boundary) {
1665
- const next = new Headers(headers);
1666
- if (!next.has("accept")) next.set("accept", codec.contentType);
1667
- if (boundary !== void 0) next.set(PAYLOAD_BOUNDARY_HEADER, boundary);
1668
- return next;
1669
- }
1670
- function assertPayloadCodecMatches(codec, contentTypeHeader) {
1671
- if (contentTypeHeader === null) return;
1672
- const received = payloadCodecIdFromContentType(contentTypeHeader);
1673
- if (received === null || received === codec.id) return;
1674
- throw new Error(`Payload codec mismatch: response used "${received}" but this client expects "${codec.id}".`);
1675
- }
1676
- function getOrCreateChunk(chunks, id) {
1677
- const existing = chunks.get(id);
1678
- if (existing !== void 0) return existing;
1679
- const settled = deferred();
1680
- const chunk = {
1681
- decoded: void 0,
1682
- hasDecoded: false,
1683
- model: null,
1684
- promise: settled.promise,
1685
- reject: settled.reject,
1686
- resolve: settled.resolve,
1687
- revision: 0,
1688
- status: "pending",
1689
- value: void 0
1690
- };
1691
- chunks.set(id, chunk);
1692
- return chunk;
1693
- }
1694
- function isPayloadBoundary(value) {
1695
- return typeof value === "function" && value.$$typeof === PayloadBoundarySymbol;
1696
- }
1697
585
  //#endregion
1698
- export { PAYLOAD_BOUNDARY_HEADER, PayloadBoundary, PayloadFetchError, createPayloadResponse, decodePayloadDataEntries, decodePayloadValue, encodePayloadDataEntries, encodePayloadValue, fetchPayload, isPayloadRequestCancelled, jsonPayloadCodec, renderToPayloadStream };
586
+ export { renderToPayloadStream };
1699
587
 
1700
588
  //# sourceMappingURL=payload.js.map