@solidjs/web 2.0.0-rc.4 → 2.0.0-rc.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dev.cjs +52 -7
- package/dist/dev.js +51 -8
- package/dist/server.cjs +162 -35
- package/dist/server.js +161 -36
- package/dist/web.cjs +32 -7
- package/dist/web.js +31 -8
- package/frames/dist/client.cjs +41 -8
- package/frames/dist/client.dev.cjs +41 -8
- package/frames/dist/client.dev.js +41 -8
- package/frames/dist/client.js +41 -8
- package/frames/dist/server.cjs +432 -44
- package/frames/dist/server.js +432 -44
- package/package.json +2 -2
- package/serialization/dist/decode.cjs +4 -2
- package/serialization/dist/decode.js +4 -2
- package/serialization/dist/serialization.cjs +12 -8
- package/serialization/dist/serialization.js +12 -8
- package/serialization/types/index.d.ts +7 -0
- package/serialization/types/serializer-decode.d.ts +14 -1
- package/serialization/types/serializer.d.ts +7 -0
- package/serialization/types-cjs/index.d.cts +7 -0
- package/serialization/types-cjs/serializer-decode.d.cts +14 -1
- package/serialization/types-cjs/serializer.d.cts +7 -0
- package/server-functions/dist/client.cjs +150 -33
- package/server-functions/dist/client.js +147 -34
- package/server-functions/dist/server.cjs +731 -118
- package/server-functions/dist/server.dev.cjs +751 -118
- package/server-functions/dist/server.dev.js +747 -119
- package/server-functions/dist/server.js +727 -119
- package/types/cookies.d.ts +6 -14
- package/types/frames/frame-client.d.ts +4 -0
- package/types/frames/serializer-decode.d.ts +14 -1
- package/types/frames/serializer.d.ts +7 -0
- package/types/jsx.d.ts +11 -16
- package/types/response.d.ts +11 -0
- package/types/serializer-decode.d.ts +14 -1
- package/types/serializer.d.ts +7 -0
- package/types/server-functions/client.d.ts +22 -2
- package/types/server-functions/flash.d.ts +9 -0
- package/types/server-functions/server.d.ts +58 -9
- package/types/server-functions/shared.d.ts +77 -14
- package/types/server-mock.d.ts +17 -2
- package/types/server.d.ts +16 -2
- package/types-cjs/cookies.d.cts +6 -14
- package/types-cjs/frames/frame-client.d.cts +4 -0
- package/types-cjs/frames/serializer-decode.d.cts +14 -1
- package/types-cjs/frames/serializer.d.cts +7 -0
- package/types-cjs/jsx.d.cts +11 -16
- package/types-cjs/response.d.cts +11 -0
- package/types-cjs/serializer-decode.d.cts +14 -1
- package/types-cjs/serializer.d.cts +7 -0
- package/types-cjs/server-functions/client.d.cts +22 -2
- package/types-cjs/server-functions/flash.d.cts +9 -0
- package/types-cjs/server-functions/server.d.cts +58 -9
- package/types-cjs/server-functions/shared.d.cts +77 -14
- package/types-cjs/server-mock.d.cts +17 -2
- package/types-cjs/server.d.cts +16 -2
package/frames/dist/server.js
CHANGED
|
@@ -123,23 +123,25 @@ const JSON_CODEC_DEPTH_LIMIT = 64;
|
|
|
123
123
|
function resolveCodecOptions({
|
|
124
124
|
plugins,
|
|
125
125
|
disabledFeatures,
|
|
126
|
-
depthLimit
|
|
126
|
+
depthLimit,
|
|
127
|
+
serializeErrorStacks
|
|
127
128
|
} = {}) {
|
|
128
129
|
return {
|
|
129
130
|
plugins: resolveSerializerPlugins(plugins),
|
|
130
131
|
disabledFeatures: disabledFeatures === undefined ? JSON_CODEC_DISABLED_FEATURES : disabledFeatures,
|
|
131
|
-
depthLimit: depthLimit === undefined ? JSON_CODEC_DEPTH_LIMIT : depthLimit
|
|
132
|
+
depthLimit: depthLimit === undefined ? JSON_CODEC_DEPTH_LIMIT : depthLimit,
|
|
133
|
+
serializeErrorStacks
|
|
132
134
|
};
|
|
133
135
|
}
|
|
134
136
|
|
|
135
137
|
const DEFAULT_DISABLED_FEATURES = Feature.AggregateError | Feature.BigIntTypedArray;
|
|
136
|
-
const serializeOnlyDisabledFeatures =
|
|
138
|
+
const serializeOnlyDisabledFeatures = serializeErrorStacks => (serializeErrorStacks === undefined ? process.env.NODE_ENV === "development" : serializeErrorStacks) ? 0 : Feature.ErrorPrototypeStack;
|
|
137
139
|
const HYDRATION_GLOBAL = "_$HY.r";
|
|
138
140
|
function createSerializer(options) {
|
|
139
141
|
return new Serializer({
|
|
140
142
|
...options,
|
|
141
143
|
plugins: resolveSerializerPlugins(options.plugins),
|
|
142
|
-
disabledFeatures: (options.disabledFeatures === undefined ? DEFAULT_DISABLED_FEATURES : options.disabledFeatures) | serializeOnlyDisabledFeatures()
|
|
144
|
+
disabledFeatures: (options.disabledFeatures === undefined ? DEFAULT_DISABLED_FEATURES : options.disabledFeatures) | serializeOnlyDisabledFeatures(options.serializeErrorStacks)
|
|
143
145
|
});
|
|
144
146
|
}
|
|
145
147
|
function createHydrationSerializer({
|
|
@@ -167,12 +169,14 @@ function createJSONSerializer({
|
|
|
167
169
|
onError,
|
|
168
170
|
plugins,
|
|
169
171
|
disabledFeatures,
|
|
170
|
-
depthLimit
|
|
172
|
+
depthLimit,
|
|
173
|
+
serializeErrorStacks
|
|
171
174
|
}) {
|
|
172
175
|
const resolved = resolveCodecOptions({
|
|
173
176
|
plugins,
|
|
174
177
|
disabledFeatures,
|
|
175
|
-
depthLimit
|
|
178
|
+
depthLimit,
|
|
179
|
+
serializeErrorStacks
|
|
176
180
|
});
|
|
177
181
|
const refs = new Map();
|
|
178
182
|
const cancels = new Set();
|
|
@@ -194,7 +198,7 @@ function createJSONSerializer({
|
|
|
194
198
|
const stream = toCrossJSONStream(value, {
|
|
195
199
|
refs,
|
|
196
200
|
plugins: resolved.plugins,
|
|
197
|
-
disabledFeatures: resolved.disabledFeatures | serializeOnlyDisabledFeatures(),
|
|
201
|
+
disabledFeatures: resolved.disabledFeatures | serializeOnlyDisabledFeatures(resolved.serializeErrorStacks),
|
|
198
202
|
onParse(node, initial) {
|
|
199
203
|
onData({
|
|
200
204
|
key,
|
|
@@ -231,6 +235,10 @@ const ENVELOPE = Symbol.for("solid.ResponseEnvelope");
|
|
|
231
235
|
function isResponseEnvelope(value) {
|
|
232
236
|
return !!(value && typeof value === "object" && value[ENVELOPE]);
|
|
233
237
|
}
|
|
238
|
+
const SAFE_ERROR = Symbol.for("solid.SafeError");
|
|
239
|
+
function isSafeError(value) {
|
|
240
|
+
return !!(value && (typeof value === "object" || typeof value === "function") && value[SAFE_ERROR]);
|
|
241
|
+
}
|
|
234
242
|
const REVALIDATE_HEADER = "X-Revalidate";
|
|
235
243
|
|
|
236
244
|
function frameAddress(id, args) {
|
|
@@ -279,6 +287,7 @@ function stableString(value, seen) {
|
|
|
279
287
|
}
|
|
280
288
|
const ERROR_HEADER = "X-Server-Function-Error";
|
|
281
289
|
const BODY_FORMAT_HEADER = "X-Server-Function-Format";
|
|
290
|
+
const REDIRECT_HEADER = "X-Server-Function-Redirect";
|
|
282
291
|
const SINGLE_FLIGHT_HEADER = "X-Single-Flight";
|
|
283
292
|
function createChunk(data) {
|
|
284
293
|
const encoder = new TextEncoder();
|
|
@@ -292,18 +301,34 @@ function createChunk(data) {
|
|
|
292
301
|
class ChunkReader {
|
|
293
302
|
constructor(stream) {
|
|
294
303
|
this.reader = stream.getReader();
|
|
295
|
-
this.
|
|
304
|
+
this.store = new Uint8Array(0);
|
|
305
|
+
this.buffer = this.store;
|
|
296
306
|
this.done = false;
|
|
297
307
|
}
|
|
298
308
|
async readChunk() {
|
|
299
309
|
const chunk = await this.reader.read();
|
|
300
|
-
if (
|
|
301
|
-
const newBuffer = new Uint8Array(this.buffer.length + chunk.value.length);
|
|
302
|
-
newBuffer.set(this.buffer);
|
|
303
|
-
newBuffer.set(chunk.value, this.buffer.length);
|
|
304
|
-
this.buffer = newBuffer;
|
|
305
|
-
} else {
|
|
310
|
+
if (chunk.done) {
|
|
306
311
|
this.done = true;
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
const incoming = chunk.value;
|
|
315
|
+
const store = this.store;
|
|
316
|
+
const start = this.buffer.byteOffset;
|
|
317
|
+
const end = start + this.buffer.length;
|
|
318
|
+
const needed = this.buffer.length + incoming.length;
|
|
319
|
+
if (end + incoming.length <= store.length) {
|
|
320
|
+
store.set(incoming, end);
|
|
321
|
+
this.buffer = store.subarray(start, end + incoming.length);
|
|
322
|
+
} else if (needed <= store.length) {
|
|
323
|
+
store.copyWithin(0, start, end);
|
|
324
|
+
store.set(incoming, this.buffer.length);
|
|
325
|
+
this.buffer = store.subarray(0, needed);
|
|
326
|
+
} else {
|
|
327
|
+
const grown = new Uint8Array(Math.max(needed, store.length * 2));
|
|
328
|
+
grown.set(this.buffer);
|
|
329
|
+
grown.set(incoming, this.buffer.length);
|
|
330
|
+
this.store = grown;
|
|
331
|
+
this.buffer = grown.subarray(0, needed);
|
|
307
332
|
}
|
|
308
333
|
}
|
|
309
334
|
async next() {
|
|
@@ -403,7 +428,8 @@ function resourceIdentity(tag, props) {
|
|
|
403
428
|
let id = "res:" + tag + ":" + (props.rel || "") + ":" + (props.href || props.src || "");
|
|
404
429
|
for (let i = 0; i < RESOURCE_QUALIFIERS.length; i++) {
|
|
405
430
|
const q = RESOURCE_QUALIFIERS[i];
|
|
406
|
-
|
|
431
|
+
const value = props[q];
|
|
432
|
+
if (value != null) id += ":" + q + "=" + (value === true ? "" : value);
|
|
407
433
|
}
|
|
408
434
|
return id;
|
|
409
435
|
}
|
|
@@ -465,6 +491,7 @@ function resolveAssets(moduleUrl, manifest) {
|
|
|
465
491
|
if (!entry) return null;
|
|
466
492
|
const css = [];
|
|
467
493
|
const js = [];
|
|
494
|
+
let preloads;
|
|
468
495
|
const visited = new Set();
|
|
469
496
|
const walk = key => {
|
|
470
497
|
if (visited.has(key)) return;
|
|
@@ -473,13 +500,26 @@ function resolveAssets(moduleUrl, manifest) {
|
|
|
473
500
|
if (!e) return;
|
|
474
501
|
js.push(joinAssetPath(base, e.file));
|
|
475
502
|
if (e.css) for (let i = 0; i < e.css.length; i++) css.push(joinAssetPath(base, e.css[i]));
|
|
503
|
+
if (e.preloads) {
|
|
504
|
+
for (let i = 0; i < e.preloads.length; i++) {
|
|
505
|
+
const link = e.preloads[i];
|
|
506
|
+
if (!link || typeof link.href !== "string" || !link.href) continue;
|
|
507
|
+
if (!preloads) preloads = [];
|
|
508
|
+
preloads.push({
|
|
509
|
+
...link,
|
|
510
|
+
href: joinAssetPath(base, link.href)
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
}
|
|
476
514
|
if (e.imports) for (let i = 0; i < e.imports.length; i++) walk(e.imports[i]);
|
|
477
515
|
};
|
|
478
516
|
walk(moduleUrl);
|
|
479
|
-
|
|
517
|
+
const assets = {
|
|
480
518
|
js,
|
|
481
519
|
css
|
|
482
520
|
};
|
|
521
|
+
if (preloads) assets.preloads = preloads;
|
|
522
|
+
return assets;
|
|
483
523
|
}
|
|
484
524
|
function registerEntryAssets(manifest) {
|
|
485
525
|
if (!manifest || typeof manifest === "function" || typeof manifest.resolve === "function") return;
|
|
@@ -489,6 +529,7 @@ function registerEntryAssets(manifest) {
|
|
|
489
529
|
if (manifest[key].isEntry) {
|
|
490
530
|
const assets = resolveAssets(key, manifest);
|
|
491
531
|
if (assets) {
|
|
532
|
+
if (assets.preloads) for (let i = 0; i < assets.preloads.length; i++) ctx.registerAsset("preload", assets.preloads[i]);
|
|
492
533
|
for (let i = 0; i < assets.css.length; i++) ctx.registerAsset("style", assets.css[i]);
|
|
493
534
|
for (let i = 1; i < assets.js.length; i++) ctx.registerAsset("module", assets.js[i]);
|
|
494
535
|
}
|
|
@@ -507,6 +548,7 @@ function createAssetTracking() {
|
|
|
507
548
|
boundaryStyles,
|
|
508
549
|
emittedAssets,
|
|
509
550
|
inlineStyles,
|
|
551
|
+
preloadLinks: null,
|
|
510
552
|
registerInlineStyle(desc) {
|
|
511
553
|
let entry = inlineStyles.get(desc.id);
|
|
512
554
|
if (!entry) {
|
|
@@ -598,6 +640,56 @@ function isCssUrl(url) {
|
|
|
598
640
|
const q = url.search(/[?#]/);
|
|
599
641
|
return (q === -1 ? url : url.slice(0, q)).endsWith(".css");
|
|
600
642
|
}
|
|
643
|
+
const PRELOAD_LINK_ATTRIBUTES = ["type", "crossorigin", "integrity", "referrerpolicy", "fetchpriority", "media"];
|
|
644
|
+
function registerPreloadLink(tracking, headRegistry, link, nonce) {
|
|
645
|
+
if (!link || typeof link !== "object" || typeof link.href !== "string" || !link.href) {
|
|
646
|
+
return null;
|
|
647
|
+
}
|
|
648
|
+
if (typeof link.as !== "string") {
|
|
649
|
+
return null;
|
|
650
|
+
}
|
|
651
|
+
const as = asciiLowerCase(link.as);
|
|
652
|
+
let destination = null;
|
|
653
|
+
switch (as) {
|
|
654
|
+
case "script":
|
|
655
|
+
case "style":
|
|
656
|
+
destination = as;
|
|
657
|
+
break;
|
|
658
|
+
case "fetch":
|
|
659
|
+
case "font":
|
|
660
|
+
case "image":
|
|
661
|
+
case "track":
|
|
662
|
+
break;
|
|
663
|
+
default:
|
|
664
|
+
return null;
|
|
665
|
+
}
|
|
666
|
+
const props = {
|
|
667
|
+
rel: "preload",
|
|
668
|
+
href: link.href,
|
|
669
|
+
as
|
|
670
|
+
};
|
|
671
|
+
for (let i = 0; i < PRELOAD_LINK_ATTRIBUTES.length; i++) {
|
|
672
|
+
const name = PRELOAD_LINK_ATTRIBUTES[i];
|
|
673
|
+
const value = link[name];
|
|
674
|
+
if (value == null || value === false) continue;
|
|
675
|
+
props[name] = value === true ? "" : String(value);
|
|
676
|
+
}
|
|
677
|
+
const identity = resourceIdentity("link", props);
|
|
678
|
+
if (headRegistry.resources.has(identity)) return null;
|
|
679
|
+
const attrs = headAttrRecord(props);
|
|
680
|
+
const nonceValue = destination && nonce && nonce[destination];
|
|
681
|
+
if (typeof nonceValue === "string" && nonceValue) attrs.nonce = nonceValue;
|
|
682
|
+
const entry = {
|
|
683
|
+
href: props.href,
|
|
684
|
+
attrs,
|
|
685
|
+
attrHtml: renderHeadAttrHtml(props) + nonceAttr(nonce, destination)
|
|
686
|
+
};
|
|
687
|
+
headRegistry.resources.add(identity);
|
|
688
|
+
let links = tracking.preloadLinks;
|
|
689
|
+
if (!links) tracking.preloadLinks = links = [];
|
|
690
|
+
links.push(entry);
|
|
691
|
+
return entry;
|
|
692
|
+
}
|
|
601
693
|
function createHeadRegistry() {
|
|
602
694
|
return {
|
|
603
695
|
pending: [],
|
|
@@ -1167,6 +1259,8 @@ function renderToStream(code, options = {}) {
|
|
|
1167
1259
|
asset(type, value) {
|
|
1168
1260
|
if (type === "module") {
|
|
1169
1261
|
buffer.write(`<link rel="modulepreload" href="${value}"${nonceAttr(nonce, "script")}>`);
|
|
1262
|
+
} else if (type === "preload") {
|
|
1263
|
+
buffer.write(`<link${value.attrHtml}>`);
|
|
1170
1264
|
} else if (type === "inline-style") {
|
|
1171
1265
|
buffer.write(renderInlineStyle(value, nonce));
|
|
1172
1266
|
} else if (type === "head-tag") {
|
|
@@ -1174,7 +1268,7 @@ function renderToStream(code, options = {}) {
|
|
|
1174
1268
|
}
|
|
1175
1269
|
},
|
|
1176
1270
|
shell(shellHtml, meta) {
|
|
1177
|
-
buffer.write(assembleDocument(shellHtml, meta.preloads, meta.inlineStyles, meta.tasks.length ? meta.tasks : "", nonce, meta.head, onHead));
|
|
1271
|
+
buffer.write(assembleDocument(shellHtml, meta.preloads, meta.preloadLinks, meta.inlineStyles, meta.tasks.length ? meta.tasks : "", nonce, meta.head, onHead));
|
|
1178
1272
|
},
|
|
1179
1273
|
...options.sink
|
|
1180
1274
|
};
|
|
@@ -1207,6 +1301,29 @@ function renderToStream(code, options = {}) {
|
|
|
1207
1301
|
}
|
|
1208
1302
|
};
|
|
1209
1303
|
const registry = new Map();
|
|
1304
|
+
const pendingSerialized = new Map();
|
|
1305
|
+
const trackSerialized = (id, p) => {
|
|
1306
|
+
let settle;
|
|
1307
|
+
const raced = Promise.race([p, new Promise(r => settle = r)]);
|
|
1308
|
+
pendingSerialized.set(id, settle);
|
|
1309
|
+
const drop = () => pendingSerialized.delete(id);
|
|
1310
|
+
p.then(drop, drop);
|
|
1311
|
+
return raced;
|
|
1312
|
+
};
|
|
1313
|
+
const abandonSubtree = key => {
|
|
1314
|
+
for (const [k, entry] of registry) {
|
|
1315
|
+
if (k.length > key.length && k.startsWith(key)) {
|
|
1316
|
+
registry.delete(k);
|
|
1317
|
+
entry.resolve();
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
for (const [id, settle] of pendingSerialized) {
|
|
1321
|
+
if (id.startsWith(key)) {
|
|
1322
|
+
pendingSerialized.delete(id);
|
|
1323
|
+
settle();
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
};
|
|
1210
1327
|
const writeTasks = () => {
|
|
1211
1328
|
if (tasks.length && !completed && firstFlushed) {
|
|
1212
1329
|
buffer.write(`<script${nonceAttr(nonce, "script")}>${tasks}</script>`);
|
|
@@ -1277,6 +1394,11 @@ function renderToStream(code, options = {}) {
|
|
|
1277
1394
|
}, nonce, tags);
|
|
1278
1395
|
},
|
|
1279
1396
|
registerAsset(type, value) {
|
|
1397
|
+
if (type === "preload") {
|
|
1398
|
+
const entry = registerPreloadLink(tracking, headRegistry, value, nonce);
|
|
1399
|
+
if (entry && firstFlushed) sink.asset("preload", entry);
|
|
1400
|
+
return;
|
|
1401
|
+
}
|
|
1280
1402
|
if (type === "inline-style") {
|
|
1281
1403
|
const entry = tracking.registerInlineStyle(value);
|
|
1282
1404
|
if (firstFlushed && !tracking.currentBoundaryId && !entry.emitted) {
|
|
@@ -1321,13 +1443,14 @@ function renderToStream(code, options = {}) {
|
|
|
1321
1443
|
},
|
|
1322
1444
|
serialize(id, p, deferStream) {
|
|
1323
1445
|
if (sharedConfig.context.noHydrate) return;
|
|
1324
|
-
if (
|
|
1325
|
-
if (deferStream) {
|
|
1446
|
+
if (p && typeof p === "object" && typeof p.then === "function") {
|
|
1447
|
+
if (!firstFlushed && deferStream) {
|
|
1326
1448
|
blockingPromises.add(p);
|
|
1327
1449
|
p.then(d => serializer.write(id, d)).catch(e => serializer.write(id, e));
|
|
1328
1450
|
return;
|
|
1329
1451
|
}
|
|
1330
|
-
|
|
1452
|
+
p = trackSerialized(id, p);
|
|
1453
|
+
if (!firstFlushed && canBatchStubs && !shellCompleted) {
|
|
1331
1454
|
(stubBatch ||= new Map()).set(id, p);
|
|
1332
1455
|
return;
|
|
1333
1456
|
}
|
|
@@ -1372,6 +1495,7 @@ function renderToStream(code, options = {}) {
|
|
|
1372
1495
|
if (registry.has(key)) {
|
|
1373
1496
|
const item = registry.get(key);
|
|
1374
1497
|
registry.delete(key);
|
|
1498
|
+
if (error) abandonSubtree(key);
|
|
1375
1499
|
if (item.children) {
|
|
1376
1500
|
for (const k in item.children) {
|
|
1377
1501
|
value = replacePlaceholder(value, k, item.children[k]);
|
|
@@ -1496,6 +1620,7 @@ function renderToStream(code, options = {}) {
|
|
|
1496
1620
|
const head = renderShellHead(headRegistry, nonce, k => registry.has(k), noScripts);
|
|
1497
1621
|
sink.shell(resolveSSRSelectValues(html), {
|
|
1498
1622
|
preloads: tracking.emittedAssets,
|
|
1623
|
+
preloadLinks: tracking.preloadLinks,
|
|
1499
1624
|
inlineStyles: tracking.inlineStyles,
|
|
1500
1625
|
tasks,
|
|
1501
1626
|
head
|
|
@@ -2417,12 +2542,12 @@ function allSettled(promises) {
|
|
|
2417
2542
|
return;
|
|
2418
2543
|
});
|
|
2419
2544
|
}
|
|
2420
|
-
function assembleDocument(html, emittedAssets, inlineStyles, scripts, nonce, headTags, onHead) {
|
|
2545
|
+
function assembleDocument(html, emittedAssets, preloadLinks, inlineStyles, scripts, nonce, headTags, onHead) {
|
|
2421
2546
|
const scriptTag = scripts ? `<script${nonceAttr(nonce, "script")}>${scripts}</script>` : "";
|
|
2422
2547
|
const title = headTags ? headTags.title : null;
|
|
2423
2548
|
let headTagsHtml = headTags ? headTags.html : "";
|
|
2424
2549
|
const headPrelude = headTags ? headTags.prelude : "";
|
|
2425
|
-
if (!onHead && title == null && !headTagsHtml && !headPrelude && !(emittedAssets && emittedAssets.size) && !(inlineStyles && inlineStyles.size)) {
|
|
2550
|
+
if (!onHead && title == null && !headTagsHtml && !headPrelude && !(emittedAssets && emittedAssets.size) && !preloadLinks && !(inlineStyles && inlineStyles.size)) {
|
|
2426
2551
|
if (!scriptTag) return html;
|
|
2427
2552
|
const xs = html.indexOf("<!--xs-->");
|
|
2428
2553
|
return xs === -1 ? html + scriptTag : html.slice(0, xs) + scriptTag + html.slice(xs);
|
|
@@ -2441,7 +2566,7 @@ function assembleDocument(html, emittedAssets, inlineStyles, scripts, nonce, hea
|
|
|
2441
2566
|
if (title != null) {
|
|
2442
2567
|
titleHtml = headTags.noScripts ? `<title data-dh="title">${escape(title)}</title>` : `<script${nonceAttr(nonce, "script")}>(function(x,t){(t=document.querySelector("title"))?(t.hasAttribute("data-dh")||t.setAttribute("data-dhf",t.textContent),t.textContent=x):(document.title=x,t=document.querySelector("title"));t&&t.setAttribute("data-dh","title")})(${JSON.stringify(title).replace(/</g, "\\u003C")})</script>`;
|
|
2443
2568
|
}
|
|
2444
|
-
onHead(headPrelude + headTagsHtml + titleHtml + renderHeadAssets(emittedAssets, inlineStyles, nonce));
|
|
2569
|
+
onHead(headPrelude + headTagsHtml + titleHtml + renderHeadAssets(emittedAssets, preloadLinks, inlineStyles, nonce));
|
|
2445
2570
|
}
|
|
2446
2571
|
if (!scriptTag) return html;
|
|
2447
2572
|
const xs = html.indexOf("<!--xs-->");
|
|
@@ -2461,13 +2586,13 @@ function assembleDocument(html, emittedAssets, inlineStyles, scripts, nonce, hea
|
|
|
2461
2586
|
headTagsHtml = `<title data-dh="title">${winner}</title>` + headTagsHtml;
|
|
2462
2587
|
}
|
|
2463
2588
|
}
|
|
2464
|
-
const head = headTagsHtml + renderHeadAssets(emittedAssets, inlineStyles, nonce);
|
|
2589
|
+
const head = headTagsHtml + renderHeadAssets(emittedAssets, preloadLinks, inlineStyles, nonce);
|
|
2465
2590
|
if (!scriptTag) return html.slice(0, headIdx) + head + html.slice(headIdx);
|
|
2466
2591
|
const xsIdx = html.indexOf("<!--xs-->");
|
|
2467
2592
|
if (xsIdx === -1) return html.slice(0, headIdx) + head + html.slice(headIdx) + scriptTag;
|
|
2468
2593
|
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);
|
|
2469
2594
|
}
|
|
2470
|
-
function renderHeadAssets(emittedAssets, inlineStyles, nonce) {
|
|
2595
|
+
function renderHeadAssets(emittedAssets, preloadLinks, inlineStyles, nonce) {
|
|
2471
2596
|
let head = "";
|
|
2472
2597
|
const styleAttr = nonceAttr(nonce, "style");
|
|
2473
2598
|
const scriptAttr = nonceAttr(nonce, "script");
|
|
@@ -2476,6 +2601,9 @@ function renderHeadAssets(emittedAssets, inlineStyles, nonce) {
|
|
|
2476
2601
|
head += isCssUrl(url) ? `<link rel="stylesheet" href="${url}"${styleAttr}>` : `<link rel="modulepreload" href="${url}"${scriptAttr}>`;
|
|
2477
2602
|
}
|
|
2478
2603
|
}
|
|
2604
|
+
if (preloadLinks) {
|
|
2605
|
+
for (const entry of preloadLinks) head += `<link${entry.attrHtml}>`;
|
|
2606
|
+
}
|
|
2479
2607
|
if (inlineStyles && inlineStyles.size) {
|
|
2480
2608
|
for (const entry of inlineStyles.values()) {
|
|
2481
2609
|
if (entry.emitted) continue;
|
|
@@ -2661,12 +2789,249 @@ function resolveSSRSync(node) {
|
|
|
2661
2789
|
if (!res.h.length) return res.t[0];
|
|
2662
2790
|
throw new Error("This value cannot be rendered synchronously. Are you missing a boundary?");
|
|
2663
2791
|
}
|
|
2664
|
-
/*#__PURE__*/new Set([ERROR_HEADER, BODY_FORMAT_HEADER, SINGLE_FLIGHT_HEADER, REVALIDATE_HEADER, "Location"].map(header => header.toLowerCase()));
|
|
2792
|
+
/*#__PURE__*/new Set([ERROR_HEADER, BODY_FORMAT_HEADER, SINGLE_FLIGHT_HEADER, REVALIDATE_HEADER, REDIRECT_HEADER, "Location"].map(header => header.toLowerCase()));
|
|
2665
2793
|
|
|
2666
2794
|
const INVOCATIONS = new WeakMap();
|
|
2667
2795
|
function getEventServerFunctionInvocation(event) {
|
|
2668
2796
|
return event && INVOCATIONS.get(event);
|
|
2669
2797
|
}
|
|
2798
|
+
function guardFailures(value, state) {
|
|
2799
|
+
if (!state) state = {
|
|
2800
|
+
seen: new WeakMap(),
|
|
2801
|
+
cyclic: new WeakSet()
|
|
2802
|
+
};
|
|
2803
|
+
const entered = enterGuard(value, state);
|
|
2804
|
+
if (!(entered instanceof Frame)) return entered;
|
|
2805
|
+
const stack = [entered];
|
|
2806
|
+
let delivered = NOTHING;
|
|
2807
|
+
for (;;) {
|
|
2808
|
+
const top = stack[stack.length - 1];
|
|
2809
|
+
const items = top.items;
|
|
2810
|
+
let pushed = null;
|
|
2811
|
+
while (top.i < items.length) {
|
|
2812
|
+
const i = top.i;
|
|
2813
|
+
let original;
|
|
2814
|
+
if (top.kind === OBJECT) {
|
|
2815
|
+
const descriptor = top.descriptors[items[i]];
|
|
2816
|
+
if ("value" in descriptor) {
|
|
2817
|
+
original = descriptor.value;
|
|
2818
|
+
} else if (typeof descriptor.get === "function") {
|
|
2819
|
+
if (top.accessorRead !== i) {
|
|
2820
|
+
try {
|
|
2821
|
+
top.accessorValue = descriptor.get.call(top.value);
|
|
2822
|
+
} catch (error) {
|
|
2823
|
+
throw sanitizeServerError(error);
|
|
2824
|
+
}
|
|
2825
|
+
top.accessorRead = i;
|
|
2826
|
+
}
|
|
2827
|
+
original = top.accessorValue;
|
|
2828
|
+
} else {
|
|
2829
|
+
top.i++;
|
|
2830
|
+
continue;
|
|
2831
|
+
}
|
|
2832
|
+
} else {
|
|
2833
|
+
original = items[i];
|
|
2834
|
+
}
|
|
2835
|
+
let guarded;
|
|
2836
|
+
if (delivered !== NOTHING) {
|
|
2837
|
+
guarded = delivered;
|
|
2838
|
+
delivered = NOTHING;
|
|
2839
|
+
} else {
|
|
2840
|
+
guarded = enterGuard(original, state);
|
|
2841
|
+
if (guarded instanceof Frame) {
|
|
2842
|
+
pushed = guarded;
|
|
2843
|
+
break;
|
|
2844
|
+
}
|
|
2845
|
+
}
|
|
2846
|
+
if (top.kind === ARRAY) {
|
|
2847
|
+
if (guarded !== original) {
|
|
2848
|
+
top.next[i] = guarded;
|
|
2849
|
+
top.changed = true;
|
|
2850
|
+
}
|
|
2851
|
+
} else if (top.kind === MAP) {
|
|
2852
|
+
if ((i & 1) === 0) top.pendingKey = guarded;else top.next.set(top.pendingKey, guarded);
|
|
2853
|
+
if (guarded !== original) top.changed = true;
|
|
2854
|
+
} else if (top.kind === SET) {
|
|
2855
|
+
top.next.add(guarded);
|
|
2856
|
+
if (guarded !== original) top.changed = true;
|
|
2857
|
+
} else if (guarded !== original || top.accessorRead === i) {
|
|
2858
|
+
Object.defineProperty(top.next, items[i], top.accessorRead === i ? {
|
|
2859
|
+
enumerable: true,
|
|
2860
|
+
configurable: true,
|
|
2861
|
+
writable: true,
|
|
2862
|
+
value: guarded
|
|
2863
|
+
} : {
|
|
2864
|
+
...top.descriptors[items[i]],
|
|
2865
|
+
value: guarded
|
|
2866
|
+
});
|
|
2867
|
+
top.changed = true;
|
|
2868
|
+
}
|
|
2869
|
+
top.i++;
|
|
2870
|
+
}
|
|
2871
|
+
if (pushed !== null) {
|
|
2872
|
+
stack.push(pushed);
|
|
2873
|
+
continue;
|
|
2874
|
+
}
|
|
2875
|
+
stack.pop();
|
|
2876
|
+
const out = keepGuarded(top.value, top.next, top.changed, state);
|
|
2877
|
+
if (stack.length === 0) return out;
|
|
2878
|
+
delivered = out;
|
|
2879
|
+
}
|
|
2880
|
+
}
|
|
2881
|
+
const NOTHING = Symbol();
|
|
2882
|
+
const ARRAY = 0;
|
|
2883
|
+
const MAP = 1;
|
|
2884
|
+
const SET = 2;
|
|
2885
|
+
const OBJECT = 3;
|
|
2886
|
+
class Frame {
|
|
2887
|
+
constructor(kind, value, next, items, descriptors) {
|
|
2888
|
+
this.kind = kind;
|
|
2889
|
+
this.value = value;
|
|
2890
|
+
this.next = next;
|
|
2891
|
+
this.items = items;
|
|
2892
|
+
this.descriptors = descriptors;
|
|
2893
|
+
this.i = 0;
|
|
2894
|
+
this.changed = false;
|
|
2895
|
+
this.accessorRead = -1;
|
|
2896
|
+
this.accessorValue = undefined;
|
|
2897
|
+
this.pendingKey = undefined;
|
|
2898
|
+
}
|
|
2899
|
+
}
|
|
2900
|
+
function enterGuard(value, state) {
|
|
2901
|
+
if (value === null || typeof value !== "object") return value;
|
|
2902
|
+
if (state.seen.has(value)) {
|
|
2903
|
+
state.cyclic.add(value);
|
|
2904
|
+
return state.seen.get(value);
|
|
2905
|
+
}
|
|
2906
|
+
if (typeof ReadableStream !== "undefined" && value instanceof ReadableStream) {
|
|
2907
|
+
let reader;
|
|
2908
|
+
const gate = state.gate;
|
|
2909
|
+
let finished = false;
|
|
2910
|
+
const close = () => {
|
|
2911
|
+
if (finished) return;
|
|
2912
|
+
finished = true;
|
|
2913
|
+
try {
|
|
2914
|
+
const cancelled = reader ? reader.cancel() : value.cancel();
|
|
2915
|
+
if (cancelled && typeof cancelled.then === "function") cancelled.then(undefined, () => {});
|
|
2916
|
+
} catch {}
|
|
2917
|
+
};
|
|
2918
|
+
const guardedStream = new ReadableStream({
|
|
2919
|
+
async pull(controller) {
|
|
2920
|
+
try {
|
|
2921
|
+
if (gate && !finished && !gate.wantsMore()) await gate.awaitDemand();
|
|
2922
|
+
if (finished) {
|
|
2923
|
+
controller.close();
|
|
2924
|
+
return;
|
|
2925
|
+
}
|
|
2926
|
+
if (!reader) reader = value.getReader();
|
|
2927
|
+
const {
|
|
2928
|
+
done,
|
|
2929
|
+
value: chunk
|
|
2930
|
+
} = await reader.read();
|
|
2931
|
+
done ? controller.close() : controller.enqueue(guardFailures(chunk, state));
|
|
2932
|
+
} catch (error) {
|
|
2933
|
+
controller.error(sanitizeServerError(error));
|
|
2934
|
+
}
|
|
2935
|
+
},
|
|
2936
|
+
cancel(reason) {
|
|
2937
|
+
finished = true;
|
|
2938
|
+
return reader ? reader.cancel(reason) : value.cancel(reason);
|
|
2939
|
+
}
|
|
2940
|
+
});
|
|
2941
|
+
if (gate) gate.onOpen(close);
|
|
2942
|
+
state.seen.set(value, guardedStream);
|
|
2943
|
+
return guardedStream;
|
|
2944
|
+
}
|
|
2945
|
+
if (typeof value.then === "function") {
|
|
2946
|
+
const guardedPromise = Promise.resolve(value).then(resolved => guardFailures(resolved, state), error => {
|
|
2947
|
+
throw sanitizeServerError(error);
|
|
2948
|
+
});
|
|
2949
|
+
state.seen.set(value, guardedPromise);
|
|
2950
|
+
return guardedPromise;
|
|
2951
|
+
}
|
|
2952
|
+
if (typeof value[Symbol.asyncIterator] === "function") {
|
|
2953
|
+
const source = value;
|
|
2954
|
+
const gate = state.gate;
|
|
2955
|
+
const guardedIterable = {
|
|
2956
|
+
[Symbol.asyncIterator]() {
|
|
2957
|
+
const iterator = source[Symbol.asyncIterator]();
|
|
2958
|
+
let finished = false;
|
|
2959
|
+
const close = () => {
|
|
2960
|
+
if (finished) return;
|
|
2961
|
+
finished = true;
|
|
2962
|
+
try {
|
|
2963
|
+
const returned = iterator.return && iterator.return();
|
|
2964
|
+
if (returned && typeof returned.then === "function") returned.then(undefined, () => {});
|
|
2965
|
+
} catch {}
|
|
2966
|
+
};
|
|
2967
|
+
if (gate) gate.onOpen(close);
|
|
2968
|
+
const step = () => finished ? Promise.resolve({
|
|
2969
|
+
done: true,
|
|
2970
|
+
value: undefined
|
|
2971
|
+
}) : iterator.next().then(step => {
|
|
2972
|
+
if (step.done) {
|
|
2973
|
+
finished = true;
|
|
2974
|
+
return step;
|
|
2975
|
+
}
|
|
2976
|
+
return {
|
|
2977
|
+
done: false,
|
|
2978
|
+
value: guardFailures(step.value, state)
|
|
2979
|
+
};
|
|
2980
|
+
}, error => {
|
|
2981
|
+
throw sanitizeServerError(error);
|
|
2982
|
+
});
|
|
2983
|
+
return {
|
|
2984
|
+
next: () => finished || !gate || gate.wantsMore() ? step() : gate.awaitDemand().then(step),
|
|
2985
|
+
return: () => {
|
|
2986
|
+
close();
|
|
2987
|
+
return Promise.resolve({
|
|
2988
|
+
done: true,
|
|
2989
|
+
value: undefined
|
|
2990
|
+
});
|
|
2991
|
+
}
|
|
2992
|
+
};
|
|
2993
|
+
}
|
|
2994
|
+
};
|
|
2995
|
+
state.seen.set(value, guardedIterable);
|
|
2996
|
+
return guardedIterable;
|
|
2997
|
+
}
|
|
2998
|
+
if (Array.isArray(value)) {
|
|
2999
|
+
const next = value.slice();
|
|
3000
|
+
state.seen.set(value, next);
|
|
3001
|
+
return new Frame(ARRAY, value, next, value, null);
|
|
3002
|
+
}
|
|
3003
|
+
if (value instanceof Map) {
|
|
3004
|
+
const next = new Map();
|
|
3005
|
+
state.seen.set(value, next);
|
|
3006
|
+
const items = [];
|
|
3007
|
+
for (const entry of value) items.push(entry[0], entry[1]);
|
|
3008
|
+
return new Frame(MAP, value, next, items, null);
|
|
3009
|
+
}
|
|
3010
|
+
if (value instanceof Set) {
|
|
3011
|
+
const next = new Set();
|
|
3012
|
+
state.seen.set(value, next);
|
|
3013
|
+
return new Frame(SET, value, next, [...value], null);
|
|
3014
|
+
}
|
|
3015
|
+
const prototype = Object.getPrototypeOf(value);
|
|
3016
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
3017
|
+
state.seen.set(value, value);
|
|
3018
|
+
return value;
|
|
3019
|
+
}
|
|
3020
|
+
const descriptors = Object.getOwnPropertyDescriptors(value);
|
|
3021
|
+
const next = Object.create(prototype, descriptors);
|
|
3022
|
+
state.seen.set(value, next);
|
|
3023
|
+
return new Frame(OBJECT, value, next, Object.keys(descriptors), descriptors);
|
|
3024
|
+
}
|
|
3025
|
+
function keepGuarded(value, next, changed, state) {
|
|
3026
|
+
if (changed || state.cyclic.has(value)) return next;
|
|
3027
|
+
state.seen.set(value, value);
|
|
3028
|
+
return value;
|
|
3029
|
+
}
|
|
3030
|
+
const GENERIC_SERVER_ERROR_MESSAGE = "Internal Server Error";
|
|
3031
|
+
function sanitizeServerError(value) {
|
|
3032
|
+
if (isSafeError(value)) return value;
|
|
3033
|
+
return new Error(GENERIC_SERVER_ERROR_MESSAGE);
|
|
3034
|
+
}
|
|
2670
3035
|
|
|
2671
3036
|
const FRAME_STREAM_HEADER = "X-Frame-Stream";
|
|
2672
3037
|
function isFrameStreamResponse(response) {
|
|
@@ -2736,6 +3101,12 @@ function serverOwned(render) {
|
|
|
2736
3101
|
function serverComponentScope(render) {
|
|
2737
3102
|
return runInServerComponentScope ? runInServerComponentScope(render) : render();
|
|
2738
3103
|
}
|
|
3104
|
+
function wirePreload(entry) {
|
|
3105
|
+
return {
|
|
3106
|
+
href: entry.href,
|
|
3107
|
+
attrs: entry.attrs
|
|
3108
|
+
};
|
|
3109
|
+
}
|
|
2739
3110
|
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))}}))";
|
|
2740
3111
|
const bootstrappedScripts = new WeakSet();
|
|
2741
3112
|
setServerComponentBootstrap(ctx => {
|
|
@@ -2780,20 +3151,28 @@ function createFrameSink(emit, frame) {
|
|
|
2780
3151
|
if (!regionKeys.has(key)) regionKeys.set(key, childId);
|
|
2781
3152
|
},
|
|
2782
3153
|
shell(html, meta = {}) {
|
|
2783
|
-
if (meta.preloads && meta.preloads.size) {
|
|
2784
|
-
const styles = [];
|
|
2785
|
-
const modules = [];
|
|
2786
|
-
for (const url of meta.preloads) {
|
|
2787
|
-
(url.endsWith(".css") ? styles : modules).push(url);
|
|
2788
|
-
}
|
|
3154
|
+
if (meta.preloads && meta.preloads.size || meta.preloadLinks) {
|
|
2789
3155
|
const chunk = {
|
|
2790
3156
|
type: "assets",
|
|
2791
3157
|
id,
|
|
2792
3158
|
version,
|
|
2793
3159
|
key: ""
|
|
2794
3160
|
};
|
|
2795
|
-
if (
|
|
2796
|
-
|
|
3161
|
+
if (meta.preloads && meta.preloads.size) {
|
|
3162
|
+
const styles = [];
|
|
3163
|
+
const modules = [];
|
|
3164
|
+
for (const url of meta.preloads) {
|
|
3165
|
+
(url.endsWith(".css") ? styles : modules).push(url);
|
|
3166
|
+
}
|
|
3167
|
+
if (styles.length) chunk.styles = styles;
|
|
3168
|
+
if (modules.length) chunk.modules = modules;
|
|
3169
|
+
}
|
|
3170
|
+
if (meta.preloadLinks) {
|
|
3171
|
+
chunk.preloads = [];
|
|
3172
|
+
for (const entry of meta.preloadLinks) {
|
|
3173
|
+
chunk.preloads.push(wirePreload(entry));
|
|
3174
|
+
}
|
|
3175
|
+
}
|
|
2797
3176
|
emit(chunk);
|
|
2798
3177
|
}
|
|
2799
3178
|
emit({
|
|
@@ -2905,15 +3284,24 @@ function createFrameSink(emit, frame) {
|
|
|
2905
3284
|
emit(chunk);
|
|
2906
3285
|
}
|
|
2907
3286
|
},
|
|
2908
|
-
asset(type,
|
|
2909
|
-
if (type
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
3287
|
+
asset(type, value) {
|
|
3288
|
+
if (type === "module") {
|
|
3289
|
+
emit({
|
|
3290
|
+
type: "assets",
|
|
3291
|
+
id,
|
|
3292
|
+
version,
|
|
3293
|
+
key: "",
|
|
3294
|
+
modules: [value]
|
|
3295
|
+
});
|
|
3296
|
+
} else if (type === "preload") {
|
|
3297
|
+
emit({
|
|
3298
|
+
type: "assets",
|
|
3299
|
+
id,
|
|
3300
|
+
version,
|
|
3301
|
+
key: "",
|
|
3302
|
+
preloads: [wirePreload(value)]
|
|
3303
|
+
});
|
|
3304
|
+
}
|
|
2917
3305
|
},
|
|
2918
3306
|
end() {
|
|
2919
3307
|
if (bindings.size) sweep();
|
|
@@ -3837,7 +4225,7 @@ function frameFlightResponse({
|
|
|
3837
4225
|
});
|
|
3838
4226
|
}
|
|
3839
4227
|
if (outcome) {
|
|
3840
|
-
const reader = new ChunkReader(serializeStream(outcome, flightCodec(codec)));
|
|
4228
|
+
const reader = new ChunkReader(serializeStream(guardFailures(outcome), flightCodec(codec)));
|
|
3841
4229
|
for (let node = await reader.next(); !node.done; node = await reader.next()) {
|
|
3842
4230
|
write({
|
|
3843
4231
|
type: "outcome",
|