@solidjs/web 2.0.0-beta.31 → 2.0.0-beta.33
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/README.md +1 -6
- package/dist/dev.cjs +285 -60
- package/dist/dev.js +267 -57
- package/dist/server.cjs +1148 -176
- package/dist/server.js +1133 -175
- package/dist/web.cjs +285 -60
- package/dist/web.js +267 -57
- package/frames/dist/client.cjs +397 -175
- package/frames/dist/client.dev.cjs +401 -175
- package/frames/dist/client.dev.js +399 -173
- package/frames/dist/client.js +395 -173
- package/frames/dist/server.cjs +1424 -277
- package/frames/dist/server.js +1426 -280
- package/package.json +69 -7
- package/serialization/decode/package.json +20 -0
- package/serialization/dist/decode.cjs +110 -0
- package/serialization/dist/decode.js +104 -0
- package/serialization/dist/serialization.cjs +106 -43
- package/serialization/dist/serialization.js +100 -44
- package/serialization/types/index.d.ts +85 -60
- package/serialization/types/serializer-decode.d.ts +182 -0
- package/serialization/types-cjs/index.d.cts +85 -60
- package/serialization/types-cjs/serializer-decode.d.cts +182 -0
- package/server-functions/dist/client.cjs +131 -98
- package/server-functions/dist/client.js +131 -99
- package/server-functions/dist/rich-args.cjs +11 -0
- package/server-functions/dist/rich-args.js +9 -0
- package/server-functions/dist/server.cjs +367 -194
- package/server-functions/dist/server.dev.cjs +1077 -0
- package/server-functions/dist/server.dev.js +1045 -0
- package/server-functions/dist/server.js +365 -195
- package/server-functions/package.json +10 -0
- package/server-functions/rich-args/package.json +20 -0
- package/storage/types/index.d.ts +1 -1
- package/storage/types-cjs/index.d.cts +1 -1
- package/types/client.d.ts +149 -6
- package/types/cookies.d.ts +93 -0
- package/types/core.d.ts +4 -2
- package/types/frames/client.d.ts +15 -1
- package/types/frames/frame-client.d.ts +63 -7
- package/types/frames/frame-sink.d.ts +26 -3
- package/types/frames/frame-transport.d.ts +40 -8
- package/types/frames/serializer.d.ts +85 -60
- package/types/frames/server.d.ts +22 -0
- package/types/index.d.ts +2 -3
- package/types/response.d.ts +45 -0
- package/types/serializer-decode.d.ts +182 -0
- package/types/serializer.d.ts +85 -60
- package/types/server-functions/client.d.ts +2 -1
- package/types/server-functions/rich-args.d.ts +10 -0
- package/types/server-functions/server.d.ts +99 -1
- package/types/server-functions/shared.d.ts +79 -1
- package/types/server-mock.d.ts +171 -59
- package/types/server.d.ts +209 -37
- package/types-cjs/client.d.cts +149 -6
- package/types-cjs/cookies.d.cts +93 -0
- package/types-cjs/core.d.cts +4 -2
- package/types-cjs/frames/client.d.cts +15 -1
- package/types-cjs/frames/frame-client.d.cts +63 -7
- package/types-cjs/frames/frame-sink.d.cts +26 -3
- package/types-cjs/frames/frame-transport.d.cts +40 -8
- package/types-cjs/frames/serializer.d.cts +85 -60
- package/types-cjs/frames/server.d.cts +22 -0
- package/types-cjs/index.d.cts +2 -3
- package/types-cjs/response.d.cts +45 -0
- package/types-cjs/serializer-decode.d.cts +182 -0
- package/types-cjs/serializer.d.cts +85 -60
- package/types-cjs/server-functions/client.d.cts +2 -1
- package/types-cjs/server-functions/rich-args.d.cts +10 -0
- package/types-cjs/server-functions/server.d.cts +99 -1
- package/types-cjs/server-functions/shared.d.cts +79 -1
- package/types-cjs/server-mock.d.cts +171 -59
- package/types-cjs/server.d.cts +209 -37
package/frames/dist/server.js
CHANGED
|
@@ -1,20 +1,130 @@
|
|
|
1
|
-
import { runWithOwner, createOwner, sharedConfig, createRoot, ssrHandleError, getOwner, NoHydration, runInServerComponentScope, Hydration } from 'solid-js';
|
|
2
|
-
import {
|
|
1
|
+
import { createMemo, runWithOwner, createOwner, sharedConfig, createRoot, ssrHandleError, getOwner, inServerComponentScope, creationStamp, NoHydration, runInServerComponentScope, Hydration, getProjectionTrace } from 'solid-js';
|
|
2
|
+
import { Feature, toCrossJSONStream, Serializer, getCrossReferenceHeader } from 'seroval';
|
|
3
3
|
import { AbortSignalPlugin, CustomEventPlugin, DOMExceptionPlugin, EventPlugin, FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLSearchParamsPlugin, URLPlugin } from 'seroval-plugins/web';
|
|
4
4
|
|
|
5
|
+
const STATE = Symbol.for("dom-expressions.container-trace-state");
|
|
6
|
+
const state = globalThis[STATE] || (globalThis[STATE] = {
|
|
7
|
+
materialized: new WeakMap(),
|
|
8
|
+
materializedValues: new WeakSet()
|
|
9
|
+
});
|
|
10
|
+
function setContainerTraceResolver(fn) {
|
|
11
|
+
state.resolveTrace = fn;
|
|
12
|
+
}
|
|
13
|
+
function isContainerTraced(value) {
|
|
14
|
+
const resolve = state.resolveTrace;
|
|
15
|
+
return !!(resolve && value && typeof value === "object" && resolve(value));
|
|
16
|
+
}
|
|
17
|
+
const TRACE = Symbol.for("dom-expressions.container-trace");
|
|
18
|
+
function envelopeContainerTraces(value) {
|
|
19
|
+
if (!state.resolveTrace || value == null || typeof value !== "object") return value;
|
|
20
|
+
const trace = state.resolveTrace(value);
|
|
21
|
+
if (trace) return {
|
|
22
|
+
[TRACE]: trace
|
|
23
|
+
};
|
|
24
|
+
if (Array.isArray(value)) {
|
|
25
|
+
let out = value;
|
|
26
|
+
for (let i = 0; i < value.length; i++) {
|
|
27
|
+
const next = envelopeContainerTraces(value[i]);
|
|
28
|
+
if (next !== value[i]) {
|
|
29
|
+
if (out === value) out = value.slice();
|
|
30
|
+
out[i] = next;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return out;
|
|
34
|
+
}
|
|
35
|
+
if (Object.getPrototypeOf(value) === Object.prototype) {
|
|
36
|
+
let out = value;
|
|
37
|
+
for (const key of Object.keys(value)) {
|
|
38
|
+
const next = envelopeContainerTraces(value[key]);
|
|
39
|
+
if (next !== value[key]) {
|
|
40
|
+
if (out === value) out = {
|
|
41
|
+
...value
|
|
42
|
+
};
|
|
43
|
+
out[key] = next;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return out;
|
|
47
|
+
}
|
|
48
|
+
return value;
|
|
49
|
+
}
|
|
50
|
+
function materialize(marker) {
|
|
51
|
+
let value = state.materialized.get(marker.$tr);
|
|
52
|
+
if (value === undefined) {
|
|
53
|
+
value = state.materializeTrace(marker);
|
|
54
|
+
state.materialized.set(marker.$tr, value);
|
|
55
|
+
if (value !== null && typeof value === "object") state.materializedValues.add(value);
|
|
56
|
+
}
|
|
57
|
+
return value;
|
|
58
|
+
}
|
|
59
|
+
function parseTrace(value, ctx) {
|
|
60
|
+
const trace = value[TRACE];
|
|
61
|
+
return {
|
|
62
|
+
a: trace.array ? 1 : 0,
|
|
63
|
+
i: ctx.parse(trace.subscribe())
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
const ContainerTracePlugin = {
|
|
67
|
+
tag: "dom-expressions/container-trace",
|
|
68
|
+
test(value) {
|
|
69
|
+
return value != null && typeof value === "object" && TRACE in value;
|
|
70
|
+
},
|
|
71
|
+
parse: {
|
|
72
|
+
sync() {
|
|
73
|
+
throw new Error("A reactive container can only be serialized by a streaming serializer.");
|
|
74
|
+
},
|
|
75
|
+
async async(value, ctx) {
|
|
76
|
+
const trace = value[TRACE];
|
|
77
|
+
return {
|
|
78
|
+
a: trace.array ? 1 : 0,
|
|
79
|
+
i: await ctx.parse(trace.subscribe())
|
|
80
|
+
};
|
|
81
|
+
},
|
|
82
|
+
stream: parseTrace
|
|
83
|
+
},
|
|
84
|
+
serialize(node, ctx) {
|
|
85
|
+
return "{$tr:" + ctx.serialize(node.i) + ",$ta:" + node.a + "}";
|
|
86
|
+
},
|
|
87
|
+
deserialize(node, ctx) {
|
|
88
|
+
const iterable = ctx.deserialize(node.i);
|
|
89
|
+
const marker = {
|
|
90
|
+
$tr: iterable,
|
|
91
|
+
$ta: node.a
|
|
92
|
+
};
|
|
93
|
+
return state.materializeTrace ? materialize(marker) : marker;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
5
97
|
const runWithHydrationScope = (id, fn) => runWithOwner(createOwner({
|
|
6
98
|
id
|
|
7
99
|
}), fn);
|
|
100
|
+
const ssrAsyncValue = value => createMemo(() => value, {
|
|
101
|
+
serialize: false
|
|
102
|
+
});
|
|
8
103
|
|
|
9
|
-
const DEFAULT_DISABLED_FEATURES = Feature.AggregateError | Feature.BigIntTypedArray;
|
|
10
|
-
const serializeOnlyDisabledFeatures = () => process.env.NODE_ENV === "development" ? 0 : Feature.ErrorPrototypeStack;
|
|
11
|
-
const HYDRATION_GLOBAL = "_$HY.r";
|
|
12
104
|
const DEFAULT_WEB_PLUGINS = Object.freeze([AbortSignalPlugin,
|
|
13
105
|
CustomEventPlugin, DOMExceptionPlugin, EventPlugin,
|
|
14
|
-
FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLSearchParamsPlugin, URLPlugin
|
|
106
|
+
FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLSearchParamsPlugin, URLPlugin,
|
|
107
|
+
ContainerTracePlugin]);
|
|
15
108
|
function resolveSerializerPlugins(customPlugins) {
|
|
16
109
|
return customPlugins ? [...customPlugins, ...DEFAULT_WEB_PLUGINS] : [...DEFAULT_WEB_PLUGINS];
|
|
17
110
|
}
|
|
111
|
+
const JSON_CODEC_DISABLED_FEATURES = Feature.RegExp;
|
|
112
|
+
const JSON_CODEC_DEPTH_LIMIT = 64;
|
|
113
|
+
function resolveCodecOptions({
|
|
114
|
+
plugins,
|
|
115
|
+
disabledFeatures,
|
|
116
|
+
depthLimit
|
|
117
|
+
} = {}) {
|
|
118
|
+
return {
|
|
119
|
+
plugins: resolveSerializerPlugins(plugins),
|
|
120
|
+
disabledFeatures: disabledFeatures === undefined ? JSON_CODEC_DISABLED_FEATURES : disabledFeatures,
|
|
121
|
+
depthLimit: depthLimit === undefined ? JSON_CODEC_DEPTH_LIMIT : depthLimit
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const DEFAULT_DISABLED_FEATURES = Feature.AggregateError | Feature.BigIntTypedArray;
|
|
126
|
+
const serializeOnlyDisabledFeatures = () => process.env.NODE_ENV === "development" ? 0 : Feature.ErrorPrototypeStack;
|
|
127
|
+
const HYDRATION_GLOBAL = "_$HY.r";
|
|
18
128
|
function createSerializer(options) {
|
|
19
129
|
return new Serializer({
|
|
20
130
|
...options,
|
|
@@ -41,34 +151,6 @@ function createHydrationSerializer({
|
|
|
41
151
|
function getLocalHeaderScript(id) {
|
|
42
152
|
return getCrossReferenceHeader(id) + ";";
|
|
43
153
|
}
|
|
44
|
-
const JSON_CODEC_DISABLED_FEATURES = Feature.RegExp;
|
|
45
|
-
const JSON_CODEC_DEPTH_LIMIT = 64;
|
|
46
|
-
function resolveCodecOptions({
|
|
47
|
-
plugins,
|
|
48
|
-
disabledFeatures,
|
|
49
|
-
depthLimit
|
|
50
|
-
} = {}) {
|
|
51
|
-
return {
|
|
52
|
-
plugins: resolveSerializerPlugins(plugins),
|
|
53
|
-
disabledFeatures: disabledFeatures === undefined ? JSON_CODEC_DISABLED_FEATURES : disabledFeatures,
|
|
54
|
-
depthLimit: depthLimit === undefined ? JSON_CODEC_DEPTH_LIMIT : depthLimit
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
function serializeJSON(value, {
|
|
58
|
-
onParse,
|
|
59
|
-
onDone,
|
|
60
|
-
onError,
|
|
61
|
-
...codecOptions
|
|
62
|
-
}) {
|
|
63
|
-
const resolved = resolveCodecOptions(codecOptions);
|
|
64
|
-
return toCrossJSONStream(value, {
|
|
65
|
-
onParse,
|
|
66
|
-
onDone,
|
|
67
|
-
onError,
|
|
68
|
-
...resolved,
|
|
69
|
-
disabledFeatures: resolved.disabledFeatures | serializeOnlyDisabledFeatures()
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
154
|
function createJSONSerializer({
|
|
73
155
|
onData,
|
|
74
156
|
onDone,
|
|
@@ -135,6 +217,146 @@ function createJSONSerializer({
|
|
|
135
217
|
};
|
|
136
218
|
}
|
|
137
219
|
|
|
220
|
+
const ENVELOPE = Symbol.for("solid.ResponseEnvelope");
|
|
221
|
+
function isResponseEnvelope(value) {
|
|
222
|
+
return !!(value && typeof value === "object" && value[ENVELOPE]);
|
|
223
|
+
}
|
|
224
|
+
const REVALIDATE_HEADER = "X-Revalidate";
|
|
225
|
+
|
|
226
|
+
function frameAddress(id, args) {
|
|
227
|
+
return args && args.length ? id + ":" + hashArguments(args) : id;
|
|
228
|
+
}
|
|
229
|
+
function hashArguments(args) {
|
|
230
|
+
let hash = 0;
|
|
231
|
+
const text = stableString(args);
|
|
232
|
+
for (let i = 0; i < text.length; i++) {
|
|
233
|
+
hash = (hash << 5) - hash + text.charCodeAt(i);
|
|
234
|
+
hash |= 0;
|
|
235
|
+
}
|
|
236
|
+
return (hash >>> 0).toString(36);
|
|
237
|
+
}
|
|
238
|
+
function stableString(value, seen) {
|
|
239
|
+
if (value === null || typeof value !== "object") {
|
|
240
|
+
return typeof value === "bigint" ? value + "n" : String(value);
|
|
241
|
+
}
|
|
242
|
+
if (value instanceof Date) return "Date:" + value.getTime();
|
|
243
|
+
seen || (seen = new Set());
|
|
244
|
+
if (seen.has(value)) return "~";
|
|
245
|
+
seen.add(value);
|
|
246
|
+
if (value instanceof Map) {
|
|
247
|
+
const entries = [];
|
|
248
|
+
for (const [k, v] of value) {
|
|
249
|
+
entries.push(stableString(k, seen) + "=>" + stableString(v, seen));
|
|
250
|
+
}
|
|
251
|
+
return "Map{" + entries.sort().join(",") + "}";
|
|
252
|
+
}
|
|
253
|
+
if (value instanceof Set) {
|
|
254
|
+
const members = [];
|
|
255
|
+
for (const v of value) members.push(stableString(v, seen));
|
|
256
|
+
return "Set{" + members.sort().join(",") + "}";
|
|
257
|
+
}
|
|
258
|
+
if (Array.isArray(value)) {
|
|
259
|
+
let out = "[";
|
|
260
|
+
for (let i = 0; i < value.length; i++) out += (i ? "," : "") + stableString(value[i], seen);
|
|
261
|
+
return out + "]";
|
|
262
|
+
}
|
|
263
|
+
const keys = Object.keys(value).sort();
|
|
264
|
+
let out = "{";
|
|
265
|
+
for (let i = 0; i < keys.length; i++) {
|
|
266
|
+
out += (i ? "," : "") + keys[i] + ":" + stableString(value[keys[i]], seen);
|
|
267
|
+
}
|
|
268
|
+
return out + "}";
|
|
269
|
+
}
|
|
270
|
+
const ERROR_HEADER = "X-Server-Function-Error";
|
|
271
|
+
const BODY_FORMAT_HEADER = "X-Server-Function-Format";
|
|
272
|
+
const SINGLE_FLIGHT_HEADER = "X-Single-Flight";
|
|
273
|
+
function createChunk(data) {
|
|
274
|
+
const encoder = new TextEncoder();
|
|
275
|
+
const encodeData = encoder.encode(data);
|
|
276
|
+
const bytes = encodeData.length;
|
|
277
|
+
const chunk = new Uint8Array(12 + bytes);
|
|
278
|
+
chunk.set(encoder.encode(`;0x${bytes.toString(16).padStart(8, "0")};`));
|
|
279
|
+
chunk.set(encodeData, 12);
|
|
280
|
+
return chunk;
|
|
281
|
+
}
|
|
282
|
+
class ChunkReader {
|
|
283
|
+
constructor(stream) {
|
|
284
|
+
this.reader = stream.getReader();
|
|
285
|
+
this.buffer = new Uint8Array(0);
|
|
286
|
+
this.done = false;
|
|
287
|
+
}
|
|
288
|
+
async readChunk() {
|
|
289
|
+
const chunk = await this.reader.read();
|
|
290
|
+
if (!chunk.done) {
|
|
291
|
+
const newBuffer = new Uint8Array(this.buffer.length + chunk.value.length);
|
|
292
|
+
newBuffer.set(this.buffer);
|
|
293
|
+
newBuffer.set(chunk.value, this.buffer.length);
|
|
294
|
+
this.buffer = newBuffer;
|
|
295
|
+
} else {
|
|
296
|
+
this.done = true;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
async next() {
|
|
300
|
+
while (this.buffer.length < 12) {
|
|
301
|
+
if (this.done) {
|
|
302
|
+
if (this.buffer.length === 0) return {
|
|
303
|
+
done: true,
|
|
304
|
+
value: undefined
|
|
305
|
+
};
|
|
306
|
+
throw new Error("Malformed server function stream.");
|
|
307
|
+
}
|
|
308
|
+
await this.readChunk();
|
|
309
|
+
}
|
|
310
|
+
const decoder = new TextDecoder();
|
|
311
|
+
const bytes = Number.parseInt(decoder.decode(this.buffer.subarray(1, 11)), 16);
|
|
312
|
+
if (Number.isNaN(bytes)) {
|
|
313
|
+
throw new Error("Malformed server function stream.");
|
|
314
|
+
}
|
|
315
|
+
while (bytes > this.buffer.length - 12) {
|
|
316
|
+
if (this.done) {
|
|
317
|
+
throw new Error("Malformed server function stream.");
|
|
318
|
+
}
|
|
319
|
+
await this.readChunk();
|
|
320
|
+
}
|
|
321
|
+
const partial = decoder.decode(this.buffer.subarray(12, 12 + bytes));
|
|
322
|
+
this.buffer = this.buffer.subarray(12 + bytes);
|
|
323
|
+
return {
|
|
324
|
+
done: false,
|
|
325
|
+
value: partial
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
async drain(interpret) {
|
|
329
|
+
while (true) {
|
|
330
|
+
const result = await this.next();
|
|
331
|
+
if (result.done) {
|
|
332
|
+
break;
|
|
333
|
+
}
|
|
334
|
+
interpret(result.value);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
function serializeStream(value, codecOptions) {
|
|
339
|
+
return new ReadableStream({
|
|
340
|
+
async start(controller) {
|
|
341
|
+
const {
|
|
342
|
+
serializeJSON
|
|
343
|
+
} = await import('@solidjs/web/serialization');
|
|
344
|
+
serializeJSON(value, {
|
|
345
|
+
...codecOptions,
|
|
346
|
+
onParse(node) {
|
|
347
|
+
controller.enqueue(createChunk(JSON.stringify(node)));
|
|
348
|
+
},
|
|
349
|
+
onDone() {
|
|
350
|
+
controller.close();
|
|
351
|
+
},
|
|
352
|
+
onError(error) {
|
|
353
|
+
controller.error(error);
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
|
|
138
360
|
const HEAD_ELIGIBLE_TAGS = new Set(["title", "meta", "link", "style", "script", "base"]);
|
|
139
361
|
const HEAD_ATTR_NAME = /^[a-zA-Z_][a-zA-Z0-9_:.-]*$/;
|
|
140
362
|
const RESOURCE_LINK_RELS = new Set(["preload", "modulepreload", "prefetch", "preconnect", "dns-prefetch", "stylesheet"]);
|
|
@@ -205,7 +427,6 @@ function resolveHead(groups) {
|
|
|
205
427
|
}
|
|
206
428
|
for (const [identity, tags] of byIdentity) {
|
|
207
429
|
if (identity === "title") {
|
|
208
|
-
if (tags.length > 1) console.warn("Multiple <title> tags in one head group; the last one wins.");
|
|
209
430
|
winners.set(identity, {
|
|
210
431
|
seq: group.seq,
|
|
211
432
|
tags: [tags[tags.length - 1]]
|
|
@@ -375,7 +596,8 @@ function createHeadRegistry() {
|
|
|
375
596
|
resources: new Set(),
|
|
376
597
|
eagerHtml: "",
|
|
377
598
|
flushed: null,
|
|
378
|
-
shellFlushed: false
|
|
599
|
+
shellFlushed: false,
|
|
600
|
+
parkedResources: []
|
|
379
601
|
};
|
|
380
602
|
}
|
|
381
603
|
function registerHeadTags(registry, context, tracking, emitResource, nonce, tags) {
|
|
@@ -389,14 +611,24 @@ function registerHeadTags(registry, context, tracking, emitResource, nonce, tags
|
|
|
389
611
|
return;
|
|
390
612
|
}
|
|
391
613
|
if (!Array.isArray(tags)) tags = [tags];
|
|
614
|
+
const probe = sharedConfig.context && sharedConfig.context._loadingPhase;
|
|
392
615
|
let replaceable = null;
|
|
393
616
|
for (let i = 0; i < tags.length; i++) {
|
|
394
617
|
const desc = tags[i];
|
|
395
618
|
if (!desc || !HEAD_ELIGIBLE_TAGS.has(desc.tag)) {
|
|
396
|
-
console.warn(`useHead: ignoring non-head tag`, desc);
|
|
397
619
|
continue;
|
|
398
620
|
}
|
|
399
621
|
const cls = classifyHeadTag(desc);
|
|
622
|
+
if (probe && !cls.resource) {
|
|
623
|
+
try {
|
|
624
|
+
evalHeadProps(desc.props || {}, cls.rel !== undefined ? {
|
|
625
|
+
rel: cls.rel
|
|
626
|
+
} : undefined);
|
|
627
|
+
evalHeadValue(desc.key);
|
|
628
|
+
} catch (err) {
|
|
629
|
+
if (ssrHandleError(err)) throw err;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
400
632
|
if (cls.resource) {
|
|
401
633
|
emitHeadResource(registry, context, tracking, emitResource, nonce, desc, cls.rel);
|
|
402
634
|
} else {
|
|
@@ -413,6 +645,51 @@ function registerHeadTags(registry, context, tracking, emitResource, nonce, tags
|
|
|
413
645
|
tags: replaceable
|
|
414
646
|
});
|
|
415
647
|
}
|
|
648
|
+
function headShellReady(registry, block) {
|
|
649
|
+
let ready = true;
|
|
650
|
+
const pends = err => {
|
|
651
|
+
const source = ssrHandleError(err, true);
|
|
652
|
+
if (!source) return false;
|
|
653
|
+
block(source);
|
|
654
|
+
ready = false;
|
|
655
|
+
return true;
|
|
656
|
+
};
|
|
657
|
+
const parked = registry.parkedResources;
|
|
658
|
+
for (let i = parked.length - 1; i >= 0; i--) {
|
|
659
|
+
const {
|
|
660
|
+
desc,
|
|
661
|
+
rel,
|
|
662
|
+
emit
|
|
663
|
+
} = parked[i];
|
|
664
|
+
try {
|
|
665
|
+
evalHeadProps(desc.props || {}, rel !== undefined ? {
|
|
666
|
+
rel
|
|
667
|
+
} : undefined);
|
|
668
|
+
} catch (err) {
|
|
669
|
+
if (pends(err)) continue;
|
|
670
|
+
parked.splice(i, 1);
|
|
671
|
+
continue;
|
|
672
|
+
}
|
|
673
|
+
parked.splice(i, 1);
|
|
674
|
+
emit();
|
|
675
|
+
}
|
|
676
|
+
for (let i = 0; i < registry.pending.length; i++) {
|
|
677
|
+
const reg = registry.pending[i];
|
|
678
|
+
if (reg.boundary !== "" || reg.list) continue;
|
|
679
|
+
for (let j = 0; j < reg.tags.length; j++) {
|
|
680
|
+
const desc = reg.tags[j];
|
|
681
|
+
try {
|
|
682
|
+
evalHeadProps(desc.props || {}, desc.rel !== undefined ? {
|
|
683
|
+
rel: desc.rel
|
|
684
|
+
} : undefined);
|
|
685
|
+
evalHeadValue(desc.key);
|
|
686
|
+
} catch (err) {
|
|
687
|
+
pends(err);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
return ready;
|
|
692
|
+
}
|
|
416
693
|
function emitHeadResource(registry, context, tracking, emitResource, nonce, desc, rel) {
|
|
417
694
|
let props;
|
|
418
695
|
try {
|
|
@@ -420,7 +697,16 @@ function emitHeadResource(registry, context, tracking, emitResource, nonce, desc
|
|
|
420
697
|
rel
|
|
421
698
|
} : undefined);
|
|
422
699
|
} catch (err) {
|
|
423
|
-
|
|
700
|
+
const loadingPhase = sharedConfig.context && sharedConfig.context._loadingPhase;
|
|
701
|
+
if (loadingPhase && ssrHandleError(err)) throw err;
|
|
702
|
+
if (!loadingPhase && !context._currentBoundaryId && !registry.shellFlushed && typeof context.block === "function" && ssrHandleError(err, true)) {
|
|
703
|
+
registry.parkedResources.push({
|
|
704
|
+
desc,
|
|
705
|
+
rel,
|
|
706
|
+
emit: () => emitHeadResource(registry, context, tracking, emitResource, nonce, desc, rel)
|
|
707
|
+
});
|
|
708
|
+
return;
|
|
709
|
+
}
|
|
424
710
|
return;
|
|
425
711
|
}
|
|
426
712
|
const identity = resourceIdentity(desc.tag, props);
|
|
@@ -482,7 +768,6 @@ function commitHeadBoundary(registry, boundary, isPendingFragment) {
|
|
|
482
768
|
try {
|
|
483
769
|
resolved = reg.list();
|
|
484
770
|
} catch (err) {
|
|
485
|
-
console.warn(`useHead: error evaluating head group membership`, err);
|
|
486
771
|
continue;
|
|
487
772
|
}
|
|
488
773
|
if (!Array.isArray(resolved)) resolved = [resolved];
|
|
@@ -490,7 +775,6 @@ function commitHeadBoundary(registry, boundary, isPendingFragment) {
|
|
|
490
775
|
for (let j = 0; j < resolved.length; j++) {
|
|
491
776
|
const desc = resolved[j];
|
|
492
777
|
if (!desc || !HEAD_ELIGIBLE_TAGS.has(desc.tag)) {
|
|
493
|
-
console.warn(`useHead: ignoring non-head tag`, desc);
|
|
494
778
|
continue;
|
|
495
779
|
}
|
|
496
780
|
const cls = classifyHeadTag(desc);
|
|
@@ -516,12 +800,10 @@ function commitHeadBoundary(registry, boundary, isPendingFragment) {
|
|
|
516
800
|
} : undefined);
|
|
517
801
|
key = evalHeadValue(desc.key);
|
|
518
802
|
} catch (err) {
|
|
519
|
-
console.warn(`useHead: error evaluating tag props`, err);
|
|
520
803
|
continue;
|
|
521
804
|
}
|
|
522
805
|
const identity = replaceableIdentity(desc.tag, props, key, "u:" + registry.uniq++);
|
|
523
806
|
if ((identity === "base" || identity === "charset") && registry.shellFlushed) {
|
|
524
|
-
console.warn(`useHead: <${desc.tag}> (${identity}) registered after shell flush is ignored`);
|
|
525
807
|
continue;
|
|
526
808
|
}
|
|
527
809
|
tags.push({
|
|
@@ -603,7 +885,6 @@ function flushHeadFragment(registry, boundary) {
|
|
|
603
885
|
for (const name in t.props) {
|
|
604
886
|
if (name === "children" || name === "ref" || name.slice(0, 2) === "on") continue;
|
|
605
887
|
if (!HEAD_ATTR_NAME.test(name)) {
|
|
606
|
-
console.warn(`useHead: ignoring invalid attribute name "${name}"`);
|
|
607
888
|
continue;
|
|
608
889
|
}
|
|
609
890
|
const v = t.props[name];
|
|
@@ -621,7 +902,6 @@ function renderHeadAttrHtml(props) {
|
|
|
621
902
|
for (const name in props) {
|
|
622
903
|
if (name === "children" || name === "ref" || name.slice(0, 2) === "on") continue;
|
|
623
904
|
if (!HEAD_ATTR_NAME.test(name)) {
|
|
624
|
-
console.warn(`useHead: ignoring invalid attribute name "${name}"`);
|
|
625
905
|
continue;
|
|
626
906
|
}
|
|
627
907
|
const v = props[name];
|
|
@@ -681,6 +961,12 @@ function renderToStream(code, options = {}) {
|
|
|
681
961
|
d();
|
|
682
962
|
}
|
|
683
963
|
};
|
|
964
|
+
const failRender = err => {
|
|
965
|
+
try {
|
|
966
|
+
options.onError ? options.onError(err) : console.error(err);
|
|
967
|
+
} catch (_) {}
|
|
968
|
+
abandon();
|
|
969
|
+
};
|
|
684
970
|
const guardSink = w => ({
|
|
685
971
|
write(payload) {
|
|
686
972
|
if (dead) return;
|
|
@@ -762,7 +1048,7 @@ function renderToStream(code, options = {}) {
|
|
|
762
1048
|
}
|
|
763
1049
|
},
|
|
764
1050
|
shell(shellHtml, meta) {
|
|
765
|
-
buffer.write(assembleDocument(shellHtml, meta.
|
|
1051
|
+
buffer.write(assembleDocument(shellHtml, meta.preloads, meta.inlineStyles, meta.tasks.length ? meta.tasks : "", nonce, meta.head, onHead));
|
|
766
1052
|
},
|
|
767
1053
|
...options.sink
|
|
768
1054
|
};
|
|
@@ -779,10 +1065,18 @@ function renderToStream(code, options = {}) {
|
|
|
779
1065
|
rootAssetsSerialized = true;
|
|
780
1066
|
serializeFragmentAssets("", tracking.boundaryModules, context);
|
|
781
1067
|
};
|
|
1068
|
+
let holds = 0;
|
|
782
1069
|
const flushEnd = () => {
|
|
783
|
-
if (!registry.size) {
|
|
1070
|
+
if (!registry.size && !holds) {
|
|
784
1071
|
serializeRootAssets();
|
|
785
|
-
queue(() => queue(() =>
|
|
1072
|
+
queue(() => queue(() => {
|
|
1073
|
+
if (context.live.end) {
|
|
1074
|
+
const end = context.live.end;
|
|
1075
|
+
context.live.end = null;
|
|
1076
|
+
end();
|
|
1077
|
+
}
|
|
1078
|
+
serializer.flush();
|
|
1079
|
+
}));
|
|
786
1080
|
}
|
|
787
1081
|
};
|
|
788
1082
|
const registry = new Map();
|
|
@@ -842,8 +1136,8 @@ function renderToStream(code, options = {}) {
|
|
|
842
1136
|
};
|
|
843
1137
|
sharedConfig.context = context = {
|
|
844
1138
|
async: true,
|
|
845
|
-
assets: [],
|
|
846
1139
|
nonce,
|
|
1140
|
+
live: {},
|
|
847
1141
|
registerHeadTags(tags) {
|
|
848
1142
|
registerHeadTags(headRegistry, context, tracking,
|
|
849
1143
|
(markup, gateEntry) => {
|
|
@@ -880,6 +1174,16 @@ function renderToStream(code, options = {}) {
|
|
|
880
1174
|
block(p) {
|
|
881
1175
|
if (!firstFlushed) blockingPromises.add(p);
|
|
882
1176
|
},
|
|
1177
|
+
hold() {
|
|
1178
|
+
holds++;
|
|
1179
|
+
let released = false;
|
|
1180
|
+
return () => {
|
|
1181
|
+
if (released) return;
|
|
1182
|
+
released = true;
|
|
1183
|
+
holds--;
|
|
1184
|
+
if (!holds) queue(flushEnd);
|
|
1185
|
+
};
|
|
1186
|
+
},
|
|
883
1187
|
replace(id, payloadFn) {
|
|
884
1188
|
if (firstFlushed) return;
|
|
885
1189
|
const placeholder = `<!--!$${id}-->`;
|
|
@@ -988,6 +1292,7 @@ function renderToStream(code, options = {}) {
|
|
|
988
1292
|
}
|
|
989
1293
|
};
|
|
990
1294
|
applyAssetTracking(context, tracking, manifest, noScripts);
|
|
1295
|
+
context.failRender = failRender;
|
|
991
1296
|
registerEntryAssets(manifest);
|
|
992
1297
|
let html = createRoot(d => {
|
|
993
1298
|
dispose = d;
|
|
@@ -1044,7 +1349,7 @@ function renderToStream(code, options = {}) {
|
|
|
1044
1349
|
if (shellCompleted) return;
|
|
1045
1350
|
sharedConfig.context = context;
|
|
1046
1351
|
if (!resolveRootHoles()) return;
|
|
1047
|
-
|
|
1352
|
+
if (!headShellReady(headRegistry, p => blockingPromises.add(p))) return;
|
|
1048
1353
|
headStyles = new Set();
|
|
1049
1354
|
for (const url of tracking.emittedAssets) {
|
|
1050
1355
|
if (isCssUrl(url)) headStyles.add(url);
|
|
@@ -1052,7 +1357,6 @@ function renderToStream(code, options = {}) {
|
|
|
1052
1357
|
serializeRootAssets();
|
|
1053
1358
|
const head = renderShellHead(headRegistry, nonce, k => registry.has(k));
|
|
1054
1359
|
sink.shell(html, {
|
|
1055
|
-
assets: assetsHtml,
|
|
1056
1360
|
preloads: tracking.emittedAssets,
|
|
1057
1361
|
inlineStyles: tracking.inlineStyles,
|
|
1058
1362
|
tasks,
|
|
@@ -1101,7 +1405,12 @@ function renderToStream(code, options = {}) {
|
|
|
1101
1405
|
allSettled(blockingPromises).then(() => {
|
|
1102
1406
|
scheduleFlush(() => {
|
|
1103
1407
|
if (dead) return resolve();
|
|
1104
|
-
|
|
1408
|
+
try {
|
|
1409
|
+
doShell();
|
|
1410
|
+
} catch (err) {
|
|
1411
|
+
failRender(err);
|
|
1412
|
+
return resolve();
|
|
1413
|
+
}
|
|
1105
1414
|
if (!shellCompleted) return flush();
|
|
1106
1415
|
const encoder = new TextEncoder();
|
|
1107
1416
|
const writer = w.getWriter();
|
|
@@ -1142,27 +1451,35 @@ function renderToStream(code, options = {}) {
|
|
|
1142
1451
|
return p;
|
|
1143
1452
|
};
|
|
1144
1453
|
return {
|
|
1145
|
-
then(
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1454
|
+
then(onFulfilled, onRejected) {
|
|
1455
|
+
const p = new Promise(resolve => {
|
|
1456
|
+
function complete() {
|
|
1457
|
+
dispose();
|
|
1458
|
+
resolve(tmp);
|
|
1459
|
+
}
|
|
1460
|
+
if (onCompleteAll) {
|
|
1461
|
+
let ogComplete = onCompleteAll;
|
|
1462
|
+
onCompleteAll = options => {
|
|
1463
|
+
ogComplete(options);
|
|
1464
|
+
complete();
|
|
1465
|
+
};
|
|
1466
|
+
} else onCompleteAll = complete;
|
|
1467
|
+
function flush() {
|
|
1468
|
+
allSettled(blockingPromises).then(() => {
|
|
1469
|
+
scheduleFlush(() => {
|
|
1470
|
+
try {
|
|
1471
|
+
if (!resolveRootHoles() || !headShellReady(headRegistry, p => blockingPromises.add(p))) return flush();
|
|
1472
|
+
} catch (err) {
|
|
1473
|
+
failRender(err);
|
|
1474
|
+
return resolve(tmp);
|
|
1475
|
+
}
|
|
1476
|
+
queue(flushEnd);
|
|
1477
|
+
});
|
|
1162
1478
|
});
|
|
1163
|
-
}
|
|
1164
|
-
|
|
1165
|
-
|
|
1479
|
+
}
|
|
1480
|
+
flush();
|
|
1481
|
+
});
|
|
1482
|
+
return p.then(onFulfilled, onRejected);
|
|
1166
1483
|
},
|
|
1167
1484
|
pipe(w) {
|
|
1168
1485
|
claimConsumer("pipe");
|
|
@@ -1170,7 +1487,15 @@ function renderToStream(code, options = {}) {
|
|
|
1170
1487
|
allSettled(blockingPromises).then(() => {
|
|
1171
1488
|
scheduleFlush(() => {
|
|
1172
1489
|
if (dead) return;
|
|
1173
|
-
|
|
1490
|
+
try {
|
|
1491
|
+
doShell();
|
|
1492
|
+
} catch (err) {
|
|
1493
|
+
failRender(err);
|
|
1494
|
+
try {
|
|
1495
|
+
w.end();
|
|
1496
|
+
} catch (_) {}
|
|
1497
|
+
return;
|
|
1498
|
+
}
|
|
1174
1499
|
if (!shellCompleted) return flush();
|
|
1175
1500
|
buffer = writable = guardSink(w);
|
|
1176
1501
|
buffer.write(tmp);
|
|
@@ -1202,9 +1527,27 @@ function renderToStream(code, options = {}) {
|
|
|
1202
1527
|
function buildAsyncWrap(err, node) {
|
|
1203
1528
|
const p = ssrHandleError(err);
|
|
1204
1529
|
if (!p) return null;
|
|
1530
|
+
if (node.$rw) return {
|
|
1531
|
+
fn: node,
|
|
1532
|
+
p
|
|
1533
|
+
};
|
|
1205
1534
|
const owner = getOwner();
|
|
1535
|
+
const live = sharedConfig.context && sharedConfig.context.liveHoles;
|
|
1536
|
+
const suppress = node.$lhSuppress || live && (live.suppressed || live.sweeping);
|
|
1537
|
+
if (!owner) {
|
|
1538
|
+
if (suppress) node.$lhSuppress = true;
|
|
1539
|
+
return {
|
|
1540
|
+
fn: node,
|
|
1541
|
+
p
|
|
1542
|
+
};
|
|
1543
|
+
}
|
|
1544
|
+
const fn = () => runWithOwner(owner, node);
|
|
1545
|
+
fn.$rw = true;
|
|
1546
|
+
if (suppress) fn.$lhSuppress = true;
|
|
1547
|
+
if (node.$lhSkip) fn.$lhSkip = true;
|
|
1548
|
+
if (node.$lhBinding) fn.$lhBinding = node.$lhBinding;
|
|
1206
1549
|
return {
|
|
1207
|
-
fn
|
|
1550
|
+
fn,
|
|
1208
1551
|
p
|
|
1209
1552
|
};
|
|
1210
1553
|
}
|
|
@@ -1264,6 +1607,326 @@ function ssrGroupSlot(fn, idx) {
|
|
|
1264
1607
|
}
|
|
1265
1608
|
};
|
|
1266
1609
|
}
|
|
1610
|
+
const holePositionCache = new WeakMap();
|
|
1611
|
+
function holeContentPositions(t) {
|
|
1612
|
+
let cached = holePositionCache.get(t);
|
|
1613
|
+
if (cached) return cached;
|
|
1614
|
+
const pos = [];
|
|
1615
|
+
const openOff = [];
|
|
1616
|
+
const closeOff = [];
|
|
1617
|
+
let inTag = false;
|
|
1618
|
+
let quote = "";
|
|
1619
|
+
let curOpen = null;
|
|
1620
|
+
let scanningName = false;
|
|
1621
|
+
for (let i = 0; i < t.length; i++) {
|
|
1622
|
+
const seg = t[i];
|
|
1623
|
+
let close = -1;
|
|
1624
|
+
const openAtStart = inTag;
|
|
1625
|
+
let reopened = false;
|
|
1626
|
+
for (let j = 0; j < seg.length; j++) {
|
|
1627
|
+
const ch = seg[j];
|
|
1628
|
+
if (quote) {
|
|
1629
|
+
if (ch === quote) quote = "";
|
|
1630
|
+
} else if (inTag) {
|
|
1631
|
+
if (scanningName && (ch === " " || ch === "\t" || ch === "\n" || ch === ">" || ch === "/")) {
|
|
1632
|
+
scanningName = false;
|
|
1633
|
+
curOpen = {
|
|
1634
|
+
seg: i,
|
|
1635
|
+
off: j
|
|
1636
|
+
};
|
|
1637
|
+
}
|
|
1638
|
+
if (ch === '"' || ch === "'") quote = ch;else if (ch === ">") {
|
|
1639
|
+
inTag = false;
|
|
1640
|
+
if (openAtStart && !reopened && close === -1) close = j;
|
|
1641
|
+
curOpen = null;
|
|
1642
|
+
}
|
|
1643
|
+
} else if (ch === "<") {
|
|
1644
|
+
inTag = true;
|
|
1645
|
+
scanningName = true;
|
|
1646
|
+
reopened = true;
|
|
1647
|
+
curOpen = null;
|
|
1648
|
+
}
|
|
1649
|
+
}
|
|
1650
|
+
if (inTag && scanningName) {
|
|
1651
|
+
scanningName = false;
|
|
1652
|
+
curOpen = {
|
|
1653
|
+
seg: i,
|
|
1654
|
+
off: seg.length
|
|
1655
|
+
};
|
|
1656
|
+
}
|
|
1657
|
+
closeOff.push(close);
|
|
1658
|
+
openOff.push(inTag && curOpen && curOpen.seg === i ? curOpen.off : -1);
|
|
1659
|
+
if (i < t.length - 1) pos.push(!inTag);
|
|
1660
|
+
}
|
|
1661
|
+
cached = {
|
|
1662
|
+
pos,
|
|
1663
|
+
openOff,
|
|
1664
|
+
closeOff
|
|
1665
|
+
};
|
|
1666
|
+
holePositionCache.set(t, cached);
|
|
1667
|
+
return cached;
|
|
1668
|
+
}
|
|
1669
|
+
function createLiveHoles(sink, scoped) {
|
|
1670
|
+
let nextId = 0;
|
|
1671
|
+
const stamp = typeof creationStamp === "function" ? creationStamp : () => 0;
|
|
1672
|
+
const inScope = scoped && typeof inServerComponentScope === "function" ? inServerComponentScope : null;
|
|
1673
|
+
const stripMarkers = html => html.replace(/<!--lh:\/?\d+-->/g, "");
|
|
1674
|
+
function resolveHoleValue(hole) {
|
|
1675
|
+
const result = {
|
|
1676
|
+
t: [""],
|
|
1677
|
+
h: [],
|
|
1678
|
+
p: []
|
|
1679
|
+
};
|
|
1680
|
+
try {
|
|
1681
|
+
resolveSSRNode(hole(), result);
|
|
1682
|
+
} catch (err) {
|
|
1683
|
+
const wrap = buildAsyncWrap(err, hole);
|
|
1684
|
+
if (!wrap) throw err;
|
|
1685
|
+
result.h.push(wrap.fn);
|
|
1686
|
+
result.p.push(wrap.p);
|
|
1687
|
+
result.t.push("");
|
|
1688
|
+
}
|
|
1689
|
+
return result;
|
|
1690
|
+
}
|
|
1691
|
+
function closeChildren(b) {
|
|
1692
|
+
for (const c of b.children) {
|
|
1693
|
+
c.closed = true;
|
|
1694
|
+
if (c.key) sink.closeBinding(c.key);
|
|
1695
|
+
closeChildren(c);
|
|
1696
|
+
}
|
|
1697
|
+
b.children.length = 0;
|
|
1698
|
+
}
|
|
1699
|
+
const engine = {
|
|
1700
|
+
suppressed: 0,
|
|
1701
|
+
sweeping: false,
|
|
1702
|
+
parent: null,
|
|
1703
|
+
recordStamp: 0,
|
|
1704
|
+
gateHit: false,
|
|
1705
|
+
content(hole) {
|
|
1706
|
+
if (hole.$lhSuppress) {
|
|
1707
|
+
const r = {
|
|
1708
|
+
t: [""],
|
|
1709
|
+
h: [],
|
|
1710
|
+
p: []
|
|
1711
|
+
};
|
|
1712
|
+
engine.suppressed++;
|
|
1713
|
+
try {
|
|
1714
|
+
try {
|
|
1715
|
+
resolveSSRNode(hole(), r);
|
|
1716
|
+
} catch (err) {
|
|
1717
|
+
const wrap = buildAsyncWrap(err, hole);
|
|
1718
|
+
if (wrap) {
|
|
1719
|
+
r.h.push(wrap.fn);
|
|
1720
|
+
r.p.push(wrap.p);
|
|
1721
|
+
r.t.push("");
|
|
1722
|
+
}
|
|
1723
|
+
}
|
|
1724
|
+
} finally {
|
|
1725
|
+
engine.suppressed--;
|
|
1726
|
+
}
|
|
1727
|
+
const b = hole.$lhBinding;
|
|
1728
|
+
if (b && !b.closed && !r.h.length && !engine.sweeping) {
|
|
1729
|
+
b.last = stripMarkers(r.t[0]);
|
|
1730
|
+
}
|
|
1731
|
+
return r.h.length ? r : r.t[0];
|
|
1732
|
+
}
|
|
1733
|
+
if (engine.suppressed || engine.sweeping) return null;
|
|
1734
|
+
if (hole.$lhSkip) return null;
|
|
1735
|
+
if (inScope && !inScope()) return null;
|
|
1736
|
+
const recordsBefore = engine.recordStamp;
|
|
1737
|
+
const ownersBefore = stamp();
|
|
1738
|
+
const owner = getOwner();
|
|
1739
|
+
const b = {
|
|
1740
|
+
key: null,
|
|
1741
|
+
children: [],
|
|
1742
|
+
last: null,
|
|
1743
|
+
closed: false,
|
|
1744
|
+
sweep() {
|
|
1745
|
+
if (b.closed) return;
|
|
1746
|
+
const prevSweeping = engine.sweeping;
|
|
1747
|
+
engine.sweeping = true;
|
|
1748
|
+
engine.gateHit = false;
|
|
1749
|
+
const sweepOwnersBefore = stamp();
|
|
1750
|
+
let res;
|
|
1751
|
+
try {
|
|
1752
|
+
res = owner ? runWithOwner(owner, () => resolveHoleValue(hole)) : resolveHoleValue(hole);
|
|
1753
|
+
} catch (err) {
|
|
1754
|
+
b.closed = true;
|
|
1755
|
+
sink.closeBinding(b.key);
|
|
1756
|
+
sink.error(b.key, String(err && err.message || err));
|
|
1757
|
+
return;
|
|
1758
|
+
} finally {
|
|
1759
|
+
engine.sweeping = prevSweeping;
|
|
1760
|
+
}
|
|
1761
|
+
if (engine.gateHit || stamp() !== sweepOwnersBefore) {
|
|
1762
|
+
b.closed = true;
|
|
1763
|
+
sink.closeBinding(b.key);
|
|
1764
|
+
return;
|
|
1765
|
+
}
|
|
1766
|
+
if (res.h.length) return;
|
|
1767
|
+
const html = res.t[0];
|
|
1768
|
+
if (b.last === null || html === b.last) return;
|
|
1769
|
+
b.last = html;
|
|
1770
|
+
closeChildren(b);
|
|
1771
|
+
sink.hole(b.key, html);
|
|
1772
|
+
}
|
|
1773
|
+
};
|
|
1774
|
+
if (engine.parent) engine.parent.children.push(b);
|
|
1775
|
+
const prevParent = engine.parent;
|
|
1776
|
+
engine.parent = b;
|
|
1777
|
+
let value;
|
|
1778
|
+
let escalated = null;
|
|
1779
|
+
try {
|
|
1780
|
+
value = hole();
|
|
1781
|
+
} catch (err) {
|
|
1782
|
+
const wrap = buildAsyncWrap(err, hole);
|
|
1783
|
+
if (!wrap) {
|
|
1784
|
+
engine.parent = prevParent;
|
|
1785
|
+
closeChildren(b);
|
|
1786
|
+
return "";
|
|
1787
|
+
}
|
|
1788
|
+
escalated = wrap;
|
|
1789
|
+
}
|
|
1790
|
+
if (!escalated && (typeof value === "function" && value.$lhSkip || value !== null && typeof value === "object" && value.$slot)) {
|
|
1791
|
+
engine.parent = prevParent;
|
|
1792
|
+
const r = {
|
|
1793
|
+
t: [""],
|
|
1794
|
+
h: [],
|
|
1795
|
+
p: []
|
|
1796
|
+
};
|
|
1797
|
+
engine.suppressed++;
|
|
1798
|
+
try {
|
|
1799
|
+
resolveSSRNode(value, r);
|
|
1800
|
+
} finally {
|
|
1801
|
+
engine.suppressed--;
|
|
1802
|
+
}
|
|
1803
|
+
return r.h.length ? r : r.t[0];
|
|
1804
|
+
}
|
|
1805
|
+
let res;
|
|
1806
|
+
if (escalated) {
|
|
1807
|
+
closeChildren(b);
|
|
1808
|
+
escalated.fn.$lhSuppress = true;
|
|
1809
|
+
escalated.fn.$lhBinding = b;
|
|
1810
|
+
res = {
|
|
1811
|
+
t: ["", ""],
|
|
1812
|
+
h: [escalated.fn],
|
|
1813
|
+
p: [escalated.p]
|
|
1814
|
+
};
|
|
1815
|
+
} else {
|
|
1816
|
+
res = {
|
|
1817
|
+
t: [""],
|
|
1818
|
+
h: [],
|
|
1819
|
+
p: []
|
|
1820
|
+
};
|
|
1821
|
+
try {
|
|
1822
|
+
resolveSSRNode(value, res);
|
|
1823
|
+
} catch (_) {
|
|
1824
|
+
engine.parent = prevParent;
|
|
1825
|
+
closeChildren(b);
|
|
1826
|
+
return "";
|
|
1827
|
+
}
|
|
1828
|
+
}
|
|
1829
|
+
engine.parent = prevParent;
|
|
1830
|
+
if (engine.recordStamp !== recordsBefore || stamp() !== ownersBefore) {
|
|
1831
|
+
return res.h.length ? res : res.t[0];
|
|
1832
|
+
}
|
|
1833
|
+
const id = nextId++;
|
|
1834
|
+
const key = b.key = "lh:" + id;
|
|
1835
|
+
const open = `<!--lh:${id}-->`;
|
|
1836
|
+
const close = `<!--lh:/${id}-->`;
|
|
1837
|
+
if (!res.h.length) {
|
|
1838
|
+
b.last = stripMarkers(res.t[0]);
|
|
1839
|
+
sink.openBinding(key, b);
|
|
1840
|
+
return open + res.t[0] + close;
|
|
1841
|
+
}
|
|
1842
|
+
const t = res.t.slice();
|
|
1843
|
+
t[0] = open + t[0];
|
|
1844
|
+
t[t.length - 1] += close;
|
|
1845
|
+
sink.openBinding(key, b);
|
|
1846
|
+
return {
|
|
1847
|
+
t,
|
|
1848
|
+
h: res.h,
|
|
1849
|
+
p: res.p
|
|
1850
|
+
};
|
|
1851
|
+
},
|
|
1852
|
+
mint() {
|
|
1853
|
+
return nextId++;
|
|
1854
|
+
},
|
|
1855
|
+
active() {
|
|
1856
|
+
return !inScope || inScope();
|
|
1857
|
+
},
|
|
1858
|
+
attr(cap) {
|
|
1859
|
+
const owner = getOwner();
|
|
1860
|
+
const b = {
|
|
1861
|
+
key: "lha:" + cap.id,
|
|
1862
|
+
children: [],
|
|
1863
|
+
last: cap.base,
|
|
1864
|
+
closed: false,
|
|
1865
|
+
sweep() {
|
|
1866
|
+
if (b.closed) return;
|
|
1867
|
+
const prevSweeping = engine.sweeping;
|
|
1868
|
+
engine.sweeping = true;
|
|
1869
|
+
engine.gateHit = false;
|
|
1870
|
+
const sweepOwnersBefore = stamp();
|
|
1871
|
+
let html = "";
|
|
1872
|
+
try {
|
|
1873
|
+
let group = null;
|
|
1874
|
+
let groupVal = null;
|
|
1875
|
+
const run = () => {
|
|
1876
|
+
for (const part of cap.parts) {
|
|
1877
|
+
if (typeof part === "string") {
|
|
1878
|
+
html += part;
|
|
1879
|
+
continue;
|
|
1880
|
+
}
|
|
1881
|
+
let v;
|
|
1882
|
+
if (part.g) {
|
|
1883
|
+
if (group !== part.g) {
|
|
1884
|
+
group = part.g;
|
|
1885
|
+
groupVal = part.g();
|
|
1886
|
+
}
|
|
1887
|
+
v = groupVal[part.i];
|
|
1888
|
+
} else {
|
|
1889
|
+
v = part.f();
|
|
1890
|
+
}
|
|
1891
|
+
const vt = typeof v;
|
|
1892
|
+
if (vt === "string" || vt === "number") html += v;
|
|
1893
|
+
}
|
|
1894
|
+
};
|
|
1895
|
+
owner ? runWithOwner(owner, run) : run();
|
|
1896
|
+
} catch (err) {
|
|
1897
|
+
if (ssrHandleError(err, true)) return;
|
|
1898
|
+
b.closed = true;
|
|
1899
|
+
sink.closeBinding(b.key);
|
|
1900
|
+
sink.error("lha:" + cap.id, String(err && err.message || err));
|
|
1901
|
+
return;
|
|
1902
|
+
} finally {
|
|
1903
|
+
engine.sweeping = prevSweeping;
|
|
1904
|
+
}
|
|
1905
|
+
if (engine.gateHit || stamp() !== sweepOwnersBefore) {
|
|
1906
|
+
b.closed = true;
|
|
1907
|
+
sink.closeBinding(b.key);
|
|
1908
|
+
return;
|
|
1909
|
+
}
|
|
1910
|
+
if (html === b.last) return;
|
|
1911
|
+
const before = attrNames(b.last);
|
|
1912
|
+
const after = attrNames(html);
|
|
1913
|
+
const removed = before.filter(n => !after.includes(n));
|
|
1914
|
+
b.last = html;
|
|
1915
|
+
sink.attr(String(cap.id), html, removed);
|
|
1916
|
+
}
|
|
1917
|
+
};
|
|
1918
|
+
sink.openBinding(b.key, b);
|
|
1919
|
+
}
|
|
1920
|
+
};
|
|
1921
|
+
return engine;
|
|
1922
|
+
}
|
|
1923
|
+
function attrNames(text) {
|
|
1924
|
+
const names = [];
|
|
1925
|
+
const re = /(?:^|\s)([^\s=/>"']+)(?:="[^"]*")?/g;
|
|
1926
|
+
let m;
|
|
1927
|
+
while (m = re.exec(text)) names.push(m[1]);
|
|
1928
|
+
return names;
|
|
1929
|
+
}
|
|
1267
1930
|
function ssr(t) {
|
|
1268
1931
|
const len = arguments.length;
|
|
1269
1932
|
if (len === 1) return {
|
|
@@ -1274,13 +1937,54 @@ function ssr(t) {
|
|
|
1274
1937
|
let lastGroup = null;
|
|
1275
1938
|
let lastGroupVal = null;
|
|
1276
1939
|
let lastGroupIdx = 0;
|
|
1940
|
+
const live = sharedConfig.context && sharedConfig.context.liveHoles;
|
|
1941
|
+
const hp = live ? holeContentPositions(t) : null;
|
|
1942
|
+
let lastOpen = null;
|
|
1943
|
+
let cap = null;
|
|
1944
|
+
if (live && hp.openOff[0] >= 0) lastOpen = {
|
|
1945
|
+
r: null,
|
|
1946
|
+
seg: -1,
|
|
1947
|
+
off: hp.openOff[0]
|
|
1948
|
+
};
|
|
1949
|
+
const captureStart = () => {
|
|
1950
|
+
if (cap) return true;
|
|
1951
|
+
if (!lastOpen || live.suppressed || live.sweeping || !live.active()) return false;
|
|
1952
|
+
if (lastOpen.r !== result || result !== null && lastOpen.seg !== result.t.length - 1) {
|
|
1953
|
+
return false;
|
|
1954
|
+
}
|
|
1955
|
+
const id = live.mint();
|
|
1956
|
+
const inject = ` data-lha="${id}"`;
|
|
1957
|
+
let prefix;
|
|
1958
|
+
if (result === null) {
|
|
1959
|
+
s = s.slice(0, lastOpen.off) + inject + s.slice(lastOpen.off);
|
|
1960
|
+
prefix = s.slice(lastOpen.off + inject.length);
|
|
1961
|
+
} else {
|
|
1962
|
+
const seg = result.t[lastOpen.seg];
|
|
1963
|
+
result.t[lastOpen.seg] = seg.slice(0, lastOpen.off) + inject + seg.slice(lastOpen.off);
|
|
1964
|
+
prefix = result.t[lastOpen.seg].slice(lastOpen.off + inject.length);
|
|
1965
|
+
}
|
|
1966
|
+
cap = {
|
|
1967
|
+
id,
|
|
1968
|
+
parts: [prefix],
|
|
1969
|
+
base: prefix
|
|
1970
|
+
};
|
|
1971
|
+
return true;
|
|
1972
|
+
};
|
|
1277
1973
|
for (let i = 1; i < len; i++) {
|
|
1278
1974
|
const hole = arguments[i];
|
|
1279
1975
|
const ht = typeof hole;
|
|
1280
1976
|
if (ht === "string") {
|
|
1281
1977
|
if (result === null) s += hole;else result.t[result.t.length - 1] += hole;
|
|
1978
|
+
if (cap) {
|
|
1979
|
+
cap.parts.push(hole);
|
|
1980
|
+
cap.base += hole;
|
|
1981
|
+
}
|
|
1282
1982
|
} else if (ht === "number") {
|
|
1283
1983
|
if (result === null) s += hole;else result.t[result.t.length - 1] += hole;
|
|
1984
|
+
if (cap) {
|
|
1985
|
+
cap.parts.push("" + hole);
|
|
1986
|
+
cap.base += hole;
|
|
1987
|
+
}
|
|
1284
1988
|
} else if (hole == null || ht === "boolean") ; else if (ht === "function" && hole.$g) {
|
|
1285
1989
|
let value;
|
|
1286
1990
|
let hasValue = false;
|
|
@@ -1304,7 +2008,14 @@ function ssr(t) {
|
|
|
1304
2008
|
if (Array.isArray(lastGroupVal)) {
|
|
1305
2009
|
value = lastGroupVal[lastGroupIdx++];
|
|
1306
2010
|
hasValue = true;
|
|
2011
|
+
if (live && !hp.pos[i - 1] && captureStart()) {
|
|
2012
|
+
cap.parts.push({
|
|
2013
|
+
g: hole,
|
|
2014
|
+
i: lastGroupIdx - 1
|
|
2015
|
+
});
|
|
2016
|
+
}
|
|
1307
2017
|
} else {
|
|
2018
|
+
cap = null;
|
|
1308
2019
|
result.h.push(ssrGroupSlot(lastGroupVal.fn, lastGroupIdx++));
|
|
1309
2020
|
result.p.push(lastGroupVal.p);
|
|
1310
2021
|
result.t.push("");
|
|
@@ -1314,6 +2025,7 @@ function ssr(t) {
|
|
|
1314
2025
|
const vt = typeof value;
|
|
1315
2026
|
if (vt === "string" || vt === "number") {
|
|
1316
2027
|
if (result === null) s += value;else result.t[result.t.length - 1] += value;
|
|
2028
|
+
if (cap && !hp.pos[i - 1]) cap.base += value;
|
|
1317
2029
|
} else if (value == null || vt === "boolean") ; else if (result !== null) {
|
|
1318
2030
|
resolveSSRNode(value, result);
|
|
1319
2031
|
} else {
|
|
@@ -1331,19 +2043,67 @@ function ssr(t) {
|
|
|
1331
2043
|
}
|
|
1332
2044
|
}
|
|
1333
2045
|
}
|
|
1334
|
-
} else if (result !== null) {
|
|
1335
|
-
resolveSSRNode(hole, result);
|
|
1336
2046
|
} else if (ht === "function") {
|
|
1337
|
-
|
|
1338
|
-
if (
|
|
1339
|
-
|
|
1340
|
-
t
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
2047
|
+
let liveNode = null;
|
|
2048
|
+
if (live && hp.pos[i - 1] && (liveNode = live.content(hole)) !== null) {
|
|
2049
|
+
if (typeof liveNode === "string") {
|
|
2050
|
+
if (result === null) s += liveNode;else result.t[result.t.length - 1] += liveNode;
|
|
2051
|
+
} else {
|
|
2052
|
+
if (result === null) {
|
|
2053
|
+
result = {
|
|
2054
|
+
t: [s],
|
|
2055
|
+
h: [],
|
|
2056
|
+
p: []
|
|
2057
|
+
};
|
|
2058
|
+
s = "";
|
|
2059
|
+
}
|
|
2060
|
+
resolveSSRNode(liveNode, result);
|
|
2061
|
+
}
|
|
2062
|
+
} else if (result !== null) {
|
|
2063
|
+
const inTag = live && !hp.pos[i - 1];
|
|
2064
|
+
const capturing = inTag && captureStart();
|
|
2065
|
+
const li = capturing ? result.t.length - 1 : 0;
|
|
2066
|
+
const before = capturing ? result.t[li].length : 0;
|
|
2067
|
+
if (live) live.suppressed++;
|
|
2068
|
+
try {
|
|
2069
|
+
resolveSSRNode(hole, result);
|
|
2070
|
+
} finally {
|
|
2071
|
+
if (live) live.suppressed--;
|
|
2072
|
+
}
|
|
2073
|
+
if (capturing) {
|
|
2074
|
+
if (result.t.length - 1 === li) {
|
|
2075
|
+
cap.base += result.t[li].slice(before);
|
|
2076
|
+
cap.parts.push({
|
|
2077
|
+
f: hole
|
|
2078
|
+
});
|
|
2079
|
+
} else {
|
|
2080
|
+
cap = null;
|
|
2081
|
+
}
|
|
2082
|
+
}
|
|
2083
|
+
} else {
|
|
2084
|
+
const capturing = live && !hp.pos[i - 1] && captureStart();
|
|
2085
|
+
const r = tryResolveFunctionHole(hole);
|
|
2086
|
+
if (typeof r === "string") {
|
|
2087
|
+
s += r;
|
|
2088
|
+
if (capturing) {
|
|
2089
|
+
cap.base += r;
|
|
2090
|
+
cap.parts.push({
|
|
2091
|
+
f: hole
|
|
2092
|
+
});
|
|
2093
|
+
}
|
|
2094
|
+
} else {
|
|
2095
|
+
if (capturing) cap = null;
|
|
2096
|
+
result = {
|
|
2097
|
+
t: [s],
|
|
2098
|
+
h: [],
|
|
2099
|
+
p: []
|
|
2100
|
+
};
|
|
2101
|
+
s = "";
|
|
2102
|
+
appendResolvedNode(result, r);
|
|
2103
|
+
}
|
|
1346
2104
|
}
|
|
2105
|
+
} else if (result !== null) {
|
|
2106
|
+
resolveSSRNode(hole, result);
|
|
1347
2107
|
} else {
|
|
1348
2108
|
const r = tryResolveString(hole);
|
|
1349
2109
|
if (typeof r === "string") {
|
|
@@ -1359,6 +2119,32 @@ function ssr(t) {
|
|
|
1359
2119
|
}
|
|
1360
2120
|
}
|
|
1361
2121
|
const next = t[i];
|
|
2122
|
+
if (live) {
|
|
2123
|
+
if (cap) {
|
|
2124
|
+
const co = hp.closeOff[i];
|
|
2125
|
+
if (co >= 0) {
|
|
2126
|
+
const tail = next.slice(0, co);
|
|
2127
|
+
cap.parts.push(tail);
|
|
2128
|
+
cap.base += tail;
|
|
2129
|
+
live.attr(cap);
|
|
2130
|
+
cap = null;
|
|
2131
|
+
} else {
|
|
2132
|
+
cap.parts.push(next);
|
|
2133
|
+
cap.base += next;
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2136
|
+
if (hp.openOff[i] >= 0) {
|
|
2137
|
+
lastOpen = result === null ? {
|
|
2138
|
+
r: null,
|
|
2139
|
+
seg: -1,
|
|
2140
|
+
off: s.length + hp.openOff[i]
|
|
2141
|
+
} : {
|
|
2142
|
+
r: result,
|
|
2143
|
+
seg: result.t.length - 1,
|
|
2144
|
+
off: result.t[result.t.length - 1].length + hp.openOff[i]
|
|
2145
|
+
};
|
|
2146
|
+
}
|
|
2147
|
+
}
|
|
1362
2148
|
if (result === null) s += next;else result.t[result.t.length - 1] += next;
|
|
1363
2149
|
}
|
|
1364
2150
|
if (result === null) return {
|
|
@@ -1447,17 +2233,11 @@ function allSettled(promises) {
|
|
|
1447
2233
|
return;
|
|
1448
2234
|
});
|
|
1449
2235
|
}
|
|
1450
|
-
function
|
|
1451
|
-
if (!assets || !assets.length) return "";
|
|
1452
|
-
let out = "";
|
|
1453
|
-
for (let i = 0, len = assets.length; i < len; i++) out += assets[i]();
|
|
1454
|
-
return out;
|
|
1455
|
-
}
|
|
1456
|
-
function assembleDocument(html, assetsHtml, emittedAssets, inlineStyles, scripts, nonce, headTags, onHead) {
|
|
2236
|
+
function assembleDocument(html, emittedAssets, inlineStyles, scripts, nonce, headTags, onHead) {
|
|
1457
2237
|
const scriptTag = scripts ? `<script${nonce ? ` nonce="${nonce}"` : ""}>${scripts}</script>` : "";
|
|
1458
2238
|
const headTagsHtml = headTags ? headTags.html : "";
|
|
1459
2239
|
const headPrelude = headTags ? headTags.prelude : "";
|
|
1460
|
-
if (!onHead && !
|
|
2240
|
+
if (!onHead && !headTagsHtml && !headPrelude && !(emittedAssets && emittedAssets.size) && !(inlineStyles && inlineStyles.size)) {
|
|
1461
2241
|
if (!scriptTag) return html;
|
|
1462
2242
|
const xs = html.indexOf("<!--xs-->");
|
|
1463
2243
|
return xs === -1 ? html + scriptTag : html.slice(0, xs) + scriptTag + html.slice(xs);
|
|
@@ -1472,13 +2252,13 @@ function assembleDocument(html, assetsHtml, emittedAssets, inlineStyles, scripts
|
|
|
1472
2252
|
const headIdx = html.indexOf("</head>");
|
|
1473
2253
|
if (headIdx === -1) {
|
|
1474
2254
|
if (onHead) {
|
|
1475
|
-
onHead(headPrelude + headTagsHtml +
|
|
2255
|
+
onHead(headPrelude + headTagsHtml + renderHeadAssets(emittedAssets, inlineStyles, nonce));
|
|
1476
2256
|
}
|
|
1477
2257
|
if (!scriptTag) return html;
|
|
1478
2258
|
const xs = html.indexOf("<!--xs-->");
|
|
1479
2259
|
return xs === -1 ? html + scriptTag : html.slice(0, xs) + scriptTag + html.slice(xs);
|
|
1480
2260
|
}
|
|
1481
|
-
const head = headTagsHtml +
|
|
2261
|
+
const head = headTagsHtml + renderHeadAssets(emittedAssets, inlineStyles, nonce);
|
|
1482
2262
|
if (!scriptTag) return html.slice(0, headIdx) + head + html.slice(headIdx);
|
|
1483
2263
|
const xsIdx = html.indexOf("<!--xs-->");
|
|
1484
2264
|
if (xsIdx === -1) return html.slice(0, headIdx) + head + html.slice(headIdx) + scriptTag;
|
|
@@ -1597,7 +2377,6 @@ function tryResolveString(node) {
|
|
|
1597
2377
|
merge: node
|
|
1598
2378
|
};
|
|
1599
2379
|
if (node.t === undefined) {
|
|
1600
|
-
console.warn(`Unrecognized value. Skipped inserting`, node);
|
|
1601
2380
|
return "";
|
|
1602
2381
|
}
|
|
1603
2382
|
return Array.isArray(node.t) ? node.t[0] : node.t;
|
|
@@ -1622,13 +2401,19 @@ function resolveSSRNode(node, result = {
|
|
|
1622
2401
|
if (t === "string" || t === "number") {
|
|
1623
2402
|
result.t[result.t.length - 1] += node;
|
|
1624
2403
|
} else if (node == null || t === "boolean") ; else if (Array.isArray(node)) {
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
2404
|
+
const slotLive = node.$slot && sharedConfig.context && sharedConfig.context.liveHoles;
|
|
2405
|
+
if (slotLive) slotLive.suppressed++;
|
|
2406
|
+
try {
|
|
2407
|
+
let prevNonObj = false;
|
|
2408
|
+
for (let i = 0, len = node.length; i < len; i++) {
|
|
2409
|
+
const item = node[i];
|
|
2410
|
+
const itemNonObj = item !== null && typeof item !== "object";
|
|
2411
|
+
if (!top && prevNonObj && itemNonObj) result.t[result.t.length - 1] += `<!--!$-->`;
|
|
2412
|
+
prevNonObj = itemNonObj;
|
|
2413
|
+
resolveSSRNode(item, result);
|
|
2414
|
+
}
|
|
2415
|
+
} finally {
|
|
2416
|
+
if (slotLive) slotLive.suppressed--;
|
|
1632
2417
|
}
|
|
1633
2418
|
} else if (t === "object") {
|
|
1634
2419
|
if (node.h) {
|
|
@@ -1640,16 +2425,22 @@ function resolveSSRNode(node, result = {
|
|
|
1640
2425
|
}
|
|
1641
2426
|
} else if (node.t !== undefined) {
|
|
1642
2427
|
result.t[result.t.length - 1] += node.t;
|
|
1643
|
-
} else
|
|
2428
|
+
} else ;
|
|
1644
2429
|
} else if (t === "function") {
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
2430
|
+
const live = sharedConfig.context && sharedConfig.context.liveHoles;
|
|
2431
|
+
let liveNode = null;
|
|
2432
|
+
if (live && (liveNode = live.content(node)) !== null) {
|
|
2433
|
+
if (typeof liveNode === "string") result.t[result.t.length - 1] += liveNode;else resolveSSRNode(liveNode, result);
|
|
2434
|
+
} else {
|
|
2435
|
+
try {
|
|
2436
|
+
resolveSSRNode(node(), result);
|
|
2437
|
+
} catch (err) {
|
|
2438
|
+
const wrap = buildAsyncWrap(err, node);
|
|
2439
|
+
if (wrap) {
|
|
2440
|
+
result.h.push(wrap.fn);
|
|
2441
|
+
result.p.push(wrap.p);
|
|
2442
|
+
result.t.push("");
|
|
2443
|
+
}
|
|
1653
2444
|
}
|
|
1654
2445
|
}
|
|
1655
2446
|
}
|
|
@@ -1660,142 +2451,7 @@ function resolveSSRSync(node) {
|
|
|
1660
2451
|
if (!res.h.length) return res.t[0];
|
|
1661
2452
|
throw new Error("This value cannot be rendered synchronously. Are you missing a boundary?");
|
|
1662
2453
|
}
|
|
1663
|
-
|
|
1664
|
-
function frameAddress(id, args) {
|
|
1665
|
-
return args && args.length ? id + ":" + hashArguments(args) : id;
|
|
1666
|
-
}
|
|
1667
|
-
function hashArguments(args) {
|
|
1668
|
-
let hash = 0;
|
|
1669
|
-
const text = stableString(args);
|
|
1670
|
-
for (let i = 0; i < text.length; i++) {
|
|
1671
|
-
hash = (hash << 5) - hash + text.charCodeAt(i);
|
|
1672
|
-
hash |= 0;
|
|
1673
|
-
}
|
|
1674
|
-
return (hash >>> 0).toString(36);
|
|
1675
|
-
}
|
|
1676
|
-
function stableString(value, seen) {
|
|
1677
|
-
if (value === null || typeof value !== "object") {
|
|
1678
|
-
return typeof value === "bigint" ? value + "n" : String(value);
|
|
1679
|
-
}
|
|
1680
|
-
if (value instanceof Date) return "Date:" + value.getTime();
|
|
1681
|
-
seen || (seen = new Set());
|
|
1682
|
-
if (seen.has(value)) return "~";
|
|
1683
|
-
seen.add(value);
|
|
1684
|
-
if (value instanceof Map) {
|
|
1685
|
-
const entries = [];
|
|
1686
|
-
for (const [k, v] of value) {
|
|
1687
|
-
entries.push(stableString(k, seen) + "=>" + stableString(v, seen));
|
|
1688
|
-
}
|
|
1689
|
-
return "Map{" + entries.sort().join(",") + "}";
|
|
1690
|
-
}
|
|
1691
|
-
if (value instanceof Set) {
|
|
1692
|
-
const members = [];
|
|
1693
|
-
for (const v of value) members.push(stableString(v, seen));
|
|
1694
|
-
return "Set{" + members.sort().join(",") + "}";
|
|
1695
|
-
}
|
|
1696
|
-
if (Array.isArray(value)) {
|
|
1697
|
-
let out = "[";
|
|
1698
|
-
for (let i = 0; i < value.length; i++) out += (i ? "," : "") + stableString(value[i], seen);
|
|
1699
|
-
return out + "]";
|
|
1700
|
-
}
|
|
1701
|
-
const keys = Object.keys(value).sort();
|
|
1702
|
-
let out = "{";
|
|
1703
|
-
for (let i = 0; i < keys.length; i++) {
|
|
1704
|
-
out += (i ? "," : "") + keys[i] + ":" + stableString(value[keys[i]], seen);
|
|
1705
|
-
}
|
|
1706
|
-
return out + "}";
|
|
1707
|
-
}
|
|
1708
|
-
const SINGLE_FLIGHT_HEADER = "X-Single-Flight";
|
|
1709
|
-
function createChunk(data) {
|
|
1710
|
-
const encodeData = new TextEncoder().encode(data);
|
|
1711
|
-
const bytes = encodeData.length;
|
|
1712
|
-
const baseHex = bytes.toString(16);
|
|
1713
|
-
const totalHex = "00000000".substring(0, 8 - baseHex.length) + baseHex;
|
|
1714
|
-
const head = new TextEncoder().encode(`;0x${totalHex};`);
|
|
1715
|
-
const chunk = new Uint8Array(12 + bytes);
|
|
1716
|
-
chunk.set(head);
|
|
1717
|
-
chunk.set(encodeData, 12);
|
|
1718
|
-
return chunk;
|
|
1719
|
-
}
|
|
1720
|
-
class ChunkReader {
|
|
1721
|
-
constructor(stream) {
|
|
1722
|
-
this.reader = stream.getReader();
|
|
1723
|
-
this.buffer = new Uint8Array(0);
|
|
1724
|
-
this.done = false;
|
|
1725
|
-
}
|
|
1726
|
-
async readChunk() {
|
|
1727
|
-
const chunk = await this.reader.read();
|
|
1728
|
-
if (!chunk.done) {
|
|
1729
|
-
const newBuffer = new Uint8Array(this.buffer.length + chunk.value.length);
|
|
1730
|
-
newBuffer.set(this.buffer);
|
|
1731
|
-
newBuffer.set(chunk.value, this.buffer.length);
|
|
1732
|
-
this.buffer = newBuffer;
|
|
1733
|
-
} else {
|
|
1734
|
-
this.done = true;
|
|
1735
|
-
}
|
|
1736
|
-
}
|
|
1737
|
-
async next() {
|
|
1738
|
-
while (this.buffer.length < 12) {
|
|
1739
|
-
if (this.done) {
|
|
1740
|
-
if (this.buffer.length === 0) return {
|
|
1741
|
-
done: true,
|
|
1742
|
-
value: undefined
|
|
1743
|
-
};
|
|
1744
|
-
throw new Error("Malformed server function stream.");
|
|
1745
|
-
}
|
|
1746
|
-
await this.readChunk();
|
|
1747
|
-
}
|
|
1748
|
-
const head = new TextDecoder().decode(this.buffer.subarray(1, 11));
|
|
1749
|
-
const bytes = Number.parseInt(head, 16);
|
|
1750
|
-
if (Number.isNaN(bytes)) {
|
|
1751
|
-
throw new Error("Malformed server function stream.");
|
|
1752
|
-
}
|
|
1753
|
-
while (bytes > this.buffer.length - 12) {
|
|
1754
|
-
if (this.done) {
|
|
1755
|
-
throw new Error("Malformed server function stream.");
|
|
1756
|
-
}
|
|
1757
|
-
await this.readChunk();
|
|
1758
|
-
}
|
|
1759
|
-
const partial = new TextDecoder().decode(this.buffer.subarray(12, 12 + bytes));
|
|
1760
|
-
this.buffer = this.buffer.subarray(12 + bytes);
|
|
1761
|
-
return {
|
|
1762
|
-
done: false,
|
|
1763
|
-
value: partial
|
|
1764
|
-
};
|
|
1765
|
-
}
|
|
1766
|
-
async drain(interpret) {
|
|
1767
|
-
while (true) {
|
|
1768
|
-
const result = await this.next();
|
|
1769
|
-
if (result.done) {
|
|
1770
|
-
break;
|
|
1771
|
-
}
|
|
1772
|
-
interpret(result.value);
|
|
1773
|
-
}
|
|
1774
|
-
}
|
|
1775
|
-
}
|
|
1776
|
-
function serializeStream(value, codecOptions) {
|
|
1777
|
-
return new ReadableStream({
|
|
1778
|
-
start(controller) {
|
|
1779
|
-
serializeJSON(value, {
|
|
1780
|
-
...codecOptions,
|
|
1781
|
-
onParse(node) {
|
|
1782
|
-
controller.enqueue(createChunk(JSON.stringify(node)));
|
|
1783
|
-
},
|
|
1784
|
-
onDone() {
|
|
1785
|
-
controller.close();
|
|
1786
|
-
},
|
|
1787
|
-
onError(error) {
|
|
1788
|
-
controller.error(error);
|
|
1789
|
-
}
|
|
1790
|
-
});
|
|
1791
|
-
}
|
|
1792
|
-
});
|
|
1793
|
-
}
|
|
1794
|
-
|
|
1795
|
-
const ENVELOPE = Symbol.for("solid.ResponseEnvelope");
|
|
1796
|
-
function isResponseEnvelope(value) {
|
|
1797
|
-
return !!(value && typeof value === "object" && value[ENVELOPE]);
|
|
1798
|
-
}
|
|
2454
|
+
/*#__PURE__*/new Set([ERROR_HEADER, BODY_FORMAT_HEADER, SINGLE_FLIGHT_HEADER, REVALIDATE_HEADER, "Location"].map(header => header.toLowerCase()));
|
|
1799
2455
|
|
|
1800
2456
|
const INVOCATIONS = new WeakMap();
|
|
1801
2457
|
function getEventServerFunctionInvocation(event) {
|
|
@@ -1819,7 +2475,7 @@ function parseServerComponent(value, ctx) {
|
|
|
1819
2475
|
address: ctx.parse(value[SERVER_COMPONENT_ADDRESS])
|
|
1820
2476
|
};
|
|
1821
2477
|
}
|
|
1822
|
-
const ServerComponentPlugin =
|
|
2478
|
+
const ServerComponentPlugin = {
|
|
1823
2479
|
tag: "dom-expressions/server-component",
|
|
1824
2480
|
test(value) {
|
|
1825
2481
|
return typeof value === "function" && SERVER_COMPONENT in value;
|
|
@@ -1843,18 +2499,17 @@ const ServerComponentPlugin = /*#__PURE__*/createPlugin({
|
|
|
1843
2499
|
ctx.deserialize(node.address);
|
|
1844
2500
|
return globalThis._$SC.r(id);
|
|
1845
2501
|
}
|
|
1846
|
-
}
|
|
2502
|
+
};
|
|
1847
2503
|
function flightCodec(codec) {
|
|
1848
2504
|
const plugins = codec && codec.plugins || [];
|
|
1849
|
-
|
|
1850
|
-
if (plugin && plugin.tag === "dom-expressions/server-component") return codec;
|
|
1851
|
-
}
|
|
2505
|
+
if (plugins.some(plugin => plugin && plugin.tag === ServerComponentPlugin.tag)) return codec;
|
|
1852
2506
|
return {
|
|
1853
2507
|
...codec,
|
|
1854
2508
|
plugins: [...plugins, ServerComponentPlugin]
|
|
1855
2509
|
};
|
|
1856
2510
|
}
|
|
1857
2511
|
|
|
2512
|
+
const scopeStamp = typeof creationStamp === "function" ? creationStamp : () => 0;
|
|
1858
2513
|
function serverOwned(render) {
|
|
1859
2514
|
return NoHydration ? NoHydration({
|
|
1860
2515
|
get children() {
|
|
@@ -1879,6 +2534,29 @@ function createFrameSink(emit, frame) {
|
|
|
1879
2534
|
version
|
|
1880
2535
|
} = frame;
|
|
1881
2536
|
const styledKeys = new Set();
|
|
2537
|
+
const bindings = new Map();
|
|
2538
|
+
const sweepMinted = new Set();
|
|
2539
|
+
const argRefVersions = new Map();
|
|
2540
|
+
let sweepScheduled = false;
|
|
2541
|
+
let closed = false;
|
|
2542
|
+
let epoch = 0;
|
|
2543
|
+
const sweep = () => {
|
|
2544
|
+
epoch++;
|
|
2545
|
+
for (const b of [...bindings.values()]) {
|
|
2546
|
+
try {
|
|
2547
|
+
b.sweep();
|
|
2548
|
+
} catch (_) {
|
|
2549
|
+
}
|
|
2550
|
+
}
|
|
2551
|
+
};
|
|
2552
|
+
const scheduleSweep = () => {
|
|
2553
|
+
if (closed || sweepScheduled || !bindings.size) return;
|
|
2554
|
+
sweepScheduled = true;
|
|
2555
|
+
queueMicrotask(() => {
|
|
2556
|
+
sweepScheduled = false;
|
|
2557
|
+
if (!closed) sweep();
|
|
2558
|
+
});
|
|
2559
|
+
};
|
|
1882
2560
|
const regionKeys = new Map();
|
|
1883
2561
|
const frameOf = key => regionKeys.get(key) || id;
|
|
1884
2562
|
return {
|
|
@@ -1920,6 +2598,7 @@ function createFrameSink(emit, frame) {
|
|
|
1920
2598
|
version,
|
|
1921
2599
|
payload: record
|
|
1922
2600
|
});
|
|
2601
|
+
scheduleSweep();
|
|
1923
2602
|
} else {
|
|
1924
2603
|
emit({
|
|
1925
2604
|
type: "data",
|
|
@@ -1929,6 +2608,7 @@ function createFrameSink(emit, frame) {
|
|
|
1929
2608
|
node: record.node,
|
|
1930
2609
|
initial: record.initial
|
|
1931
2610
|
});
|
|
2611
|
+
if (!sweepMinted.has(record.key)) scheduleSweep();
|
|
1932
2612
|
}
|
|
1933
2613
|
},
|
|
1934
2614
|
fragment(key, value, meta = {}) {
|
|
@@ -1965,6 +2645,7 @@ function createFrameSink(emit, frame) {
|
|
|
1965
2645
|
key,
|
|
1966
2646
|
html: value
|
|
1967
2647
|
});
|
|
2648
|
+
scheduleSweep();
|
|
1968
2649
|
if (meta.error) {
|
|
1969
2650
|
emit({
|
|
1970
2651
|
type: "error",
|
|
@@ -2019,6 +2700,8 @@ function createFrameSink(emit, frame) {
|
|
|
2019
2700
|
});
|
|
2020
2701
|
},
|
|
2021
2702
|
end() {
|
|
2703
|
+
if (bindings.size) sweep();
|
|
2704
|
+
closed = true;
|
|
2022
2705
|
emit({
|
|
2023
2706
|
type: "complete",
|
|
2024
2707
|
id,
|
|
@@ -2050,6 +2733,44 @@ function createFrameSink(emit, frame) {
|
|
|
2050
2733
|
version,
|
|
2051
2734
|
html
|
|
2052
2735
|
});
|
|
2736
|
+
},
|
|
2737
|
+
hole(key, html) {
|
|
2738
|
+
emit({
|
|
2739
|
+
type: "hole",
|
|
2740
|
+
id,
|
|
2741
|
+
version,
|
|
2742
|
+
key,
|
|
2743
|
+
html
|
|
2744
|
+
});
|
|
2745
|
+
},
|
|
2746
|
+
attr(key, attrs, removed) {
|
|
2747
|
+
const chunk = {
|
|
2748
|
+
type: "attr",
|
|
2749
|
+
id,
|
|
2750
|
+
version,
|
|
2751
|
+
key,
|
|
2752
|
+
attrs
|
|
2753
|
+
};
|
|
2754
|
+
if (removed && removed.length) chunk.removed = removed;
|
|
2755
|
+
emit(chunk);
|
|
2756
|
+
},
|
|
2757
|
+
openBinding(key, b) {
|
|
2758
|
+
bindings.set(key, b);
|
|
2759
|
+
},
|
|
2760
|
+
closeBinding(key) {
|
|
2761
|
+
bindings.delete(key);
|
|
2762
|
+
},
|
|
2763
|
+
mintRef(ref) {
|
|
2764
|
+
sweepMinted.add(ref);
|
|
2765
|
+
},
|
|
2766
|
+
nextArgRef(ledgerKey) {
|
|
2767
|
+
const n = (argRefVersions.get(ledgerKey) || 0) + 1;
|
|
2768
|
+
argRefVersions.set(ledgerKey, n);
|
|
2769
|
+
return n;
|
|
2770
|
+
},
|
|
2771
|
+
commit: scheduleSweep,
|
|
2772
|
+
get epoch() {
|
|
2773
|
+
return epoch;
|
|
2053
2774
|
}
|
|
2054
2775
|
};
|
|
2055
2776
|
}
|
|
@@ -2059,7 +2780,15 @@ function renderToFrameStream(code, options = {}) {
|
|
|
2059
2780
|
function renderServerComponent(component, options = {}) {
|
|
2060
2781
|
return frameStream((sink, frame) => {
|
|
2061
2782
|
const props = createSlotProps(sink, frame);
|
|
2062
|
-
return () =>
|
|
2783
|
+
return () => {
|
|
2784
|
+
const ctx = sharedConfig.context;
|
|
2785
|
+
if (ctx) {
|
|
2786
|
+
ctx.commit = sink.commit;
|
|
2787
|
+
ctx.commitEpoch = () => sink.epoch;
|
|
2788
|
+
ctx.liveHoles = createLiveHoles(sink);
|
|
2789
|
+
}
|
|
2790
|
+
return serverComponentScope(() => component(props));
|
|
2791
|
+
};
|
|
2063
2792
|
}, options);
|
|
2064
2793
|
}
|
|
2065
2794
|
function frameStream(makeCode, options) {
|
|
@@ -2117,7 +2846,8 @@ function frameStream(makeCode, options) {
|
|
|
2117
2846
|
}
|
|
2118
2847
|
function slotRange(occurrence) {
|
|
2119
2848
|
return {
|
|
2120
|
-
t: `<!--slot:${occurrence}:start--><!--slot:${occurrence}:end
|
|
2849
|
+
t: `<!--slot:${occurrence}:start--><!--slot:${occurrence}:end-->`,
|
|
2850
|
+
$slot: true
|
|
2121
2851
|
};
|
|
2122
2852
|
}
|
|
2123
2853
|
const OCCURRENCE_UNSAFE = /[^A-Za-z0-9_.-]/g;
|
|
@@ -2136,14 +2866,57 @@ function occurrenceId(prop, raw, counts) {
|
|
|
2136
2866
|
counts[prop] = n + 1;
|
|
2137
2867
|
return `${prop}#${n}`;
|
|
2138
2868
|
}
|
|
2869
|
+
function isAsyncValue(v) {
|
|
2870
|
+
return !!v && typeof v === "object" && (typeof v.then === "function" || typeof v[Symbol.asyncIterator] === "function");
|
|
2871
|
+
}
|
|
2872
|
+
function tapFirstYield(iterable) {
|
|
2873
|
+
const iter = iterable[Symbol.asyncIterator]();
|
|
2874
|
+
const firstStep = Promise.resolve(iter.next());
|
|
2875
|
+
return {
|
|
2876
|
+
first: firstStep.then(r => r.done ? undefined : r.value),
|
|
2877
|
+
rest: {
|
|
2878
|
+
[Symbol.asyncIterator]() {
|
|
2879
|
+
let replayed = false;
|
|
2880
|
+
return {
|
|
2881
|
+
next: () => {
|
|
2882
|
+
if (!replayed) {
|
|
2883
|
+
replayed = true;
|
|
2884
|
+
return firstStep;
|
|
2885
|
+
}
|
|
2886
|
+
return iter.next();
|
|
2887
|
+
},
|
|
2888
|
+
return: v => iter.return ? iter.return(v) : Promise.resolve({
|
|
2889
|
+
done: true,
|
|
2890
|
+
value: v
|
|
2891
|
+
}),
|
|
2892
|
+
throw: e => iter.throw ? iter.throw(e) : Promise.reject(e)
|
|
2893
|
+
};
|
|
2894
|
+
}
|
|
2895
|
+
}
|
|
2896
|
+
};
|
|
2897
|
+
}
|
|
2898
|
+
function suppressedFill(render) {
|
|
2899
|
+
const live = sharedConfig.context && sharedConfig.context.liveHoles;
|
|
2900
|
+
if (!live) return render();
|
|
2901
|
+
live.suppressed++;
|
|
2902
|
+
try {
|
|
2903
|
+
return render();
|
|
2904
|
+
} finally {
|
|
2905
|
+
live.suppressed--;
|
|
2906
|
+
}
|
|
2907
|
+
}
|
|
2139
2908
|
function createDocumentSlotProps(clientProps, frameId) {
|
|
2140
2909
|
const counts = Object.create(null);
|
|
2141
2910
|
const getters = new Map();
|
|
2142
|
-
const range = (occurrence, content) =>
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2911
|
+
const range = (occurrence, content) => {
|
|
2912
|
+
const r = [{
|
|
2913
|
+
t: `<!--slot:${occurrence}:start-->`
|
|
2914
|
+
}, content, {
|
|
2915
|
+
t: `<!--slot:${occurrence}:end-->`
|
|
2916
|
+
}];
|
|
2917
|
+
r.$slot = true;
|
|
2918
|
+
return r;
|
|
2919
|
+
};
|
|
2147
2920
|
const zoneOwner = getOwner ? getOwner() : null;
|
|
2148
2921
|
const scoped = (occurrence, render) => {
|
|
2149
2922
|
const id = `sc-${frameId}-${occurrence}-`;
|
|
@@ -2166,27 +2939,68 @@ function createDocumentSlotProps(clientProps, frameId) {
|
|
|
2166
2939
|
if (!fn) {
|
|
2167
2940
|
fn = (...callArgs) => {
|
|
2168
2941
|
if (callArgs.length === 0 || callArgs[0] === undefined) {
|
|
2169
|
-
return scoped(prop, () => {
|
|
2942
|
+
return suppressedFill(() => scoped(prop, () => {
|
|
2170
2943
|
const value = clientProps[prop];
|
|
2171
2944
|
return range(prop, typeof value === "function" ? value() : value);
|
|
2172
|
-
});
|
|
2945
|
+
}));
|
|
2173
2946
|
}
|
|
2174
2947
|
const raw = callArgs[0];
|
|
2175
2948
|
const occurrence = occurrenceId(prop, raw, counts);
|
|
2176
2949
|
const slot = clientProps[prop];
|
|
2177
2950
|
if (typeof slot !== "function") return range(occurrence, undefined);
|
|
2178
2951
|
const resolved = {};
|
|
2952
|
+
const liveArgs = sharedConfig.context && sharedConfig.context.live && sharedConfig.context.live.args;
|
|
2179
2953
|
const vals = {};
|
|
2954
|
+
const evals = {};
|
|
2955
|
+
const states = {};
|
|
2956
|
+
const minted = {};
|
|
2180
2957
|
for (const key of Object.keys(raw)) {
|
|
2181
2958
|
if (key === "$key") continue;
|
|
2182
|
-
|
|
2183
|
-
|
|
2959
|
+
const desc = Object.getOwnPropertyDescriptor(raw, key);
|
|
2960
|
+
let evaluate = null;
|
|
2961
|
+
let value;
|
|
2962
|
+
if (desc.get) {
|
|
2963
|
+
const get = desc.get;
|
|
2964
|
+
evaluate = () => unwrapThunks(get.call(raw));
|
|
2965
|
+
} else {
|
|
2966
|
+
value = desc.value;
|
|
2967
|
+
if (typeof value === "function") {
|
|
2968
|
+
const fn = value;
|
|
2969
|
+
evaluate = () => unwrapThunks(fn);
|
|
2970
|
+
}
|
|
2971
|
+
}
|
|
2972
|
+
if (evaluate) {
|
|
2973
|
+
evals[key] = evaluate;
|
|
2974
|
+
const stampBefore = scopeStamp();
|
|
2975
|
+
try {
|
|
2976
|
+
value = evaluate();
|
|
2977
|
+
states[key] = {
|
|
2978
|
+
settled: true,
|
|
2979
|
+
last: value
|
|
2980
|
+
};
|
|
2981
|
+
} catch (err) {
|
|
2982
|
+
const blocked = ssrHandleError && ssrHandleError(err);
|
|
2983
|
+
if (!blocked) throw err;
|
|
2984
|
+
const state = states[key] = {
|
|
2985
|
+
settled: false,
|
|
2986
|
+
last: undefined
|
|
2987
|
+
};
|
|
2988
|
+
value = retryArgUntilSettled(evaluate, blocked, key, occurrence, v => {
|
|
2989
|
+
state.settled = true;
|
|
2990
|
+
state.last = v;
|
|
2991
|
+
if (liveArgs) liveArgs.commit();
|
|
2992
|
+
});
|
|
2993
|
+
}
|
|
2994
|
+
if (scopeStamp() !== stampBefore) minted[key] = true;
|
|
2995
|
+
}
|
|
2184
2996
|
vals[key] = value;
|
|
2185
2997
|
}
|
|
2186
2998
|
const regions = [];
|
|
2187
2999
|
for (const key of Object.keys(vals)) {
|
|
2188
3000
|
const value = vals[key];
|
|
2189
|
-
if (
|
|
3001
|
+
if (isContainerTraced(value)) {
|
|
3002
|
+
resolved[key] = value;
|
|
3003
|
+
} else if (isServerContent(value)) {
|
|
2190
3004
|
const childId = `${frameId}.${occurrence}.${key}`;
|
|
2191
3005
|
const region = {
|
|
2192
3006
|
key,
|
|
@@ -2205,11 +3019,27 @@ function createDocumentSlotProps(clientProps, frameId) {
|
|
|
2205
3019
|
t: FRAME_ELEMENT_CLOSE
|
|
2206
3020
|
}];
|
|
2207
3021
|
};
|
|
3022
|
+
} else if (ssrAsyncValue && isAsyncValue(value)) {
|
|
3023
|
+
let readable = value;
|
|
3024
|
+
if (typeof value.then !== "function") {
|
|
3025
|
+
const {
|
|
3026
|
+
first,
|
|
3027
|
+
rest
|
|
3028
|
+
} = tapFirstYield(value);
|
|
3029
|
+
readable = first;
|
|
3030
|
+
vals[key] = rest;
|
|
3031
|
+
}
|
|
3032
|
+
const read = ssrAsyncValue(readable);
|
|
3033
|
+
Object.defineProperty(resolved, key, {
|
|
3034
|
+
get: read,
|
|
3035
|
+
enumerable: true,
|
|
3036
|
+
configurable: true
|
|
3037
|
+
});
|
|
2208
3038
|
} else {
|
|
2209
3039
|
resolved[key] = value;
|
|
2210
3040
|
}
|
|
2211
3041
|
}
|
|
2212
|
-
const out = scoped(occurrence, () => range(occurrence, slot(resolved)));
|
|
3042
|
+
const out = suppressedFill(() => scoped(occurrence, () => range(occurrence, slot(resolved))));
|
|
2213
3043
|
const unused = regions.filter(r => !r.used);
|
|
2214
3044
|
if (sharedConfig.context) {
|
|
2215
3045
|
const args = {};
|
|
@@ -2222,17 +3052,33 @@ function createDocumentSlotProps(clientProps, frameId) {
|
|
|
2222
3052
|
};
|
|
2223
3053
|
continue;
|
|
2224
3054
|
}
|
|
2225
|
-
if (isServerContent(value)) continue;
|
|
2226
|
-
args[key] = value;
|
|
3055
|
+
if (!isContainerTraced(value) && isServerContent(value)) continue;
|
|
3056
|
+
args[key] = envelopeContainerTraces(value);
|
|
2227
3057
|
}
|
|
2228
|
-
sharedConfig.context.serialize(`sc:slot:${frameId}:${occurrence}`,
|
|
3058
|
+
sharedConfig.context.serialize(`sc:slot:${frameId}:${occurrence}`, {
|
|
3059
|
+
...args
|
|
3060
|
+
});
|
|
2229
3061
|
for (const region of unused) {
|
|
2230
3062
|
region.locked = true;
|
|
2231
3063
|
sharedConfig.context.serialize(`sc:region:${region.childId}`, resolveRegionHtml(sharedConfig.context, region.value));
|
|
2232
3064
|
}
|
|
3065
|
+
if (liveArgs) {
|
|
3066
|
+
for (const key of Object.keys(evals)) {
|
|
3067
|
+
if (regions.some(r => r.key === key)) continue;
|
|
3068
|
+
if (minted[key]) continue;
|
|
3069
|
+
const ledgerKey = `${frameId}:${occurrence}:${key}`;
|
|
3070
|
+
openArgBinding(liveArgs, ledgerKey, occurrence, key, evals[key], states[key], value => {
|
|
3071
|
+
args[key] = envelopeContainerTraces(value);
|
|
3072
|
+
liveArgs.slot(frameId, occurrence, {
|
|
3073
|
+
...args
|
|
3074
|
+
});
|
|
3075
|
+
});
|
|
3076
|
+
}
|
|
3077
|
+
}
|
|
2233
3078
|
}
|
|
2234
3079
|
return out;
|
|
2235
3080
|
};
|
|
3081
|
+
fn.$lhSkip = true;
|
|
2236
3082
|
getters.set(prop, fn);
|
|
2237
3083
|
}
|
|
2238
3084
|
return fn;
|
|
@@ -2246,6 +3092,113 @@ function frameElementOpen(id) {
|
|
|
2246
3092
|
return `<${FRAME_TAG} ${FRAME_ID_ATTR}="${escaped}" style="display:contents">`;
|
|
2247
3093
|
}
|
|
2248
3094
|
const FRAME_ELEMENT_CLOSE = `</${FRAME_TAG}>`;
|
|
3095
|
+
function armDocumentLiveHoles(ctx) {
|
|
3096
|
+
if (!ctx || ctx.liveHoles !== undefined) return;
|
|
3097
|
+
const live = ctx.live;
|
|
3098
|
+
if (live && live.holes !== undefined) {
|
|
3099
|
+
ctx.liveHoles = live.holes;
|
|
3100
|
+
if (live.holes) {
|
|
3101
|
+
ctx.commit = live.commit;
|
|
3102
|
+
ctx.commitEpoch = live.commitEpoch;
|
|
3103
|
+
}
|
|
3104
|
+
return;
|
|
3105
|
+
}
|
|
3106
|
+
if (!live || !ctx.async || ctx.noHydrate || !ctx.serialize || typeof ReadableStream !== "function") {
|
|
3107
|
+
ctx.liveHoles = null;
|
|
3108
|
+
if (live) live.holes = null;
|
|
3109
|
+
return;
|
|
3110
|
+
}
|
|
3111
|
+
const bindings = new Map();
|
|
3112
|
+
let epoch = 0;
|
|
3113
|
+
let sweepScheduled = false;
|
|
3114
|
+
let closed = false;
|
|
3115
|
+
const sweep = () => {
|
|
3116
|
+
epoch++;
|
|
3117
|
+
for (const b of [...bindings.values()]) {
|
|
3118
|
+
try {
|
|
3119
|
+
b.sweep();
|
|
3120
|
+
} catch (_) {
|
|
3121
|
+
}
|
|
3122
|
+
}
|
|
3123
|
+
};
|
|
3124
|
+
const scheduleSweep = () => {
|
|
3125
|
+
if (closed || sweepScheduled || !bindings.size) return;
|
|
3126
|
+
sweepScheduled = true;
|
|
3127
|
+
queueMicrotask(() => {
|
|
3128
|
+
sweepScheduled = false;
|
|
3129
|
+
if (!closed) sweep();
|
|
3130
|
+
});
|
|
3131
|
+
};
|
|
3132
|
+
let channel;
|
|
3133
|
+
ctx.serialize("sc:live", new ReadableStream({
|
|
3134
|
+
start(c) {
|
|
3135
|
+
channel = c;
|
|
3136
|
+
}
|
|
3137
|
+
}));
|
|
3138
|
+
const push = op => {
|
|
3139
|
+
if (!closed) channel.enqueue(op);
|
|
3140
|
+
};
|
|
3141
|
+
ctx.liveHoles = live.holes = createLiveHoles({
|
|
3142
|
+
openBinding(key, b) {
|
|
3143
|
+
bindings.set(key, b);
|
|
3144
|
+
},
|
|
3145
|
+
closeBinding(key) {
|
|
3146
|
+
bindings.delete(key);
|
|
3147
|
+
},
|
|
3148
|
+
hole(key, html) {
|
|
3149
|
+
push({
|
|
3150
|
+
type: "hole",
|
|
3151
|
+
key,
|
|
3152
|
+
html
|
|
3153
|
+
});
|
|
3154
|
+
},
|
|
3155
|
+
attr(key, attrs, removed) {
|
|
3156
|
+
const op = {
|
|
3157
|
+
type: "attr",
|
|
3158
|
+
key,
|
|
3159
|
+
attrs
|
|
3160
|
+
};
|
|
3161
|
+
if (removed && removed.length) op.removed = removed;
|
|
3162
|
+
push(op);
|
|
3163
|
+
},
|
|
3164
|
+
error(key, error) {
|
|
3165
|
+
push({
|
|
3166
|
+
type: "error",
|
|
3167
|
+
key,
|
|
3168
|
+
error
|
|
3169
|
+
});
|
|
3170
|
+
},
|
|
3171
|
+
commit: scheduleSweep,
|
|
3172
|
+
get epoch() {
|
|
3173
|
+
return epoch;
|
|
3174
|
+
}
|
|
3175
|
+
}, true);
|
|
3176
|
+
ctx.commit = live.commit = scheduleSweep;
|
|
3177
|
+
ctx.commitEpoch = live.commitEpoch = () => epoch;
|
|
3178
|
+
live.args = {
|
|
3179
|
+
openBinding(key, b) {
|
|
3180
|
+
bindings.set(key, b);
|
|
3181
|
+
},
|
|
3182
|
+
closeBinding(key) {
|
|
3183
|
+
bindings.delete(key);
|
|
3184
|
+
},
|
|
3185
|
+
slot(fid, occurrence, args) {
|
|
3186
|
+
push({
|
|
3187
|
+
type: "slot",
|
|
3188
|
+
fid,
|
|
3189
|
+
key: occurrence,
|
|
3190
|
+
args
|
|
3191
|
+
});
|
|
3192
|
+
},
|
|
3193
|
+
commit: scheduleSweep
|
|
3194
|
+
};
|
|
3195
|
+
live.end = () => {
|
|
3196
|
+
if (closed) return;
|
|
3197
|
+
if (bindings.size) sweep();
|
|
3198
|
+
closed = true;
|
|
3199
|
+
channel.close();
|
|
3200
|
+
};
|
|
3201
|
+
}
|
|
2249
3202
|
function frameTransformDirectResult(value, {
|
|
2250
3203
|
id,
|
|
2251
3204
|
args
|
|
@@ -2256,6 +3209,7 @@ function frameTransformDirectResult(value, {
|
|
|
2256
3209
|
t: frameElementOpen(id)
|
|
2257
3210
|
},
|
|
2258
3211
|
serverOwned(() => {
|
|
3212
|
+
armDocumentLiveHoles(sharedConfig.context);
|
|
2259
3213
|
const slotProps = createDocumentSlotProps(props, id);
|
|
2260
3214
|
return serverComponentScope(() => component(slotProps));
|
|
2261
3215
|
}), {
|
|
@@ -2292,6 +3246,76 @@ function isServerContent(value) {
|
|
|
2292
3246
|
}
|
|
2293
3247
|
return false;
|
|
2294
3248
|
}
|
|
3249
|
+
function unwrapThunks(value) {
|
|
3250
|
+
for (let d = 0; typeof value === "function" && d < 16; d++) value = value();
|
|
3251
|
+
return value;
|
|
3252
|
+
}
|
|
3253
|
+
function contentArgError(key, occurrence) {
|
|
3254
|
+
return new Error("Async slot arg resolved to JSX (arg '" + key + "' of " + occurrence + "). Async args must resolve to serializable values; render async content through a boundary instead.");
|
|
3255
|
+
}
|
|
3256
|
+
function retryArgUntilSettled(evaluate, blocked, key, occurrence, onSettle) {
|
|
3257
|
+
const owner = getOwner();
|
|
3258
|
+
return new Promise((resolve, reject) => {
|
|
3259
|
+
const retry = () => {
|
|
3260
|
+
try {
|
|
3261
|
+
const value = owner ? runWithOwner(owner, evaluate) : evaluate();
|
|
3262
|
+
if (isServerContent(value)) {
|
|
3263
|
+
reject(contentArgError(key, occurrence));
|
|
3264
|
+
return;
|
|
3265
|
+
}
|
|
3266
|
+
if (onSettle) onSettle(value);
|
|
3267
|
+
resolve(value);
|
|
3268
|
+
} catch (err) {
|
|
3269
|
+
const next = ssrHandleError && ssrHandleError(err);
|
|
3270
|
+
if (next) next.then(retry, retry);else reject(err);
|
|
3271
|
+
}
|
|
3272
|
+
};
|
|
3273
|
+
blocked.then(retry, retry);
|
|
3274
|
+
});
|
|
3275
|
+
}
|
|
3276
|
+
function openArgBinding(sink, ledgerKey, occurrence, key, evaluate, state, emit) {
|
|
3277
|
+
const owner = getOwner();
|
|
3278
|
+
sink.openBinding(ledgerKey, {
|
|
3279
|
+
sweep() {
|
|
3280
|
+
if (!state.settled) return;
|
|
3281
|
+
let value;
|
|
3282
|
+
const stampBefore = scopeStamp();
|
|
3283
|
+
try {
|
|
3284
|
+
value = owner ? runWithOwner(owner, evaluate) : evaluate();
|
|
3285
|
+
} catch (err) {
|
|
3286
|
+
const blocked = ssrHandleError && ssrHandleError(err);
|
|
3287
|
+
if (!blocked) {
|
|
3288
|
+
sink.closeBinding(ledgerKey);
|
|
3289
|
+
emit(Promise.reject(err instanceof Error ? err : new Error(String(err))));
|
|
3290
|
+
return;
|
|
3291
|
+
}
|
|
3292
|
+
if (scopeStamp() !== stampBefore) {
|
|
3293
|
+
sink.closeBinding(ledgerKey);
|
|
3294
|
+
return;
|
|
3295
|
+
}
|
|
3296
|
+
state.settled = false;
|
|
3297
|
+
emit(retryArgUntilSettled(evaluate, blocked, key, occurrence, v => {
|
|
3298
|
+
state.settled = true;
|
|
3299
|
+
state.last = v;
|
|
3300
|
+
sink.commit();
|
|
3301
|
+
}));
|
|
3302
|
+
return;
|
|
3303
|
+
}
|
|
3304
|
+
if (scopeStamp() !== stampBefore) {
|
|
3305
|
+
sink.closeBinding(ledgerKey);
|
|
3306
|
+
return;
|
|
3307
|
+
}
|
|
3308
|
+
if (value === state.last) return;
|
|
3309
|
+
state.last = value;
|
|
3310
|
+
if (isServerContent(value)) {
|
|
3311
|
+
sink.closeBinding(ledgerKey);
|
|
3312
|
+
emit(Promise.reject(contentArgError(key, occurrence)));
|
|
3313
|
+
return;
|
|
3314
|
+
}
|
|
3315
|
+
emit(value);
|
|
3316
|
+
}
|
|
3317
|
+
});
|
|
3318
|
+
}
|
|
2295
3319
|
function createSlotProps(sink, frame) {
|
|
2296
3320
|
const counts = Object.create(null);
|
|
2297
3321
|
const getters = new Map();
|
|
@@ -2308,9 +3332,21 @@ function createSlotProps(sink, frame) {
|
|
|
2308
3332
|
if (callArgs.length === 0 || callArgs[0] === undefined) {
|
|
2309
3333
|
return slotRange(prop);
|
|
2310
3334
|
}
|
|
3335
|
+
const live = sharedConfig.context && sharedConfig.context.liveHoles;
|
|
3336
|
+
if (live) {
|
|
3337
|
+
if (live.sweeping) {
|
|
3338
|
+
live.gateHit = true;
|
|
3339
|
+
return {
|
|
3340
|
+
t: "",
|
|
3341
|
+
$slot: true
|
|
3342
|
+
};
|
|
3343
|
+
}
|
|
3344
|
+
live.recordStamp++;
|
|
3345
|
+
}
|
|
2311
3346
|
const raw = callArgs[0];
|
|
2312
3347
|
const occurrence = occurrenceId(prop, raw, counts);
|
|
2313
3348
|
const args = {};
|
|
3349
|
+
const opened = [];
|
|
2314
3350
|
for (const key of Object.keys(raw)) {
|
|
2315
3351
|
if (key === "$key") continue;
|
|
2316
3352
|
const childId = `${frame.id}.${occurrence}.${key}`;
|
|
@@ -2321,12 +3357,47 @@ function createSlotProps(sink, frame) {
|
|
|
2321
3357
|
return origRegister.call(ctx, fragKey, fragOptions);
|
|
2322
3358
|
};
|
|
2323
3359
|
try {
|
|
2324
|
-
|
|
2325
|
-
|
|
3360
|
+
const desc = Object.getOwnPropertyDescriptor(raw, key);
|
|
3361
|
+
let evaluate = null;
|
|
3362
|
+
let value;
|
|
3363
|
+
let state = null;
|
|
3364
|
+
const stampBefore = scopeStamp();
|
|
3365
|
+
try {
|
|
3366
|
+
if (desc.get) {
|
|
3367
|
+
const get = desc.get;
|
|
3368
|
+
evaluate = () => unwrapThunks(get.call(raw));
|
|
3369
|
+
value = evaluate();
|
|
3370
|
+
} else {
|
|
3371
|
+
value = desc.value;
|
|
3372
|
+
if (typeof value === "function") {
|
|
3373
|
+
const fn = value;
|
|
3374
|
+
evaluate = () => unwrapThunks(fn);
|
|
3375
|
+
value = evaluate();
|
|
3376
|
+
}
|
|
3377
|
+
}
|
|
3378
|
+
} catch (err) {
|
|
3379
|
+
const blocked = ssrHandleError && ssrHandleError(err);
|
|
3380
|
+
if (!blocked) throw err;
|
|
3381
|
+
state = {
|
|
3382
|
+
settled: false,
|
|
3383
|
+
last: undefined
|
|
3384
|
+
};
|
|
3385
|
+
const pendingState = state;
|
|
3386
|
+
value = retryArgUntilSettled(evaluate, blocked, key, occurrence, v => {
|
|
3387
|
+
pendingState.settled = true;
|
|
3388
|
+
pendingState.last = v;
|
|
3389
|
+
sink.commit();
|
|
3390
|
+
});
|
|
3391
|
+
}
|
|
3392
|
+
const mintedEval = scopeStamp() !== stampBefore;
|
|
2326
3393
|
const t = typeof value;
|
|
2327
3394
|
if (value == null || t === "string" || t === "number" || t === "boolean") {
|
|
2328
3395
|
args[key] = value;
|
|
2329
|
-
|
|
3396
|
+
if (evaluate) state = {
|
|
3397
|
+
settled: true,
|
|
3398
|
+
last: value
|
|
3399
|
+
};
|
|
3400
|
+
} else if (!isContainerTraced(value) && isServerContent(value)) {
|
|
2330
3401
|
const resolved = ctx.resolve(value);
|
|
2331
3402
|
if (resolved.h.length) {
|
|
2332
3403
|
throw new Error("Async server content in a slot arg needs a boundary (arg '" + key + "' of " + occurrence + "). Wrap the async read in a <Suspense>, or move it above the slot.");
|
|
@@ -2337,30 +3408,72 @@ function createSlotProps(sink, frame) {
|
|
|
2337
3408
|
};
|
|
2338
3409
|
} else {
|
|
2339
3410
|
const ref = `arg:${occurrence}:${key}`;
|
|
2340
|
-
ctx.serialize(ref, value);
|
|
3411
|
+
ctx.serialize(ref, envelopeContainerTraces(value));
|
|
2341
3412
|
args[key] = {
|
|
2342
3413
|
$ref: ref
|
|
2343
3414
|
};
|
|
3415
|
+
if (evaluate && !state) state = {
|
|
3416
|
+
settled: true,
|
|
3417
|
+
last: value
|
|
3418
|
+
};
|
|
2344
3419
|
}
|
|
3420
|
+
if (evaluate && state && !mintedEval) opened.push({
|
|
3421
|
+
key,
|
|
3422
|
+
evaluate,
|
|
3423
|
+
state
|
|
3424
|
+
});
|
|
2345
3425
|
} finally {
|
|
2346
3426
|
ctx.registerFragment = origRegister;
|
|
2347
3427
|
}
|
|
2348
3428
|
}
|
|
2349
|
-
sink.slot(occurrence,
|
|
3429
|
+
sink.slot(occurrence, {
|
|
3430
|
+
...args
|
|
3431
|
+
});
|
|
3432
|
+
const ctx = sharedConfig.context;
|
|
3433
|
+
for (const b of opened) {
|
|
3434
|
+
const key = b.key;
|
|
3435
|
+
const ledgerKey = `${occurrence}:${key}`;
|
|
3436
|
+
openArgBinding(sink, ledgerKey, occurrence, key, b.evaluate, b.state, value => {
|
|
3437
|
+
const t = typeof value;
|
|
3438
|
+
if (value == null || t === "string" || t === "number" || t === "boolean") {
|
|
3439
|
+
args[key] = value;
|
|
3440
|
+
} else {
|
|
3441
|
+
const ref = `arg:${occurrence}:${key}@${sink.nextArgRef(ledgerKey)}`;
|
|
3442
|
+
sink.mintRef(ref);
|
|
3443
|
+
ctx.serialize(ref, envelopeContainerTraces(value));
|
|
3444
|
+
args[key] = {
|
|
3445
|
+
$ref: ref
|
|
3446
|
+
};
|
|
3447
|
+
}
|
|
3448
|
+
sink.slot(occurrence, {
|
|
3449
|
+
...args
|
|
3450
|
+
});
|
|
3451
|
+
});
|
|
3452
|
+
}
|
|
2350
3453
|
return slotRange(occurrence);
|
|
2351
3454
|
};
|
|
3455
|
+
fn.$lhSkip = true;
|
|
2352
3456
|
getters.set(prop, fn);
|
|
2353
3457
|
}
|
|
2354
3458
|
return fn;
|
|
2355
3459
|
}
|
|
2356
3460
|
});
|
|
2357
3461
|
}
|
|
3462
|
+
function copyInitHeaders(init) {
|
|
3463
|
+
if (!init || !init.getSetCookie) return new Headers(init);
|
|
3464
|
+
const headers = new Headers();
|
|
3465
|
+
init.forEach((value, key) => {
|
|
3466
|
+
if (key !== "set-cookie") headers.append(key, value);
|
|
3467
|
+
});
|
|
3468
|
+
for (const cookie of init.getSetCookie()) headers.append("Set-Cookie", cookie);
|
|
3469
|
+
return headers;
|
|
3470
|
+
}
|
|
2358
3471
|
function serverComponentResponse(component, options = {}, init = {}) {
|
|
2359
3472
|
const {
|
|
2360
3473
|
id = "",
|
|
2361
3474
|
version = 1
|
|
2362
3475
|
} = options.frame || {};
|
|
2363
|
-
const headers =
|
|
3476
|
+
const headers = copyInitHeaders(init.headers);
|
|
2364
3477
|
headers.set("Content-Type", "application/x-frame-stream");
|
|
2365
3478
|
headers.set(FRAME_STREAM_HEADER, id);
|
|
2366
3479
|
headers.set("X-Content-Raw", "1");
|
|
@@ -2371,16 +3484,27 @@ function serverComponentResponse(component, options = {}, init = {}) {
|
|
|
2371
3484
|
version
|
|
2372
3485
|
}
|
|
2373
3486
|
});
|
|
3487
|
+
let closed = false;
|
|
2374
3488
|
const body = new ReadableStream({
|
|
2375
3489
|
start(controller) {
|
|
2376
3490
|
stream.pipe({
|
|
2377
3491
|
write(chunk) {
|
|
2378
|
-
|
|
3492
|
+
if (closed) return;
|
|
3493
|
+
try {
|
|
3494
|
+
controller.enqueue(createChunk(JSON.stringify(chunk)));
|
|
3495
|
+
} catch (_) {
|
|
3496
|
+
closed = true;
|
|
3497
|
+
}
|
|
2379
3498
|
},
|
|
2380
3499
|
end() {
|
|
3500
|
+
if (closed) return;
|
|
3501
|
+
closed = true;
|
|
2381
3502
|
controller.close();
|
|
2382
3503
|
}
|
|
2383
3504
|
});
|
|
3505
|
+
},
|
|
3506
|
+
cancel() {
|
|
3507
|
+
closed = true;
|
|
2384
3508
|
}
|
|
2385
3509
|
});
|
|
2386
3510
|
return new Response(body, {
|
|
@@ -2459,14 +3583,22 @@ function frameFlightResponse({
|
|
|
2459
3583
|
codec
|
|
2460
3584
|
}, init = {}) {
|
|
2461
3585
|
const frames = primary ? [primary, ...regions] : regions;
|
|
2462
|
-
const headers =
|
|
3586
|
+
const headers = copyInitHeaders(init.headers);
|
|
2463
3587
|
headers.set("Content-Type", "application/x-frame-stream");
|
|
2464
3588
|
headers.set(FRAME_STREAM_HEADER, primary ? primary.id : "");
|
|
2465
3589
|
headers.set("X-Content-Raw", "1");
|
|
2466
3590
|
headers.set(SINGLE_FLIGHT_HEADER, "true");
|
|
3591
|
+
let closed = false;
|
|
2467
3592
|
const body = new ReadableStream({
|
|
2468
3593
|
async start(controller) {
|
|
2469
|
-
const write = chunk =>
|
|
3594
|
+
const write = chunk => {
|
|
3595
|
+
if (closed) return;
|
|
3596
|
+
try {
|
|
3597
|
+
controller.enqueue(createChunk(JSON.stringify(chunk)));
|
|
3598
|
+
} catch (_) {
|
|
3599
|
+
closed = true;
|
|
3600
|
+
}
|
|
3601
|
+
};
|
|
2470
3602
|
try {
|
|
2471
3603
|
for (const {
|
|
2472
3604
|
id,
|
|
@@ -2493,10 +3625,19 @@ function frameFlightResponse({
|
|
|
2493
3625
|
});
|
|
2494
3626
|
}
|
|
2495
3627
|
}
|
|
2496
|
-
|
|
3628
|
+
if (!closed) {
|
|
3629
|
+
closed = true;
|
|
3630
|
+
controller.close();
|
|
3631
|
+
}
|
|
2497
3632
|
} catch (err) {
|
|
2498
|
-
|
|
3633
|
+
if (!closed) {
|
|
3634
|
+
closed = true;
|
|
3635
|
+
controller.error(err);
|
|
3636
|
+
}
|
|
2499
3637
|
}
|
|
3638
|
+
},
|
|
3639
|
+
cancel() {
|
|
3640
|
+
closed = true;
|
|
2500
3641
|
}
|
|
2501
3642
|
});
|
|
2502
3643
|
return new Response(body, {
|
|
@@ -2505,4 +3646,9 @@ function frameFlightResponse({
|
|
|
2505
3646
|
});
|
|
2506
3647
|
}
|
|
2507
3648
|
|
|
2508
|
-
|
|
3649
|
+
setContainerTraceResolver(getProjectionTrace);
|
|
3650
|
+
function asyncArg(value) {
|
|
3651
|
+
return value;
|
|
3652
|
+
}
|
|
3653
|
+
|
|
3654
|
+
export { FRAME_STREAM_HEADER, SERVER_COMPONENT_BOOTSTRAP, ServerComponentPlugin, asyncArg, createFrameSink, frameTransformDirectResult, frameTransformFlightResult, frameTransformResult, isFrameStreamResponse, renderServerComponent, renderToFrameStream, serverComponentResponse };
|