@solidjs/web 2.0.0-experimental.9 → 2.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -4
- package/dist/dev.cjs +1588 -224
- package/dist/dev.js +1513 -200
- package/dist/server.cjs +2722 -254
- package/dist/server.js +2659 -245
- package/dist/web.cjs +1524 -218
- package/dist/web.js +1449 -194
- package/frames/dist/client.cjs +1916 -0
- package/frames/dist/client.dev.cjs +1933 -0
- package/frames/dist/client.dev.js +1921 -0
- package/frames/dist/client.js +1904 -0
- package/frames/dist/server.cjs +3756 -0
- package/frames/dist/server.js +3743 -0
- package/frames/package.json +30 -0
- package/package.json +350 -37
- package/serialization/decode/package.json +20 -0
- package/serialization/dist/decode.cjs +122 -0
- package/serialization/dist/decode.js +116 -0
- package/serialization/dist/serialization.cjs +244 -0
- package/serialization/dist/serialization.js +227 -0
- package/serialization/package.json +20 -0
- package/serialization/types/index.d.ts +182 -0
- package/serialization/types/serializer-decode.d.ts +182 -0
- package/serialization/types-cjs/index.d.cts +182 -0
- package/serialization/types-cjs/package.json +3 -0
- package/serialization/types-cjs/serializer-decode.d.cts +182 -0
- package/server-functions/dist/client.cjs +793 -0
- package/server-functions/dist/client.js +763 -0
- package/server-functions/dist/rich-args.cjs +11 -0
- package/server-functions/dist/rich-args.js +9 -0
- package/server-functions/dist/server.cjs +1171 -0
- package/server-functions/dist/server.dev.cjs +1171 -0
- package/server-functions/dist/server.dev.js +1137 -0
- package/server-functions/dist/server.js +1137 -0
- package/server-functions/package.json +40 -0
- package/server-functions/rich-args/package.json +20 -0
- package/storage/package.json +8 -3
- package/storage/types/index.d.ts +26 -0
- package/storage/types-cjs/index.d.cts +28 -0
- package/storage/types-cjs/package.json +3 -0
- package/types/client.d.ts +290 -27
- package/types/cookies.d.ts +93 -0
- package/types/core.d.ts +6 -2
- package/types/frames/client.d.ts +36 -0
- package/types/frames/frame-client.d.ts +338 -0
- package/types/frames/frame-sink.d.ts +194 -0
- package/types/frames/frame-transport.d.ts +222 -0
- package/types/frames/serializer.d.ts +182 -0
- package/types/frames/server.d.ts +52 -0
- package/types/index.d.ts +223 -24
- package/types/jsx-properties.d.ts +93 -0
- package/types/jsx.d.ts +4159 -1
- package/types/response.d.ts +174 -0
- package/types/serializer-decode.d.ts +182 -0
- package/types/serializer.d.ts +182 -0
- package/types/server-functions/client.d.ts +231 -0
- package/types/server-functions/flash.d.ts +38 -0
- package/types/server-functions/rich-args.d.ts +10 -0
- package/types/server-functions/server.d.ts +616 -0
- package/types/server-functions/shared.d.ts +523 -0
- package/types/server-mock.d.ts +249 -12
- package/types/server.d.ts +424 -51
- package/types-cjs/client.d.cts +337 -0
- package/types-cjs/cookies.d.cts +93 -0
- package/types-cjs/core.d.cts +6 -0
- package/types-cjs/frames/client.d.cts +36 -0
- package/types-cjs/frames/frame-client.d.cts +338 -0
- package/types-cjs/frames/frame-sink.d.cts +194 -0
- package/types-cjs/frames/frame-transport.d.cts +222 -0
- package/types-cjs/frames/serializer.d.cts +182 -0
- package/types-cjs/frames/server.d.cts +52 -0
- package/types-cjs/index.d.cts +244 -0
- package/types-cjs/jsx-properties.d.cts +93 -0
- package/types-cjs/jsx.d.cts +4159 -0
- package/types-cjs/package.json +3 -0
- package/types-cjs/response.d.cts +174 -0
- package/types-cjs/serializer-decode.d.cts +182 -0
- package/types-cjs/serializer.d.cts +182 -0
- package/types-cjs/server-functions/client.d.cts +231 -0
- package/types-cjs/server-functions/flash.d.cts +38 -0
- package/types-cjs/server-functions/rich-args.d.cts +10 -0
- package/types-cjs/server-functions/server.d.cts +616 -0
- package/types-cjs/server-functions/shared.d.cts +523 -0
- package/types-cjs/server-mock.d.cts +277 -0
- package/types-cjs/server.d.cts +523 -0
|
@@ -0,0 +1,3743 @@
|
|
|
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
|
+
import { AbortSignalPlugin, CustomEventPlugin, DOMExceptionPlugin, EventPlugin, FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLSearchParamsPlugin, URLPlugin } from 'seroval-plugins/web';
|
|
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
|
+
|
|
97
|
+
const runWithHydrationScope = (id, fn) => runWithOwner(createOwner({
|
|
98
|
+
id
|
|
99
|
+
}), fn);
|
|
100
|
+
const ssrAsyncValue = value => createMemo(() => value, {
|
|
101
|
+
serialize: false
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const DEFAULT_WEB_PLUGINS = Object.freeze([AbortSignalPlugin,
|
|
105
|
+
CustomEventPlugin, DOMExceptionPlugin, EventPlugin,
|
|
106
|
+
FormDataPlugin, HeadersPlugin, ReadableStreamPlugin, RequestPlugin, ResponsePlugin, URLSearchParamsPlugin, URLPlugin,
|
|
107
|
+
ContainerTracePlugin]);
|
|
108
|
+
function resolveSerializerPlugins(customPlugins) {
|
|
109
|
+
return customPlugins ? [...customPlugins, ...DEFAULT_WEB_PLUGINS] : [...DEFAULT_WEB_PLUGINS];
|
|
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";
|
|
128
|
+
function createSerializer(options) {
|
|
129
|
+
return new Serializer({
|
|
130
|
+
...options,
|
|
131
|
+
plugins: resolveSerializerPlugins(options.plugins),
|
|
132
|
+
disabledFeatures: (options.disabledFeatures === undefined ? DEFAULT_DISABLED_FEATURES : options.disabledFeatures) | serializeOnlyDisabledFeatures()
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
function createHydrationSerializer({
|
|
136
|
+
onData,
|
|
137
|
+
onDone,
|
|
138
|
+
scopeId,
|
|
139
|
+
onError,
|
|
140
|
+
plugins
|
|
141
|
+
}) {
|
|
142
|
+
return createSerializer({
|
|
143
|
+
scopeId,
|
|
144
|
+
plugins,
|
|
145
|
+
globalIdentifier: HYDRATION_GLOBAL,
|
|
146
|
+
onData,
|
|
147
|
+
onDone,
|
|
148
|
+
onError
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
function getLocalHeaderScript(id) {
|
|
152
|
+
return getCrossReferenceHeader(id) + ";";
|
|
153
|
+
}
|
|
154
|
+
function createJSONSerializer({
|
|
155
|
+
onData,
|
|
156
|
+
onDone,
|
|
157
|
+
onError,
|
|
158
|
+
plugins,
|
|
159
|
+
disabledFeatures,
|
|
160
|
+
depthLimit
|
|
161
|
+
}) {
|
|
162
|
+
const resolved = resolveCodecOptions({
|
|
163
|
+
plugins,
|
|
164
|
+
disabledFeatures,
|
|
165
|
+
depthLimit
|
|
166
|
+
});
|
|
167
|
+
const refs = new Map();
|
|
168
|
+
const cancels = new Set();
|
|
169
|
+
let pendingWrites = 0;
|
|
170
|
+
let flushed = false;
|
|
171
|
+
let done = false;
|
|
172
|
+
const maybeDone = () => {
|
|
173
|
+
if (flushed && pendingWrites === 0 && !done) {
|
|
174
|
+
done = true;
|
|
175
|
+
onDone && onDone();
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
return {
|
|
179
|
+
write(key, value) {
|
|
180
|
+
if (flushed) return;
|
|
181
|
+
pendingWrites++;
|
|
182
|
+
let settled = false;
|
|
183
|
+
let cancel = null;
|
|
184
|
+
const stream = toCrossJSONStream(value, {
|
|
185
|
+
refs,
|
|
186
|
+
plugins: resolved.plugins,
|
|
187
|
+
disabledFeatures: resolved.disabledFeatures | serializeOnlyDisabledFeatures(),
|
|
188
|
+
onParse(node, initial) {
|
|
189
|
+
onData({
|
|
190
|
+
key,
|
|
191
|
+
node,
|
|
192
|
+
initial
|
|
193
|
+
});
|
|
194
|
+
},
|
|
195
|
+
onError,
|
|
196
|
+
onDone() {
|
|
197
|
+
settled = true;
|
|
198
|
+
if (cancel) cancels.delete(cancel);
|
|
199
|
+
pendingWrites--;
|
|
200
|
+
maybeDone();
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
if (!settled) {
|
|
204
|
+
cancel = stream;
|
|
205
|
+
cancels.add(cancel);
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
flush() {
|
|
209
|
+
flushed = true;
|
|
210
|
+
maybeDone();
|
|
211
|
+
},
|
|
212
|
+
close() {
|
|
213
|
+
flushed = true;
|
|
214
|
+
for (const cancel of cancels) cancel();
|
|
215
|
+
cancels.clear();
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
}
|
|
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
|
+
|
|
360
|
+
const HEAD_ELIGIBLE_TAGS = new Set(["title", "meta", "link", "style", "script", "base"]);
|
|
361
|
+
const HEAD_ATTR_NAME = /^[a-zA-Z_][a-zA-Z0-9_:.-]*$/;
|
|
362
|
+
const RESOURCE_LINK_RELS = new Set(["preload", "modulepreload", "prefetch", "preconnect", "dns-prefetch", "stylesheet"]);
|
|
363
|
+
const RESOURCE_QUALIFIERS = ["as", "crossorigin", "type", "media", "imagesrcset", "imagesizes"];
|
|
364
|
+
const STYLESHEET_FETCH_META = new Set(["crossorigin", "integrity", "referrerpolicy", "fetchpriority"]);
|
|
365
|
+
function evalHeadValue(v) {
|
|
366
|
+
return typeof v === "function" ? v() : v;
|
|
367
|
+
}
|
|
368
|
+
function evalHeadProps(props, presets) {
|
|
369
|
+
const out = {};
|
|
370
|
+
for (const name in props) out[name] = presets && name in presets ? presets[name] : evalHeadValue(props[name]);
|
|
371
|
+
return out;
|
|
372
|
+
}
|
|
373
|
+
function classifyHeadTag(desc) {
|
|
374
|
+
const tag = desc.tag;
|
|
375
|
+
if (tag === "link") {
|
|
376
|
+
const rel = evalHeadValue(desc.props && desc.props.rel);
|
|
377
|
+
return {
|
|
378
|
+
resource: RESOURCE_LINK_RELS.has(rel),
|
|
379
|
+
rel
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
if (tag === "style") return {
|
|
383
|
+
resource: !!(desc.props && "href" in desc.props)
|
|
384
|
+
};
|
|
385
|
+
if (tag === "script") return {
|
|
386
|
+
resource: !!(desc.props && "src" in desc.props)
|
|
387
|
+
};
|
|
388
|
+
return {
|
|
389
|
+
resource: false
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
function resourceIdentity(tag, props) {
|
|
393
|
+
let id = "res:" + tag + ":" + (props.rel || "") + ":" + (props.href || props.src || "");
|
|
394
|
+
for (let i = 0; i < RESOURCE_QUALIFIERS.length; i++) {
|
|
395
|
+
const q = RESOURCE_QUALIFIERS[i];
|
|
396
|
+
if (props[q] != null) id += ":" + q + "=" + props[q];
|
|
397
|
+
}
|
|
398
|
+
return id;
|
|
399
|
+
}
|
|
400
|
+
function replaceableIdentity(tag, props, key, unique) {
|
|
401
|
+
if (tag === "title") return "title";
|
|
402
|
+
if (tag === "base") return "base";
|
|
403
|
+
if (tag === "meta" && props.charset != null) return "charset";
|
|
404
|
+
if (key != null) return tag + ":key:" + key;
|
|
405
|
+
if (tag === "meta") {
|
|
406
|
+
for (const ns of ["name", "property", "http-equiv"]) if (props[ns] != null) return "meta:" + ns + ":" + props[ns] + (props.media != null ? ":media=" + props.media : "");
|
|
407
|
+
return unique;
|
|
408
|
+
}
|
|
409
|
+
if (tag === "link") {
|
|
410
|
+
const rel = props.rel || "";
|
|
411
|
+
if (rel === "icon" || rel === "apple-touch-icon") return "link:" + rel + (props.sizes != null ? ":sizes=" + props.sizes : "") + (props.type != null ? ":type=" + props.type : "");
|
|
412
|
+
return "link:" + rel + ":" + (props.href || "");
|
|
413
|
+
}
|
|
414
|
+
return unique;
|
|
415
|
+
}
|
|
416
|
+
function resolveHead(groups) {
|
|
417
|
+
const winners = new Map();
|
|
418
|
+
const sorted = groups.slice().sort((a, b) => a.seq - b.seq);
|
|
419
|
+
for (let i = 0; i < sorted.length; i++) {
|
|
420
|
+
const group = sorted[i];
|
|
421
|
+
const byIdentity = new Map();
|
|
422
|
+
for (let j = 0; j < group.tags.length; j++) {
|
|
423
|
+
const t = group.tags[j];
|
|
424
|
+
let list = byIdentity.get(t.identity);
|
|
425
|
+
if (!list) byIdentity.set(t.identity, list = []);
|
|
426
|
+
list.push(t);
|
|
427
|
+
}
|
|
428
|
+
for (const [identity, tags] of byIdentity) {
|
|
429
|
+
if (identity === "title") {
|
|
430
|
+
winners.set(identity, {
|
|
431
|
+
seq: group.seq,
|
|
432
|
+
tags: [tags[tags.length - 1]]
|
|
433
|
+
});
|
|
434
|
+
} else {
|
|
435
|
+
winners.set(identity, {
|
|
436
|
+
seq: group.seq,
|
|
437
|
+
tags
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
return winners;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
function joinAssetPath(base, file) {
|
|
446
|
+
if (/^(?:[a-z][a-z0-9+.-]*:)?\/\//i.test(file)) return file;
|
|
447
|
+
if (typeof base !== "string" || !base) base = "/";
|
|
448
|
+
if (base[base.length - 1] !== "/") base += "/";
|
|
449
|
+
return base + (file[0] === "/" ? file.slice(1) : file);
|
|
450
|
+
}
|
|
451
|
+
function resolveAssets(moduleUrl, manifest) {
|
|
452
|
+
if (!manifest) return null;
|
|
453
|
+
const base = manifest._base;
|
|
454
|
+
const entry = manifest[moduleUrl];
|
|
455
|
+
if (!entry) return null;
|
|
456
|
+
const css = [];
|
|
457
|
+
const js = [];
|
|
458
|
+
const visited = new Set();
|
|
459
|
+
const walk = key => {
|
|
460
|
+
if (visited.has(key)) return;
|
|
461
|
+
visited.add(key);
|
|
462
|
+
const e = manifest[key];
|
|
463
|
+
if (!e) return;
|
|
464
|
+
js.push(joinAssetPath(base, e.file));
|
|
465
|
+
if (e.css) for (let i = 0; i < e.css.length; i++) css.push(joinAssetPath(base, e.css[i]));
|
|
466
|
+
if (e.imports) for (let i = 0; i < e.imports.length; i++) walk(e.imports[i]);
|
|
467
|
+
};
|
|
468
|
+
walk(moduleUrl);
|
|
469
|
+
return {
|
|
470
|
+
js,
|
|
471
|
+
css
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
function registerEntryAssets(manifest) {
|
|
475
|
+
if (!manifest || typeof manifest === "function" || typeof manifest.resolve === "function") return;
|
|
476
|
+
const ctx = sharedConfig.context;
|
|
477
|
+
if (!ctx?.registerAsset) return;
|
|
478
|
+
for (const key in manifest) {
|
|
479
|
+
if (manifest[key].isEntry) {
|
|
480
|
+
const assets = resolveAssets(key, manifest);
|
|
481
|
+
if (assets) {
|
|
482
|
+
for (let i = 0; i < assets.css.length; i++) ctx.registerAsset("style", assets.css[i]);
|
|
483
|
+
}
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
function createAssetTracking() {
|
|
489
|
+
const boundaryModules = new Map();
|
|
490
|
+
const boundaryStyles = new Map();
|
|
491
|
+
const emittedAssets = new Set();
|
|
492
|
+
const inlineStyles = new Map();
|
|
493
|
+
let currentBoundaryId = null;
|
|
494
|
+
return {
|
|
495
|
+
boundaryModules,
|
|
496
|
+
boundaryStyles,
|
|
497
|
+
emittedAssets,
|
|
498
|
+
inlineStyles,
|
|
499
|
+
registerInlineStyle(desc) {
|
|
500
|
+
let entry = inlineStyles.get(desc.id);
|
|
501
|
+
if (!entry) {
|
|
502
|
+
entry = {
|
|
503
|
+
id: desc.id,
|
|
504
|
+
content: desc.content || "",
|
|
505
|
+
attrs: desc.attrs,
|
|
506
|
+
emitted: false
|
|
507
|
+
};
|
|
508
|
+
inlineStyles.set(desc.id, entry);
|
|
509
|
+
}
|
|
510
|
+
if (currentBoundaryId) {
|
|
511
|
+
let styles = boundaryStyles.get(currentBoundaryId);
|
|
512
|
+
if (!styles) {
|
|
513
|
+
styles = new Set();
|
|
514
|
+
boundaryStyles.set(currentBoundaryId, styles);
|
|
515
|
+
}
|
|
516
|
+
styles.add(entry);
|
|
517
|
+
}
|
|
518
|
+
return entry;
|
|
519
|
+
},
|
|
520
|
+
get currentBoundaryId() {
|
|
521
|
+
return currentBoundaryId;
|
|
522
|
+
},
|
|
523
|
+
set currentBoundaryId(v) {
|
|
524
|
+
currentBoundaryId = v;
|
|
525
|
+
},
|
|
526
|
+
registerModule(key, entryUrl) {
|
|
527
|
+
const id = currentBoundaryId || "";
|
|
528
|
+
let map = boundaryModules.get(id);
|
|
529
|
+
if (!map) {
|
|
530
|
+
map = {};
|
|
531
|
+
boundaryModules.set(id, map);
|
|
532
|
+
}
|
|
533
|
+
map[key] = entryUrl;
|
|
534
|
+
},
|
|
535
|
+
getBoundaryModules(id) {
|
|
536
|
+
return boundaryModules.get(id) || null;
|
|
537
|
+
},
|
|
538
|
+
getBoundaryStyles(id) {
|
|
539
|
+
return boundaryStyles.get(id) || null;
|
|
540
|
+
}
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
function warnUnresolvedModuleAssets(moduleUrl, warned) {
|
|
544
|
+
if (warned.has(moduleUrl)) return;
|
|
545
|
+
warned.add(moduleUrl);
|
|
546
|
+
console.error(`Asset manifest returned no client assets for module "${moduleUrl}". ` + "If this module is a server-rendered lazy() component, its entry will be missing from " + "the serialized hydration asset map, the client will be unable to preload it, and " + "hydration will fail with 'lazy() module \"…\" was not preloaded before hydration'. " + "This means the integration's asset resolver (dev manifest bridge or build client " + "manifest) failed to answer for this module — check the integration's server logs, " + "restart the dev server, or verify the module is included in the client build.");
|
|
547
|
+
}
|
|
548
|
+
function guardResolvedAssets(moduleUrl, result, warned) {
|
|
549
|
+
if (result && typeof result.then === "function") {
|
|
550
|
+
return result.then(assets => {
|
|
551
|
+
if (!assets || !assets.js || !assets.js.length) warnUnresolvedModuleAssets(moduleUrl, warned);
|
|
552
|
+
return assets;
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
if (!result || !result.js || !result.js.length) warnUnresolvedModuleAssets(moduleUrl, warned);
|
|
556
|
+
return result;
|
|
557
|
+
}
|
|
558
|
+
function applyAssetTracking(context, tracking, manifest, noScripts) {
|
|
559
|
+
const warned = new Set();
|
|
560
|
+
const guard = noScripts ? resolve => resolve : resolve => moduleUrl => guardResolvedAssets(moduleUrl, resolve(moduleUrl), warned);
|
|
561
|
+
Object.defineProperty(context, "_currentBoundaryId", {
|
|
562
|
+
get() {
|
|
563
|
+
return tracking.currentBoundaryId;
|
|
564
|
+
},
|
|
565
|
+
set(v) {
|
|
566
|
+
tracking.currentBoundaryId = v;
|
|
567
|
+
},
|
|
568
|
+
configurable: true,
|
|
569
|
+
enumerable: true
|
|
570
|
+
});
|
|
571
|
+
context.registerModule = tracking.registerModule;
|
|
572
|
+
context.getBoundaryModules = tracking.getBoundaryModules;
|
|
573
|
+
if (typeof manifest === "function") {
|
|
574
|
+
context.resolveAssets = guard(manifest);
|
|
575
|
+
} else if (manifest && typeof manifest.resolve === "function") {
|
|
576
|
+
context.resolveAssets = guard(key => manifest.resolve(key));
|
|
577
|
+
if (typeof manifest.resolveSync === "function") {
|
|
578
|
+
context.resolveAssetsSync = key => manifest.resolveSync(key);
|
|
579
|
+
}
|
|
580
|
+
} else if (manifest) {
|
|
581
|
+
const resolve = moduleUrl => resolveAssets(moduleUrl, manifest);
|
|
582
|
+
context.resolveAssets = guard(resolve);
|
|
583
|
+
context.resolveAssetsSync = resolve;
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
function isCssUrl(url) {
|
|
587
|
+
const q = url.search(/[?#]/);
|
|
588
|
+
return (q === -1 ? url : url.slice(0, q)).endsWith(".css");
|
|
589
|
+
}
|
|
590
|
+
function createHeadRegistry() {
|
|
591
|
+
return {
|
|
592
|
+
pending: [],
|
|
593
|
+
committed: [],
|
|
594
|
+
seq: 0,
|
|
595
|
+
uniq: 0,
|
|
596
|
+
resources: new Set(),
|
|
597
|
+
eagerHtml: "",
|
|
598
|
+
flushed: null,
|
|
599
|
+
shellFlushed: false,
|
|
600
|
+
parkedResources: []
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
function registerHeadTags(registry, context, tracking, emitResource, nonce, tags) {
|
|
604
|
+
const boundary = context._currentBoundaryId || "";
|
|
605
|
+
if (typeof tags === "function") {
|
|
606
|
+
registry.pending.push({
|
|
607
|
+
boundary,
|
|
608
|
+
list: tags,
|
|
609
|
+
resource: (desc, rel) => emitHeadResource(registry, context, tracking, emitResource, nonce, desc, rel)
|
|
610
|
+
});
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
if (!Array.isArray(tags)) tags = [tags];
|
|
614
|
+
const probe = sharedConfig.context && sharedConfig.context._loadingPhase;
|
|
615
|
+
let replaceable = null;
|
|
616
|
+
for (let i = 0; i < tags.length; i++) {
|
|
617
|
+
const desc = tags[i];
|
|
618
|
+
if (!desc || !HEAD_ELIGIBLE_TAGS.has(desc.tag)) {
|
|
619
|
+
continue;
|
|
620
|
+
}
|
|
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
|
+
}
|
|
632
|
+
if (cls.resource) {
|
|
633
|
+
emitHeadResource(registry, context, tracking, emitResource, nonce, desc, cls.rel);
|
|
634
|
+
} else {
|
|
635
|
+
(replaceable || (replaceable = [])).push(cls.rel !== undefined ? {
|
|
636
|
+
tag: desc.tag,
|
|
637
|
+
props: desc.props,
|
|
638
|
+
key: desc.key,
|
|
639
|
+
rel: cls.rel
|
|
640
|
+
} : desc);
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
if (replaceable) registry.pending.push({
|
|
644
|
+
boundary,
|
|
645
|
+
tags: replaceable
|
|
646
|
+
});
|
|
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
|
+
}
|
|
693
|
+
function emitHeadResource(registry, context, tracking, emitResource, nonce, desc, rel) {
|
|
694
|
+
let props;
|
|
695
|
+
try {
|
|
696
|
+
props = evalHeadProps(desc.props || {}, rel !== undefined ? {
|
|
697
|
+
rel
|
|
698
|
+
} : undefined);
|
|
699
|
+
} catch (err) {
|
|
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
|
+
}
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
const identity = resourceIdentity(desc.tag, props);
|
|
713
|
+
if (registry.resources.has(identity)) return;
|
|
714
|
+
registry.resources.add(identity);
|
|
715
|
+
if (desc.tag === "link" && (rel === "stylesheet" || rel === "modulepreload")) {
|
|
716
|
+
let plain = true;
|
|
717
|
+
let gateable = rel === "stylesheet";
|
|
718
|
+
for (const name in props) {
|
|
719
|
+
if (name === "rel" || name === "href") continue;
|
|
720
|
+
plain = false;
|
|
721
|
+
if (!STYLESHEET_FETCH_META.has(name)) gateable = false;
|
|
722
|
+
}
|
|
723
|
+
if (plain && props.href != null) {
|
|
724
|
+
const isCss = isCssUrl(props.href);
|
|
725
|
+
if (rel === "stylesheet" ? isCss : !isCss) {
|
|
726
|
+
context.registerAsset(rel === "stylesheet" ? "style" : "module", props.href);
|
|
727
|
+
return;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
if (gateable && props.href != null) {
|
|
731
|
+
const attrHtml = renderHeadAttrHtml(props);
|
|
732
|
+
const entry = {
|
|
733
|
+
href: props.href,
|
|
734
|
+
attrHtml,
|
|
735
|
+
attrs: headAttrRecord(props)
|
|
736
|
+
};
|
|
737
|
+
if (tracking.currentBoundaryId) {
|
|
738
|
+
let styles = tracking.boundaryStyles.get(tracking.currentBoundaryId);
|
|
739
|
+
if (!styles) tracking.boundaryStyles.set(tracking.currentBoundaryId, styles = new Set());
|
|
740
|
+
styles.add(entry);
|
|
741
|
+
}
|
|
742
|
+
const markup = `<link${attrHtml}>`;
|
|
743
|
+
if (emitResource) emitResource(markup, entry);else {
|
|
744
|
+
registry.eagerHtml += markup;
|
|
745
|
+
entry.emitted = true;
|
|
746
|
+
}
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
const url = props.href || props.src;
|
|
751
|
+
if (url != null && tracking.emittedAssets.has(url)) return;
|
|
752
|
+
const markup = renderHeadTagMarkup(desc.tag, props, null, nonce);
|
|
753
|
+
if (emitResource) emitResource(markup);else registry.eagerHtml += markup;
|
|
754
|
+
}
|
|
755
|
+
function commitHeadBoundary(registry, boundary, isPendingFragment) {
|
|
756
|
+
const keep = [];
|
|
757
|
+
const groups = [];
|
|
758
|
+
for (let i = 0; i < registry.pending.length; i++) {
|
|
759
|
+
const reg = registry.pending[i];
|
|
760
|
+
const mine = boundary === "" ? !(isPendingFragment && reg.boundary !== "" && isPendingFragment(reg.boundary)) : reg.boundary === boundary;
|
|
761
|
+
if (!mine) {
|
|
762
|
+
keep.push(reg);
|
|
763
|
+
continue;
|
|
764
|
+
}
|
|
765
|
+
let descs = reg.tags;
|
|
766
|
+
if (reg.list) {
|
|
767
|
+
let resolved;
|
|
768
|
+
try {
|
|
769
|
+
resolved = reg.list();
|
|
770
|
+
} catch (err) {
|
|
771
|
+
continue;
|
|
772
|
+
}
|
|
773
|
+
if (!Array.isArray(resolved)) resolved = [resolved];
|
|
774
|
+
descs = [];
|
|
775
|
+
for (let j = 0; j < resolved.length; j++) {
|
|
776
|
+
const desc = resolved[j];
|
|
777
|
+
if (!desc || !HEAD_ELIGIBLE_TAGS.has(desc.tag)) {
|
|
778
|
+
continue;
|
|
779
|
+
}
|
|
780
|
+
const cls = classifyHeadTag(desc);
|
|
781
|
+
if (cls.resource) {
|
|
782
|
+
reg.resource(desc, cls.rel);
|
|
783
|
+
} else {
|
|
784
|
+
descs.push(cls.rel !== undefined ? {
|
|
785
|
+
tag: desc.tag,
|
|
786
|
+
props: desc.props,
|
|
787
|
+
key: desc.key,
|
|
788
|
+
rel: cls.rel
|
|
789
|
+
} : desc);
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
const tags = [];
|
|
794
|
+
for (let j = 0; j < descs.length; j++) {
|
|
795
|
+
const desc = descs[j];
|
|
796
|
+
let props, key;
|
|
797
|
+
try {
|
|
798
|
+
props = evalHeadProps(desc.props || {}, desc.rel !== undefined ? {
|
|
799
|
+
rel: desc.rel
|
|
800
|
+
} : undefined);
|
|
801
|
+
key = evalHeadValue(desc.key);
|
|
802
|
+
} catch (err) {
|
|
803
|
+
continue;
|
|
804
|
+
}
|
|
805
|
+
const identity = replaceableIdentity(desc.tag, props, key, "u:" + registry.uniq++);
|
|
806
|
+
if ((identity === "base" || identity === "charset") && registry.shellFlushed) {
|
|
807
|
+
continue;
|
|
808
|
+
}
|
|
809
|
+
tags.push({
|
|
810
|
+
tag: desc.tag,
|
|
811
|
+
props,
|
|
812
|
+
identity
|
|
813
|
+
});
|
|
814
|
+
}
|
|
815
|
+
if (tags.length) groups.push({
|
|
816
|
+
seq: registry.seq++,
|
|
817
|
+
tags
|
|
818
|
+
});
|
|
819
|
+
}
|
|
820
|
+
registry.pending = keep;
|
|
821
|
+
for (let i = 0; i < groups.length; i++) registry.committed.push(groups[i]);
|
|
822
|
+
return groups;
|
|
823
|
+
}
|
|
824
|
+
function adoptHeadBoundary(registry, childKey, parentKey) {
|
|
825
|
+
for (let i = 0; i < registry.pending.length; i++) {
|
|
826
|
+
if (registry.pending[i].boundary === childKey) registry.pending[i].boundary = parentKey;
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
function dropHeadBoundary(registry, boundary) {
|
|
830
|
+
registry.pending = registry.pending.filter(reg => reg.boundary !== boundary);
|
|
831
|
+
}
|
|
832
|
+
function headGroupSignature(winner) {
|
|
833
|
+
let sig = "" + winner.seq;
|
|
834
|
+
for (let i = 0; i < winner.tags.length; i++) {
|
|
835
|
+
const t = winner.tags[i];
|
|
836
|
+
sig += "|" + t.tag + JSON.stringify(t.props);
|
|
837
|
+
}
|
|
838
|
+
return sig;
|
|
839
|
+
}
|
|
840
|
+
function renderShellHead(registry, nonce, isPendingFragment) {
|
|
841
|
+
commitHeadBoundary(registry, "", isPendingFragment);
|
|
842
|
+
registry.shellFlushed = true;
|
|
843
|
+
const winners = resolveHead(registry.committed);
|
|
844
|
+
registry.flushed = new Map();
|
|
845
|
+
let prelude = "";
|
|
846
|
+
let links = "";
|
|
847
|
+
let metas = "";
|
|
848
|
+
let others = "";
|
|
849
|
+
let scripts = "";
|
|
850
|
+
for (const [identity, winner] of winners) {
|
|
851
|
+
registry.flushed.set(identity, headGroupSignature(winner));
|
|
852
|
+
for (let i = 0; i < winner.tags.length; i++) {
|
|
853
|
+
const t = winner.tags[i];
|
|
854
|
+
const markup = renderHeadTagMarkup(t.tag, t.props, identity, nonce);
|
|
855
|
+
if (identity === "charset" || identity === "base") prelude += markup;else if (t.tag === "link" || t.tag === "style") links += markup;else if (t.tag === "meta") metas += markup;else if (t.tag === "script") scripts += markup;else others += markup;
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
return {
|
|
859
|
+
prelude,
|
|
860
|
+
html: registry.eagerHtml + links + metas + others + scripts
|
|
861
|
+
};
|
|
862
|
+
}
|
|
863
|
+
function flushHeadFragment(registry, boundary) {
|
|
864
|
+
const groups = commitHeadBoundary(registry, boundary);
|
|
865
|
+
if (!groups.length) return null;
|
|
866
|
+
const winners = resolveHead(registry.committed);
|
|
867
|
+
const affected = new Set();
|
|
868
|
+
for (let i = 0; i < groups.length; i++) for (let j = 0; j < groups[i].tags.length; j++) affected.add(groups[i].tags[j].identity);
|
|
869
|
+
const ops = [];
|
|
870
|
+
for (const identity of affected) {
|
|
871
|
+
const winner = winners.get(identity);
|
|
872
|
+
const sig = headGroupSignature(winner);
|
|
873
|
+
if (registry.flushed.get(identity) === sig) continue;
|
|
874
|
+
const existed = registry.flushed.has(identity);
|
|
875
|
+
registry.flushed.set(identity, sig);
|
|
876
|
+
if (identity === "title") {
|
|
877
|
+
const children = winner.tags[0].props.children;
|
|
878
|
+
ops.push(["t", children == null ? "" : String(children)]);
|
|
879
|
+
continue;
|
|
880
|
+
}
|
|
881
|
+
if (existed) ops.push(["r", identity]);
|
|
882
|
+
for (let i = 0; i < winner.tags.length; i++) {
|
|
883
|
+
const t = winner.tags[i];
|
|
884
|
+
const attrs = {};
|
|
885
|
+
for (const name in t.props) {
|
|
886
|
+
if (name === "children" || name === "ref" || name.slice(0, 2) === "on") continue;
|
|
887
|
+
if (!HEAD_ATTR_NAME.test(name)) {
|
|
888
|
+
continue;
|
|
889
|
+
}
|
|
890
|
+
const v = t.props[name];
|
|
891
|
+
if (v == null || v === false) continue;
|
|
892
|
+
attrs[name] = v === true ? "" : String(v);
|
|
893
|
+
}
|
|
894
|
+
const children = t.props.children;
|
|
895
|
+
ops.push(["a", identity, t.tag, attrs, children == null ? null : String(children)]);
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
return ops.length ? ops : null;
|
|
899
|
+
}
|
|
900
|
+
function renderHeadAttrHtml(props) {
|
|
901
|
+
let attrs = "";
|
|
902
|
+
for (const name in props) {
|
|
903
|
+
if (name === "children" || name === "ref" || name.slice(0, 2) === "on") continue;
|
|
904
|
+
if (!HEAD_ATTR_NAME.test(name)) {
|
|
905
|
+
continue;
|
|
906
|
+
}
|
|
907
|
+
const v = props[name];
|
|
908
|
+
if (v == null || v === false) continue;
|
|
909
|
+
attrs += v === true ? ` ${name}` : ` ${name}="${escape(String(v), true)}"`;
|
|
910
|
+
}
|
|
911
|
+
return attrs;
|
|
912
|
+
}
|
|
913
|
+
function headAttrRecord(props, skipRelHref) {
|
|
914
|
+
let attrs = null;
|
|
915
|
+
for (const name in props) {
|
|
916
|
+
if (name === "children" || name === "ref" || name.slice(0, 2) === "on") continue;
|
|
917
|
+
if ((name === "rel" || name === "href")) continue;
|
|
918
|
+
if (!HEAD_ATTR_NAME.test(name)) continue;
|
|
919
|
+
const v = props[name];
|
|
920
|
+
if (v == null || v === false) continue;
|
|
921
|
+
(attrs || (attrs = {}))[name] = v === true ? "" : String(v);
|
|
922
|
+
}
|
|
923
|
+
return attrs;
|
|
924
|
+
}
|
|
925
|
+
function renderHeadTagMarkup(tag, props, identity, nonce) {
|
|
926
|
+
let attrs = renderHeadAttrHtml(props);
|
|
927
|
+
if (identity != null) attrs += ` data-dh="${escape(identity, true)}"`;
|
|
928
|
+
if (nonce && (tag === "script" || tag === "style")) attrs += ` nonce="${nonce}"`;
|
|
929
|
+
if (tag === "meta" || tag === "link" || tag === "base") return `<${tag}${attrs}>`;
|
|
930
|
+
let body = props.children == null ? "" : String(props.children);
|
|
931
|
+
if (tag === "script") body = body.replace(/<\/(script)/gi, "<\\/$1");else if (tag === "style") body = escapeStyleContent(body);else body = escape(body);
|
|
932
|
+
return `<${tag}${attrs}>${body}</${tag}>`;
|
|
933
|
+
}
|
|
934
|
+
const REPLACE_SCRIPT = `function $df(e){return _$HY.f?_$HY.f(e):$dfr(e)}function $dfr(e,n,o,t){if(!(n=document.getElementById(e)))return 0;if(!(o=document.getElementById("pl-"+e)))return(_$HY.dq=_$HY.dq||{})[e]=1,0;for(;o&&(8!==o.nodeType||o.nodeValue!=="pl-"+e);)t=o.nextSibling,o.remove(),o=t;t=o.parentNode,o.replaceWith(n.content),n.remove(),(_$HY.v=_$HY.v||{})[e]=1,_$HY.fe(e,t),_$HY.hp&&_$HY.hp[e]&&($dh(_$HY.hp[e]),delete _$HY.hp[e]),$dfd();return 1}function $dfl(e,o,n){if(!(o=document.getElementById("pl-"+e)))return(_$HY.dlq=_$HY.dlq||{})[e]=1,0;if(o._$fl)return 1;for(n=o.nextSibling;n;){if(8===n.nodeType&&n.nodeValue==="pl-"+e){o.parentNode&&o.parentNode.insertBefore(o.content.cloneNode(!0),n),o._$fl=1,$dfd();return 1}n=n.nextSibling}return 0}function $dflj(e,i){for(i=0;i<e.length;i++)$dfl(e[i])}function $dfd(e,i){if(e=_$HY.dq){_$HY.dq=0;for(i in e)$df(i)}if(e=_$HY.dlq){_$HY.dlq=0;for(i in e)$dfl(i)}}function $dfs(e,c,d){(_$HY.sc=_$HY.sc||{})[e]=c,d&&((_$HY.sd=_$HY.sd||{})[e]=1)}function $dfg(e,g,i,k){if(!(g=_$HY.sg&&_$HY.sg[e]))return;for(i=0;i<g.length;i++)if(_$HY.sc&&_$HY.sc[g[i]]>0)return;for(i=0;i<g.length;i++)k=g[i],delete _$HY.sg[k],$df(k)}function $dfc(e){if(--_$HY.sc[e]<=0){delete _$HY.sc[e],_$HY.sg&&_$HY.sg[e]?$dfg(e):!(_$HY.sd&&_$HY.sd[e])&&$df(e);_$HY.sd&&delete _$HY.sd[e]}}function $dfj(e,i,n){for(i=0;i<e.length;i++)if(_$HY.sc&&_$HY.sc[e[i]]>0){for(n=0;n<e.length;n++)(_$HY.sg=_$HY.sg||{})[e[n]]=e;return}for(i=0;i<e.length;i++)$df(e[i])}`;
|
|
935
|
+
const HEAD_SCRIPT = `function $dha(o,i,e,n){for(i=0;i<o.length;i++)e=o[i],"t"==e[0]?((n=document.querySelector("title"))||(n=document.createElement("title"),document.head.appendChild(n)),n.textContent=e[1],n.setAttribute("data-dh","title")):"r"==e[0]?$dhr(e[1]):(n=document.createElement(e[2]),Object.keys(e[3]).forEach(function(a){n.setAttribute(a,e[3][a])}),null!=e[4]&&(n.textContent=e[4]),n.setAttribute("data-dh",e[1]),document.head.appendChild(n))}function $dhr(v,l,i){for(l=document.head.querySelectorAll("[data-dh]"),i=0;i<l.length;i++)l[i].getAttribute("data-dh")==v&&l[i].remove()}function $dh(o){_$HY.h?_$HY.h(o):$dha(o)}`;
|
|
936
|
+
function renderToStream(code, options = {}) {
|
|
937
|
+
let {
|
|
938
|
+
nonce,
|
|
939
|
+
onCompleteShell,
|
|
940
|
+
onCompleteAll,
|
|
941
|
+
renderId = "",
|
|
942
|
+
noScripts,
|
|
943
|
+
manifest,
|
|
944
|
+
onHead
|
|
945
|
+
} = options;
|
|
946
|
+
let dispose;
|
|
947
|
+
let dead = false;
|
|
948
|
+
const abandon = () => {
|
|
949
|
+
if (dead) return;
|
|
950
|
+
dead = true;
|
|
951
|
+
completed = true;
|
|
952
|
+
buffer = {
|
|
953
|
+
write() {}
|
|
954
|
+
};
|
|
955
|
+
writable = {
|
|
956
|
+
end() {}
|
|
957
|
+
};
|
|
958
|
+
if (dispose) {
|
|
959
|
+
const d = dispose;
|
|
960
|
+
dispose = () => {};
|
|
961
|
+
d();
|
|
962
|
+
}
|
|
963
|
+
};
|
|
964
|
+
const failRender = err => {
|
|
965
|
+
try {
|
|
966
|
+
options.onError ? options.onError(err) : console.error(err);
|
|
967
|
+
} catch (_) {}
|
|
968
|
+
abandon();
|
|
969
|
+
};
|
|
970
|
+
const guardSink = w => ({
|
|
971
|
+
write(payload) {
|
|
972
|
+
if (dead) return;
|
|
973
|
+
try {
|
|
974
|
+
w.write(payload);
|
|
975
|
+
} catch (_) {
|
|
976
|
+
abandon();
|
|
977
|
+
}
|
|
978
|
+
},
|
|
979
|
+
end() {
|
|
980
|
+
if (dead) return;
|
|
981
|
+
try {
|
|
982
|
+
w.end();
|
|
983
|
+
} catch (_) {
|
|
984
|
+
abandon();
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
});
|
|
988
|
+
const blockingPromises = new Set();
|
|
989
|
+
let headerEmitted = false;
|
|
990
|
+
const pushTask = task => {
|
|
991
|
+
if (noScripts) return;
|
|
992
|
+
if (!headerEmitted) {
|
|
993
|
+
headerEmitted = true;
|
|
994
|
+
tasks += getLocalHeaderScript(renderId);
|
|
995
|
+
}
|
|
996
|
+
tasks += task + ";";
|
|
997
|
+
if (!timer && firstFlushed) {
|
|
998
|
+
timer = true;
|
|
999
|
+
queue(() => queue(writeTasks));
|
|
1000
|
+
}
|
|
1001
|
+
};
|
|
1002
|
+
const onDone = () => {
|
|
1003
|
+
writeTasks();
|
|
1004
|
+
doShell();
|
|
1005
|
+
onCompleteAll && onCompleteAll({
|
|
1006
|
+
write(v) {
|
|
1007
|
+
!completed && buffer.write(v);
|
|
1008
|
+
}
|
|
1009
|
+
});
|
|
1010
|
+
writable && writable.end();
|
|
1011
|
+
completed = true;
|
|
1012
|
+
if (firstFlushed) dispose();
|
|
1013
|
+
};
|
|
1014
|
+
const sink = {
|
|
1015
|
+
data(payload) {
|
|
1016
|
+
pushTask(payload);
|
|
1017
|
+
},
|
|
1018
|
+
fragment(key, value, meta) {
|
|
1019
|
+
const deferActivation = !!meta.revealGroup;
|
|
1020
|
+
const styles = meta.styles;
|
|
1021
|
+
for (let i = 0; i < styles.inline.length; i++) {
|
|
1022
|
+
buffer.write(renderInlineStyle(styles.inline[i], nonce));
|
|
1023
|
+
}
|
|
1024
|
+
if (styles.links.length) {
|
|
1025
|
+
emitTask(`$dfs("${key}",${styles.links.length},${deferActivation ? 1 : 0})`);
|
|
1026
|
+
writeTasks();
|
|
1027
|
+
for (const entry of styles.links) {
|
|
1028
|
+
buffer.write(typeof entry === "string" ? `<link rel="stylesheet" href="${entry}" onload="$dfc('${key}')" onerror="$dfc('${key}')">` : `<link${entry.attrHtml} onload="$dfc('${key}')" onerror="$dfc('${key}')">`);
|
|
1029
|
+
}
|
|
1030
|
+
buffer.write(`<template id="${key}">${value}</template>`);
|
|
1031
|
+
} else {
|
|
1032
|
+
buffer.write(`<template id="${key}">${value}</template>`);
|
|
1033
|
+
if (!deferActivation) {
|
|
1034
|
+
emitTask(`$df("${key}")`);
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
},
|
|
1038
|
+
reveal(keys, meta) {
|
|
1039
|
+
emitTask(`${meta.fallback ? "$dflj" : "$dfj"}(${JSON.stringify(keys)})`);
|
|
1040
|
+
},
|
|
1041
|
+
asset(type, value) {
|
|
1042
|
+
if (type === "module") {
|
|
1043
|
+
buffer.write(`<link rel="modulepreload" href="${value}">`);
|
|
1044
|
+
} else if (type === "inline-style") {
|
|
1045
|
+
buffer.write(renderInlineStyle(value, nonce));
|
|
1046
|
+
} else if (type === "head-tag") {
|
|
1047
|
+
buffer.write(value);
|
|
1048
|
+
}
|
|
1049
|
+
},
|
|
1050
|
+
shell(shellHtml, meta) {
|
|
1051
|
+
buffer.write(assembleDocument(shellHtml, meta.preloads, meta.inlineStyles, meta.tasks.length ? meta.tasks : "", nonce, meta.head, onHead));
|
|
1052
|
+
},
|
|
1053
|
+
...options.sink
|
|
1054
|
+
};
|
|
1055
|
+
const serializer = (options.serializer || createHydrationSerializer)({
|
|
1056
|
+
scopeId: options.renderId,
|
|
1057
|
+
plugins: options.plugins,
|
|
1058
|
+
onData: payload => sink.data(payload),
|
|
1059
|
+
onDone,
|
|
1060
|
+
onError: options.onError
|
|
1061
|
+
});
|
|
1062
|
+
let rootAssetsSerialized = false;
|
|
1063
|
+
const serializeRootAssets = () => {
|
|
1064
|
+
if (rootAssetsSerialized) return;
|
|
1065
|
+
rootAssetsSerialized = true;
|
|
1066
|
+
serializeFragmentAssets("", tracking.boundaryModules, context, renderId);
|
|
1067
|
+
};
|
|
1068
|
+
let holds = 0;
|
|
1069
|
+
const flushEnd = () => {
|
|
1070
|
+
if (!registry.size && !holds) {
|
|
1071
|
+
serializeRootAssets();
|
|
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
|
+
}));
|
|
1080
|
+
}
|
|
1081
|
+
};
|
|
1082
|
+
const registry = new Map();
|
|
1083
|
+
const writeTasks = () => {
|
|
1084
|
+
if (tasks.length && !completed && firstFlushed) {
|
|
1085
|
+
buffer.write(`<script${nonce ? ` nonce="${nonce}"` : ""}>${tasks}</script>`);
|
|
1086
|
+
tasks = "";
|
|
1087
|
+
}
|
|
1088
|
+
timer = null;
|
|
1089
|
+
};
|
|
1090
|
+
let context;
|
|
1091
|
+
let writable;
|
|
1092
|
+
let tmp = "";
|
|
1093
|
+
let tasks = "";
|
|
1094
|
+
let firstFlushed = false;
|
|
1095
|
+
let completed = false;
|
|
1096
|
+
let shellCompleted = false;
|
|
1097
|
+
let scriptFlushed = false;
|
|
1098
|
+
let headStyles;
|
|
1099
|
+
const revealGroups = new Map();
|
|
1100
|
+
let timer = null;
|
|
1101
|
+
const emitTask = task => {
|
|
1102
|
+
pushTask(`${task}${!scriptFlushed ? ";" + REPLACE_SCRIPT : ""}`);
|
|
1103
|
+
scriptFlushed = true;
|
|
1104
|
+
};
|
|
1105
|
+
function resolveRevealKeys(groupOrKeys, release, consume) {
|
|
1106
|
+
if (Array.isArray(groupOrKeys)) return groupOrKeys.slice();
|
|
1107
|
+
let group = revealGroups.get(groupOrKeys);
|
|
1108
|
+
if (!group) {
|
|
1109
|
+
if (!release) return;
|
|
1110
|
+
group = {
|
|
1111
|
+
order: [],
|
|
1112
|
+
keys: new Set(),
|
|
1113
|
+
released: true
|
|
1114
|
+
};
|
|
1115
|
+
revealGroups.set(groupOrKeys, group);
|
|
1116
|
+
} else if (release) group.released = true;
|
|
1117
|
+
if (!group.order.length) return;
|
|
1118
|
+
const keys = group.order.slice();
|
|
1119
|
+
if (consume) revealGroups.delete(groupOrKeys);
|
|
1120
|
+
return keys;
|
|
1121
|
+
}
|
|
1122
|
+
let rootHoles = null;
|
|
1123
|
+
let nextHoleId = 0;
|
|
1124
|
+
let buffer = {
|
|
1125
|
+
write(payload) {
|
|
1126
|
+
tmp += payload;
|
|
1127
|
+
}
|
|
1128
|
+
};
|
|
1129
|
+
const tracking = createAssetTracking();
|
|
1130
|
+
const headRegistry = createHeadRegistry();
|
|
1131
|
+
let headScriptFlushed = false;
|
|
1132
|
+
const emitHeadOps = (key, ops) => {
|
|
1133
|
+
const payload = JSON.stringify(ops).replace(/</g, "\\u003C");
|
|
1134
|
+
emitTask(`${!headScriptFlushed ? HEAD_SCRIPT : ""}(_$HY.hp=_$HY.hp||{})[${JSON.stringify(key)}]=${payload}`);
|
|
1135
|
+
headScriptFlushed = true;
|
|
1136
|
+
};
|
|
1137
|
+
sharedConfig.context = context = {
|
|
1138
|
+
async: true,
|
|
1139
|
+
nonce,
|
|
1140
|
+
live: {},
|
|
1141
|
+
registerHeadTags(tags) {
|
|
1142
|
+
registerHeadTags(headRegistry, context, tracking,
|
|
1143
|
+
(markup, gateEntry) => {
|
|
1144
|
+
if (!firstFlushed) {
|
|
1145
|
+
headRegistry.eagerHtml += markup;
|
|
1146
|
+
if (gateEntry) gateEntry.emitted = true;
|
|
1147
|
+
} else if (!gateEntry || !tracking.currentBoundaryId) {
|
|
1148
|
+
sink.asset("head-tag", markup);
|
|
1149
|
+
}
|
|
1150
|
+
}, nonce, tags);
|
|
1151
|
+
},
|
|
1152
|
+
registerAsset(type, value) {
|
|
1153
|
+
if (type === "inline-style") {
|
|
1154
|
+
const entry = tracking.registerInlineStyle(value);
|
|
1155
|
+
if (firstFlushed && !tracking.currentBoundaryId && !entry.emitted) {
|
|
1156
|
+
entry.emitted = true;
|
|
1157
|
+
sink.asset("inline-style", entry);
|
|
1158
|
+
}
|
|
1159
|
+
return;
|
|
1160
|
+
}
|
|
1161
|
+
if (tracking.currentBoundaryId && type === "style") {
|
|
1162
|
+
let styles = tracking.boundaryStyles.get(tracking.currentBoundaryId);
|
|
1163
|
+
if (!styles) {
|
|
1164
|
+
styles = new Set();
|
|
1165
|
+
tracking.boundaryStyles.set(tracking.currentBoundaryId, styles);
|
|
1166
|
+
}
|
|
1167
|
+
styles.add(value);
|
|
1168
|
+
}
|
|
1169
|
+
if (!tracking.emittedAssets.has(value)) {
|
|
1170
|
+
tracking.emittedAssets.add(value);
|
|
1171
|
+
if (firstFlushed) sink.asset(type, value);
|
|
1172
|
+
}
|
|
1173
|
+
},
|
|
1174
|
+
block(p) {
|
|
1175
|
+
if (!firstFlushed) blockingPromises.add(p);
|
|
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
|
+
},
|
|
1187
|
+
replace(id, payloadFn) {
|
|
1188
|
+
if (firstFlushed) return;
|
|
1189
|
+
const placeholder = `<!--!$${id}-->`;
|
|
1190
|
+
const first = html.indexOf(placeholder);
|
|
1191
|
+
if (first === -1) return;
|
|
1192
|
+
const last = html.indexOf(`<!--!$/${id}-->`, first + placeholder.length);
|
|
1193
|
+
html = html.slice(0, first) + resolveSSRSync(escape(payloadFn())) + html.slice(last + placeholder.length + 1);
|
|
1194
|
+
},
|
|
1195
|
+
serialize(id, p, deferStream) {
|
|
1196
|
+
if (sharedConfig.context.noHydrate) return;
|
|
1197
|
+
if (!firstFlushed && deferStream && typeof p === "object" && "then" in p) {
|
|
1198
|
+
blockingPromises.add(p);
|
|
1199
|
+
p.then(d => serializer.write(id, d)).catch(e => serializer.write(id, e));
|
|
1200
|
+
} else serializer.write(id, p);
|
|
1201
|
+
},
|
|
1202
|
+
escape: escape,
|
|
1203
|
+
resolve: resolveSSRNode,
|
|
1204
|
+
ssr: ssr,
|
|
1205
|
+
registerFragment(key, options) {
|
|
1206
|
+
const revealGroup = options && options.revealGroup;
|
|
1207
|
+
if (revealGroup) {
|
|
1208
|
+
let group = revealGroups.get(revealGroup);
|
|
1209
|
+
if (!group) {
|
|
1210
|
+
group = {
|
|
1211
|
+
order: [],
|
|
1212
|
+
keys: new Set(),
|
|
1213
|
+
released: false
|
|
1214
|
+
};
|
|
1215
|
+
revealGroups.set(revealGroup, group);
|
|
1216
|
+
}
|
|
1217
|
+
if (!group.keys.has(key)) {
|
|
1218
|
+
group.keys.add(key);
|
|
1219
|
+
group.order.push(key);
|
|
1220
|
+
}
|
|
1221
|
+
if (group.released) {
|
|
1222
|
+
throw new Error("registerFragment() for reveal group '" + revealGroup + "' was called after revealFragments(). Ensure template payload is emitted before grouped reveal.");
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
if (!registry.has(key)) {
|
|
1226
|
+
let resolve, reject;
|
|
1227
|
+
const p = new Promise((r, rej) => (resolve = r, reject = rej));
|
|
1228
|
+
registry.set(key, {
|
|
1229
|
+
resolve: err => queue(() => queue(() => {
|
|
1230
|
+
err ? reject(err) : resolve(true);
|
|
1231
|
+
queue(flushEnd);
|
|
1232
|
+
}))
|
|
1233
|
+
});
|
|
1234
|
+
serializer.write(key + "_fr", p);
|
|
1235
|
+
}
|
|
1236
|
+
return (value, error) => {
|
|
1237
|
+
if (registry.has(key)) {
|
|
1238
|
+
const item = registry.get(key);
|
|
1239
|
+
registry.delete(key);
|
|
1240
|
+
if (item.children) {
|
|
1241
|
+
for (const k in item.children) {
|
|
1242
|
+
value = replacePlaceholder(value, k, item.children[k]);
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
const parentKey = waitForFragments(registry, key);
|
|
1246
|
+
if (parentKey) {
|
|
1247
|
+
const parent = registry.get(parentKey);
|
|
1248
|
+
parent.children ||= {};
|
|
1249
|
+
parent.children[key] = value !== undefined ? value : "";
|
|
1250
|
+
serializeFragmentAssets(key, tracking.boundaryModules, context);
|
|
1251
|
+
propagateBoundaryStyles(key, parentKey, tracking);
|
|
1252
|
+
adoptHeadBoundary(headRegistry, key, parentKey);
|
|
1253
|
+
item.resolve();
|
|
1254
|
+
return;
|
|
1255
|
+
}
|
|
1256
|
+
if (!completed) {
|
|
1257
|
+
if (error) dropHeadBoundary(headRegistry, key);
|
|
1258
|
+
if (!firstFlushed) {
|
|
1259
|
+
queue(() => html = replacePlaceholder(html, key, value !== undefined ? value : ""));
|
|
1260
|
+
serializeFragmentAssets(key, tracking.boundaryModules, context);
|
|
1261
|
+
item.resolve(error);
|
|
1262
|
+
} else {
|
|
1263
|
+
serializeFragmentAssets(key, tracking.boundaryModules, context);
|
|
1264
|
+
const styles = collectStreamStyles(key, tracking, headStyles);
|
|
1265
|
+
const headOps = error ? null : flushHeadFragment(headRegistry, key);
|
|
1266
|
+
if (headOps) emitHeadOps(key, headOps);
|
|
1267
|
+
sink.fragment(key, resolveSSRSelectValues(value !== undefined ? value : " "), {
|
|
1268
|
+
styles,
|
|
1269
|
+
revealGroup,
|
|
1270
|
+
error
|
|
1271
|
+
});
|
|
1272
|
+
item.resolve(error);
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
return firstFlushed;
|
|
1277
|
+
};
|
|
1278
|
+
},
|
|
1279
|
+
revealFragments(groupOrKeys) {
|
|
1280
|
+
const keys = resolveRevealKeys(groupOrKeys, true, true);
|
|
1281
|
+
if (!keys) return;
|
|
1282
|
+
sink.reveal(keys, {
|
|
1283
|
+
fallback: false
|
|
1284
|
+
});
|
|
1285
|
+
},
|
|
1286
|
+
revealFallbacks(groupOrKeys) {
|
|
1287
|
+
const keys = resolveRevealKeys(groupOrKeys, false, false);
|
|
1288
|
+
if (!keys) return;
|
|
1289
|
+
sink.reveal(keys, {
|
|
1290
|
+
fallback: true
|
|
1291
|
+
});
|
|
1292
|
+
}
|
|
1293
|
+
};
|
|
1294
|
+
applyAssetTracking(context, tracking, manifest, noScripts);
|
|
1295
|
+
context.failRender = failRender;
|
|
1296
|
+
registerEntryAssets(manifest);
|
|
1297
|
+
let html = createRoot(d => {
|
|
1298
|
+
dispose = d;
|
|
1299
|
+
const res = resolveSSRNode(escape(code()));
|
|
1300
|
+
if (!res.h.length) return res.t[0];
|
|
1301
|
+
rootHoles = [];
|
|
1302
|
+
let out = res.t[0];
|
|
1303
|
+
for (let i = 0; i < res.h.length; i++) {
|
|
1304
|
+
const id = nextHoleId++;
|
|
1305
|
+
rootHoles.push({
|
|
1306
|
+
id,
|
|
1307
|
+
fn: res.h[i]
|
|
1308
|
+
});
|
|
1309
|
+
out += `<!--rh${id}-->` + res.t[i + 1];
|
|
1310
|
+
}
|
|
1311
|
+
for (const p of res.p) blockingPromises.add(p);
|
|
1312
|
+
return out;
|
|
1313
|
+
}, {
|
|
1314
|
+
id: renderId
|
|
1315
|
+
});
|
|
1316
|
+
function resolveRootHoles() {
|
|
1317
|
+
if (!rootHoles) return true;
|
|
1318
|
+
const pending = [];
|
|
1319
|
+
for (const {
|
|
1320
|
+
id,
|
|
1321
|
+
fn
|
|
1322
|
+
} of rootHoles) {
|
|
1323
|
+
const marker = `<!--rh${id}-->`;
|
|
1324
|
+
const res = resolveSSRNode(fn);
|
|
1325
|
+
if (!res.h.length) {
|
|
1326
|
+
html = html.replace(marker, res.t[0]);
|
|
1327
|
+
} else {
|
|
1328
|
+
let out = res.t[0];
|
|
1329
|
+
for (let j = 0; j < res.h.length; j++) {
|
|
1330
|
+
const newId = nextHoleId++;
|
|
1331
|
+
pending.push({
|
|
1332
|
+
id: newId,
|
|
1333
|
+
fn: res.h[j]
|
|
1334
|
+
});
|
|
1335
|
+
out += `<!--rh${newId}-->` + res.t[j + 1];
|
|
1336
|
+
}
|
|
1337
|
+
html = html.replace(marker, out);
|
|
1338
|
+
for (const p of res.p) blockingPromises.add(p);
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
if (pending.length) {
|
|
1342
|
+
rootHoles = pending;
|
|
1343
|
+
return false;
|
|
1344
|
+
}
|
|
1345
|
+
rootHoles = null;
|
|
1346
|
+
return true;
|
|
1347
|
+
}
|
|
1348
|
+
function doShell() {
|
|
1349
|
+
if (shellCompleted) return;
|
|
1350
|
+
sharedConfig.context = context;
|
|
1351
|
+
if (!resolveRootHoles()) return;
|
|
1352
|
+
if (!headShellReady(headRegistry, p => blockingPromises.add(p))) return;
|
|
1353
|
+
headStyles = new Set();
|
|
1354
|
+
for (const url of tracking.emittedAssets) {
|
|
1355
|
+
if (isCssUrl(url)) headStyles.add(url);
|
|
1356
|
+
}
|
|
1357
|
+
serializeRootAssets();
|
|
1358
|
+
const head = renderShellHead(headRegistry, nonce, k => registry.has(k));
|
|
1359
|
+
sink.shell(resolveSSRSelectValues(html), {
|
|
1360
|
+
preloads: tracking.emittedAssets,
|
|
1361
|
+
inlineStyles: tracking.inlineStyles,
|
|
1362
|
+
tasks,
|
|
1363
|
+
head
|
|
1364
|
+
});
|
|
1365
|
+
tasks = "";
|
|
1366
|
+
onCompleteShell && onCompleteShell({
|
|
1367
|
+
write(v) {
|
|
1368
|
+
!completed && buffer.write(v);
|
|
1369
|
+
}
|
|
1370
|
+
});
|
|
1371
|
+
shellCompleted = true;
|
|
1372
|
+
}
|
|
1373
|
+
const MIN_DRAIN_TURNS = 8;
|
|
1374
|
+
let lastBlockingSize = -1;
|
|
1375
|
+
let lastRegistrySize = -1;
|
|
1376
|
+
let drainTurn = 0;
|
|
1377
|
+
const scheduleFlush = fn => {
|
|
1378
|
+
const attempt = () => {
|
|
1379
|
+
if (registry.size !== lastRegistrySize || drainTurn++ < MIN_DRAIN_TURNS) {
|
|
1380
|
+
if (registry.size !== lastRegistrySize) drainTurn = 0;
|
|
1381
|
+
lastRegistrySize = registry.size;
|
|
1382
|
+
queue(attempt);
|
|
1383
|
+
return;
|
|
1384
|
+
}
|
|
1385
|
+
fn();
|
|
1386
|
+
};
|
|
1387
|
+
const progressed = blockingPromises.size !== lastBlockingSize;
|
|
1388
|
+
lastBlockingSize = blockingPromises.size;
|
|
1389
|
+
lastRegistrySize = -1;
|
|
1390
|
+
drainTurn = 0;
|
|
1391
|
+
progressed ? queue(attempt) : setTimeout(attempt);
|
|
1392
|
+
};
|
|
1393
|
+
let cachedReadable;
|
|
1394
|
+
let consumer;
|
|
1395
|
+
const claimConsumer = name => {
|
|
1396
|
+
if (consumer && consumer !== name) {
|
|
1397
|
+
throw new Error(`renderToStream result was already consumed via \`${consumer}\`; cannot also consume it via \`${name}\`. Use exactly one of \`pipe\`, \`pipeTo\`, or \`readable\`.`);
|
|
1398
|
+
}
|
|
1399
|
+
consumer = name;
|
|
1400
|
+
};
|
|
1401
|
+
const pipeToImpl = w => {
|
|
1402
|
+
let resolve;
|
|
1403
|
+
const p = new Promise(r => resolve = r);
|
|
1404
|
+
function flush() {
|
|
1405
|
+
allSettled(blockingPromises).then(() => {
|
|
1406
|
+
scheduleFlush(() => {
|
|
1407
|
+
if (dead) return resolve();
|
|
1408
|
+
try {
|
|
1409
|
+
doShell();
|
|
1410
|
+
} catch (err) {
|
|
1411
|
+
failRender(err);
|
|
1412
|
+
return resolve();
|
|
1413
|
+
}
|
|
1414
|
+
if (!shellCompleted) return flush();
|
|
1415
|
+
const encoder = new TextEncoder();
|
|
1416
|
+
const writer = w.getWriter();
|
|
1417
|
+
let pendingWrites = Promise.resolve();
|
|
1418
|
+
let ended = false;
|
|
1419
|
+
const failed = () => {
|
|
1420
|
+
if (!ended) {
|
|
1421
|
+
abandon();
|
|
1422
|
+
resolve();
|
|
1423
|
+
}
|
|
1424
|
+
};
|
|
1425
|
+
writer.closed && writer.closed.catch(failed);
|
|
1426
|
+
writable = {
|
|
1427
|
+
end() {
|
|
1428
|
+
pendingWrites.then(() => {
|
|
1429
|
+
ended = true;
|
|
1430
|
+
writer.releaseLock();
|
|
1431
|
+
w.close().catch(() => {});
|
|
1432
|
+
resolve();
|
|
1433
|
+
});
|
|
1434
|
+
}
|
|
1435
|
+
};
|
|
1436
|
+
buffer = {
|
|
1437
|
+
write(payload) {
|
|
1438
|
+
pendingWrites = pendingWrites.then(() => writer.write(encoder.encode(payload))).catch(failed);
|
|
1439
|
+
}
|
|
1440
|
+
};
|
|
1441
|
+
buffer.write(tmp);
|
|
1442
|
+
firstFlushed = true;
|
|
1443
|
+
if (completed) {
|
|
1444
|
+
dispose();
|
|
1445
|
+
writable.end();
|
|
1446
|
+
} else flushEnd();
|
|
1447
|
+
});
|
|
1448
|
+
});
|
|
1449
|
+
}
|
|
1450
|
+
flush();
|
|
1451
|
+
return p;
|
|
1452
|
+
};
|
|
1453
|
+
return {
|
|
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
|
+
});
|
|
1478
|
+
});
|
|
1479
|
+
}
|
|
1480
|
+
flush();
|
|
1481
|
+
});
|
|
1482
|
+
return p.then(onFulfilled, onRejected);
|
|
1483
|
+
},
|
|
1484
|
+
pipe(w) {
|
|
1485
|
+
claimConsumer("pipe");
|
|
1486
|
+
function flush() {
|
|
1487
|
+
allSettled(blockingPromises).then(() => {
|
|
1488
|
+
scheduleFlush(() => {
|
|
1489
|
+
if (dead) return;
|
|
1490
|
+
try {
|
|
1491
|
+
doShell();
|
|
1492
|
+
} catch (err) {
|
|
1493
|
+
failRender(err);
|
|
1494
|
+
try {
|
|
1495
|
+
w.end();
|
|
1496
|
+
} catch (_) {}
|
|
1497
|
+
return;
|
|
1498
|
+
}
|
|
1499
|
+
if (!shellCompleted) return flush();
|
|
1500
|
+
buffer = writable = guardSink(w);
|
|
1501
|
+
buffer.write(tmp);
|
|
1502
|
+
firstFlushed = true;
|
|
1503
|
+
if (completed) {
|
|
1504
|
+
dispose();
|
|
1505
|
+
writable.end();
|
|
1506
|
+
} else flushEnd();
|
|
1507
|
+
});
|
|
1508
|
+
});
|
|
1509
|
+
}
|
|
1510
|
+
flush();
|
|
1511
|
+
},
|
|
1512
|
+
pipeTo(w) {
|
|
1513
|
+
claimConsumer("pipeTo");
|
|
1514
|
+
return pipeToImpl(w);
|
|
1515
|
+
},
|
|
1516
|
+
get readable() {
|
|
1517
|
+
claimConsumer("readable");
|
|
1518
|
+
if (!cachedReadable) {
|
|
1519
|
+
const t = new TransformStream();
|
|
1520
|
+
pipeToImpl(t.writable);
|
|
1521
|
+
cachedReadable = t.readable;
|
|
1522
|
+
}
|
|
1523
|
+
return cachedReadable;
|
|
1524
|
+
}
|
|
1525
|
+
};
|
|
1526
|
+
}
|
|
1527
|
+
function buildAsyncWrap(err, node) {
|
|
1528
|
+
const p = ssrHandleError(err);
|
|
1529
|
+
if (!p) return null;
|
|
1530
|
+
if (node.$rw) return {
|
|
1531
|
+
fn: node,
|
|
1532
|
+
p
|
|
1533
|
+
};
|
|
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;
|
|
1549
|
+
return {
|
|
1550
|
+
fn,
|
|
1551
|
+
p
|
|
1552
|
+
};
|
|
1553
|
+
}
|
|
1554
|
+
function ssrFirstGroupHit(hole) {
|
|
1555
|
+
try {
|
|
1556
|
+
return hole();
|
|
1557
|
+
} catch (err) {
|
|
1558
|
+
return buildAsyncWrap(err, hole);
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
function tryResolveFunctionHole(hole) {
|
|
1562
|
+
let value;
|
|
1563
|
+
try {
|
|
1564
|
+
value = hole();
|
|
1565
|
+
} catch (err) {
|
|
1566
|
+
return buildAsyncWrap(err, hole) || "";
|
|
1567
|
+
}
|
|
1568
|
+
const t = typeof value;
|
|
1569
|
+
if (t === "string") return value;
|
|
1570
|
+
if (t === "number") return "" + value;
|
|
1571
|
+
if (value == null || t === "boolean") return "";
|
|
1572
|
+
return tryResolveString(value);
|
|
1573
|
+
}
|
|
1574
|
+
function mergeTemplateInto(result, node) {
|
|
1575
|
+
result.t[result.t.length - 1] += node.t[0];
|
|
1576
|
+
if (node.t.length > 1) {
|
|
1577
|
+
result.t.push(...node.t.slice(1));
|
|
1578
|
+
result.h.push(...node.h);
|
|
1579
|
+
result.p.push(...node.p);
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
function appendResolvedNode(result, node) {
|
|
1583
|
+
if (node.fn !== undefined) {
|
|
1584
|
+
result.h.push(node.fn);
|
|
1585
|
+
result.p.push(node.p);
|
|
1586
|
+
result.t.push("");
|
|
1587
|
+
} else if (node.merge !== undefined) mergeTemplateInto(result, node.merge);else resolveSSRNode(node.bail, result);
|
|
1588
|
+
}
|
|
1589
|
+
let _lastGroupFn = null;
|
|
1590
|
+
let _lastGroupArr = null;
|
|
1591
|
+
let _lastGroupErr = null;
|
|
1592
|
+
function ssrGroupSlot(fn, idx) {
|
|
1593
|
+
return () => {
|
|
1594
|
+
if (idx > 0 && _lastGroupFn === fn) {
|
|
1595
|
+
if (_lastGroupArr !== null) return _lastGroupArr[idx];
|
|
1596
|
+
throw _lastGroupErr;
|
|
1597
|
+
}
|
|
1598
|
+
_lastGroupFn = fn;
|
|
1599
|
+
_lastGroupArr = null;
|
|
1600
|
+
_lastGroupErr = null;
|
|
1601
|
+
try {
|
|
1602
|
+
_lastGroupArr = fn();
|
|
1603
|
+
return _lastGroupArr[idx];
|
|
1604
|
+
} catch (err) {
|
|
1605
|
+
_lastGroupErr = err;
|
|
1606
|
+
throw err;
|
|
1607
|
+
}
|
|
1608
|
+
};
|
|
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
|
+
}
|
|
1930
|
+
function ssr(t) {
|
|
1931
|
+
const len = arguments.length;
|
|
1932
|
+
if (len === 1) return {
|
|
1933
|
+
t
|
|
1934
|
+
};
|
|
1935
|
+
let s = t[0];
|
|
1936
|
+
let result = null;
|
|
1937
|
+
let lastGroup = null;
|
|
1938
|
+
let lastGroupVal = null;
|
|
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
|
+
};
|
|
1973
|
+
for (let i = 1; i < len; i++) {
|
|
1974
|
+
const hole = arguments[i];
|
|
1975
|
+
const ht = typeof hole;
|
|
1976
|
+
if (ht === "string") {
|
|
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
|
+
}
|
|
1982
|
+
} else if (ht === "number") {
|
|
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
|
+
}
|
|
1988
|
+
} else if (hole == null || ht === "boolean") ; else if (ht === "function" && hole.$g) {
|
|
1989
|
+
let value;
|
|
1990
|
+
let hasValue = false;
|
|
1991
|
+
if (lastGroup !== hole) {
|
|
1992
|
+
const r = ssrFirstGroupHit(hole);
|
|
1993
|
+
if (r !== null) {
|
|
1994
|
+
lastGroup = hole;
|
|
1995
|
+
lastGroupVal = r;
|
|
1996
|
+
lastGroupIdx = 0;
|
|
1997
|
+
if (!Array.isArray(r) && result === null) {
|
|
1998
|
+
result = {
|
|
1999
|
+
t: [s],
|
|
2000
|
+
h: [],
|
|
2001
|
+
p: []
|
|
2002
|
+
};
|
|
2003
|
+
s = "";
|
|
2004
|
+
}
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
2007
|
+
if (lastGroup === hole) {
|
|
2008
|
+
if (Array.isArray(lastGroupVal)) {
|
|
2009
|
+
value = lastGroupVal[lastGroupIdx++];
|
|
2010
|
+
hasValue = true;
|
|
2011
|
+
if (live && !hp.pos[i - 1] && captureStart()) {
|
|
2012
|
+
cap.parts.push({
|
|
2013
|
+
g: hole,
|
|
2014
|
+
i: lastGroupIdx - 1
|
|
2015
|
+
});
|
|
2016
|
+
}
|
|
2017
|
+
} else {
|
|
2018
|
+
cap = null;
|
|
2019
|
+
result.h.push(ssrGroupSlot(lastGroupVal.fn, lastGroupIdx++));
|
|
2020
|
+
result.p.push(lastGroupVal.p);
|
|
2021
|
+
result.t.push("");
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
if (hasValue) {
|
|
2025
|
+
const vt = typeof value;
|
|
2026
|
+
if (vt === "string" || vt === "number") {
|
|
2027
|
+
if (result === null) s += value;else result.t[result.t.length - 1] += value;
|
|
2028
|
+
if (cap && !hp.pos[i - 1]) cap.base += value;
|
|
2029
|
+
} else if (value == null || vt === "boolean") ; else if (result !== null) {
|
|
2030
|
+
resolveSSRNode(value, result);
|
|
2031
|
+
} else {
|
|
2032
|
+
const rs = tryResolveString(value);
|
|
2033
|
+
if (typeof rs === "string") {
|
|
2034
|
+
s += rs;
|
|
2035
|
+
} else {
|
|
2036
|
+
result = {
|
|
2037
|
+
t: [s],
|
|
2038
|
+
h: [],
|
|
2039
|
+
p: []
|
|
2040
|
+
};
|
|
2041
|
+
s = "";
|
|
2042
|
+
if (rs.merge !== undefined) mergeTemplateInto(result, rs.merge);else resolveSSRNode(rs.bail, result);
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
2045
|
+
}
|
|
2046
|
+
} else if (ht === "function") {
|
|
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
|
+
}
|
|
2104
|
+
}
|
|
2105
|
+
} else if (result !== null) {
|
|
2106
|
+
resolveSSRNode(hole, result);
|
|
2107
|
+
} else {
|
|
2108
|
+
const r = tryResolveString(hole);
|
|
2109
|
+
if (typeof r === "string") {
|
|
2110
|
+
s += r;
|
|
2111
|
+
} else {
|
|
2112
|
+
result = {
|
|
2113
|
+
t: [s],
|
|
2114
|
+
h: [],
|
|
2115
|
+
p: []
|
|
2116
|
+
};
|
|
2117
|
+
s = "";
|
|
2118
|
+
appendResolvedNode(result, r);
|
|
2119
|
+
}
|
|
2120
|
+
}
|
|
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
|
+
}
|
|
2148
|
+
if (result === null) s += next;else result.t[result.t.length - 1] += next;
|
|
2149
|
+
}
|
|
2150
|
+
if (result === null) return {
|
|
2151
|
+
t: s
|
|
2152
|
+
};
|
|
2153
|
+
return result;
|
|
2154
|
+
}
|
|
2155
|
+
function decodeSSREntities(s) {
|
|
2156
|
+
return s.indexOf("&") < 0 ? s : s.replace(/"/g, '"').replace(/</g, "<").replace(/&/g, "&");
|
|
2157
|
+
}
|
|
2158
|
+
const SELECT_VALUE_ATTR = /\svalue="([^"]*)"/;
|
|
2159
|
+
function tagEnd(html, i) {
|
|
2160
|
+
for (let j = i + 1; j < html.length; j++) {
|
|
2161
|
+
const c = html.charCodeAt(j);
|
|
2162
|
+
if (c === 34) {
|
|
2163
|
+
j = html.indexOf('"', j + 1);
|
|
2164
|
+
if (j < 0) return -1;
|
|
2165
|
+
} else if (c === 62) return j;
|
|
2166
|
+
}
|
|
2167
|
+
return -1;
|
|
2168
|
+
}
|
|
2169
|
+
function optionText(html, from) {
|
|
2170
|
+
let t = "";
|
|
2171
|
+
let i = from;
|
|
2172
|
+
for (;;) {
|
|
2173
|
+
const lt = html.indexOf("<", i);
|
|
2174
|
+
if (lt < 0) return t + html.slice(i);
|
|
2175
|
+
t += html.slice(i, lt);
|
|
2176
|
+
if (!html.startsWith("<!--", lt)) return t;
|
|
2177
|
+
const ce = html.indexOf("-->", lt);
|
|
2178
|
+
if (ce < 0) return t;
|
|
2179
|
+
i = ce + 3;
|
|
2180
|
+
}
|
|
2181
|
+
}
|
|
2182
|
+
function tagIs(html, i, name) {
|
|
2183
|
+
if (!html.startsWith(name, i + 1)) return false;
|
|
2184
|
+
const c = html.charCodeAt(i + 1 + name.length);
|
|
2185
|
+
return c === 32 || c === 62 || c === 9 || c === 10 || c === 13;
|
|
2186
|
+
}
|
|
2187
|
+
function resolveSSRSelectValues(html) {
|
|
2188
|
+
if (html.indexOf("<select") < 0) return html;
|
|
2189
|
+
let out = "";
|
|
2190
|
+
let idx = 0;
|
|
2191
|
+
let sel = null;
|
|
2192
|
+
let i = html.indexOf("<");
|
|
2193
|
+
while (i >= 0) {
|
|
2194
|
+
let e;
|
|
2195
|
+
if (html.charCodeAt(i + 1) === 33) {
|
|
2196
|
+
e = html.charCodeAt(i + 2) === 45 ? html.indexOf("-->", i) : html.indexOf(">", i);
|
|
2197
|
+
if (e < 0) break;
|
|
2198
|
+
if (html.charCodeAt(i + 2) === 45) e += 2;
|
|
2199
|
+
} else {
|
|
2200
|
+
e = tagEnd(html, i);
|
|
2201
|
+
if (e < 0) break;
|
|
2202
|
+
if (sel) {
|
|
2203
|
+
if (html.startsWith("</select>", i)) {
|
|
2204
|
+
out += html.slice(idx, sel.strip) + html.slice(sel.stripEnd, sel.body);
|
|
2205
|
+
let seg = sel.body;
|
|
2206
|
+
if (!sel.defaulted) {
|
|
2207
|
+
for (let k = 0; k < sel.marks.length; k++) {
|
|
2208
|
+
out += html.slice(seg, sel.marks[k]) + " selected";
|
|
2209
|
+
seg = sel.marks[k];
|
|
2210
|
+
}
|
|
2211
|
+
}
|
|
2212
|
+
out += html.slice(seg, i);
|
|
2213
|
+
idx = i;
|
|
2214
|
+
sel = null;
|
|
2215
|
+
} else if (tagIs(html, i, "option")) {
|
|
2216
|
+
const attrs = html.slice(i + 7, e);
|
|
2217
|
+
if (/\sselected(?=[\s=]|$)/.test(attrs)) sel.defaulted = true;else {
|
|
2218
|
+
const vm = SELECT_VALUE_ATTR.exec(attrs);
|
|
2219
|
+
const value = vm ? decodeSSREntities(vm[1]) : decodeSSREntities(optionText(html, e + 1)).replace(/\s+/g, " ").trim();
|
|
2220
|
+
if (sel.values.includes(value)) sel.marks.push(e);
|
|
2221
|
+
}
|
|
2222
|
+
}
|
|
2223
|
+
} else if (tagIs(html, i, "select")) {
|
|
2224
|
+
const m = SELECT_VALUE_ATTR.exec(html.slice(i, e + 1));
|
|
2225
|
+
if (m) {
|
|
2226
|
+
const bound = decodeSSREntities(m[1]);
|
|
2227
|
+
sel = {
|
|
2228
|
+
values: /\smultiple(?=[\s>=])/.test(html.slice(i, e + 1)) ? bound.split(",") : [bound],
|
|
2229
|
+
strip: i + m.index,
|
|
2230
|
+
stripEnd: i + m.index + m[0].length,
|
|
2231
|
+
body: e + 1,
|
|
2232
|
+
marks: [],
|
|
2233
|
+
defaulted: false
|
|
2234
|
+
};
|
|
2235
|
+
}
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
i = html.indexOf("<", e + 1);
|
|
2239
|
+
}
|
|
2240
|
+
return out + html.slice(idx);
|
|
2241
|
+
}
|
|
2242
|
+
function escape(s, attr) {
|
|
2243
|
+
const t = typeof s;
|
|
2244
|
+
if (t !== "string") {
|
|
2245
|
+
if (!attr && Array.isArray(s)) {
|
|
2246
|
+
const joined = tryJoinPlainSSRArray(s);
|
|
2247
|
+
if (joined !== undefined) return joined;
|
|
2248
|
+
s = s.slice();
|
|
2249
|
+
for (let i = 0; i < s.length; i++) s[i] = escape(s[i]);
|
|
2250
|
+
return s;
|
|
2251
|
+
}
|
|
2252
|
+
if (attr) {
|
|
2253
|
+
if (s == null || t === "boolean" || t === "number") return s;
|
|
2254
|
+
return escape(String(s), attr);
|
|
2255
|
+
}
|
|
2256
|
+
return s;
|
|
2257
|
+
}
|
|
2258
|
+
const i = s.search(attr ? ESCAPE_ATTR : ESCAPE_CONTENT);
|
|
2259
|
+
if (i < 0) return s;
|
|
2260
|
+
return escapeSlow(s, attr, i);
|
|
2261
|
+
}
|
|
2262
|
+
const ESCAPE_CONTENT = /[&<]/;
|
|
2263
|
+
const ESCAPE_ATTR = /[&"]/;
|
|
2264
|
+
function escapeSlow(s, attr, start) {
|
|
2265
|
+
const delim = attr ? '"' : "<";
|
|
2266
|
+
const delimCode = attr ? 34 : 60;
|
|
2267
|
+
const escDelim = attr ? """ : "<";
|
|
2268
|
+
const c0 = s.charCodeAt(start);
|
|
2269
|
+
let iDelim = c0 === delimCode ? start : s.indexOf(delim, start);
|
|
2270
|
+
let iAmp = c0 === 38 ? start : s.indexOf("&", start);
|
|
2271
|
+
let left = 0,
|
|
2272
|
+
out = "";
|
|
2273
|
+
while (iDelim >= 0 && iAmp >= 0) {
|
|
2274
|
+
if (iDelim < iAmp) {
|
|
2275
|
+
if (left < iDelim) out += s.substring(left, iDelim);
|
|
2276
|
+
out += escDelim;
|
|
2277
|
+
left = iDelim + 1;
|
|
2278
|
+
iDelim = s.indexOf(delim, left);
|
|
2279
|
+
} else {
|
|
2280
|
+
if (left < iAmp) out += s.substring(left, iAmp);
|
|
2281
|
+
out += "&";
|
|
2282
|
+
left = iAmp + 1;
|
|
2283
|
+
iAmp = s.indexOf("&", left);
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
2286
|
+
if (iDelim >= 0) {
|
|
2287
|
+
do {
|
|
2288
|
+
if (left < iDelim) out += s.substring(left, iDelim);
|
|
2289
|
+
out += escDelim;
|
|
2290
|
+
left = iDelim + 1;
|
|
2291
|
+
iDelim = s.indexOf(delim, left);
|
|
2292
|
+
} while (iDelim >= 0);
|
|
2293
|
+
} else while (iAmp >= 0) {
|
|
2294
|
+
if (left < iAmp) out += s.substring(left, iAmp);
|
|
2295
|
+
out += "&";
|
|
2296
|
+
left = iAmp + 1;
|
|
2297
|
+
iAmp = s.indexOf("&", left);
|
|
2298
|
+
}
|
|
2299
|
+
return left < s.length ? out + s.substring(left) : out;
|
|
2300
|
+
}
|
|
2301
|
+
function tryJoinPlainSSRArray(nodes) {
|
|
2302
|
+
if (nodes.length === 0) return undefined;
|
|
2303
|
+
let out = "";
|
|
2304
|
+
for (let i = 0, len = nodes.length; i < len; i++) {
|
|
2305
|
+
const node = nodes[i];
|
|
2306
|
+
if (node == null || typeof node !== "object" || node.h || typeof node.t !== "string") {
|
|
2307
|
+
return undefined;
|
|
2308
|
+
}
|
|
2309
|
+
out += node.t;
|
|
2310
|
+
}
|
|
2311
|
+
return out;
|
|
2312
|
+
}
|
|
2313
|
+
function queue(fn) {
|
|
2314
|
+
return Promise.resolve().then(fn);
|
|
2315
|
+
}
|
|
2316
|
+
function allSettled(promises) {
|
|
2317
|
+
let size = promises.size;
|
|
2318
|
+
return Promise.allSettled(promises).then(() => {
|
|
2319
|
+
if (promises.size !== size) return allSettled(promises);
|
|
2320
|
+
return;
|
|
2321
|
+
});
|
|
2322
|
+
}
|
|
2323
|
+
function assembleDocument(html, emittedAssets, inlineStyles, scripts, nonce, headTags, onHead) {
|
|
2324
|
+
const scriptTag = scripts ? `<script${nonce ? ` nonce="${nonce}"` : ""}>${scripts}</script>` : "";
|
|
2325
|
+
const headTagsHtml = headTags ? headTags.html : "";
|
|
2326
|
+
const headPrelude = headTags ? headTags.prelude : "";
|
|
2327
|
+
if (!onHead && !headTagsHtml && !headPrelude && !(emittedAssets && emittedAssets.size) && !(inlineStyles && inlineStyles.size)) {
|
|
2328
|
+
if (!scriptTag) return html;
|
|
2329
|
+
const xs = html.indexOf("<!--xs-->");
|
|
2330
|
+
return xs === -1 ? html + scriptTag : html.slice(0, xs) + scriptTag + html.slice(xs);
|
|
2331
|
+
}
|
|
2332
|
+
if (headPrelude) {
|
|
2333
|
+
const open = html.match(/<head(?:\s[^>]*)?>/);
|
|
2334
|
+
if (open) {
|
|
2335
|
+
const at = open.index + open[0].length;
|
|
2336
|
+
html = html.slice(0, at) + headPrelude + html.slice(at);
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2339
|
+
const headIdx = html.indexOf("</head>");
|
|
2340
|
+
if (headIdx === -1) {
|
|
2341
|
+
if (onHead) {
|
|
2342
|
+
onHead(headPrelude + headTagsHtml + renderHeadAssets(emittedAssets, inlineStyles, nonce));
|
|
2343
|
+
}
|
|
2344
|
+
if (!scriptTag) return html;
|
|
2345
|
+
const xs = html.indexOf("<!--xs-->");
|
|
2346
|
+
return xs === -1 ? html + scriptTag : html.slice(0, xs) + scriptTag + html.slice(xs);
|
|
2347
|
+
}
|
|
2348
|
+
const head = headTagsHtml + renderHeadAssets(emittedAssets, inlineStyles, nonce);
|
|
2349
|
+
if (!scriptTag) return html.slice(0, headIdx) + head + html.slice(headIdx);
|
|
2350
|
+
const xsIdx = html.indexOf("<!--xs-->");
|
|
2351
|
+
if (xsIdx === -1) return html.slice(0, headIdx) + head + html.slice(headIdx) + scriptTag;
|
|
2352
|
+
return xsIdx < headIdx ? html.slice(0, xsIdx) + scriptTag + html.slice(xsIdx, headIdx) + head + html.slice(headIdx) : html.slice(0, headIdx) + head + html.slice(headIdx, xsIdx) + scriptTag + html.slice(xsIdx);
|
|
2353
|
+
}
|
|
2354
|
+
function renderHeadAssets(emittedAssets, inlineStyles, nonce) {
|
|
2355
|
+
let head = "";
|
|
2356
|
+
if (emittedAssets && emittedAssets.size) {
|
|
2357
|
+
for (const url of emittedAssets) {
|
|
2358
|
+
head += isCssUrl(url) ? `<link rel="stylesheet" href="${url}">` : `<link rel="modulepreload" href="${url}">`;
|
|
2359
|
+
}
|
|
2360
|
+
}
|
|
2361
|
+
if (inlineStyles && inlineStyles.size) {
|
|
2362
|
+
for (const entry of inlineStyles.values()) {
|
|
2363
|
+
if (entry.emitted) continue;
|
|
2364
|
+
entry.emitted = true;
|
|
2365
|
+
head += renderInlineStyle(entry, nonce);
|
|
2366
|
+
}
|
|
2367
|
+
}
|
|
2368
|
+
return head;
|
|
2369
|
+
}
|
|
2370
|
+
function serializeFragmentAssets(key, boundaryModules, context, name = key) {
|
|
2371
|
+
const map = boundaryModules.get(key);
|
|
2372
|
+
if (!map || !Object.keys(map).length) return;
|
|
2373
|
+
context.serialize(name + "_assets", {
|
|
2374
|
+
...map
|
|
2375
|
+
});
|
|
2376
|
+
}
|
|
2377
|
+
function propagateBoundaryStyles(childKey, parentKey, tracking) {
|
|
2378
|
+
const childStyles = tracking.getBoundaryStyles(childKey);
|
|
2379
|
+
if (!childStyles) return;
|
|
2380
|
+
let parentStyles = tracking.boundaryStyles.get(parentKey);
|
|
2381
|
+
if (!parentStyles) {
|
|
2382
|
+
parentStyles = new Set();
|
|
2383
|
+
tracking.boundaryStyles.set(parentKey, parentStyles);
|
|
2384
|
+
}
|
|
2385
|
+
for (const url of childStyles) {
|
|
2386
|
+
parentStyles.add(url);
|
|
2387
|
+
}
|
|
2388
|
+
}
|
|
2389
|
+
function collectStreamStyles(key, tracking, headStyles) {
|
|
2390
|
+
const styles = tracking.getBoundaryStyles(key);
|
|
2391
|
+
const links = [];
|
|
2392
|
+
const inline = [];
|
|
2393
|
+
if (!styles) return {
|
|
2394
|
+
links,
|
|
2395
|
+
inline
|
|
2396
|
+
};
|
|
2397
|
+
for (const entry of styles) {
|
|
2398
|
+
if (typeof entry === "string") {
|
|
2399
|
+
if (!headStyles || !headStyles.has(entry)) links.push(entry);
|
|
2400
|
+
} else if (entry.emitted) {
|
|
2401
|
+
continue;
|
|
2402
|
+
} else if (entry.attrHtml !== undefined) {
|
|
2403
|
+
entry.emitted = true;
|
|
2404
|
+
links.push(entry);
|
|
2405
|
+
} else {
|
|
2406
|
+
entry.emitted = true;
|
|
2407
|
+
inline.push(entry);
|
|
2408
|
+
}
|
|
2409
|
+
}
|
|
2410
|
+
return {
|
|
2411
|
+
links,
|
|
2412
|
+
inline
|
|
2413
|
+
};
|
|
2414
|
+
}
|
|
2415
|
+
function escapeStyleContent(content) {
|
|
2416
|
+
return content.replace(/<\/(style)/gi, "<\\/$1");
|
|
2417
|
+
}
|
|
2418
|
+
function renderInlineStyle(entry, nonce) {
|
|
2419
|
+
let attrs = "";
|
|
2420
|
+
if (entry.attrs) {
|
|
2421
|
+
for (const name in entry.attrs) {
|
|
2422
|
+
attrs += ` ${name}="${escape(String(entry.attrs[name]), true)}"`;
|
|
2423
|
+
}
|
|
2424
|
+
}
|
|
2425
|
+
return `<style${nonce ? ` nonce="${nonce}"` : ""} data-asset="${escape(entry.id, true)}"${attrs}>${escapeStyleContent(entry.content)}</style>`;
|
|
2426
|
+
}
|
|
2427
|
+
function waitForFragments(registry, key) {
|
|
2428
|
+
for (const k of [...registry.keys()].reverse()) {
|
|
2429
|
+
if (key.startsWith(k)) return k;
|
|
2430
|
+
}
|
|
2431
|
+
return false;
|
|
2432
|
+
}
|
|
2433
|
+
function replacePlaceholder(html, key, value) {
|
|
2434
|
+
const marker = `<template id="pl-${key}">`;
|
|
2435
|
+
const close = `<!--pl-${key}-->`;
|
|
2436
|
+
const first = html.indexOf(marker);
|
|
2437
|
+
if (first === -1) return html;
|
|
2438
|
+
const last = html.indexOf(close, first + marker.length);
|
|
2439
|
+
return html.slice(0, first) + value + html.slice(last + close.length);
|
|
2440
|
+
}
|
|
2441
|
+
function tryResolveString(node) {
|
|
2442
|
+
const t = typeof node;
|
|
2443
|
+
if (t === "string") return node;
|
|
2444
|
+
if (t === "number") return "" + node;
|
|
2445
|
+
if (node == null || t === "boolean") return "";
|
|
2446
|
+
if (t === "object") {
|
|
2447
|
+
if (Array.isArray(node)) {
|
|
2448
|
+
const joined = tryJoinPlainSSRArray(node);
|
|
2449
|
+
if (joined !== undefined) return joined;
|
|
2450
|
+
let s = "";
|
|
2451
|
+
let prevNonObj = false;
|
|
2452
|
+
for (let i = 0, len = node.length; i < len; i++) {
|
|
2453
|
+
const item = node[i];
|
|
2454
|
+
const itemNonObj = item !== null && typeof item !== "object";
|
|
2455
|
+
if (prevNonObj && itemNonObj) s += "<!--!$-->";
|
|
2456
|
+
prevNonObj = itemNonObj;
|
|
2457
|
+
const r = tryResolveString(item);
|
|
2458
|
+
if (typeof r !== "string") return {
|
|
2459
|
+
bail: node
|
|
2460
|
+
};
|
|
2461
|
+
s += r;
|
|
2462
|
+
}
|
|
2463
|
+
return s;
|
|
2464
|
+
}
|
|
2465
|
+
if (node.h && node.h.length > 0) return {
|
|
2466
|
+
merge: node
|
|
2467
|
+
};
|
|
2468
|
+
if (node.t === undefined) {
|
|
2469
|
+
return "";
|
|
2470
|
+
}
|
|
2471
|
+
return Array.isArray(node.t) ? node.t[0] : node.t;
|
|
2472
|
+
}
|
|
2473
|
+
if (t === "function") {
|
|
2474
|
+
let v;
|
|
2475
|
+
try {
|
|
2476
|
+
v = node();
|
|
2477
|
+
} catch (err) {
|
|
2478
|
+
return buildAsyncWrap(err, node) || "";
|
|
2479
|
+
}
|
|
2480
|
+
return tryResolveString(v);
|
|
2481
|
+
}
|
|
2482
|
+
return "";
|
|
2483
|
+
}
|
|
2484
|
+
function resolveSSRNode(node, result = {
|
|
2485
|
+
t: [""],
|
|
2486
|
+
h: [],
|
|
2487
|
+
p: []
|
|
2488
|
+
}, top) {
|
|
2489
|
+
const t = typeof node;
|
|
2490
|
+
if (t === "string" || t === "number") {
|
|
2491
|
+
result.t[result.t.length - 1] += node;
|
|
2492
|
+
} else if (node == null || t === "boolean") ; else if (Array.isArray(node)) {
|
|
2493
|
+
const slotLive = node.$slot && sharedConfig.context && sharedConfig.context.liveHoles;
|
|
2494
|
+
if (slotLive) slotLive.suppressed++;
|
|
2495
|
+
try {
|
|
2496
|
+
let prevNonObj = false;
|
|
2497
|
+
for (let i = 0, len = node.length; i < len; i++) {
|
|
2498
|
+
const item = node[i];
|
|
2499
|
+
const itemNonObj = item !== null && typeof item !== "object";
|
|
2500
|
+
if (!top && prevNonObj && itemNonObj) result.t[result.t.length - 1] += `<!--!$-->`;
|
|
2501
|
+
prevNonObj = itemNonObj;
|
|
2502
|
+
resolveSSRNode(item, result);
|
|
2503
|
+
}
|
|
2504
|
+
} finally {
|
|
2505
|
+
if (slotLive) slotLive.suppressed--;
|
|
2506
|
+
}
|
|
2507
|
+
} else if (t === "object") {
|
|
2508
|
+
if (node.h) {
|
|
2509
|
+
result.t[result.t.length - 1] += node.t[0];
|
|
2510
|
+
if (node.t.length > 1) {
|
|
2511
|
+
result.t.push(...node.t.slice(1));
|
|
2512
|
+
result.h.push(...node.h);
|
|
2513
|
+
result.p.push(...node.p);
|
|
2514
|
+
}
|
|
2515
|
+
} else if (node.t !== undefined) {
|
|
2516
|
+
result.t[result.t.length - 1] += node.t;
|
|
2517
|
+
} else ;
|
|
2518
|
+
} else if (t === "function") {
|
|
2519
|
+
const live = sharedConfig.context && sharedConfig.context.liveHoles;
|
|
2520
|
+
let liveNode = null;
|
|
2521
|
+
if (live && (liveNode = live.content(node)) !== null) {
|
|
2522
|
+
if (typeof liveNode === "string") result.t[result.t.length - 1] += liveNode;else resolveSSRNode(liveNode, result);
|
|
2523
|
+
} else {
|
|
2524
|
+
try {
|
|
2525
|
+
resolveSSRNode(node(), result);
|
|
2526
|
+
} catch (err) {
|
|
2527
|
+
const wrap = buildAsyncWrap(err, node);
|
|
2528
|
+
if (wrap) {
|
|
2529
|
+
result.h.push(wrap.fn);
|
|
2530
|
+
result.p.push(wrap.p);
|
|
2531
|
+
result.t.push("");
|
|
2532
|
+
}
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
}
|
|
2536
|
+
return result;
|
|
2537
|
+
}
|
|
2538
|
+
function resolveSSRSync(node) {
|
|
2539
|
+
const res = resolveSSRNode(node);
|
|
2540
|
+
if (!res.h.length) return res.t[0];
|
|
2541
|
+
throw new Error("This value cannot be rendered synchronously. Are you missing a boundary?");
|
|
2542
|
+
}
|
|
2543
|
+
/*#__PURE__*/new Set([ERROR_HEADER, BODY_FORMAT_HEADER, SINGLE_FLIGHT_HEADER, REVALIDATE_HEADER, "Location"].map(header => header.toLowerCase()));
|
|
2544
|
+
|
|
2545
|
+
const INVOCATIONS = new WeakMap();
|
|
2546
|
+
function getEventServerFunctionInvocation(event) {
|
|
2547
|
+
return event && INVOCATIONS.get(event);
|
|
2548
|
+
}
|
|
2549
|
+
|
|
2550
|
+
const FRAME_STREAM_HEADER = "X-Frame-Stream";
|
|
2551
|
+
function isFrameStreamResponse(response) {
|
|
2552
|
+
return response.headers.has(FRAME_STREAM_HEADER);
|
|
2553
|
+
}
|
|
2554
|
+
const SERVER_COMPONENT = /*#__PURE__*/Symbol.for("dom-expressions.server-component");
|
|
2555
|
+
const SERVER_COMPONENT_SOURCE = /*#__PURE__*/Symbol.for("dom-expressions.server-component-source");
|
|
2556
|
+
const SERVER_COMPONENT_ADDRESS = /*#__PURE__*/Symbol.for("dom-expressions.server-component-address");
|
|
2557
|
+
let serverComponentRegistryExpr;
|
|
2558
|
+
function setServerComponentBootstrap(resolve) {
|
|
2559
|
+
serverComponentRegistryExpr = resolve;
|
|
2560
|
+
}
|
|
2561
|
+
function parseServerComponent(value, ctx) {
|
|
2562
|
+
return {
|
|
2563
|
+
id: ctx.parse(value[SERVER_COMPONENT]),
|
|
2564
|
+
address: ctx.parse(value[SERVER_COMPONENT_ADDRESS])
|
|
2565
|
+
};
|
|
2566
|
+
}
|
|
2567
|
+
const ServerComponentPlugin = {
|
|
2568
|
+
tag: "dom-expressions/server-component",
|
|
2569
|
+
test(value) {
|
|
2570
|
+
return typeof value === "function" && SERVER_COMPONENT in value;
|
|
2571
|
+
},
|
|
2572
|
+
parse: {
|
|
2573
|
+
sync: parseServerComponent,
|
|
2574
|
+
async async(value, ctx) {
|
|
2575
|
+
return {
|
|
2576
|
+
id: await ctx.parse(value[SERVER_COMPONENT]),
|
|
2577
|
+
address: await ctx.parse(value[SERVER_COMPONENT_ADDRESS])
|
|
2578
|
+
};
|
|
2579
|
+
},
|
|
2580
|
+
stream: parseServerComponent
|
|
2581
|
+
},
|
|
2582
|
+
serialize(node, ctx) {
|
|
2583
|
+
const registry = serverComponentRegistryExpr ? serverComponentRegistryExpr(ctx) : "self._$SC";
|
|
2584
|
+
return registry + ".r(" + ctx.serialize(node.id) + "," + ctx.serialize(node.address) + ")";
|
|
2585
|
+
},
|
|
2586
|
+
deserialize(node, ctx) {
|
|
2587
|
+
const id = ctx.deserialize(node.id);
|
|
2588
|
+
ctx.deserialize(node.address);
|
|
2589
|
+
return globalThis._$SC.r(id);
|
|
2590
|
+
}
|
|
2591
|
+
};
|
|
2592
|
+
function flightCodec(codec) {
|
|
2593
|
+
const plugins = codec && codec.plugins || [];
|
|
2594
|
+
if (plugins.some(plugin => plugin && plugin.tag === ServerComponentPlugin.tag)) return codec;
|
|
2595
|
+
return {
|
|
2596
|
+
...codec,
|
|
2597
|
+
plugins: [...plugins, ServerComponentPlugin]
|
|
2598
|
+
};
|
|
2599
|
+
}
|
|
2600
|
+
|
|
2601
|
+
const scopeStamp = typeof creationStamp === "function" ? creationStamp : () => 0;
|
|
2602
|
+
function serverOwned(render) {
|
|
2603
|
+
return NoHydration ? NoHydration({
|
|
2604
|
+
get children() {
|
|
2605
|
+
return render();
|
|
2606
|
+
}
|
|
2607
|
+
}) : render();
|
|
2608
|
+
}
|
|
2609
|
+
function serverComponentScope(render) {
|
|
2610
|
+
return runInServerComponentScope ? runInServerComponentScope(render) : render();
|
|
2611
|
+
}
|
|
2612
|
+
const SERVER_COMPONENT_BOOTSTRAP_EXPR = "(self._$SC||(self._$SC={c:{},a:{},r(i,a){a&&(this.a[a]=i,this.reg&&this.reg(a,i));return this.c[i]||(this.c[i]=(p,b)=>self._$SC.impl(i,p,b))}}))";
|
|
2613
|
+
const bootstrappedScripts = new WeakSet();
|
|
2614
|
+
setServerComponentBootstrap(ctx => {
|
|
2615
|
+
if (bootstrappedScripts.has(ctx)) return "self._$SC";
|
|
2616
|
+
bootstrappedScripts.add(ctx);
|
|
2617
|
+
return SERVER_COMPONENT_BOOTSTRAP_EXPR;
|
|
2618
|
+
});
|
|
2619
|
+
const SERVER_COMPONENT_BOOTSTRAP = SERVER_COMPONENT_BOOTSTRAP_EXPR + ";";
|
|
2620
|
+
function createFrameSink(emit, frame) {
|
|
2621
|
+
const {
|
|
2622
|
+
id,
|
|
2623
|
+
version
|
|
2624
|
+
} = frame;
|
|
2625
|
+
const styledKeys = new Set();
|
|
2626
|
+
const bindings = new Map();
|
|
2627
|
+
const sweepMinted = new Set();
|
|
2628
|
+
const argRefVersions = new Map();
|
|
2629
|
+
let sweepScheduled = false;
|
|
2630
|
+
let closed = false;
|
|
2631
|
+
let epoch = 0;
|
|
2632
|
+
const sweep = () => {
|
|
2633
|
+
epoch++;
|
|
2634
|
+
for (const b of [...bindings.values()]) {
|
|
2635
|
+
try {
|
|
2636
|
+
b.sweep();
|
|
2637
|
+
} catch (_) {
|
|
2638
|
+
}
|
|
2639
|
+
}
|
|
2640
|
+
};
|
|
2641
|
+
const scheduleSweep = () => {
|
|
2642
|
+
if (closed || sweepScheduled || !bindings.size) return;
|
|
2643
|
+
sweepScheduled = true;
|
|
2644
|
+
queueMicrotask(() => {
|
|
2645
|
+
sweepScheduled = false;
|
|
2646
|
+
if (!closed) sweep();
|
|
2647
|
+
});
|
|
2648
|
+
};
|
|
2649
|
+
const regionKeys = new Map();
|
|
2650
|
+
const frameOf = key => regionKeys.get(key) || id;
|
|
2651
|
+
return {
|
|
2652
|
+
tagRegion(key, childId) {
|
|
2653
|
+
if (!regionKeys.has(key)) regionKeys.set(key, childId);
|
|
2654
|
+
},
|
|
2655
|
+
shell(html, meta = {}) {
|
|
2656
|
+
if (meta.preloads && meta.preloads.size) {
|
|
2657
|
+
const styles = [];
|
|
2658
|
+
const modules = [];
|
|
2659
|
+
for (const url of meta.preloads) {
|
|
2660
|
+
(url.endsWith(".css") ? styles : modules).push(url);
|
|
2661
|
+
}
|
|
2662
|
+
const chunk = {
|
|
2663
|
+
type: "assets",
|
|
2664
|
+
id,
|
|
2665
|
+
version,
|
|
2666
|
+
key: ""
|
|
2667
|
+
};
|
|
2668
|
+
if (styles.length) chunk.styles = styles;
|
|
2669
|
+
if (modules.length) chunk.modules = modules;
|
|
2670
|
+
emit(chunk);
|
|
2671
|
+
}
|
|
2672
|
+
emit({
|
|
2673
|
+
type: "html",
|
|
2674
|
+
id,
|
|
2675
|
+
version,
|
|
2676
|
+
html
|
|
2677
|
+
});
|
|
2678
|
+
},
|
|
2679
|
+
data(record) {
|
|
2680
|
+
if (record && typeof record.key === "string" && (record.key.endsWith("_fr") || /^\d+$/.test(record.key))) {
|
|
2681
|
+
return;
|
|
2682
|
+
}
|
|
2683
|
+
if (typeof record === "string") {
|
|
2684
|
+
emit({
|
|
2685
|
+
type: "data",
|
|
2686
|
+
id,
|
|
2687
|
+
version,
|
|
2688
|
+
payload: record
|
|
2689
|
+
});
|
|
2690
|
+
scheduleSweep();
|
|
2691
|
+
} else {
|
|
2692
|
+
emit({
|
|
2693
|
+
type: "data",
|
|
2694
|
+
id,
|
|
2695
|
+
version,
|
|
2696
|
+
key: record.key,
|
|
2697
|
+
node: record.node,
|
|
2698
|
+
initial: record.initial
|
|
2699
|
+
});
|
|
2700
|
+
if (!sweepMinted.has(record.key)) scheduleSweep();
|
|
2701
|
+
}
|
|
2702
|
+
},
|
|
2703
|
+
fragment(key, value, meta = {}) {
|
|
2704
|
+
const fid = frameOf(key);
|
|
2705
|
+
const links = meta.styles && meta.styles.links || [];
|
|
2706
|
+
const inline = meta.styles && meta.styles.inline || [];
|
|
2707
|
+
if (links.length || inline.length) {
|
|
2708
|
+
if (links.length) styledKeys.add(key);
|
|
2709
|
+
const chunk = {
|
|
2710
|
+
type: "assets",
|
|
2711
|
+
id: fid,
|
|
2712
|
+
version,
|
|
2713
|
+
key
|
|
2714
|
+
};
|
|
2715
|
+
if (links.length) {
|
|
2716
|
+
chunk.styles = links.map(e => typeof e === "string" ? e : e.attrs ? {
|
|
2717
|
+
href: e.href,
|
|
2718
|
+
attrs: e.attrs
|
|
2719
|
+
} : e.href);
|
|
2720
|
+
}
|
|
2721
|
+
if (inline.length) {
|
|
2722
|
+
chunk.inlineStyles = inline.map(e => ({
|
|
2723
|
+
id: e.id,
|
|
2724
|
+
content: e.content,
|
|
2725
|
+
attrs: e.attrs
|
|
2726
|
+
}));
|
|
2727
|
+
}
|
|
2728
|
+
emit(chunk);
|
|
2729
|
+
}
|
|
2730
|
+
emit({
|
|
2731
|
+
type: "fragment",
|
|
2732
|
+
id: fid,
|
|
2733
|
+
version,
|
|
2734
|
+
key,
|
|
2735
|
+
html: value
|
|
2736
|
+
});
|
|
2737
|
+
scheduleSweep();
|
|
2738
|
+
if (meta.error) {
|
|
2739
|
+
emit({
|
|
2740
|
+
type: "error",
|
|
2741
|
+
id: fid,
|
|
2742
|
+
version,
|
|
2743
|
+
key,
|
|
2744
|
+
error: {
|
|
2745
|
+
message: String(meta.error && meta.error.message || meta.error)
|
|
2746
|
+
}
|
|
2747
|
+
});
|
|
2748
|
+
}
|
|
2749
|
+
if (!meta.revealGroup) {
|
|
2750
|
+
emit({
|
|
2751
|
+
type: "reveal",
|
|
2752
|
+
id: fid,
|
|
2753
|
+
version,
|
|
2754
|
+
keys: [key],
|
|
2755
|
+
waitForStyles: !!links.length
|
|
2756
|
+
});
|
|
2757
|
+
}
|
|
2758
|
+
},
|
|
2759
|
+
reveal(keys, meta = {}) {
|
|
2760
|
+
const byFrame = new Map();
|
|
2761
|
+
for (const key of keys) {
|
|
2762
|
+
const fid = frameOf(key);
|
|
2763
|
+
let group = byFrame.get(fid);
|
|
2764
|
+
if (!group) byFrame.set(fid, group = []);
|
|
2765
|
+
group.push(key);
|
|
2766
|
+
}
|
|
2767
|
+
for (const [fid, groupKeys] of byFrame) {
|
|
2768
|
+
let waitForStyles = false;
|
|
2769
|
+
for (const key of groupKeys) if (styledKeys.has(key)) waitForStyles = true;
|
|
2770
|
+
const chunk = {
|
|
2771
|
+
type: "reveal",
|
|
2772
|
+
id: fid,
|
|
2773
|
+
version,
|
|
2774
|
+
keys: groupKeys,
|
|
2775
|
+
waitForStyles
|
|
2776
|
+
};
|
|
2777
|
+
if (meta.fallback) chunk.fallback = true;
|
|
2778
|
+
emit(chunk);
|
|
2779
|
+
}
|
|
2780
|
+
},
|
|
2781
|
+
asset(type, url) {
|
|
2782
|
+
if (type !== "module") return;
|
|
2783
|
+
emit({
|
|
2784
|
+
type: "assets",
|
|
2785
|
+
id,
|
|
2786
|
+
version,
|
|
2787
|
+
key: "",
|
|
2788
|
+
modules: [url]
|
|
2789
|
+
});
|
|
2790
|
+
},
|
|
2791
|
+
end() {
|
|
2792
|
+
if (bindings.size) sweep();
|
|
2793
|
+
closed = true;
|
|
2794
|
+
emit({
|
|
2795
|
+
type: "complete",
|
|
2796
|
+
id,
|
|
2797
|
+
version
|
|
2798
|
+
});
|
|
2799
|
+
},
|
|
2800
|
+
error(errorId, error) {
|
|
2801
|
+
emit({
|
|
2802
|
+
type: "error",
|
|
2803
|
+
id,
|
|
2804
|
+
version,
|
|
2805
|
+
key: errorId,
|
|
2806
|
+
error
|
|
2807
|
+
});
|
|
2808
|
+
},
|
|
2809
|
+
slot(key, args) {
|
|
2810
|
+
emit({
|
|
2811
|
+
type: "slot",
|
|
2812
|
+
id,
|
|
2813
|
+
version,
|
|
2814
|
+
key,
|
|
2815
|
+
args
|
|
2816
|
+
});
|
|
2817
|
+
},
|
|
2818
|
+
region(childId, html) {
|
|
2819
|
+
emit({
|
|
2820
|
+
type: "html",
|
|
2821
|
+
id: childId,
|
|
2822
|
+
version,
|
|
2823
|
+
html
|
|
2824
|
+
});
|
|
2825
|
+
},
|
|
2826
|
+
hole(key, html) {
|
|
2827
|
+
emit({
|
|
2828
|
+
type: "hole",
|
|
2829
|
+
id,
|
|
2830
|
+
version,
|
|
2831
|
+
key,
|
|
2832
|
+
html
|
|
2833
|
+
});
|
|
2834
|
+
},
|
|
2835
|
+
attr(key, attrs, removed) {
|
|
2836
|
+
const chunk = {
|
|
2837
|
+
type: "attr",
|
|
2838
|
+
id,
|
|
2839
|
+
version,
|
|
2840
|
+
key,
|
|
2841
|
+
attrs
|
|
2842
|
+
};
|
|
2843
|
+
if (removed && removed.length) chunk.removed = removed;
|
|
2844
|
+
emit(chunk);
|
|
2845
|
+
},
|
|
2846
|
+
openBinding(key, b) {
|
|
2847
|
+
bindings.set(key, b);
|
|
2848
|
+
},
|
|
2849
|
+
closeBinding(key) {
|
|
2850
|
+
bindings.delete(key);
|
|
2851
|
+
},
|
|
2852
|
+
mintRef(ref) {
|
|
2853
|
+
sweepMinted.add(ref);
|
|
2854
|
+
},
|
|
2855
|
+
nextArgRef(ledgerKey) {
|
|
2856
|
+
const n = (argRefVersions.get(ledgerKey) || 0) + 1;
|
|
2857
|
+
argRefVersions.set(ledgerKey, n);
|
|
2858
|
+
return n;
|
|
2859
|
+
},
|
|
2860
|
+
commit: scheduleSweep,
|
|
2861
|
+
get epoch() {
|
|
2862
|
+
return epoch;
|
|
2863
|
+
}
|
|
2864
|
+
};
|
|
2865
|
+
}
|
|
2866
|
+
function renderToFrameStream(code, options = {}) {
|
|
2867
|
+
return frameStream(() => code, options);
|
|
2868
|
+
}
|
|
2869
|
+
function renderServerComponent(component, options = {}) {
|
|
2870
|
+
return frameStream((sink, frame) => {
|
|
2871
|
+
const props = createSlotProps(sink, frame);
|
|
2872
|
+
return () => {
|
|
2873
|
+
const ctx = sharedConfig.context;
|
|
2874
|
+
if (ctx) {
|
|
2875
|
+
ctx.commit = sink.commit;
|
|
2876
|
+
ctx.commitEpoch = () => sink.epoch;
|
|
2877
|
+
ctx.liveHoles = createLiveHoles(sink);
|
|
2878
|
+
}
|
|
2879
|
+
return serverComponentScope(() => component(props));
|
|
2880
|
+
};
|
|
2881
|
+
}, options);
|
|
2882
|
+
}
|
|
2883
|
+
function frameStream(makeCode, options) {
|
|
2884
|
+
const {
|
|
2885
|
+
id = "",
|
|
2886
|
+
version = 1
|
|
2887
|
+
} = options.frame || {};
|
|
2888
|
+
const frame = {
|
|
2889
|
+
id,
|
|
2890
|
+
version
|
|
2891
|
+
};
|
|
2892
|
+
function stream(w) {
|
|
2893
|
+
const emit = chunk => w.write(chunk);
|
|
2894
|
+
const sink = createFrameSink(emit, frame);
|
|
2895
|
+
emit({
|
|
2896
|
+
type: "start",
|
|
2897
|
+
id,
|
|
2898
|
+
version
|
|
2899
|
+
});
|
|
2900
|
+
const code = makeCode(sink, frame);
|
|
2901
|
+
try {
|
|
2902
|
+
renderToStream(() => serverOwned(code), {
|
|
2903
|
+
serializer: createJSONSerializer,
|
|
2904
|
+
...options,
|
|
2905
|
+
sink
|
|
2906
|
+
}).pipe({
|
|
2907
|
+
write() {},
|
|
2908
|
+
end() {
|
|
2909
|
+
sink.end();
|
|
2910
|
+
w.end && w.end();
|
|
2911
|
+
}
|
|
2912
|
+
});
|
|
2913
|
+
} catch (err) {
|
|
2914
|
+
sink.error("", err instanceof Error ? err.message : String(err));
|
|
2915
|
+
sink.end();
|
|
2916
|
+
w.end && w.end();
|
|
2917
|
+
}
|
|
2918
|
+
}
|
|
2919
|
+
return {
|
|
2920
|
+
pipe: stream,
|
|
2921
|
+
then(onFulfilled, onRejected) {
|
|
2922
|
+
return new Promise((resolve, reject) => {
|
|
2923
|
+
const chunks = [];
|
|
2924
|
+
try {
|
|
2925
|
+
stream({
|
|
2926
|
+
write: chunk => chunks.push(chunk),
|
|
2927
|
+
end: () => resolve(chunks)
|
|
2928
|
+
});
|
|
2929
|
+
} catch (err) {
|
|
2930
|
+
reject(err);
|
|
2931
|
+
}
|
|
2932
|
+
}).then(onFulfilled, onRejected);
|
|
2933
|
+
}
|
|
2934
|
+
};
|
|
2935
|
+
}
|
|
2936
|
+
function slotRange(occurrence) {
|
|
2937
|
+
return {
|
|
2938
|
+
t: `<!--slot:${occurrence}:start--><!--slot:${occurrence}:end-->`,
|
|
2939
|
+
$slot: true
|
|
2940
|
+
};
|
|
2941
|
+
}
|
|
2942
|
+
const OCCURRENCE_UNSAFE = /[^A-Za-z0-9_.-]/g;
|
|
2943
|
+
function encodeOccurrenceKey(key) {
|
|
2944
|
+
return String(key).replace(OCCURRENCE_UNSAFE, c => {
|
|
2945
|
+
const code = c.codePointAt(0);
|
|
2946
|
+
return "%" + (code < 16 ? "0" : "") + code.toString(16);
|
|
2947
|
+
});
|
|
2948
|
+
}
|
|
2949
|
+
function occurrenceId(prop, raw, counts) {
|
|
2950
|
+
const k = raw.$key;
|
|
2951
|
+
if (typeof k === "string" || typeof k === "number") {
|
|
2952
|
+
return `${prop}#${encodeOccurrenceKey(k)}`;
|
|
2953
|
+
}
|
|
2954
|
+
const n = counts[prop] || 0;
|
|
2955
|
+
counts[prop] = n + 1;
|
|
2956
|
+
return `${prop}#${n}`;
|
|
2957
|
+
}
|
|
2958
|
+
function isAsyncValue(v) {
|
|
2959
|
+
return !!v && typeof v === "object" && (typeof v.then === "function" || typeof v[Symbol.asyncIterator] === "function");
|
|
2960
|
+
}
|
|
2961
|
+
function tapFirstYield(iterable) {
|
|
2962
|
+
const iter = iterable[Symbol.asyncIterator]();
|
|
2963
|
+
const firstStep = Promise.resolve(iter.next());
|
|
2964
|
+
return {
|
|
2965
|
+
first: firstStep.then(r => r.done ? undefined : r.value),
|
|
2966
|
+
rest: {
|
|
2967
|
+
[Symbol.asyncIterator]() {
|
|
2968
|
+
let replayed = false;
|
|
2969
|
+
return {
|
|
2970
|
+
next: () => {
|
|
2971
|
+
if (!replayed) {
|
|
2972
|
+
replayed = true;
|
|
2973
|
+
return firstStep;
|
|
2974
|
+
}
|
|
2975
|
+
return iter.next();
|
|
2976
|
+
},
|
|
2977
|
+
return: v => iter.return ? iter.return(v) : Promise.resolve({
|
|
2978
|
+
done: true,
|
|
2979
|
+
value: v
|
|
2980
|
+
}),
|
|
2981
|
+
throw: e => iter.throw ? iter.throw(e) : Promise.reject(e)
|
|
2982
|
+
};
|
|
2983
|
+
}
|
|
2984
|
+
}
|
|
2985
|
+
};
|
|
2986
|
+
}
|
|
2987
|
+
function suppressedFill(render) {
|
|
2988
|
+
const live = sharedConfig.context && sharedConfig.context.liveHoles;
|
|
2989
|
+
if (!live) return render();
|
|
2990
|
+
live.suppressed++;
|
|
2991
|
+
try {
|
|
2992
|
+
return render();
|
|
2993
|
+
} finally {
|
|
2994
|
+
live.suppressed--;
|
|
2995
|
+
}
|
|
2996
|
+
}
|
|
2997
|
+
function createDocumentSlotProps(clientProps, frameId) {
|
|
2998
|
+
const counts = Object.create(null);
|
|
2999
|
+
const getters = new Map();
|
|
3000
|
+
const range = (occurrence, content) => {
|
|
3001
|
+
const r = [{
|
|
3002
|
+
t: `<!--slot:${occurrence}:start-->`
|
|
3003
|
+
}, content, {
|
|
3004
|
+
t: `<!--slot:${occurrence}:end-->`
|
|
3005
|
+
}];
|
|
3006
|
+
r.$slot = true;
|
|
3007
|
+
return r;
|
|
3008
|
+
};
|
|
3009
|
+
const zoneOwner = getOwner ? getOwner() : null;
|
|
3010
|
+
const scoped = (occurrence, render) => {
|
|
3011
|
+
const id = `sc-${frameId}-${occurrence}-`;
|
|
3012
|
+
const run = () => Hydration ? Hydration({
|
|
3013
|
+
id,
|
|
3014
|
+
get children() {
|
|
3015
|
+
return render();
|
|
3016
|
+
}
|
|
3017
|
+
}) : runWithHydrationScope(id, render);
|
|
3018
|
+
return zoneOwner ? runWithOwner(zoneOwner, run) : run();
|
|
3019
|
+
};
|
|
3020
|
+
return new Proxy(Object.create(null), {
|
|
3021
|
+
has() {
|
|
3022
|
+
return true;
|
|
3023
|
+
},
|
|
3024
|
+
get(_, prop) {
|
|
3025
|
+
if (typeof prop !== "string") return undefined;
|
|
3026
|
+
if (prop === "then") return undefined;
|
|
3027
|
+
let fn = getters.get(prop);
|
|
3028
|
+
if (!fn) {
|
|
3029
|
+
fn = (...callArgs) => {
|
|
3030
|
+
if (callArgs.length === 0 || callArgs[0] === undefined) {
|
|
3031
|
+
return suppressedFill(() => scoped(prop, () => {
|
|
3032
|
+
const value = clientProps[prop];
|
|
3033
|
+
return range(prop, typeof value === "function" ? value() : value);
|
|
3034
|
+
}));
|
|
3035
|
+
}
|
|
3036
|
+
const raw = callArgs[0];
|
|
3037
|
+
const occurrence = occurrenceId(prop, raw, counts);
|
|
3038
|
+
const slot = clientProps[prop];
|
|
3039
|
+
if (typeof slot !== "function") return range(occurrence, undefined);
|
|
3040
|
+
const resolved = {};
|
|
3041
|
+
const liveArgs = sharedConfig.context && sharedConfig.context.live && sharedConfig.context.live.args;
|
|
3042
|
+
const vals = {};
|
|
3043
|
+
const evals = {};
|
|
3044
|
+
const states = {};
|
|
3045
|
+
const minted = {};
|
|
3046
|
+
for (const key of Object.keys(raw)) {
|
|
3047
|
+
if (key === "$key") continue;
|
|
3048
|
+
const desc = Object.getOwnPropertyDescriptor(raw, key);
|
|
3049
|
+
let evaluate = null;
|
|
3050
|
+
let value;
|
|
3051
|
+
if (desc.get) {
|
|
3052
|
+
const get = desc.get;
|
|
3053
|
+
evaluate = () => unwrapThunks(get.call(raw));
|
|
3054
|
+
} else {
|
|
3055
|
+
value = desc.value;
|
|
3056
|
+
if (typeof value === "function") {
|
|
3057
|
+
const fn = value;
|
|
3058
|
+
evaluate = () => unwrapThunks(fn);
|
|
3059
|
+
}
|
|
3060
|
+
}
|
|
3061
|
+
if (evaluate) {
|
|
3062
|
+
evals[key] = evaluate;
|
|
3063
|
+
const stampBefore = scopeStamp();
|
|
3064
|
+
try {
|
|
3065
|
+
value = evaluate();
|
|
3066
|
+
states[key] = {
|
|
3067
|
+
settled: true,
|
|
3068
|
+
last: value
|
|
3069
|
+
};
|
|
3070
|
+
} catch (err) {
|
|
3071
|
+
const blocked = ssrHandleError && ssrHandleError(err);
|
|
3072
|
+
if (!blocked) throw err;
|
|
3073
|
+
const state = states[key] = {
|
|
3074
|
+
settled: false,
|
|
3075
|
+
last: undefined
|
|
3076
|
+
};
|
|
3077
|
+
value = retryArgUntilSettled(evaluate, blocked, key, occurrence, v => {
|
|
3078
|
+
state.settled = true;
|
|
3079
|
+
state.last = v;
|
|
3080
|
+
if (liveArgs) liveArgs.commit();
|
|
3081
|
+
});
|
|
3082
|
+
}
|
|
3083
|
+
if (scopeStamp() !== stampBefore) minted[key] = true;
|
|
3084
|
+
}
|
|
3085
|
+
vals[key] = value;
|
|
3086
|
+
}
|
|
3087
|
+
const regions = [];
|
|
3088
|
+
for (const key of Object.keys(vals)) {
|
|
3089
|
+
const value = vals[key];
|
|
3090
|
+
if (isContainerTraced(value)) {
|
|
3091
|
+
resolved[key] = value;
|
|
3092
|
+
} else if (isServerContent(value)) {
|
|
3093
|
+
const childId = `${frameId}.${occurrence}.${key}`;
|
|
3094
|
+
const region = {
|
|
3095
|
+
key,
|
|
3096
|
+
childId,
|
|
3097
|
+
value,
|
|
3098
|
+
used: false,
|
|
3099
|
+
locked: false
|
|
3100
|
+
};
|
|
3101
|
+
regions.push(region);
|
|
3102
|
+
resolved[key] = () => {
|
|
3103
|
+
if (region.locked) return [];
|
|
3104
|
+
region.used = true;
|
|
3105
|
+
return [{
|
|
3106
|
+
t: frameElementOpen(childId)
|
|
3107
|
+
}, value, {
|
|
3108
|
+
t: FRAME_ELEMENT_CLOSE
|
|
3109
|
+
}];
|
|
3110
|
+
};
|
|
3111
|
+
} else if (ssrAsyncValue && isAsyncValue(value)) {
|
|
3112
|
+
let readable = value;
|
|
3113
|
+
if (typeof value.then !== "function") {
|
|
3114
|
+
const {
|
|
3115
|
+
first,
|
|
3116
|
+
rest
|
|
3117
|
+
} = tapFirstYield(value);
|
|
3118
|
+
readable = first;
|
|
3119
|
+
vals[key] = rest;
|
|
3120
|
+
}
|
|
3121
|
+
const read = ssrAsyncValue(readable);
|
|
3122
|
+
Object.defineProperty(resolved, key, {
|
|
3123
|
+
get: read,
|
|
3124
|
+
enumerable: true,
|
|
3125
|
+
configurable: true
|
|
3126
|
+
});
|
|
3127
|
+
} else {
|
|
3128
|
+
resolved[key] = value;
|
|
3129
|
+
}
|
|
3130
|
+
}
|
|
3131
|
+
const out = suppressedFill(() => scoped(occurrence, () => range(occurrence, slot(resolved))));
|
|
3132
|
+
const unused = regions.filter(r => !r.used);
|
|
3133
|
+
if (sharedConfig.context) {
|
|
3134
|
+
const args = {};
|
|
3135
|
+
for (const key of Object.keys(vals)) {
|
|
3136
|
+
const value = vals[key];
|
|
3137
|
+
const region = regions.find(r => r.key === key);
|
|
3138
|
+
if (region) {
|
|
3139
|
+
args[key] = {
|
|
3140
|
+
$frame: region.childId
|
|
3141
|
+
};
|
|
3142
|
+
continue;
|
|
3143
|
+
}
|
|
3144
|
+
if (!isContainerTraced(value) && isServerContent(value)) continue;
|
|
3145
|
+
args[key] = envelopeContainerTraces(value);
|
|
3146
|
+
}
|
|
3147
|
+
sharedConfig.context.serialize(`sc:slot:${frameId}:${occurrence}`, {
|
|
3148
|
+
...args
|
|
3149
|
+
});
|
|
3150
|
+
for (const region of unused) {
|
|
3151
|
+
region.locked = true;
|
|
3152
|
+
sharedConfig.context.serialize(`sc:region:${region.childId}`, resolveRegionHtml(sharedConfig.context, region.value));
|
|
3153
|
+
}
|
|
3154
|
+
if (liveArgs) {
|
|
3155
|
+
for (const key of Object.keys(evals)) {
|
|
3156
|
+
if (regions.some(r => r.key === key)) continue;
|
|
3157
|
+
if (minted[key]) continue;
|
|
3158
|
+
const ledgerKey = `${frameId}:${occurrence}:${key}`;
|
|
3159
|
+
openArgBinding(liveArgs, ledgerKey, occurrence, key, evals[key], states[key], value => {
|
|
3160
|
+
args[key] = envelopeContainerTraces(value);
|
|
3161
|
+
liveArgs.slot(frameId, occurrence, {
|
|
3162
|
+
...args
|
|
3163
|
+
});
|
|
3164
|
+
});
|
|
3165
|
+
}
|
|
3166
|
+
}
|
|
3167
|
+
}
|
|
3168
|
+
return out;
|
|
3169
|
+
};
|
|
3170
|
+
fn.$lhSkip = true;
|
|
3171
|
+
getters.set(prop, fn);
|
|
3172
|
+
}
|
|
3173
|
+
return fn;
|
|
3174
|
+
}
|
|
3175
|
+
});
|
|
3176
|
+
}
|
|
3177
|
+
const FRAME_TAG = "dx-frame";
|
|
3178
|
+
const FRAME_ID_ATTR = "data-fid";
|
|
3179
|
+
function frameElementOpen(id) {
|
|
3180
|
+
const escaped = sharedConfig.context ? sharedConfig.context.escape(String(id), true) : String(id);
|
|
3181
|
+
return `<${FRAME_TAG} ${FRAME_ID_ATTR}="${escaped}" style="display:contents">`;
|
|
3182
|
+
}
|
|
3183
|
+
const FRAME_ELEMENT_CLOSE = `</${FRAME_TAG}>`;
|
|
3184
|
+
function armDocumentLiveHoles(ctx) {
|
|
3185
|
+
if (!ctx || ctx.liveHoles !== undefined) return;
|
|
3186
|
+
const live = ctx.live;
|
|
3187
|
+
if (live && live.holes !== undefined) {
|
|
3188
|
+
ctx.liveHoles = live.holes;
|
|
3189
|
+
if (live.holes) {
|
|
3190
|
+
ctx.commit = live.commit;
|
|
3191
|
+
ctx.commitEpoch = live.commitEpoch;
|
|
3192
|
+
}
|
|
3193
|
+
return;
|
|
3194
|
+
}
|
|
3195
|
+
if (!live || !ctx.async || ctx.noHydrate || !ctx.serialize || typeof ReadableStream !== "function") {
|
|
3196
|
+
ctx.liveHoles = null;
|
|
3197
|
+
if (live) live.holes = null;
|
|
3198
|
+
return;
|
|
3199
|
+
}
|
|
3200
|
+
const bindings = new Map();
|
|
3201
|
+
let epoch = 0;
|
|
3202
|
+
let sweepScheduled = false;
|
|
3203
|
+
let closed = false;
|
|
3204
|
+
const sweep = () => {
|
|
3205
|
+
epoch++;
|
|
3206
|
+
for (const b of [...bindings.values()]) {
|
|
3207
|
+
try {
|
|
3208
|
+
b.sweep();
|
|
3209
|
+
} catch (_) {
|
|
3210
|
+
}
|
|
3211
|
+
}
|
|
3212
|
+
};
|
|
3213
|
+
const scheduleSweep = () => {
|
|
3214
|
+
if (closed || sweepScheduled || !bindings.size) return;
|
|
3215
|
+
sweepScheduled = true;
|
|
3216
|
+
queueMicrotask(() => {
|
|
3217
|
+
sweepScheduled = false;
|
|
3218
|
+
if (!closed) sweep();
|
|
3219
|
+
});
|
|
3220
|
+
};
|
|
3221
|
+
let channel;
|
|
3222
|
+
ctx.serialize("sc:live", new ReadableStream({
|
|
3223
|
+
start(c) {
|
|
3224
|
+
channel = c;
|
|
3225
|
+
}
|
|
3226
|
+
}));
|
|
3227
|
+
const push = op => {
|
|
3228
|
+
if (!closed) channel.enqueue(op);
|
|
3229
|
+
};
|
|
3230
|
+
ctx.liveHoles = live.holes = createLiveHoles({
|
|
3231
|
+
openBinding(key, b) {
|
|
3232
|
+
bindings.set(key, b);
|
|
3233
|
+
},
|
|
3234
|
+
closeBinding(key) {
|
|
3235
|
+
bindings.delete(key);
|
|
3236
|
+
},
|
|
3237
|
+
hole(key, html) {
|
|
3238
|
+
push({
|
|
3239
|
+
type: "hole",
|
|
3240
|
+
key,
|
|
3241
|
+
html
|
|
3242
|
+
});
|
|
3243
|
+
},
|
|
3244
|
+
attr(key, attrs, removed) {
|
|
3245
|
+
const op = {
|
|
3246
|
+
type: "attr",
|
|
3247
|
+
key,
|
|
3248
|
+
attrs
|
|
3249
|
+
};
|
|
3250
|
+
if (removed && removed.length) op.removed = removed;
|
|
3251
|
+
push(op);
|
|
3252
|
+
},
|
|
3253
|
+
error(key, error) {
|
|
3254
|
+
push({
|
|
3255
|
+
type: "error",
|
|
3256
|
+
key,
|
|
3257
|
+
error
|
|
3258
|
+
});
|
|
3259
|
+
},
|
|
3260
|
+
commit: scheduleSweep,
|
|
3261
|
+
get epoch() {
|
|
3262
|
+
return epoch;
|
|
3263
|
+
}
|
|
3264
|
+
}, true);
|
|
3265
|
+
ctx.commit = live.commit = scheduleSweep;
|
|
3266
|
+
ctx.commitEpoch = live.commitEpoch = () => epoch;
|
|
3267
|
+
live.args = {
|
|
3268
|
+
openBinding(key, b) {
|
|
3269
|
+
bindings.set(key, b);
|
|
3270
|
+
},
|
|
3271
|
+
closeBinding(key) {
|
|
3272
|
+
bindings.delete(key);
|
|
3273
|
+
},
|
|
3274
|
+
slot(fid, occurrence, args) {
|
|
3275
|
+
push({
|
|
3276
|
+
type: "slot",
|
|
3277
|
+
fid,
|
|
3278
|
+
key: occurrence,
|
|
3279
|
+
args
|
|
3280
|
+
});
|
|
3281
|
+
},
|
|
3282
|
+
commit: scheduleSweep
|
|
3283
|
+
};
|
|
3284
|
+
live.end = () => {
|
|
3285
|
+
if (closed) return;
|
|
3286
|
+
if (bindings.size) sweep();
|
|
3287
|
+
closed = true;
|
|
3288
|
+
channel.close();
|
|
3289
|
+
};
|
|
3290
|
+
}
|
|
3291
|
+
function frameTransformDirectResult(value, {
|
|
3292
|
+
id,
|
|
3293
|
+
args
|
|
3294
|
+
}) {
|
|
3295
|
+
if (typeof value !== "function") return value;
|
|
3296
|
+
const component = value;
|
|
3297
|
+
const wrapped = props => [{
|
|
3298
|
+
t: frameElementOpen(id)
|
|
3299
|
+
},
|
|
3300
|
+
serverOwned(() => {
|
|
3301
|
+
armDocumentLiveHoles(sharedConfig.context);
|
|
3302
|
+
const slotProps = createDocumentSlotProps(props, id);
|
|
3303
|
+
return serverComponentScope(() => component(slotProps));
|
|
3304
|
+
}), {
|
|
3305
|
+
t: FRAME_ELEMENT_CLOSE
|
|
3306
|
+
}];
|
|
3307
|
+
wrapped[SERVER_COMPONENT] = id;
|
|
3308
|
+
wrapped[SERVER_COMPONENT_SOURCE] = component;
|
|
3309
|
+
wrapped[SERVER_COMPONENT_ADDRESS] = frameAddress(id, args);
|
|
3310
|
+
return wrapped;
|
|
3311
|
+
}
|
|
3312
|
+
function resolveRegionHtml(ctx, node) {
|
|
3313
|
+
const res = ctx.resolve(node);
|
|
3314
|
+
if (!res || !res.t) return String(res ?? "");
|
|
3315
|
+
if (!res.h || !res.h.length) return res.t[0];
|
|
3316
|
+
return Promise.all(res.p).then(() => {
|
|
3317
|
+
let out = Promise.resolve(res.t[0]);
|
|
3318
|
+
for (let i = 0; i < res.h.length; i++) {
|
|
3319
|
+
const hole = res.h[i];
|
|
3320
|
+
const tail = res.t[i + 1];
|
|
3321
|
+
out = out.then(acc => Promise.resolve(resolveRegionHtml(ctx, hole)).then(part => acc + part + tail));
|
|
3322
|
+
}
|
|
3323
|
+
return out;
|
|
3324
|
+
});
|
|
3325
|
+
}
|
|
3326
|
+
function isServerContent(value) {
|
|
3327
|
+
if (value && typeof value === "object") {
|
|
3328
|
+
if ("t" in value) return true;
|
|
3329
|
+
if (Array.isArray(value) && value.length > 0) {
|
|
3330
|
+
for (const item of value) {
|
|
3331
|
+
if (!(item && typeof item === "object" && "t" in item)) return false;
|
|
3332
|
+
}
|
|
3333
|
+
return true;
|
|
3334
|
+
}
|
|
3335
|
+
}
|
|
3336
|
+
return false;
|
|
3337
|
+
}
|
|
3338
|
+
function unwrapThunks(value) {
|
|
3339
|
+
for (let d = 0; typeof value === "function" && d < 16; d++) value = value();
|
|
3340
|
+
return value;
|
|
3341
|
+
}
|
|
3342
|
+
function contentArgError(key, occurrence) {
|
|
3343
|
+
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.");
|
|
3344
|
+
}
|
|
3345
|
+
function retryArgUntilSettled(evaluate, blocked, key, occurrence, onSettle) {
|
|
3346
|
+
const owner = getOwner();
|
|
3347
|
+
return new Promise((resolve, reject) => {
|
|
3348
|
+
const retry = () => {
|
|
3349
|
+
try {
|
|
3350
|
+
const value = owner ? runWithOwner(owner, evaluate) : evaluate();
|
|
3351
|
+
if (isServerContent(value)) {
|
|
3352
|
+
reject(contentArgError(key, occurrence));
|
|
3353
|
+
return;
|
|
3354
|
+
}
|
|
3355
|
+
if (onSettle) onSettle(value);
|
|
3356
|
+
resolve(value);
|
|
3357
|
+
} catch (err) {
|
|
3358
|
+
const next = ssrHandleError && ssrHandleError(err);
|
|
3359
|
+
if (next) next.then(retry, retry);else reject(err);
|
|
3360
|
+
}
|
|
3361
|
+
};
|
|
3362
|
+
blocked.then(retry, retry);
|
|
3363
|
+
});
|
|
3364
|
+
}
|
|
3365
|
+
function openArgBinding(sink, ledgerKey, occurrence, key, evaluate, state, emit) {
|
|
3366
|
+
const owner = getOwner();
|
|
3367
|
+
sink.openBinding(ledgerKey, {
|
|
3368
|
+
sweep() {
|
|
3369
|
+
if (!state.settled) return;
|
|
3370
|
+
let value;
|
|
3371
|
+
const stampBefore = scopeStamp();
|
|
3372
|
+
try {
|
|
3373
|
+
value = owner ? runWithOwner(owner, evaluate) : evaluate();
|
|
3374
|
+
} catch (err) {
|
|
3375
|
+
const blocked = ssrHandleError && ssrHandleError(err);
|
|
3376
|
+
if (!blocked) {
|
|
3377
|
+
sink.closeBinding(ledgerKey);
|
|
3378
|
+
emit(Promise.reject(err instanceof Error ? err : new Error(String(err))));
|
|
3379
|
+
return;
|
|
3380
|
+
}
|
|
3381
|
+
if (scopeStamp() !== stampBefore) {
|
|
3382
|
+
sink.closeBinding(ledgerKey);
|
|
3383
|
+
return;
|
|
3384
|
+
}
|
|
3385
|
+
state.settled = false;
|
|
3386
|
+
emit(retryArgUntilSettled(evaluate, blocked, key, occurrence, v => {
|
|
3387
|
+
state.settled = true;
|
|
3388
|
+
state.last = v;
|
|
3389
|
+
sink.commit();
|
|
3390
|
+
}));
|
|
3391
|
+
return;
|
|
3392
|
+
}
|
|
3393
|
+
if (scopeStamp() !== stampBefore) {
|
|
3394
|
+
sink.closeBinding(ledgerKey);
|
|
3395
|
+
return;
|
|
3396
|
+
}
|
|
3397
|
+
if (value === state.last) return;
|
|
3398
|
+
state.last = value;
|
|
3399
|
+
if (isServerContent(value)) {
|
|
3400
|
+
sink.closeBinding(ledgerKey);
|
|
3401
|
+
emit(Promise.reject(contentArgError(key, occurrence)));
|
|
3402
|
+
return;
|
|
3403
|
+
}
|
|
3404
|
+
emit(value);
|
|
3405
|
+
}
|
|
3406
|
+
});
|
|
3407
|
+
}
|
|
3408
|
+
function createSlotProps(sink, frame) {
|
|
3409
|
+
const counts = Object.create(null);
|
|
3410
|
+
const getters = new Map();
|
|
3411
|
+
return new Proxy(Object.create(null), {
|
|
3412
|
+
has() {
|
|
3413
|
+
return true;
|
|
3414
|
+
},
|
|
3415
|
+
get(_, prop) {
|
|
3416
|
+
if (typeof prop !== "string") return undefined;
|
|
3417
|
+
if (prop === "then") return undefined;
|
|
3418
|
+
let fn = getters.get(prop);
|
|
3419
|
+
if (!fn) {
|
|
3420
|
+
fn = (...callArgs) => {
|
|
3421
|
+
if (callArgs.length === 0 || callArgs[0] === undefined) {
|
|
3422
|
+
return slotRange(prop);
|
|
3423
|
+
}
|
|
3424
|
+
const live = sharedConfig.context && sharedConfig.context.liveHoles;
|
|
3425
|
+
if (live) {
|
|
3426
|
+
if (live.sweeping) {
|
|
3427
|
+
live.gateHit = true;
|
|
3428
|
+
return {
|
|
3429
|
+
t: "",
|
|
3430
|
+
$slot: true
|
|
3431
|
+
};
|
|
3432
|
+
}
|
|
3433
|
+
live.recordStamp++;
|
|
3434
|
+
}
|
|
3435
|
+
const raw = callArgs[0];
|
|
3436
|
+
const occurrence = occurrenceId(prop, raw, counts);
|
|
3437
|
+
const args = {};
|
|
3438
|
+
const opened = [];
|
|
3439
|
+
for (const key of Object.keys(raw)) {
|
|
3440
|
+
if (key === "$key") continue;
|
|
3441
|
+
const childId = `${frame.id}.${occurrence}.${key}`;
|
|
3442
|
+
const ctx = sharedConfig.context;
|
|
3443
|
+
const origRegister = ctx.registerFragment;
|
|
3444
|
+
ctx.registerFragment = (fragKey, fragOptions) => {
|
|
3445
|
+
sink.tagRegion(fragKey, childId);
|
|
3446
|
+
return origRegister.call(ctx, fragKey, fragOptions);
|
|
3447
|
+
};
|
|
3448
|
+
try {
|
|
3449
|
+
const desc = Object.getOwnPropertyDescriptor(raw, key);
|
|
3450
|
+
let evaluate = null;
|
|
3451
|
+
let value;
|
|
3452
|
+
let state = null;
|
|
3453
|
+
const stampBefore = scopeStamp();
|
|
3454
|
+
try {
|
|
3455
|
+
if (desc.get) {
|
|
3456
|
+
const get = desc.get;
|
|
3457
|
+
evaluate = () => unwrapThunks(get.call(raw));
|
|
3458
|
+
value = evaluate();
|
|
3459
|
+
} else {
|
|
3460
|
+
value = desc.value;
|
|
3461
|
+
if (typeof value === "function") {
|
|
3462
|
+
const fn = value;
|
|
3463
|
+
evaluate = () => unwrapThunks(fn);
|
|
3464
|
+
value = evaluate();
|
|
3465
|
+
}
|
|
3466
|
+
}
|
|
3467
|
+
} catch (err) {
|
|
3468
|
+
const blocked = ssrHandleError && ssrHandleError(err);
|
|
3469
|
+
if (!blocked) throw err;
|
|
3470
|
+
state = {
|
|
3471
|
+
settled: false,
|
|
3472
|
+
last: undefined
|
|
3473
|
+
};
|
|
3474
|
+
const pendingState = state;
|
|
3475
|
+
value = retryArgUntilSettled(evaluate, blocked, key, occurrence, v => {
|
|
3476
|
+
pendingState.settled = true;
|
|
3477
|
+
pendingState.last = v;
|
|
3478
|
+
sink.commit();
|
|
3479
|
+
});
|
|
3480
|
+
}
|
|
3481
|
+
const mintedEval = scopeStamp() !== stampBefore;
|
|
3482
|
+
const t = typeof value;
|
|
3483
|
+
if (value == null || t === "string" || t === "number" || t === "boolean") {
|
|
3484
|
+
args[key] = value;
|
|
3485
|
+
if (evaluate) state = {
|
|
3486
|
+
settled: true,
|
|
3487
|
+
last: value
|
|
3488
|
+
};
|
|
3489
|
+
} else if (!isContainerTraced(value) && isServerContent(value)) {
|
|
3490
|
+
const resolved = ctx.resolve(value);
|
|
3491
|
+
if (resolved.h.length) {
|
|
3492
|
+
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.");
|
|
3493
|
+
}
|
|
3494
|
+
sink.region(childId, resolved.t[0]);
|
|
3495
|
+
args[key] = {
|
|
3496
|
+
$frame: childId
|
|
3497
|
+
};
|
|
3498
|
+
} else {
|
|
3499
|
+
const ref = `arg:${occurrence}:${key}`;
|
|
3500
|
+
ctx.serialize(ref, envelopeContainerTraces(value));
|
|
3501
|
+
args[key] = {
|
|
3502
|
+
$ref: ref
|
|
3503
|
+
};
|
|
3504
|
+
if (evaluate && !state) state = {
|
|
3505
|
+
settled: true,
|
|
3506
|
+
last: value
|
|
3507
|
+
};
|
|
3508
|
+
}
|
|
3509
|
+
if (evaluate && state && !mintedEval) opened.push({
|
|
3510
|
+
key,
|
|
3511
|
+
evaluate,
|
|
3512
|
+
state
|
|
3513
|
+
});
|
|
3514
|
+
} finally {
|
|
3515
|
+
ctx.registerFragment = origRegister;
|
|
3516
|
+
}
|
|
3517
|
+
}
|
|
3518
|
+
sink.slot(occurrence, {
|
|
3519
|
+
...args
|
|
3520
|
+
});
|
|
3521
|
+
const ctx = sharedConfig.context;
|
|
3522
|
+
for (const b of opened) {
|
|
3523
|
+
const key = b.key;
|
|
3524
|
+
const ledgerKey = `${occurrence}:${key}`;
|
|
3525
|
+
openArgBinding(sink, ledgerKey, occurrence, key, b.evaluate, b.state, value => {
|
|
3526
|
+
const t = typeof value;
|
|
3527
|
+
if (value == null || t === "string" || t === "number" || t === "boolean") {
|
|
3528
|
+
args[key] = value;
|
|
3529
|
+
} else {
|
|
3530
|
+
const ref = `arg:${occurrence}:${key}@${sink.nextArgRef(ledgerKey)}`;
|
|
3531
|
+
sink.mintRef(ref);
|
|
3532
|
+
ctx.serialize(ref, envelopeContainerTraces(value));
|
|
3533
|
+
args[key] = {
|
|
3534
|
+
$ref: ref
|
|
3535
|
+
};
|
|
3536
|
+
}
|
|
3537
|
+
sink.slot(occurrence, {
|
|
3538
|
+
...args
|
|
3539
|
+
});
|
|
3540
|
+
});
|
|
3541
|
+
}
|
|
3542
|
+
return slotRange(occurrence);
|
|
3543
|
+
};
|
|
3544
|
+
fn.$lhSkip = true;
|
|
3545
|
+
getters.set(prop, fn);
|
|
3546
|
+
}
|
|
3547
|
+
return fn;
|
|
3548
|
+
}
|
|
3549
|
+
});
|
|
3550
|
+
}
|
|
3551
|
+
function copyInitHeaders(init) {
|
|
3552
|
+
if (!init || !init.getSetCookie) return new Headers(init);
|
|
3553
|
+
const headers = new Headers();
|
|
3554
|
+
init.forEach((value, key) => {
|
|
3555
|
+
if (key !== "set-cookie") headers.append(key, value);
|
|
3556
|
+
});
|
|
3557
|
+
for (const cookie of init.getSetCookie()) headers.append("Set-Cookie", cookie);
|
|
3558
|
+
return headers;
|
|
3559
|
+
}
|
|
3560
|
+
function serverComponentResponse(component, options = {}, init = {}) {
|
|
3561
|
+
const {
|
|
3562
|
+
id = "",
|
|
3563
|
+
version = 1
|
|
3564
|
+
} = options.frame || {};
|
|
3565
|
+
const headers = copyInitHeaders(init.headers);
|
|
3566
|
+
headers.set("Content-Type", "application/x-frame-stream");
|
|
3567
|
+
headers.set(FRAME_STREAM_HEADER, id);
|
|
3568
|
+
headers.set("X-Content-Raw", "1");
|
|
3569
|
+
const stream = renderServerComponent(component, {
|
|
3570
|
+
...options,
|
|
3571
|
+
frame: {
|
|
3572
|
+
id,
|
|
3573
|
+
version
|
|
3574
|
+
}
|
|
3575
|
+
});
|
|
3576
|
+
let closed = false;
|
|
3577
|
+
const body = new ReadableStream({
|
|
3578
|
+
start(controller) {
|
|
3579
|
+
stream.pipe({
|
|
3580
|
+
write(chunk) {
|
|
3581
|
+
if (closed) return;
|
|
3582
|
+
try {
|
|
3583
|
+
controller.enqueue(createChunk(JSON.stringify(chunk)));
|
|
3584
|
+
} catch (_) {
|
|
3585
|
+
closed = true;
|
|
3586
|
+
}
|
|
3587
|
+
},
|
|
3588
|
+
end() {
|
|
3589
|
+
if (closed) return;
|
|
3590
|
+
closed = true;
|
|
3591
|
+
controller.close();
|
|
3592
|
+
}
|
|
3593
|
+
});
|
|
3594
|
+
},
|
|
3595
|
+
cancel() {
|
|
3596
|
+
closed = true;
|
|
3597
|
+
}
|
|
3598
|
+
});
|
|
3599
|
+
return new Response(body, {
|
|
3600
|
+
status: init.status || 200,
|
|
3601
|
+
headers
|
|
3602
|
+
});
|
|
3603
|
+
}
|
|
3604
|
+
function frameTransformResult(event, result, context) {
|
|
3605
|
+
let init;
|
|
3606
|
+
if (isResponseEnvelope(result)) {
|
|
3607
|
+
const {
|
|
3608
|
+
response,
|
|
3609
|
+
value
|
|
3610
|
+
} = result;
|
|
3611
|
+
if (typeof value !== "function") return result;
|
|
3612
|
+
init = response ? {
|
|
3613
|
+
headers: response.headers,
|
|
3614
|
+
status: response.status
|
|
3615
|
+
} : undefined;
|
|
3616
|
+
result = value;
|
|
3617
|
+
}
|
|
3618
|
+
if (typeof result !== "function") return result;
|
|
3619
|
+
if (context && context.collectsFlight) return init ? {
|
|
3620
|
+
response: init,
|
|
3621
|
+
value: result
|
|
3622
|
+
} : result;
|
|
3623
|
+
const invocation = getEventServerFunctionInvocation(event);
|
|
3624
|
+
return serverComponentResponse(result, {
|
|
3625
|
+
frame: {
|
|
3626
|
+
id: invocation && invocation.id || ""
|
|
3627
|
+
}
|
|
3628
|
+
}, init);
|
|
3629
|
+
}
|
|
3630
|
+
async function frameTransformFlightResult(event, outcome, context) {
|
|
3631
|
+
const {
|
|
3632
|
+
value,
|
|
3633
|
+
data
|
|
3634
|
+
} = outcome;
|
|
3635
|
+
const regions = [];
|
|
3636
|
+
let serialized = data;
|
|
3637
|
+
if (data && typeof data === "object") {
|
|
3638
|
+
serialized = {};
|
|
3639
|
+
const keys = Object.keys(data);
|
|
3640
|
+
const values = await Promise.all(keys.map(key => data[key]));
|
|
3641
|
+
for (let i = 0; i < keys.length; i++) {
|
|
3642
|
+
const entry = values[i];
|
|
3643
|
+
serialized[keys[i]] = entry;
|
|
3644
|
+
if (typeof entry === "function") {
|
|
3645
|
+
regions.push({
|
|
3646
|
+
id: entry[SERVER_COMPONENT_ADDRESS] || keys[i],
|
|
3647
|
+
component: entry[SERVER_COMPONENT_SOURCE] || entry
|
|
3648
|
+
});
|
|
3649
|
+
}
|
|
3650
|
+
}
|
|
3651
|
+
}
|
|
3652
|
+
const invocation = getEventServerFunctionInvocation(event);
|
|
3653
|
+
const primary = typeof value === "function" ? {
|
|
3654
|
+
id: invocation && invocation.id || "",
|
|
3655
|
+
component: value
|
|
3656
|
+
} : undefined;
|
|
3657
|
+
if (!primary && !regions.length) return undefined;
|
|
3658
|
+
return frameFlightResponse({
|
|
3659
|
+
primary,
|
|
3660
|
+
regions,
|
|
3661
|
+
outcome: {
|
|
3662
|
+
value: primary ? undefined : value,
|
|
3663
|
+
data: serialized
|
|
3664
|
+
},
|
|
3665
|
+
codec: context && context.codec
|
|
3666
|
+
});
|
|
3667
|
+
}
|
|
3668
|
+
function frameFlightResponse({
|
|
3669
|
+
primary,
|
|
3670
|
+
regions = [],
|
|
3671
|
+
outcome,
|
|
3672
|
+
codec
|
|
3673
|
+
}, init = {}) {
|
|
3674
|
+
const frames = primary ? [primary, ...regions] : regions;
|
|
3675
|
+
const headers = copyInitHeaders(init.headers);
|
|
3676
|
+
headers.set("Content-Type", "application/x-frame-stream");
|
|
3677
|
+
headers.set(FRAME_STREAM_HEADER, primary ? primary.id : "");
|
|
3678
|
+
headers.set("X-Content-Raw", "1");
|
|
3679
|
+
headers.set(SINGLE_FLIGHT_HEADER, "true");
|
|
3680
|
+
let closed = false;
|
|
3681
|
+
const body = new ReadableStream({
|
|
3682
|
+
async start(controller) {
|
|
3683
|
+
const write = chunk => {
|
|
3684
|
+
if (closed) return;
|
|
3685
|
+
try {
|
|
3686
|
+
controller.enqueue(createChunk(JSON.stringify(chunk)));
|
|
3687
|
+
} catch (_) {
|
|
3688
|
+
closed = true;
|
|
3689
|
+
}
|
|
3690
|
+
};
|
|
3691
|
+
try {
|
|
3692
|
+
for (const {
|
|
3693
|
+
id,
|
|
3694
|
+
component
|
|
3695
|
+
} of frames) {
|
|
3696
|
+
await new Promise(resolve => {
|
|
3697
|
+
renderServerComponent(component, {
|
|
3698
|
+
frame: {
|
|
3699
|
+
id,
|
|
3700
|
+
version: 1
|
|
3701
|
+
}
|
|
3702
|
+
}).pipe({
|
|
3703
|
+
write,
|
|
3704
|
+
end: resolve
|
|
3705
|
+
});
|
|
3706
|
+
});
|
|
3707
|
+
}
|
|
3708
|
+
if (outcome) {
|
|
3709
|
+
const reader = new ChunkReader(serializeStream(outcome, flightCodec(codec)));
|
|
3710
|
+
for (let node = await reader.next(); !node.done; node = await reader.next()) {
|
|
3711
|
+
write({
|
|
3712
|
+
type: "outcome",
|
|
3713
|
+
payload: node.value
|
|
3714
|
+
});
|
|
3715
|
+
}
|
|
3716
|
+
}
|
|
3717
|
+
if (!closed) {
|
|
3718
|
+
closed = true;
|
|
3719
|
+
controller.close();
|
|
3720
|
+
}
|
|
3721
|
+
} catch (err) {
|
|
3722
|
+
if (!closed) {
|
|
3723
|
+
closed = true;
|
|
3724
|
+
controller.error(err);
|
|
3725
|
+
}
|
|
3726
|
+
}
|
|
3727
|
+
},
|
|
3728
|
+
cancel() {
|
|
3729
|
+
closed = true;
|
|
3730
|
+
}
|
|
3731
|
+
});
|
|
3732
|
+
return new Response(body, {
|
|
3733
|
+
status: init.status || 200,
|
|
3734
|
+
headers
|
|
3735
|
+
});
|
|
3736
|
+
}
|
|
3737
|
+
|
|
3738
|
+
setContainerTraceResolver(getProjectionTrace);
|
|
3739
|
+
function asyncArg(value) {
|
|
3740
|
+
return value;
|
|
3741
|
+
}
|
|
3742
|
+
|
|
3743
|
+
export { FRAME_STREAM_HEADER, SERVER_COMPONENT_BOOTSTRAP, ServerComponentPlugin, asyncArg, createFrameSink, frameTransformDirectResult, frameTransformFlightResult, frameTransformResult, isFrameStreamResponse, renderServerComponent, renderToFrameStream, serverComponentResponse };
|