@bgub/fig-server 0.0.1 → 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/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 deferred, c as streamHighWaterMark, i as createStaticDispatcher, l as withContextValue, n as cloneContextValues, r as componentStack, s as streamFlowBlocked } from "./shared-Bna74_aZ.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,82 @@ 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(), 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"
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;
568
79
  };
569
- return initial.revision > refreshed.revision ? {
570
- ...initial,
571
- source: "initial"
572
- } : {
573
- ...refreshed,
574
- source: "refresh"
575
- };
576
- }
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
80
  }
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, stack) {
606
88
  request.pendingTasks += 1;
607
89
  return {
608
90
  contextValues,
609
91
  id,
610
- kind,
611
92
  stack,
612
- value
93
+ ...value
613
94
  };
614
95
  }
615
96
  function performWork(request) {
616
97
  if (request.status === "closed") return;
617
- if (request.status === "opening") request.status = "open";
618
98
  const tasks = request.pingedTasks;
619
99
  request.pingedTasks = [];
620
100
  for (const task of tasks) retryTask(request, task);
621
101
  flushRows(request);
622
102
  }
623
103
  function retryTask(request, task) {
624
- const frame = createRenderFrame(request, cloneContextValues(task.contextValues), task.stack);
104
+ const frame = {
105
+ contextValues: cloneContextValues(task.contextValues),
106
+ dispatcher: null,
107
+ pendingAssets: [],
108
+ request,
109
+ stack: task.stack
110
+ };
625
111
  try {
626
- const value = task.kind === "node" ? serializeNode(task.value, frame) : serializeValue(readThenable(task.value), frame);
112
+ let value;
113
+ switch (task.kind) {
114
+ case "node":
115
+ value = serializeNode(task.value, frame);
116
+ break;
117
+ case "node-promise":
118
+ value = serializeNode(readThenable(task.value), frame);
119
+ break;
120
+ case "promise":
121
+ value = serializeValue(readThenable(task.value), frame);
122
+ break;
123
+ }
124
+ flushFrameAssets(frame, task.id);
627
125
  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, {
126
+ emitRow(request, {
634
127
  id: task.id,
635
128
  tag: "model",
636
129
  value
@@ -638,15 +131,12 @@ function retryTask(request, task) {
638
131
  finishTask(request);
639
132
  } catch (error) {
640
133
  if (isThenable(error)) {
134
+ flushFrameAssets(frame, task.id);
641
135
  error.then(() => pingTask(request, task), () => pingTask(request, task));
642
136
  return;
643
137
  }
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, {
138
+ flushFrameAssets(frame, task.id);
139
+ emitRow(request, {
650
140
  id: task.id,
651
141
  tag: "error",
652
142
  value: errorRowPayload(request, error, task.stack)
@@ -662,7 +152,7 @@ function emitDataRows(request) {
662
152
  const entries = [];
663
153
  for (const snapshot of request.pendingDataSnapshots.values()) {
664
154
  if (!snapshot.hasValue || snapshot.status === "refreshing") continue;
665
- const key = normalizeDataResourceKey(snapshot.key);
155
+ const key = snapshot.canonicalKey;
666
156
  if (request.emittedDataKeys.has(key)) {
667
157
  request.pendingDataSnapshots.delete(snapshot.canonicalKey);
668
158
  continue;
@@ -679,13 +169,14 @@ function emitDataRows(request) {
679
169
  value: encodePayloadDataEntries(entries)
680
170
  });
681
171
  }
682
- function createRenderFrame(request, contextValues, stack) {
683
- return {
684
- contextValues,
685
- dispatcher: null,
686
- request,
687
- stack
688
- };
172
+ function flushFrameAssets(frame, rowId) {
173
+ if (frame.pendingAssets.length === 0) return;
174
+ const value = frame.pendingAssets.splice(0);
175
+ emitRow(frame.request, {
176
+ for: rowId,
177
+ tag: "assets",
178
+ value
179
+ });
689
180
  }
690
181
  function createPayloadDispatcher(frame) {
691
182
  return createStaticDispatcher({
@@ -711,18 +202,27 @@ function serializeNode(node, frame) {
711
202
  if (node === null || node === void 0 || typeof node === "boolean") return node === void 0 ? { $fig: "undefined" } : node;
712
203
  if (typeof node === "string" || typeof node === "number") return node;
713
204
  if (isPortal(node)) return null;
714
- if (!isValidElement(node)) throw invalidChildError$1(node);
715
- return serializeElement(node, frame, false);
205
+ if (isValidElement(node)) return serializeElement(node, frame, false);
206
+ if (isThenable(node)) return outlineTask(frame, {
207
+ kind: "node-promise",
208
+ value: node
209
+ }, "promise", node);
210
+ throw invalidChildError$1(node);
716
211
  }
717
212
  function serializeNodeOrLazy(node, frame, preserveElementIdentity = false) {
718
- const graphCheckpoint = checkpointGraph(frame.request.graph);
213
+ const graphCheckpoint = checkpointPayloadGraph(frame.request.graph);
214
+ const assetCheckpoint = frame.pendingAssets.length;
719
215
  try {
720
216
  if (!isValidElement(node)) return serializeNode(node, frame);
721
217
  return serializeElement(node, frame, preserveElementIdentity);
722
218
  } 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");
219
+ rollbackPayloadGraph(frame.request.graph, graphCheckpoint);
220
+ const scopedAssets = frame.pendingAssets.splice(assetCheckpoint);
221
+ if (isThenable(error)) return outlineTask(frame, {
222
+ kind: "node",
223
+ value: node
224
+ }, "lazy", error, scopedAssets);
225
+ return outlineError(frame, error, "lazy", scopedAssets);
726
226
  }
727
227
  }
728
228
  function serializeElement(element, frame, preserveIdentity) {
@@ -733,20 +233,6 @@ function serializeElement(element, frame, preserveIdentity) {
733
233
  $fig: "client",
734
234
  id: emitClientReference(frame.request, type)
735
235
  }, 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
236
  if (isContext(type)) return serializeContextProvider(type, element.props, frame);
751
237
  if (isAssets(type)) return serializeAssets(element.props, frame);
752
238
  if (isSuspense(type)) return serializeElementModel(element, { $fig: "suspense" }, frame, preserveIdentity, suspenseTreeProps);
@@ -757,17 +243,20 @@ function serializeElement(element, frame, preserveIdentity) {
757
243
  throw new Error("Unsupported Fig element type during payload render.");
758
244
  }
759
245
  function serializeElementModel(element, type, frame, preserveIdentity, treeProps = emptyTreeProps) {
760
- const id = preserveIdentity ? defineGraphElement(frame.request.graph, element) : void 0;
246
+ const id = preserveIdentity ? definePayloadGraphElement(frame.request.graph, element) : void 0;
761
247
  if (typeof id === "object") return id;
762
- return {
248
+ const model = {
763
249
  $fig: "element",
764
- ...id === void 0 ? null : { id },
765
250
  key: element.key,
766
- props: serializeProps(element.props, frame, treeProps),
251
+ props: serializeProps(element.props, frame, treeProps, typeof type === "string"),
767
252
  type
768
253
  };
254
+ if (id !== void 0) model.id = id;
255
+ return model;
769
256
  }
770
257
  function serializeFunctionComponent(type, props, frame) {
258
+ const assetCheckpoint = frame.pendingAssets.length;
259
+ frame.pendingAssets.push(...serializeAssetResources(frame.request, frame.request.componentAssets?.(type)));
771
260
  frame.dispatcher ??= createPayloadDispatcher(frame);
772
261
  const previousDispatcher = setCurrentDispatcher(frame.dispatcher);
773
262
  const previousDataStore = setCurrentDataStore(frame.request.dataStore);
@@ -778,7 +267,14 @@ function serializeFunctionComponent(type, props, frame) {
778
267
  };
779
268
  try {
780
269
  const result = type(props);
781
- return serializeNode(isThenable(result) ? readThenable(result) : result, frame);
270
+ if (isThenable(result)) {
271
+ const scopedAssets = frame.pendingAssets.splice(assetCheckpoint);
272
+ return outlineTask(frame, {
273
+ kind: "node-promise",
274
+ value: result
275
+ }, "promise", result, scopedAssets);
276
+ }
277
+ return serializeNode(result, frame);
782
278
  } catch (error) {
783
279
  recordErrorStack(error, frame.stack);
784
280
  throw error;
@@ -792,16 +288,18 @@ function serializeContextProvider(context, props, frame) {
792
288
  return withContextValue(frame.contextValues, context, props.value, () => serializeNode(props.children, frame));
793
289
  }
794
290
  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
- });
291
+ frame.pendingAssets.push(...serializeAssetResources(frame.request, props.assets));
800
292
  return serializeNode(props.children, frame);
801
293
  }
802
- function serializeProps(props, frame, treeProps) {
294
+ function serializeProps(props, frame, treeProps, hostElement = false) {
295
+ const clientOnlyBehavior = hostElement ? clientOnlyHostBehavior(props) : void 0;
296
+ 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
297
  const value = {};
804
- for (const [name, child] of Object.entries(props)) value[name] = treeProps.has(name) ? serializeTreeProp(child, frame) : serializeValue(child, frame);
298
+ for (const name of Object.keys(props)) {
299
+ if (hostElement && name === "mix") continue;
300
+ const child = props[name];
301
+ value[name] = treeProps.has(name) ? serializeTreeProp(child, frame) : serializeValue(child, frame);
302
+ }
805
303
  return {
806
304
  $fig: "object",
807
305
  value
@@ -812,273 +310,50 @@ function serializeTreeProp(value, frame) {
812
310
  return serializeNodeOrLazy(value, frame);
813
311
  }
814
312
  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);
313
+ if (isPlainPayloadValue(value)) return encodePayloadValueWithGraph(value, frame.request.graph);
314
+ if (isClientReference(value)) return {
315
+ $fig: "client",
316
+ id: emitClientReference(frame.request, value)
317
+ };
824
318
  if (isValidElement(value)) return serializeNodeOrLazy(value, frame, true);
825
319
  if (isPortal(value)) return null;
320
+ if (isThenable(value)) return outlineTask(frame, {
321
+ kind: "promise",
322
+ value
323
+ }, "promise", value);
324
+ if (typeof value === "function") throw new Error("Functions cannot be passed to client references.");
826
325
  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));
326
+ if (value instanceof Date) return encodePayloadValueWithGraph(value, frame.request.graph);
327
+ if (value instanceof Map) return serializePayloadMap(value, frame.request.graph, ([key, item]) => [serializeValue(key, frame), serializeValue(item, frame)]);
328
+ if (value instanceof Set) return serializePayloadSet(value, frame.request.graph, (item) => serializeValue(item, frame));
329
+ if (Array.isArray(value)) return serializePayloadArray(value, frame.request.graph, () => value, (item) => serializeValue(item, frame));
330
+ return serializePayloadPlainObject(value, frame.request.graph, (child) => serializeValue(child, frame));
832
331
  }
833
332
  throw new Error(`Cannot serialize ${typeof value} into the payload.`);
834
333
  }
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
- };
862
- }
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
- throw new Error(`Cannot serialize ${typeof value} into the payload.`);
877
- }
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) {
334
+ function outlineTask(frame, value, referenceKind, wakeable, scopedAssets = []) {
1070
335
  const request = frame.request;
1071
336
  const id = request.nextRowId++;
1072
- const task = createTask(request, id, kind, value, cloneContextValues(frame.contextValues), stackForError(wakeable, frame.stack));
337
+ if (scopedAssets.length > 0) emitRow(request, {
338
+ for: id,
339
+ tag: "assets",
340
+ value: scopedAssets
341
+ });
342
+ const task = createTask(request, id, value, cloneContextValues(frame.contextValues), stackForError(wakeable, frame.stack));
1073
343
  wakeable.then(() => pingTask(request, task), () => pingTask(request, task));
1074
344
  return {
1075
345
  $fig: referenceKind,
1076
346
  id
1077
347
  };
1078
348
  }
1079
- function outlineError(frame, error, referenceKind) {
349
+ function outlineError(frame, error, referenceKind, scopedAssets) {
1080
350
  const request = frame.request;
1081
351
  const id = request.nextRowId++;
352
+ if (scopedAssets.length > 0) emitRow(request, {
353
+ for: id,
354
+ tag: "assets",
355
+ value: scopedAssets
356
+ });
1082
357
  emitRow(request, {
1083
358
  id,
1084
359
  tag: "error",
@@ -1107,27 +382,15 @@ function stackForError(error, fallback) {
1107
382
  if (typeof error !== "object" || error === null) return fallback;
1108
383
  return errorStacks.get(error) ?? fallback;
1109
384
  }
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
385
  function clientReferenceExportName(id) {
1122
386
  const hashIndex = id.lastIndexOf("#");
1123
387
  if (hashIndex === -1) return void 0;
1124
- const exportName = id.slice(hashIndex + 1);
1125
- return exportName === "" ? void 0 : exportName;
388
+ return id.slice(hashIndex + 1) || void 0;
1126
389
  }
1127
390
  function emitClientReference(request, reference) {
1128
391
  const existing = request.clientReferenceRows.get(reference.id);
1129
392
  if (existing !== void 0) return existing;
1130
- const assets = serializeClientReferenceAssets(request, reference);
393
+ const assets = serializeAssetResources(request, collectClientReferenceAssets(request, reference));
1131
394
  const value = { id: reference.id };
1132
395
  if (assets.length > 0) value.assets = assets;
1133
396
  const exportName = clientReferenceExportName(reference.id);
@@ -1142,18 +405,16 @@ function emitClientReference(request, reference) {
1142
405
  });
1143
406
  return id;
1144
407
  }
1145
- function serializeClientReferenceAssets(request, reference) {
1146
- return serializeAssetResources(request, collectClientReferenceAssets(request, reference));
1147
- }
1148
408
  function serializeAssetResources(request, value) {
1149
409
  const input = isFigAssetResource(value) ? [value] : Array.isArray(value) ? value : [];
1150
410
  const resources = [];
1151
411
  for (const resource of input) {
1152
412
  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);
413
+ if (assetResourceDestination(resource) === "stream") {
414
+ const key = assetResourceKey(resource);
415
+ if (request.emittedAssetKeys.has(key)) continue;
416
+ request.emittedAssetKeys.add(key);
417
+ }
1157
418
  resources.push(serializeAssetResource(resource));
1158
419
  }
1159
420
  return resources;
@@ -1167,62 +428,91 @@ function collectClientReferenceAssets(request, reference) {
1167
428
  }
1168
429
  function serializeAssetResource(resource) {
1169
430
  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,
431
+ case "stylesheet": {
432
+ const model = {
433
+ href: resource.href,
434
+ kind: resource.kind
435
+ };
436
+ if (resource.crossorigin !== void 0) model.crossorigin = resource.crossorigin;
437
+ if (resource.media !== void 0) model.media = resource.media;
438
+ if (resource.precedence !== void 0) model.precedence = resource.precedence;
439
+ return model;
440
+ }
441
+ case "preload": {
442
+ const model = {
443
+ as: resource.as,
444
+ href: resource.href,
445
+ kind: resource.kind
446
+ };
447
+ if (resource.crossorigin !== void 0) model.crossorigin = resource.crossorigin;
448
+ if (resource.fetchpriority !== void 0) model.fetchpriority = resource.fetchpriority;
449
+ if (resource.type !== void 0) model.type = resource.type;
450
+ return model;
451
+ }
452
+ case "modulepreload": {
453
+ const model = {
454
+ href: resource.href,
455
+ kind: resource.kind
456
+ };
457
+ if (resource.crossorigin !== void 0) model.crossorigin = resource.crossorigin;
458
+ if (resource.fetchpriority !== void 0) model.fetchpriority = resource.fetchpriority;
459
+ return model;
460
+ }
461
+ case "script": {
462
+ const model = {
463
+ kind: resource.kind,
464
+ src: resource.src
465
+ };
466
+ if (resource.async !== void 0) model.async = resource.async;
467
+ if (resource.crossorigin !== void 0) model.crossorigin = resource.crossorigin;
468
+ if (resource.defer !== void 0) model.defer = resource.defer;
469
+ if (resource.module !== void 0) model.module = resource.module;
470
+ return model;
471
+ }
472
+ case "font": {
473
+ const model = {
474
+ href: resource.href,
475
+ kind: resource.kind,
476
+ type: resource.type
477
+ };
478
+ if (resource.crossorigin !== void 0) model.crossorigin = resource.crossorigin;
479
+ if (resource.fetchpriority !== void 0) model.fetchpriority = resource.fetchpriority;
480
+ return model;
481
+ }
482
+ case "preconnect": {
483
+ const model = {
484
+ href: resource.href,
485
+ kind: resource.kind
486
+ };
487
+ if (resource.crossorigin !== void 0) model.crossorigin = resource.crossorigin;
488
+ return model;
489
+ }
490
+ case "title": return {
1203
491
  kind: resource.kind,
1204
- type: resource.type
492
+ value: resource.value
1205
493
  };
1206
- case "preconnect": return {
1207
- ...resource.crossOrigin === void 0 ? {} : { crossOrigin: resource.crossOrigin },
1208
- href: resource.href,
1209
- kind: resource.kind
1210
- };
1211
- case "title":
1212
- case "meta": throw new Error("Head-only resources cannot be serialized into the payload.");
494
+ case "meta": {
495
+ const model = { kind: resource.kind };
496
+ if (resource.charset !== void 0) model.charset = resource.charset;
497
+ if (resource.content !== void 0) model.content = resource.content;
498
+ if (resource["http-equiv"] !== void 0) model["http-equiv"] = resource["http-equiv"];
499
+ if (resource.key !== void 0) model.key = resource.key;
500
+ if (resource.name !== void 0) model.name = resource.name;
501
+ if (resource.property !== void 0) model.property = resource.property;
502
+ return model;
503
+ }
1213
504
  }
1214
- return unsupportedSerializedAssetResource(resource);
1215
- }
1216
- function unsupportedSerializedAssetResource(resource) {
1217
- throw new Error(`Unsupported asset resource kind: ${resource.kind}`);
1218
505
  }
1219
506
  function emitRow(request, row) {
1220
- request.queuedRows.push(request.codec.encodeRow(row));
507
+ request.queuedRows.push(jsonPayloadCodec.encodeRow(row));
1221
508
  flushRows(request);
1222
509
  }
1223
510
  function pingTask(request, task) {
1224
511
  if (request.status === "closed") return;
1225
512
  request.pingedTasks.push(task);
513
+ scheduleWork(request);
514
+ }
515
+ function scheduleWork(request) {
1226
516
  if (request.workScheduled) return;
1227
517
  request.workScheduled = true;
1228
518
  queueMicrotask(() => {
@@ -1232,21 +522,29 @@ function pingTask(request, task) {
1232
522
  }
1233
523
  function flushRows(request) {
1234
524
  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 = [];
525
+ if (request.flushingRows) return;
526
+ request.flushingRows = true;
527
+ try {
528
+ let flushed = 0;
529
+ while (flushed < request.queuedRows.length && !streamFlowBlocked(request.controller)) {
530
+ request.controller.enqueue(request.queuedRows[flushed]);
531
+ flushed += 1;
532
+ }
533
+ if (flushed === request.queuedRows.length) request.queuedRows.length = 0;
534
+ else if (flushed > 0) request.queuedRows = request.queuedRows.slice(flushed);
535
+ } finally {
536
+ request.flushingRows = false;
1239
537
  }
1240
- if (request.pendingTasks === 0) {
538
+ if (request.pendingTasks === 0 && request.queuedRows.length === 0) {
1241
539
  request.status = "closed";
1242
- cleanupPayloadAbortListener(request);
540
+ request.cleanupAbortListener();
1243
541
  request.dataStore.dispose();
1244
542
  request.controller.close();
1245
543
  }
1246
544
  }
1247
545
  function closeWithError(request, error) {
1248
546
  if (request.status === "closed") return;
1249
- cleanupPayloadAbortListener(request);
547
+ request.cleanupAbortListener();
1250
548
  request.status = "closed";
1251
549
  request.dataStore.dispose();
1252
550
  request.allReady.reject(error);
@@ -1255,446 +553,20 @@ function closeWithError(request, error) {
1255
553
  function abortPayloadRequest(request, reason) {
1256
554
  closeWithError(request, reason ?? new PayloadRequestCancelledError());
1257
555
  }
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
556
  function flattenChildArrays(children) {
557
+ if (!children.some(Array.isArray)) return children;
1265
558
  const collected = [];
1266
- for (const child of children) if (Array.isArray(child)) collected.push(...flattenChildArrays(child));
559
+ for (const child of children) if (Array.isArray(child)) for (const nested of flattenChildArrays(child)) collected.push(nested);
1267
560
  else collected.push(child);
1268
561
  return collected;
1269
562
  }
1270
563
  function invalidChildError$1(value) {
1271
564
  return /* @__PURE__ */ new Error(`Invalid Fig child in payload render: ${describeInvalidChild(value)}.`);
1272
565
  }
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
566
  function throwIfAborted(signal) {
1297
567
  if (signal?.aborted) throw new PayloadRequestCancelledError();
1298
568
  }
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
569
  //#endregion
1698
- export { PAYLOAD_BOUNDARY_HEADER, PayloadBoundary, PayloadFetchError, createPayloadResponse, decodePayloadDataEntries, decodePayloadValue, encodePayloadDataEntries, encodePayloadValue, fetchPayload, isPayloadRequestCancelled, jsonPayloadCodec, renderToPayloadStream };
570
+ export { renderToPayloadStream };
1699
571
 
1700
572
  //# sourceMappingURL=payload.js.map