@bgub/fig 0.1.0-alpha.2 → 0.1.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/dist-development/element-B7mCQIMi.js +314 -0
- package/dist-development/element-B7mCQIMi.js.map +1 -0
- package/dist-development/index.js +4 -0
- package/dist-development/internal.js +172 -0
- package/dist-development/internal.js.map +1 -0
- package/dist-development/jsx-runtime.js +23 -0
- package/dist-development/jsx-runtime.js.map +1 -0
- package/dist-development/payload-format-KTNaSI4h.js +366 -0
- package/dist-development/payload-format-KTNaSI4h.js.map +1 -0
- package/dist-development/payload.js +429 -0
- package/dist-development/payload.js.map +1 -0
- package/dist-development/resource-CP2OynG0.js +336 -0
- package/dist-development/resource-CP2OynG0.js.map +1 -0
- package/dist-development/transition-B4XiOWAj.js +750 -0
- package/dist-development/transition-B4XiOWAj.js.map +1 -0
- package/package.json +7 -1
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
import { I as readPromise, f as Fragment, g as createElement, m as ViewTransition, p as Suspense, s as FigElementSymbol } from "./element-B7mCQIMi.js";
|
|
2
|
+
import { b as trackThenable, l as isFigAssetResource, o as assets, t as assetResourceDestination, v as isThenable } from "./resource-CP2OynG0.js";
|
|
3
|
+
import { a as decodePayloadRecord, f as errorFromPayloadValue, h as jsonPayloadCodec, i as decodePayloadDataEntries, p as isPayloadSpecialModel, s as decodePayloadValueTag } from "./payload-format-KTNaSI4h.js";
|
|
4
|
+
//#region src/payload.ts
|
|
5
|
+
const resolverEntries = /* @__PURE__ */ new WeakMap();
|
|
6
|
+
function createPayloadClientReferenceResolver(resolve) {
|
|
7
|
+
const entries = /* @__PURE__ */ new Map();
|
|
8
|
+
const resolver = Object.assign((reference) => resolve(reference), {
|
|
9
|
+
clear: () => entries.clear(),
|
|
10
|
+
delete: (id) => entries.delete(id)
|
|
11
|
+
});
|
|
12
|
+
resolverEntries.set(resolver, entries);
|
|
13
|
+
return resolver;
|
|
14
|
+
}
|
|
15
|
+
const elementGates = /* @__PURE__ */ new WeakMap();
|
|
16
|
+
const elementAssets = /* @__PURE__ */ new WeakMap();
|
|
17
|
+
var PayloadDecodeAbortedError = class extends Error {
|
|
18
|
+
constructor(reason) {
|
|
19
|
+
super("Payload decode aborted.", reason === void 0 ? void 0 : { cause: reason });
|
|
20
|
+
this.name = "PayloadDecodeAbortedError";
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Decode a payload row stream. The returned promise resolves with the
|
|
25
|
+
* decoded root FigNode as soon as the root row decodes (and rejects only
|
|
26
|
+
* when the stream fails before producing a root value, or with the root
|
|
27
|
+
* row's own error); decoding continues in the background, filling outlined
|
|
28
|
+
* holes as their rows arrive. Post-root failures reject the holes they
|
|
29
|
+
* strand and report through `onStreamDone`. Aborting `options.signal`
|
|
30
|
+
* ignores remaining rows and rejects unresolved holes with an internal
|
|
31
|
+
* cancellation reason.
|
|
32
|
+
*/
|
|
33
|
+
function decodePayloadStream(stream, options = {}) {
|
|
34
|
+
return new PayloadStreamDecode(stream, options).value;
|
|
35
|
+
}
|
|
36
|
+
const noop = () => void 0;
|
|
37
|
+
function deferred() {
|
|
38
|
+
let resolve = noop;
|
|
39
|
+
let reject = noop;
|
|
40
|
+
return {
|
|
41
|
+
promise: new Promise((innerResolve, innerReject) => {
|
|
42
|
+
resolve = innerResolve;
|
|
43
|
+
reject = innerReject;
|
|
44
|
+
}),
|
|
45
|
+
reject,
|
|
46
|
+
resolve
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function decodeAssetResources(serialized) {
|
|
50
|
+
if (serialized === void 0) return null;
|
|
51
|
+
const assets = serialized.filter(isFigAssetResource);
|
|
52
|
+
return assets.length === 0 ? null : assets;
|
|
53
|
+
}
|
|
54
|
+
var PayloadStreamDecode = class {
|
|
55
|
+
options;
|
|
56
|
+
value;
|
|
57
|
+
chunks = /* @__PURE__ */ new Map();
|
|
58
|
+
objectRefs = /* @__PURE__ */ new Map();
|
|
59
|
+
rowGates = /* @__PURE__ */ new Map();
|
|
60
|
+
rowAssets = /* @__PURE__ */ new Map();
|
|
61
|
+
clientRowGates = /* @__PURE__ */ new Map();
|
|
62
|
+
clientRowAssets = /* @__PURE__ */ new Map();
|
|
63
|
+
rowDecoder;
|
|
64
|
+
reader = null;
|
|
65
|
+
done = false;
|
|
66
|
+
gateRelease = deferred();
|
|
67
|
+
removeAbortListener = noop;
|
|
68
|
+
decodeChild = (model) => this.decodeModel(model);
|
|
69
|
+
valueRefs = {
|
|
70
|
+
define: (id, create, fill) => this.defineObjectRef(id, create, fill),
|
|
71
|
+
read: (id) => {
|
|
72
|
+
if (!this.objectRefs.has(id)) throw new Error(`Payload referenced unknown object id ${id}.`);
|
|
73
|
+
return this.objectRefs.get(id);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
constructor(stream, options) {
|
|
77
|
+
this.options = options;
|
|
78
|
+
this.rowDecoder = jsonPayloadCodec.createDecoder((row) => this.handleRow(row));
|
|
79
|
+
this.value = this.chunkPromise(this.getChunk(0));
|
|
80
|
+
this.ingest(stream);
|
|
81
|
+
const signal = options.signal;
|
|
82
|
+
if (signal !== void 0) if (signal.aborted) this.abort(signal.reason);
|
|
83
|
+
else {
|
|
84
|
+
const onAbort = () => this.abort(signal.reason);
|
|
85
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
86
|
+
this.removeAbortListener = () => signal.removeEventListener("abort", onAbort);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
abort(reason) {
|
|
90
|
+
if (this.done) return;
|
|
91
|
+
const error = new PayloadDecodeAbortedError(reason);
|
|
92
|
+
this.gateRelease.resolve(void 0);
|
|
93
|
+
this.reader?.cancel(error).catch(noop);
|
|
94
|
+
this.rejectUnresolved(error);
|
|
95
|
+
this.settle({ status: "aborted" });
|
|
96
|
+
}
|
|
97
|
+
async ingest(stream) {
|
|
98
|
+
const reader = stream.getReader();
|
|
99
|
+
this.reader = reader;
|
|
100
|
+
try {
|
|
101
|
+
for (;;) {
|
|
102
|
+
const { done, value } = await reader.read();
|
|
103
|
+
if (this.done) return;
|
|
104
|
+
if (done) break;
|
|
105
|
+
this.rowDecoder.decode(value);
|
|
106
|
+
}
|
|
107
|
+
this.rowDecoder.flush();
|
|
108
|
+
this.finishIngestion();
|
|
109
|
+
} catch (error) {
|
|
110
|
+
if (this.done) return;
|
|
111
|
+
reader.cancel(error).catch(noop);
|
|
112
|
+
this.failIngestion(error);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
finishIngestion() {
|
|
116
|
+
let truncated = false;
|
|
117
|
+
for (const chunk of this.chunks.values()) if (!chunk.arrived) {
|
|
118
|
+
truncated = true;
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
if (truncated) {
|
|
122
|
+
this.failIngestion(/* @__PURE__ */ new Error("Payload stream ended before all referenced rows arrived."));
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
this.settle({ status: "complete" });
|
|
126
|
+
}
|
|
127
|
+
failIngestion(error) {
|
|
128
|
+
if (this.done) return;
|
|
129
|
+
this.rejectUnresolved(error);
|
|
130
|
+
this.settle({
|
|
131
|
+
status: "failed",
|
|
132
|
+
error
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
rejectUnresolved(error) {
|
|
136
|
+
for (const chunk of this.chunks.values()) {
|
|
137
|
+
if (chunk.arrived) continue;
|
|
138
|
+
chunk.arrived = true;
|
|
139
|
+
this.rejectChunk(chunk, error);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
settle(result) {
|
|
143
|
+
if (this.done) return;
|
|
144
|
+
this.done = true;
|
|
145
|
+
this.removeAbortListener();
|
|
146
|
+
try {
|
|
147
|
+
const observed = this.options.onStreamDone?.(result);
|
|
148
|
+
if (isThenable(observed)) Promise.resolve(observed).then(noop, noop);
|
|
149
|
+
} catch {}
|
|
150
|
+
}
|
|
151
|
+
handleRow(row) {
|
|
152
|
+
if (this.done) return;
|
|
153
|
+
switch (row.tag) {
|
|
154
|
+
case "model": {
|
|
155
|
+
const chunk = this.getChunk(row.id);
|
|
156
|
+
let decoded = this.decodeModel(row.value);
|
|
157
|
+
const retainedAssets = this.rowAssets.get(row.id);
|
|
158
|
+
if (retainedAssets !== void 0) {
|
|
159
|
+
this.rowAssets.delete(row.id);
|
|
160
|
+
decoded = assets(retainedAssets, decoded);
|
|
161
|
+
}
|
|
162
|
+
chunk.arrived = true;
|
|
163
|
+
const gates = this.rowGates.get(row.id);
|
|
164
|
+
if (gates === void 0) {
|
|
165
|
+
this.fulfillChunk(chunk, decoded);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
this.rowGates.delete(row.id);
|
|
169
|
+
Promise.race([Promise.all(gates), this.gateRelease.promise]).then(() => this.fulfillChunk(chunk, decoded));
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
case "client": {
|
|
173
|
+
const chunk = this.getChunk(row.id);
|
|
174
|
+
const reference = { id: row.value.id };
|
|
175
|
+
if (row.value.exportName !== void 0) reference.exportName = row.value.exportName;
|
|
176
|
+
if (row.value.ssr === true) reference.ssr = true;
|
|
177
|
+
const assets = decodeAssetResources(row.value.assets);
|
|
178
|
+
if (assets !== null) reference.assets = assets;
|
|
179
|
+
const retainedAssets = this.retainedAssets(assets);
|
|
180
|
+
if (retainedAssets !== null) this.clientRowAssets.set(row.id, retainedAssets);
|
|
181
|
+
const gate = this.prepareAssets(assets);
|
|
182
|
+
if (gate !== null) {
|
|
183
|
+
trackThenable(gate);
|
|
184
|
+
this.clientRowGates.set(row.id, gate);
|
|
185
|
+
gate.then(() => {
|
|
186
|
+
this.clientRowGates.delete(row.id);
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
const component = this.clientReferenceComponent(reference, gate, retainedAssets !== null);
|
|
190
|
+
chunk.arrived = true;
|
|
191
|
+
this.fulfillChunk(chunk, component);
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
case "error": {
|
|
195
|
+
const chunk = this.getChunk(row.id);
|
|
196
|
+
chunk.arrived = true;
|
|
197
|
+
this.rowGates.delete(row.id);
|
|
198
|
+
this.rowAssets.delete(row.id);
|
|
199
|
+
this.rejectChunk(chunk, errorFromPayloadValue(row.value));
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
case "data": {
|
|
203
|
+
const hydrate = this.options.hydrate;
|
|
204
|
+
if (hydrate === void 0) return;
|
|
205
|
+
hydrate(decodePayloadDataEntries(row.value));
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
case "assets": {
|
|
209
|
+
const decodedAssets = decodeAssetResources(row.value);
|
|
210
|
+
const retainedAssets = this.retainedAssets(decodedAssets);
|
|
211
|
+
if (retainedAssets !== null && row.for !== void 0) {
|
|
212
|
+
const retained = this.rowAssets.get(row.for);
|
|
213
|
+
this.rowAssets.set(row.for, retained === void 0 ? retainedAssets : [...retained, ...retainedAssets]);
|
|
214
|
+
}
|
|
215
|
+
const gate = this.prepareAssets(decodedAssets);
|
|
216
|
+
if (gate === null || row.for === void 0) return;
|
|
217
|
+
const gates = this.rowGates.get(row.for);
|
|
218
|
+
if (gates === void 0) this.rowGates.set(row.for, [gate]);
|
|
219
|
+
else gates.push(gate);
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
prepareAssets(assets) {
|
|
225
|
+
const prepare = this.options.prepareAssets;
|
|
226
|
+
if (prepare === void 0 || assets === null) return null;
|
|
227
|
+
const delivery = assets.filter((resource) => assetResourceDestination(resource) === "stream");
|
|
228
|
+
if (delivery.length === 0) return null;
|
|
229
|
+
let result;
|
|
230
|
+
try {
|
|
231
|
+
result = prepare(delivery);
|
|
232
|
+
} catch {
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
if (!isThenable(result)) return null;
|
|
236
|
+
const gate = Promise.resolve(result).then(noop, noop);
|
|
237
|
+
trackThenable(gate);
|
|
238
|
+
return gate;
|
|
239
|
+
}
|
|
240
|
+
retainedAssets(assets) {
|
|
241
|
+
if (assets === null) return null;
|
|
242
|
+
const retained = this.options.retainAssets === true ? assets : assets.filter((resource) => assetResourceDestination(resource) === "head");
|
|
243
|
+
return retained.length === 0 ? null : retained;
|
|
244
|
+
}
|
|
245
|
+
clientReferenceComponent(reference, gate, retainsAssets) {
|
|
246
|
+
const resolve = this.options.resolveClientReference;
|
|
247
|
+
const entries = resolve === void 0 ? void 0 : resolverEntries.get(resolve);
|
|
248
|
+
const existing = entries?.get(reference.id);
|
|
249
|
+
if (existing !== void 0) return existing;
|
|
250
|
+
let resolved;
|
|
251
|
+
try {
|
|
252
|
+
resolved = resolve?.(reference);
|
|
253
|
+
} catch (error) {
|
|
254
|
+
resolved = Promise.reject(error);
|
|
255
|
+
}
|
|
256
|
+
if (resolved === void 0) return function PayloadUnresolvedClientComponent() {
|
|
257
|
+
throw new Error(`Cannot render client reference "${reference.id}" because decodePayloadStream was not configured with a matching resolveClientReference.`);
|
|
258
|
+
};
|
|
259
|
+
if (entries === void 0 && gate === null && !isThenable(resolved) && !retainsAssets) return resolved;
|
|
260
|
+
const component = clientReferenceWrapper(resolved, reference.id);
|
|
261
|
+
entries?.set(reference.id, component);
|
|
262
|
+
return component;
|
|
263
|
+
}
|
|
264
|
+
getChunk(id) {
|
|
265
|
+
const existing = this.chunks.get(id);
|
|
266
|
+
if (existing !== void 0) return existing;
|
|
267
|
+
const chunk = {
|
|
268
|
+
arrived: false,
|
|
269
|
+
deferred: null,
|
|
270
|
+
id,
|
|
271
|
+
promise: null,
|
|
272
|
+
result: { status: "pending" }
|
|
273
|
+
};
|
|
274
|
+
this.chunks.set(id, chunk);
|
|
275
|
+
return chunk;
|
|
276
|
+
}
|
|
277
|
+
chunkPromise(chunk) {
|
|
278
|
+
if (chunk.promise !== null) return chunk.promise;
|
|
279
|
+
if (chunk.result.status === "fulfilled") chunk.promise = Promise.resolve(chunk.result.value);
|
|
280
|
+
else if (chunk.result.status === "rejected") {
|
|
281
|
+
chunk.promise = Promise.reject(chunk.result.error);
|
|
282
|
+
chunk.promise.catch(noop);
|
|
283
|
+
} else {
|
|
284
|
+
chunk.deferred = deferred();
|
|
285
|
+
chunk.promise = chunk.deferred.promise;
|
|
286
|
+
}
|
|
287
|
+
trackThenable(chunk.promise);
|
|
288
|
+
return chunk.promise;
|
|
289
|
+
}
|
|
290
|
+
fulfillChunk(chunk, value) {
|
|
291
|
+
if (chunk.result.status !== "pending") return;
|
|
292
|
+
chunk.result = {
|
|
293
|
+
status: "fulfilled",
|
|
294
|
+
value
|
|
295
|
+
};
|
|
296
|
+
chunk.deferred?.resolve(value);
|
|
297
|
+
}
|
|
298
|
+
rejectChunk(chunk, error) {
|
|
299
|
+
if (chunk.result.status !== "pending") return;
|
|
300
|
+
chunk.result = {
|
|
301
|
+
error,
|
|
302
|
+
status: "rejected"
|
|
303
|
+
};
|
|
304
|
+
if (chunk.deferred !== null) {
|
|
305
|
+
chunk.deferred.reject(error);
|
|
306
|
+
chunk.promise?.catch(noop);
|
|
307
|
+
}
|
|
308
|
+
if (chunk.id !== 0 && !(error instanceof PayloadDecodeAbortedError)) this.observeHoleError(error);
|
|
309
|
+
}
|
|
310
|
+
observeHoleError(error) {
|
|
311
|
+
try {
|
|
312
|
+
const observed = this.options.onHoleError?.(error);
|
|
313
|
+
if (isThenable(observed)) Promise.resolve(observed).then(noop, noop);
|
|
314
|
+
} catch {}
|
|
315
|
+
}
|
|
316
|
+
readChunkForRender(id) {
|
|
317
|
+
const chunk = this.getChunk(id);
|
|
318
|
+
if (chunk.result.status === "rejected") throw chunk.result.error;
|
|
319
|
+
if (chunk.result.status === "pending") return readPromise(this.chunkPromise(chunk));
|
|
320
|
+
return chunk.result.value;
|
|
321
|
+
}
|
|
322
|
+
decodeModel(model) {
|
|
323
|
+
if (model === null) return null;
|
|
324
|
+
if (Array.isArray(model)) return model.map(this.decodeChild);
|
|
325
|
+
if (typeof model !== "object") return model;
|
|
326
|
+
if (isPayloadSpecialModel(model)) return this.decodeSpecialModel(model);
|
|
327
|
+
return decodePayloadRecord(model, this.decodeChild);
|
|
328
|
+
}
|
|
329
|
+
decodeSpecialModel(model) {
|
|
330
|
+
switch (model.$fig) {
|
|
331
|
+
case "element": {
|
|
332
|
+
if (model.id !== void 0) return this.defineObjectRef(model.id, () => ({
|
|
333
|
+
$$typeof: FigElementSymbol,
|
|
334
|
+
key: model.key,
|
|
335
|
+
props: {},
|
|
336
|
+
type: Fragment
|
|
337
|
+
}), (element) => {
|
|
338
|
+
element.type = this.decodeElementType(model.type);
|
|
339
|
+
const props = this.decodeModel(model.props);
|
|
340
|
+
element.props = props;
|
|
341
|
+
this.attachElementDelivery(model.type, props);
|
|
342
|
+
});
|
|
343
|
+
const type = this.decodeElementType(model.type);
|
|
344
|
+
const props = this.decodeModel(model.props);
|
|
345
|
+
if (model.key !== null) props.key = model.key;
|
|
346
|
+
const element = createElement(type, props);
|
|
347
|
+
this.attachElementDelivery(model.type, element.props);
|
|
348
|
+
return element;
|
|
349
|
+
}
|
|
350
|
+
case "client": {
|
|
351
|
+
const chunk = this.chunks.get(model.id);
|
|
352
|
+
if (chunk === void 0 || chunk.result.status !== "fulfilled") throw new Error(`Payload model referenced client row ${model.id} before it arrived.`);
|
|
353
|
+
return chunk.result.value;
|
|
354
|
+
}
|
|
355
|
+
case "fragment": return Fragment;
|
|
356
|
+
case "lazy":
|
|
357
|
+
this.getChunk(model.id);
|
|
358
|
+
return createElement(PayloadStreamHole, {
|
|
359
|
+
decode: this,
|
|
360
|
+
id: model.id
|
|
361
|
+
});
|
|
362
|
+
case "promise": return this.chunkPromise(this.getChunk(model.id));
|
|
363
|
+
case "suspense": return Suspense;
|
|
364
|
+
case "view-transition": return ViewTransition;
|
|
365
|
+
default: return decodePayloadValueTag(model, this.valueRefs, this.decodeChild);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
decodeElementType(type) {
|
|
369
|
+
if (typeof type === "string") return type;
|
|
370
|
+
return this.decodeSpecialModel(type);
|
|
371
|
+
}
|
|
372
|
+
attachElementDelivery(typeModel, props) {
|
|
373
|
+
if (typeof typeModel === "string" || typeModel.$fig !== "client") return;
|
|
374
|
+
const gate = this.clientRowGates.get(typeModel.id);
|
|
375
|
+
if (gate !== void 0) elementGates.set(props, gate);
|
|
376
|
+
const assets = this.clientRowAssets.get(typeModel.id);
|
|
377
|
+
if (assets !== void 0) elementAssets.set(props, assets);
|
|
378
|
+
}
|
|
379
|
+
defineObjectRef(id, create, fill) {
|
|
380
|
+
if (this.objectRefs.has(id)) return this.objectRefs.get(id);
|
|
381
|
+
const value = create();
|
|
382
|
+
this.objectRefs.set(id, value);
|
|
383
|
+
try {
|
|
384
|
+
fill(value);
|
|
385
|
+
return value;
|
|
386
|
+
} catch (error) {
|
|
387
|
+
this.objectRefs.delete(id);
|
|
388
|
+
throw error;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
function PayloadStreamHole(props) {
|
|
393
|
+
return props.decode.readChunkForRender(props.id);
|
|
394
|
+
}
|
|
395
|
+
function clientReferenceWrapper(resolved, referenceId) {
|
|
396
|
+
let render;
|
|
397
|
+
if (!isThenable(resolved)) render = (props) => createElement(resolved, props);
|
|
398
|
+
else {
|
|
399
|
+
const pending = Promise.resolve(resolved);
|
|
400
|
+
trackThenable(pending);
|
|
401
|
+
let type = null;
|
|
402
|
+
render = (props) => {
|
|
403
|
+
if (type === null) type = clientReferenceType(readPromise(pending), referenceId);
|
|
404
|
+
return createElement(type, props);
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
function PayloadClientContent(content) {
|
|
408
|
+
if (content.gate !== void 0) readPromise(content.gate);
|
|
409
|
+
return render(content.props);
|
|
410
|
+
}
|
|
411
|
+
return function PayloadClientComponent(props) {
|
|
412
|
+
return attachElementAssets(props, createElement(PayloadClientContent, {
|
|
413
|
+
gate: elementGates.get(props),
|
|
414
|
+
props
|
|
415
|
+
}));
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
function attachElementAssets(props, node) {
|
|
419
|
+
const resources = elementAssets.get(props);
|
|
420
|
+
return resources === void 0 ? node : assets(resources, node);
|
|
421
|
+
}
|
|
422
|
+
function clientReferenceType(value, id) {
|
|
423
|
+
if (typeof value === "function") return value;
|
|
424
|
+
throw new Error(`Client reference "${id}" did not resolve to a component.`);
|
|
425
|
+
}
|
|
426
|
+
//#endregion
|
|
427
|
+
export { createPayloadClientReferenceResolver, decodePayloadStream };
|
|
428
|
+
|
|
429
|
+
//# sourceMappingURL=payload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payload.js","names":["attachAssets"],"sources":["../src/payload.ts"],"sourcesContent":["import type { FigDataHydrationEntry } from \"./data.ts\";\nimport {\n type AwaitedFigNode,\n createElement,\n type ElementType,\n FigElementSymbol,\n type FigNode,\n Fragment,\n type Key,\n type Props,\n Suspense,\n ViewTransition,\n} from \"./element.ts\";\nimport { readPromise } from \"./hooks.ts\";\nimport {\n decodePayloadDataEntries,\n decodePayloadRecord,\n decodePayloadValueTag,\n errorFromPayloadValue,\n isPayloadSpecialModel,\n jsonPayloadCodec,\n type PayloadDecodeRefs,\n type PayloadElementModel,\n type PayloadModel,\n type PayloadRow,\n type PayloadRowDecoder,\n type PayloadSpecialModel,\n type SerializedAssetResource,\n} from \"./payload-format.ts\";\nimport {\n assetResourceDestination,\n assets as attachAssets,\n type FigAssetResource,\n isFigAssetResource,\n} from \"./resource.ts\";\nimport { isThenable, trackThenable } from \"./thenables.ts\";\n\nexport interface PayloadClientReference {\n assets?: readonly FigAssetResource[];\n exportName?: string;\n id: string;\n ssr?: boolean;\n}\n\nexport type ResolveClientReference = (\n reference: PayloadClientReference,\n) => ElementType<any> | PromiseLike<ElementType<any>> | undefined;\n\n/**\n * A caller-owned stateful resolver: a `ResolveClientReference` that also\n * owns component identity. Decodes given one (as `resolveClientReference`)\n * resolve every client reference to a single resolver-owned wrapper per\n * reference id, so re-decoding a payload updates islands in place instead\n * of remounting them. The caller owns the lifetime: drop entries when their\n * modules change (HMR) or the manifest swaps.\n */\nexport interface PayloadClientReferenceResolver {\n (\n reference: PayloadClientReference,\n ): ElementType<any> | PromiseLike<ElementType<any>> | undefined;\n clear(): void;\n delete(id: string): boolean;\n}\n\nconst resolverEntries = new WeakMap<\n ResolveClientReference,\n Map<string, ElementType<any>>\n>();\n\nexport function createPayloadClientReferenceResolver(\n resolve: ResolveClientReference,\n): PayloadClientReferenceResolver {\n const entries = new Map<string, ElementType<any>>();\n const resolver = Object.assign(\n (reference: PayloadClientReference) => resolve(reference),\n {\n clear: (): void => entries.clear(),\n delete: (id: string): boolean => entries.delete(id),\n },\n );\n resolverEntries.set(resolver, entries);\n return resolver;\n}\n\n// Reveal gates ride the decoded element instances, not the reference\n// wrapper: each decode attaches its own gate to the elements it\n// materializes. Identity lives on the component type; the asset dependency\n// lives on the element — so a mounted island (a previous decode's elements)\n// can never be re-suspended by a newer decode's pending assets, while the\n// newer decode's elements gate on exactly the assets they declared.\n// Elements minted outside a decode from a cached component carry no gate\n// and render ungated: they declared no dependency.\nconst elementGates = new WeakMap<Props, Promise<void>>();\nconst elementAssets = new WeakMap<Props, readonly FigAssetResource[]>();\n\nexport type PayloadDecodeCompletion =\n | { status: \"aborted\" }\n | { status: \"complete\" }\n | { status: \"failed\"; error: unknown };\n\nexport interface PayloadDecodeOptions {\n /**\n * Receives decoded `data` rows for hydration into a data store. The\n * capability itself is expected to be generation-guarded and to ignore\n * entries after its caller loses authority.\n */\n hydrate?: (entries: readonly FigDataHydrationEntry[]) => void;\n /**\n * Observes every outlined hole rejection — an `error` row or a stream\n * failure stranding referenced rows, before or after the root fulfills.\n * Abort cancellation is excluded. Called once per rejected hole; the\n * observer is never awaited and cannot break decoding.\n */\n onHoleError?: (error: unknown) => unknown;\n /**\n * Observes the end of ingestion: called exactly once when the stream\n * settles as complete, failed, or aborted. Post-root failures reject the\n * holes they strand, but a failure with no pending slot is otherwise\n * invisible — this is the hook for reporting it. The callback is never\n * awaited, and its exceptions and rejections are swallowed, so an\n * observer cannot block or break decode teardown.\n */\n onStreamDone?: (result: PayloadDecodeCompletion) => unknown;\n /**\n * Called with delivery asset resources as soon as their rows arrive\n * (e.g. fig-dom's insertAssetResources). A returned promise gates the\n * reveal of only the content that declared a dependency on those assets;\n * gate settlement — fulfilled or rejected — releases the reveal, so a\n * failed asset never blocks content.\n */\n prepareAssets?: (\n assets: readonly FigAssetResource[],\n ) => void | PromiseLike<void>;\n /**\n * Retains delivery asset dependencies as `assets(...)` declarations on\n * their decoded owners. Document metadata is always retained because its\n * owner may mutate the document only when it commits. Server document\n * renderers enable this option to retain delivery assets too.\n */\n retainAssets?: boolean;\n /**\n * Resolves client-reference rows to components. A plain function keeps\n * identity per decode: gated and asynchronously resolved references decode\n * to per-decode wrappers and remount on re-decode. A stateful resolver\n * (created by `createPayloadClientReferenceResolver`) keeps every\n * resolvable reference's identity stable across the decodes sharing it.\n */\n resolveClientReference?: ResolveClientReference;\n signal?: AbortSignal;\n}\n\nclass PayloadDecodeAbortedError extends Error {\n constructor(reason?: unknown) {\n super(\n \"Payload decode aborted.\",\n reason === undefined ? undefined : { cause: reason },\n );\n this.name = \"PayloadDecodeAbortedError\";\n }\n}\n\n/**\n * Decode a payload row stream. The returned promise resolves with the\n * decoded root FigNode as soon as the root row decodes (and rejects only\n * when the stream fails before producing a root value, or with the root\n * row's own error); decoding continues in the background, filling outlined\n * holes as their rows arrive. Post-root failures reject the holes they\n * strand and report through `onStreamDone`. Aborting `options.signal`\n * ignores remaining rows and rejects unresolved holes with an internal\n * cancellation reason.\n */\nexport function decodePayloadStream(\n stream: ReadableStream<Uint8Array>,\n options: PayloadDecodeOptions = {},\n): Promise<AwaitedFigNode> {\n return new PayloadStreamDecode(stream, options).value;\n}\n\ntype DecodeChunk = {\n // The chunk's row has been ingested (decoded or rejected); reveal may still\n // be waiting on an asset gate. Truncation and abort reject only chunks\n // whose rows never arrived.\n arrived: boolean;\n // Materialized lazily: most rows settle synchronously at arrival and are\n // only ever read through result, so eagerly allocating a promise and\n // its controls per row would be waste.\n deferred: Deferred<unknown> | null;\n id: number;\n promise: Promise<unknown> | null;\n result:\n | { status: \"pending\" }\n | { status: \"fulfilled\"; value: unknown }\n | { status: \"rejected\"; error: unknown };\n};\n\ntype DecodingElement = {\n $$typeof: symbol;\n key: Key | null;\n props: Props;\n type: ElementType<any>;\n};\n\nconst noop = (): void => undefined;\n\ninterface Deferred<T> {\n promise: Promise<T>;\n reject: (reason: unknown) => void;\n resolve: (value: T) => void;\n}\n\nfunction deferred<T>(): Deferred<T> {\n let resolve: Deferred<T>[\"resolve\"] = noop;\n let reject: Deferred<T>[\"reject\"] = noop;\n const promise = new Promise<T>((innerResolve, innerReject) => {\n resolve = innerResolve;\n reject = innerReject;\n });\n return { promise, reject, resolve };\n}\n\nfunction decodeAssetResources(\n serialized: readonly SerializedAssetResource[] | undefined,\n): FigAssetResource[] | null {\n if (serialized === undefined) return null;\n const assets = serialized.filter(isFigAssetResource);\n return assets.length === 0 ? null : assets;\n}\n\nclass PayloadStreamDecode {\n readonly value: Promise<AwaitedFigNode>;\n\n private readonly chunks = new Map<number, DecodeChunk>();\n private readonly objectRefs = new Map<number, unknown>();\n // Asset gates registered for a row id (assets rows carry `for`); consumed\n // when that row arrives.\n private readonly rowGates = new Map<number, Array<PromiseLike<void>>>();\n private readonly rowAssets = new Map<number, readonly FigAssetResource[]>();\n // Unsettled reveal gates for arrived client rows, attached per element as\n // models referencing the row materialize (see elementGates).\n private readonly clientRowGates = new Map<number, Promise<void>>();\n private readonly clientRowAssets = new Map<\n number,\n readonly FigAssetResource[]\n >();\n private readonly rowDecoder: PayloadRowDecoder;\n private reader: ReadableStreamDefaultReader<Uint8Array> | null = null;\n private done = false;\n // Resolved on abort so arrived-but-gated chunks reveal instead of waiting\n // for asset gates that may never settle.\n private readonly gateRelease = deferred<void>();\n private removeAbortListener: () => void = noop;\n // One closure and one refs adapter reused across every decoded model, so\n // the per-node decode loop allocates only the decoded values themselves.\n private readonly decodeChild = (model: PayloadModel): unknown =>\n this.decodeModel(model);\n private readonly valueRefs: PayloadDecodeRefs = {\n define: (id, create, fill) => this.defineObjectRef(id, create, fill),\n read: (id) => {\n if (!this.objectRefs.has(id)) {\n throw new Error(`Payload referenced unknown object id ${id}.`);\n }\n return this.objectRefs.get(id);\n },\n };\n\n constructor(\n stream: ReadableStream<Uint8Array>,\n private readonly options: PayloadDecodeOptions,\n ) {\n this.rowDecoder = jsonPayloadCodec.createDecoder((row) =>\n this.handleRow(row),\n );\n this.value = this.chunkPromise(this.getChunk(0)) as Promise<AwaitedFigNode>;\n\n void this.ingest(stream);\n\n const signal = options.signal;\n if (signal !== undefined) {\n if (signal.aborted) {\n this.abort(signal.reason);\n } else {\n const onAbort = () => this.abort(signal.reason);\n signal.addEventListener(\"abort\", onAbort, { once: true });\n this.removeAbortListener = () =>\n signal.removeEventListener(\"abort\", onAbort);\n }\n }\n }\n\n abort(reason?: unknown): void {\n if (this.done) return;\n const error = new PayloadDecodeAbortedError(reason);\n this.gateRelease.resolve(undefined);\n void this.reader?.cancel(error).catch(noop);\n this.rejectUnresolved(error);\n this.settle({ status: \"aborted\" });\n }\n\n private async ingest(stream: ReadableStream<Uint8Array>): Promise<void> {\n const reader = stream.getReader();\n this.reader = reader;\n\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (this.done) return;\n if (done) break;\n this.rowDecoder.decode(value);\n }\n this.rowDecoder.flush();\n this.finishIngestion();\n } catch (error) {\n if (this.done) return;\n void reader.cancel(error).catch(noop);\n this.failIngestion(error);\n }\n }\n\n private finishIngestion(): void {\n let truncated = false;\n for (const chunk of this.chunks.values()) {\n if (!chunk.arrived) {\n truncated = true;\n break;\n }\n }\n if (truncated) {\n // The server closes the stream only after every outlined row has been\n // written, so an unresolved reference at end-of-stream is truncation.\n this.failIngestion(\n new Error(\"Payload stream ended before all referenced rows arrived.\"),\n );\n return;\n }\n this.settle({ status: \"complete\" });\n }\n\n private failIngestion(error: unknown): void {\n if (this.done) return;\n this.rejectUnresolved(error);\n this.settle({ status: \"failed\", error });\n }\n\n private rejectUnresolved(error: unknown): void {\n for (const chunk of this.chunks.values()) {\n if (chunk.arrived) continue;\n chunk.arrived = true;\n this.rejectChunk(chunk, error);\n }\n }\n\n private settle(result: PayloadDecodeCompletion): void {\n if (this.done) return;\n this.done = true;\n this.removeAbortListener();\n try {\n const observed = this.options.onStreamDone?.(result);\n // An async observer's rejection must not surface as an unhandled\n // rejection any more than a sync throw may break teardown.\n if (isThenable(observed)) void Promise.resolve(observed).then(noop, noop);\n } catch {\n // An observer must not be able to break ingestion teardown.\n }\n }\n\n private handleRow(row: PayloadRow): void {\n if (this.done) return;\n\n switch (row.tag) {\n case \"model\": {\n const chunk = this.getChunk(row.id);\n let decoded = this.decodeModel(row.value);\n const retainedAssets = this.rowAssets.get(row.id);\n if (retainedAssets !== undefined) {\n this.rowAssets.delete(row.id);\n decoded = attachAssets(retainedAssets, decoded as FigNode);\n }\n chunk.arrived = true;\n const gates = this.rowGates.get(row.id);\n if (gates === undefined) {\n this.fulfillChunk(chunk, decoded);\n return;\n }\n this.rowGates.delete(row.id);\n void Promise.race([Promise.all(gates), this.gateRelease.promise]).then(\n () => this.fulfillChunk(chunk, decoded),\n );\n return;\n }\n case \"client\": {\n const chunk = this.getChunk(row.id);\n const reference: PayloadClientReference = { id: row.value.id };\n if (row.value.exportName !== undefined) {\n reference.exportName = row.value.exportName;\n }\n if (row.value.ssr === true) reference.ssr = true;\n const assets = decodeAssetResources(row.value.assets);\n if (assets !== null) {\n reference.assets = assets;\n }\n const retainedAssets = this.retainedAssets(assets);\n if (retainedAssets !== null) {\n this.clientRowAssets.set(row.id, retainedAssets);\n }\n const gate = this.prepareAssets(assets);\n if (gate !== null) {\n // Elements referencing this row inherit the gate as they\n // materialize; once it settles there is nothing left to gate.\n // Track it now so a gate that settles before its first render\n // read (e.g. awaited by a router's pre-commit prepare) resolves\n // synchronously instead of suspending for a retry beat.\n trackThenable(gate);\n this.clientRowGates.set(row.id, gate);\n void gate.then(() => {\n this.clientRowGates.delete(row.id);\n });\n }\n const component = this.clientReferenceComponent(\n reference,\n gate,\n retainedAssets !== null,\n );\n chunk.arrived = true;\n this.fulfillChunk(chunk, component);\n return;\n }\n case \"error\": {\n const chunk = this.getChunk(row.id);\n chunk.arrived = true;\n // Reveal-gating a failure is pointless; drop any gates aimed here.\n this.rowGates.delete(row.id);\n this.rowAssets.delete(row.id);\n this.rejectChunk(chunk, errorFromPayloadValue(row.value));\n return;\n }\n case \"data\": {\n const hydrate = this.options.hydrate;\n if (hydrate === undefined) return;\n hydrate(decodePayloadDataEntries(row.value));\n return;\n }\n case \"assets\": {\n const decodedAssets = decodeAssetResources(row.value);\n const retainedAssets = this.retainedAssets(decodedAssets);\n if (retainedAssets !== null && row.for !== undefined) {\n const retained = this.rowAssets.get(row.for);\n this.rowAssets.set(\n row.for,\n retained === undefined\n ? retainedAssets\n : [...retained, ...retainedAssets],\n );\n }\n const gate = this.prepareAssets(decodedAssets);\n if (gate === null || row.for === undefined) return;\n const gates = this.rowGates.get(row.for);\n if (gates === undefined) this.rowGates.set(row.for, [gate]);\n else gates.push(gate);\n return;\n }\n }\n }\n\n // Never rejects and never blocks content on a failed asset: a rejected\n // prepareAssets result (or synchronous throw) settles the gate.\n private prepareAssets(\n assets: readonly FigAssetResource[] | null,\n ): Promise<void> | null {\n const prepare = this.options.prepareAssets;\n if (prepare === undefined || assets === null) return null;\n const delivery = assets.filter(\n (resource) => assetResourceDestination(resource) === \"stream\",\n );\n if (delivery.length === 0) return null;\n\n let result: void | PromiseLike<void>;\n try {\n result = prepare(delivery);\n } catch {\n return null;\n }\n if (!isThenable(result)) return null;\n const gate = Promise.resolve(result).then(noop, noop);\n trackThenable(gate);\n return gate;\n }\n\n private retainedAssets(\n assets: readonly FigAssetResource[] | null,\n ): readonly FigAssetResource[] | null {\n if (assets === null) return null;\n const retained =\n this.options.retainAssets === true\n ? assets\n : assets.filter(\n (resource) => assetResourceDestination(resource) === \"head\",\n );\n return retained.length === 0 ? null : retained;\n }\n\n private clientReferenceComponent(\n reference: PayloadClientReference,\n gate: Promise<void> | null,\n retainsAssets: boolean,\n ): ElementType<any> {\n const resolve = this.options.resolveClientReference;\n const entries =\n resolve === undefined ? undefined : resolverEntries.get(resolve);\n const existing = entries?.get(reference.id);\n if (existing !== undefined) return existing;\n\n let resolved: ReturnType<ResolveClientReference>;\n try {\n resolved = resolve?.(reference);\n } catch (error) {\n resolved = Promise.reject(error);\n }\n\n if (resolved === undefined) {\n // Never cached: a stateful resolver that cannot resolve this\n // reference must not latch the error component for later decodes\n // that can.\n return function PayloadUnresolvedClientComponent(): never {\n throw new Error(\n `Cannot render client reference \"${reference.id}\" because decodePayloadStream was not configured with a matching resolveClientReference.`,\n );\n };\n }\n\n // Without a stateful resolver, an ungated synchronously resolved\n // reference decodes to the component itself, so its element type is\n // stable across decodes whenever the resolver's answer is — re-decoding\n // updates the client component in place and its state survives.\n if (\n entries === undefined &&\n gate === null &&\n !isThenable(resolved) &&\n !retainsAssets\n ) {\n return resolved;\n }\n\n const component = clientReferenceWrapper(resolved, reference.id);\n entries?.set(reference.id, component);\n return component;\n }\n\n private getChunk(id: number): DecodeChunk {\n const existing = this.chunks.get(id);\n if (existing !== undefined) return existing;\n\n const chunk: DecodeChunk = {\n arrived: false,\n deferred: null,\n id,\n promise: null,\n result: { status: \"pending\" },\n };\n this.chunks.set(id, chunk);\n return chunk;\n }\n\n // Materializes (and registers with the thenable registry) on first access:\n // a settled chunk becomes an already-settled promise, a pending one gets\n // live resolvers that fulfillChunk/rejectChunk drive.\n private chunkPromise(chunk: DecodeChunk): Promise<unknown> {\n if (chunk.promise !== null) return chunk.promise;\n\n if (chunk.result.status === \"fulfilled\") {\n chunk.promise = Promise.resolve(chunk.result.value);\n } else if (chunk.result.status === \"rejected\") {\n chunk.promise = Promise.reject(chunk.result.error);\n // Holes nobody awaits must not become unhandled rejections; readers\n // still observe the stored error.\n void chunk.promise.catch(noop);\n } else {\n chunk.deferred = deferred<unknown>();\n chunk.promise = chunk.deferred.promise;\n }\n trackThenable(chunk.promise);\n return chunk.promise;\n }\n\n private fulfillChunk(chunk: DecodeChunk, value: unknown): void {\n if (chunk.result.status !== \"pending\") return;\n chunk.result = { status: \"fulfilled\", value };\n chunk.deferred?.resolve(value);\n }\n\n private rejectChunk(chunk: DecodeChunk, error: unknown): void {\n if (chunk.result.status !== \"pending\") return;\n chunk.result = { error, status: \"rejected\" };\n if (chunk.deferred !== null) {\n chunk.deferred.reject(error);\n void chunk.promise?.catch(noop);\n }\n if (chunk.id !== 0 && !(error instanceof PayloadDecodeAbortedError)) {\n this.observeHoleError(error);\n }\n }\n\n private observeHoleError(error: unknown): void {\n try {\n const observed = this.options.onHoleError?.(error);\n if (isThenable(observed)) void Promise.resolve(observed).then(noop, noop);\n } catch {\n // Error attribution/reporting is observational and cannot break decode.\n }\n }\n\n readChunkForRender(id: number): unknown {\n const chunk = this.getChunk(id);\n if (chunk.result.status === \"rejected\") throw chunk.result.error;\n if (chunk.result.status === \"pending\")\n return readPromise(this.chunkPromise(chunk));\n return chunk.result.value;\n }\n\n private decodeModel(model: PayloadModel): unknown {\n if (model === null) return null;\n if (Array.isArray(model)) return model.map(this.decodeChild);\n if (typeof model !== \"object\") return model;\n\n if (isPayloadSpecialModel(model)) return this.decodeSpecialModel(model);\n\n return decodePayloadRecord(model, this.decodeChild);\n }\n\n private decodeSpecialModel(\n model: PayloadElementModel | PayloadSpecialModel,\n ): unknown {\n switch (model.$fig) {\n case \"element\": {\n if (model.id !== undefined) {\n return this.defineObjectRef(\n model.id,\n (): DecodingElement => ({\n $$typeof: FigElementSymbol,\n key: model.key,\n props: {},\n type: Fragment,\n }),\n (element) => {\n element.type = this.decodeElementType(model.type);\n const props = this.decodeModel(model.props) as Props;\n element.props = props;\n this.attachElementDelivery(model.type, props);\n },\n );\n }\n const type = this.decodeElementType(model.type);\n const props = this.decodeModel(model.props) as Props & {\n key?: Key | null;\n };\n if (model.key !== null) props.key = model.key;\n const element = createElement(type, props);\n // createElement copies props, so the gate keys the element's own\n // props object — the one the component will receive.\n this.attachElementDelivery(model.type, element.props);\n return element;\n }\n case \"client\": {\n const chunk = this.chunks.get(model.id);\n if (chunk === undefined || chunk.result.status !== \"fulfilled\") {\n throw new Error(\n `Payload model referenced client row ${model.id} before it arrived.`,\n );\n }\n return chunk.result.value;\n }\n case \"fragment\":\n return Fragment;\n case \"lazy\":\n // Materialize the hole's chunk now: abort and truncation reject\n // every unresolved chunk, which must include holes that decoded but\n // were never read.\n this.getChunk(model.id);\n return createElement(PayloadStreamHole, { decode: this, id: model.id });\n case \"promise\":\n // Promise props are handed straight to consumers, so the promise\n // (and its thenable-registry tracking) materializes here.\n return this.chunkPromise(this.getChunk(model.id));\n case \"suspense\":\n return Suspense;\n case \"view-transition\":\n return ViewTransition;\n default:\n // Every remaining tag is an ordinary value tag; the shared codec\n // decoder handles it against this decode's request-wide ref store.\n return decodePayloadValueTag(model, this.valueRefs, this.decodeChild);\n }\n }\n\n private decodeElementType(\n type: string | PayloadSpecialModel,\n ): ElementType<any> {\n if (typeof type === \"string\") return type;\n return this.decodeSpecialModel(type) as ElementType<any>;\n }\n\n // A client-referencing element inherits its decode's unsettled row gate;\n // the reference wrapper reads it per element instance at render.\n private attachElementDelivery(\n typeModel: string | PayloadSpecialModel,\n props: Props,\n ): void {\n if (typeof typeModel === \"string\" || typeModel.$fig !== \"client\") return;\n const gate = this.clientRowGates.get(typeModel.id);\n if (gate !== undefined) elementGates.set(props, gate);\n const assets = this.clientRowAssets.get(typeModel.id);\n if (assets !== undefined) elementAssets.set(props, assets);\n }\n\n private defineObjectRef<T>(\n id: number,\n create: () => T,\n fill: (value: T) => void,\n ): T {\n if (this.objectRefs.has(id)) return this.objectRefs.get(id) as T;\n\n const value = create();\n this.objectRefs.set(id, value);\n try {\n fill(value);\n return value;\n } catch (error) {\n this.objectRefs.delete(id);\n throw error;\n }\n }\n}\n\nfunction PayloadStreamHole(props: {\n decode: PayloadStreamDecode;\n id: number;\n}): FigNode {\n return props.decode.readChunkForRender(props.id) as FigNode;\n}\n\n// The one client-reference wrapper: attaches the per-element asset\n// declarations, reads the per-element reveal gate (elementGates), resolves\n// the component, renders it. Owned by a stateful resolver it is reused\n// across decodes, so island identity survives re-decodes whether a given\n// decode arrives gated or not; otherwise it lives for a single decode.\n// Asynchronous resolution starts at row arrival — overlapping the rest of\n// the stream instead of serializing behind it — and latches its type;\n// thenable tracking lets a resolution settled before its first render read\n// synchronously instead of suspending for a retry beat.\n//\n// Assets attach above the suspension points: the outer component always\n// completes, so a renderer delivers the declarations with the segment that\n// contains the reference even while the module load or reveal gate still\n// suspends the content below. The reveal gate and the reference's own\n// props ride explicit content props — createElement clones props objects,\n// so the per-element WeakMaps cannot be read through the inner element.\nfunction clientReferenceWrapper(\n resolved: ElementType<any> | PromiseLike<ElementType<any>>,\n referenceId: string,\n): ElementType<any> {\n let render: (props: Props) => FigNode;\n if (!isThenable(resolved)) {\n render = (props) => createElement(resolved, props);\n } else {\n const pending = Promise.resolve(resolved);\n trackThenable(pending);\n let type: ElementType<any> | null = null;\n render = (props) => {\n if (type === null) {\n type = clientReferenceType(readPromise(pending), referenceId);\n }\n return createElement(type, props);\n };\n }\n\n function PayloadClientContent(content: {\n gate?: Promise<void>;\n props: Props;\n }): FigNode {\n // Suspends while pending; gates never reject (prepareAssets results\n // settle through noop handlers).\n if (content.gate !== undefined) readPromise(content.gate);\n return render(content.props);\n }\n\n return function PayloadClientComponent(props: Props): FigNode {\n return attachElementAssets(\n props,\n createElement(PayloadClientContent, {\n gate: elementGates.get(props),\n props,\n }),\n );\n };\n}\n\nfunction attachElementAssets(props: Props, node: FigNode): FigNode {\n const resources = elementAssets.get(props);\n return resources === undefined ? node : attachAssets(resources, node);\n}\n\nfunction clientReferenceType(value: unknown, id: string): ElementType<any> {\n if (typeof value === \"function\") return value as ElementType<any>;\n throw new Error(`Client reference \"${id}\" did not resolve to a component.`);\n}\n"],"mappings":"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"}
|