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