@solidjs/web 2.0.0-rc.4 → 2.0.0-rc.6
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 +163 -36
- package/dist/dev.js +161 -37
- package/dist/server.cjs +178 -37
- package/dist/server.js +177 -38
- package/dist/web.cjs +143 -36
- package/dist/web.js +141 -37
- 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 +497 -44
- package/frames/dist/server.js +497 -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 +164 -35
- package/server-functions/dist/client.js +161 -36
- package/server-functions/dist/server.cjs +899 -136
- package/server-functions/dist/server.dev.cjs +919 -136
- package/server-functions/dist/server.dev.js +915 -137
- package/server-functions/dist/server.js +895 -137
- package/types/client.d.ts +2 -1
- package/types/constants.d.ts +3 -1
- 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 +131 -11
- 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/client.d.cts +2 -1
- package/types-cjs/constants.d.cts +3 -1
- 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 +131 -11
- 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/dist/server.cjs
CHANGED
|
@@ -49,6 +49,15 @@ const Namespaces = {
|
|
|
49
49
|
const VoidElements = /*#__PURE__*/new Set(["area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr"]);
|
|
50
50
|
const RawTextElements = /*#__PURE__*/new Set(["style", "script", "noscript", "template", "textarea", "title"]);
|
|
51
51
|
const DOMElements = /*#__PURE__*/new Set(/*#__PURE__*/"a,abbr,acronym,address,applet,area,article,aside,audio,b,base,basefont,bdi,bdo,bgsound,big,blink,blockquote,body,br,button,canvas,caption,center,cite,code,col,colgroup,content,data,datalist,dd,del,details,dfn,dialog,dir,div,dl,dt,em,embed,fieldset,figcaption,figure,font,footer,form,frame,frameset,h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,i,iframe,image,img,input,ins,isindex,kbd,keygen,label,legend,li,link,listing,main,map,mark,marquee,math,menu,menuitem,meta,meter,multicol,nav,nextid,nobr,noembed,noframes,noindex,noscript,object,ol,optgroup,option,output,p,param,picture,plaintext,portal,pre,progress,q,rb,rp,rt,rtc,ruby,s,samp,script,search,section,select,shadow,slot,small,source,spacer,span,strike,strong,style,sub,summary,sup,svg,table,tbody,td,template,textarea,tfoot,th,thead,time,title,tr,track,tt,u,ul,var,video,wbr,webview,xmp".split(","));
|
|
52
|
+
const COMPOSED_BODY_FRAMING = /*#__PURE__*/new Set(["content-length", "content-encoding", "transfer-encoding"]);
|
|
53
|
+
function isHttpNavigationTarget(target) {
|
|
54
|
+
try {
|
|
55
|
+
const protocol = new URL(target, "http://base.invalid").protocol;
|
|
56
|
+
return protocol === "http:" || protocol === "https:";
|
|
57
|
+
} catch {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
52
61
|
|
|
53
62
|
const transparentOptions = {
|
|
54
63
|
transparent: true,
|
|
@@ -151,13 +160,13 @@ function resolveSerializerPlugins(customPlugins) {
|
|
|
151
160
|
seroval.Feature.RegExp;
|
|
152
161
|
|
|
153
162
|
const DEFAULT_DISABLED_FEATURES = seroval.Feature.AggregateError | seroval.Feature.BigIntTypedArray;
|
|
154
|
-
const serializeOnlyDisabledFeatures =
|
|
163
|
+
const serializeOnlyDisabledFeatures = serializeErrorStacks => (serializeErrorStacks === undefined ? process.env.NODE_ENV === "development" : serializeErrorStacks) ? 0 : seroval.Feature.ErrorPrototypeStack;
|
|
155
164
|
const HYDRATION_GLOBAL = "_$HY.r";
|
|
156
165
|
function createSerializer(options) {
|
|
157
166
|
return new seroval.Serializer({
|
|
158
167
|
...options,
|
|
159
168
|
plugins: resolveSerializerPlugins(options.plugins),
|
|
160
|
-
disabledFeatures: (options.disabledFeatures === undefined ? DEFAULT_DISABLED_FEATURES : options.disabledFeatures) | serializeOnlyDisabledFeatures()
|
|
169
|
+
disabledFeatures: (options.disabledFeatures === undefined ? DEFAULT_DISABLED_FEATURES : options.disabledFeatures) | serializeOnlyDisabledFeatures(options.serializeErrorStacks)
|
|
161
170
|
});
|
|
162
171
|
}
|
|
163
172
|
function createHydrationSerializer({
|
|
@@ -214,6 +223,7 @@ function isSafeError(value) {
|
|
|
214
223
|
return !!(value && (typeof value === "object" || typeof value === "function") && value[SAFE_ERROR]);
|
|
215
224
|
}
|
|
216
225
|
const REVALIDATE_HEADER = "X-Revalidate";
|
|
226
|
+
const RESPONSE_HEADER_VALUE_LIMIT = 4096;
|
|
217
227
|
function initWithRevalidate(init = {}) {
|
|
218
228
|
const resolved = typeof init === "number" ? {
|
|
219
229
|
status: init
|
|
@@ -234,7 +244,13 @@ function initWithRevalidate(init = {}) {
|
|
|
234
244
|
} else {
|
|
235
245
|
headers = new Headers(responseInit.headers);
|
|
236
246
|
}
|
|
237
|
-
revalidate !== undefined
|
|
247
|
+
if (revalidate !== undefined) {
|
|
248
|
+
const keys = revalidate.toString();
|
|
249
|
+
if (keys.length > RESPONSE_HEADER_VALUE_LIMIT) {
|
|
250
|
+
throw new TypeError(`revalidate names ${keys.length} characters of cache keys; past ` + `${RESPONSE_HEADER_VALUE_LIMIT} the ${REVALIDATE_HEADER} header would overflow ` + `receivers (an 8 KiB proxy buffer holds the whole header block) and the response ` + `dies at the socket after the mutation committed. Split the invalidation across ` + `calls or use coarser keys — a dropped key would be a silently stale cache, so ` + `the runtime refuses rather than trims.`);
|
|
251
|
+
}
|
|
252
|
+
headers.set(REVALIDATE_HEADER, keys);
|
|
253
|
+
}
|
|
238
254
|
return {
|
|
239
255
|
responseInit,
|
|
240
256
|
headers
|
|
@@ -252,7 +268,12 @@ function redirect(url, init = 302) {
|
|
|
252
268
|
responseInit.status = 302;
|
|
253
269
|
}
|
|
254
270
|
const target = typeof url === "string" ? url : url[HREF];
|
|
255
|
-
|
|
271
|
+
const location = typeof target === "string" ? target : String(url);
|
|
272
|
+
const encoded = location.replace(/[^\x00-\x7f]/gu, encodeURIComponent);
|
|
273
|
+
if (encoded.length > RESPONSE_HEADER_VALUE_LIMIT) {
|
|
274
|
+
throw new TypeError(`redirect() target is ${encoded.length} characters; past ` + `${RESPONSE_HEADER_VALUE_LIMIT} the Location header (and the scripted transport's ` + `redirect header) would overflow receivers and the response dies at the socket. ` + `A target this size is usually unbounded input echoed into the url — carry the ` + `state server-side instead. Refused rather than trimmed: a cut target is a ` + `different address.`);
|
|
275
|
+
}
|
|
276
|
+
headers.set("Location", encoded);
|
|
256
277
|
return new Response(null, {
|
|
257
278
|
...responseInit,
|
|
258
279
|
headers
|
|
@@ -268,11 +289,19 @@ function reload(init = {}) {
|
|
|
268
289
|
headers
|
|
269
290
|
});
|
|
270
291
|
}
|
|
292
|
+
const NULL_BODY_STATUSES = new Set([204, 205, 304]);
|
|
271
293
|
function respond(value, init = {}) {
|
|
272
294
|
const {
|
|
273
295
|
responseInit,
|
|
274
296
|
headers
|
|
275
297
|
} = initWithRevalidate(init);
|
|
298
|
+
for (const header of COMPOSED_BODY_FRAMING) headers.delete(header);
|
|
299
|
+
if (NULL_BODY_STATUSES.has(responseInit.status)) {
|
|
300
|
+
return new ResponseEnvelope(new Response(null, {
|
|
301
|
+
...responseInit,
|
|
302
|
+
headers
|
|
303
|
+
}), value);
|
|
304
|
+
}
|
|
276
305
|
headers.set("Content-Type", "application/json");
|
|
277
306
|
return new ResponseEnvelope(new Response(JSON.stringify(value), {
|
|
278
307
|
...responseInit,
|
|
@@ -323,6 +352,7 @@ function serializeCookie(name, value, options = {}) {
|
|
|
323
352
|
if (options.expires) cookie += `; Expires=${options.expires.toUTCString()}`;
|
|
324
353
|
if (options.httpOnly) cookie += "; HttpOnly";
|
|
325
354
|
if (options.secure) cookie += "; Secure";
|
|
355
|
+
if (options.partitioned) cookie += "; Partitioned";
|
|
326
356
|
if (options.sameSite) {
|
|
327
357
|
const sameSite = options.sameSite.toLowerCase();
|
|
328
358
|
cookie += `; SameSite=${sameSite === "none" ? "None" : sameSite === "strict" ? "Strict" : "Lax"}`;
|
|
@@ -340,6 +370,7 @@ function clearFlashCookie() {
|
|
|
340
370
|
|
|
341
371
|
const ERROR_HEADER = "X-Server-Function-Error";
|
|
342
372
|
const BODY_FORMAT_HEADER = "X-Server-Function-Format";
|
|
373
|
+
const REDIRECT_HEADER = "X-Server-Function-Redirect";
|
|
343
374
|
const SINGLE_FLIGHT_HEADER = "X-Single-Flight";
|
|
344
375
|
|
|
345
376
|
const HEAD_ELIGIBLE_TAGS = new Set(["title", "meta", "link", "style", "script", "base"]);
|
|
@@ -378,7 +409,8 @@ function resourceIdentity(tag, props) {
|
|
|
378
409
|
let id = "res:" + tag + ":" + (props.rel || "") + ":" + (props.href || props.src || "");
|
|
379
410
|
for (let i = 0; i < RESOURCE_QUALIFIERS.length; i++) {
|
|
380
411
|
const q = RESOURCE_QUALIFIERS[i];
|
|
381
|
-
|
|
412
|
+
const value = props[q];
|
|
413
|
+
if (value != null) id += ":" + q + "=" + (value === true ? "" : value);
|
|
382
414
|
}
|
|
383
415
|
return id;
|
|
384
416
|
}
|
|
@@ -440,6 +472,7 @@ function resolveAssets(moduleUrl, manifest) {
|
|
|
440
472
|
if (!entry) return null;
|
|
441
473
|
const css = [];
|
|
442
474
|
const js = [];
|
|
475
|
+
let preloads;
|
|
443
476
|
const visited = new Set();
|
|
444
477
|
const walk = key => {
|
|
445
478
|
if (visited.has(key)) return;
|
|
@@ -448,13 +481,26 @@ function resolveAssets(moduleUrl, manifest) {
|
|
|
448
481
|
if (!e) return;
|
|
449
482
|
js.push(joinAssetPath(base, e.file));
|
|
450
483
|
if (e.css) for (let i = 0; i < e.css.length; i++) css.push(joinAssetPath(base, e.css[i]));
|
|
484
|
+
if (e.preloads) {
|
|
485
|
+
for (let i = 0; i < e.preloads.length; i++) {
|
|
486
|
+
const link = e.preloads[i];
|
|
487
|
+
if (!link || typeof link.href !== "string" || !link.href) continue;
|
|
488
|
+
if (!preloads) preloads = [];
|
|
489
|
+
preloads.push({
|
|
490
|
+
...link,
|
|
491
|
+
href: joinAssetPath(base, link.href)
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
}
|
|
451
495
|
if (e.imports) for (let i = 0; i < e.imports.length; i++) walk(e.imports[i]);
|
|
452
496
|
};
|
|
453
497
|
walk(moduleUrl);
|
|
454
|
-
|
|
498
|
+
const assets = {
|
|
455
499
|
js,
|
|
456
500
|
css
|
|
457
501
|
};
|
|
502
|
+
if (preloads) assets.preloads = preloads;
|
|
503
|
+
return assets;
|
|
458
504
|
}
|
|
459
505
|
function registerEntryAssets(manifest) {
|
|
460
506
|
if (!manifest || typeof manifest === "function" || typeof manifest.resolve === "function") return;
|
|
@@ -464,6 +510,7 @@ function registerEntryAssets(manifest) {
|
|
|
464
510
|
if (manifest[key].isEntry) {
|
|
465
511
|
const assets = resolveAssets(key, manifest);
|
|
466
512
|
if (assets) {
|
|
513
|
+
if (assets.preloads) for (let i = 0; i < assets.preloads.length; i++) ctx.registerAsset("preload", assets.preloads[i]);
|
|
467
514
|
for (let i = 0; i < assets.css.length; i++) ctx.registerAsset("style", assets.css[i]);
|
|
468
515
|
for (let i = 1; i < assets.js.length; i++) ctx.registerAsset("module", assets.js[i]);
|
|
469
516
|
}
|
|
@@ -482,6 +529,7 @@ function createAssetTracking() {
|
|
|
482
529
|
boundaryStyles,
|
|
483
530
|
emittedAssets,
|
|
484
531
|
inlineStyles,
|
|
532
|
+
preloadLinks: null,
|
|
485
533
|
registerInlineStyle(desc) {
|
|
486
534
|
let entry = inlineStyles.get(desc.id);
|
|
487
535
|
if (!entry) {
|
|
@@ -573,6 +621,56 @@ function isCssUrl(url) {
|
|
|
573
621
|
const q = url.search(/[?#]/);
|
|
574
622
|
return (q === -1 ? url : url.slice(0, q)).endsWith(".css");
|
|
575
623
|
}
|
|
624
|
+
const PRELOAD_LINK_ATTRIBUTES = ["type", "crossorigin", "integrity", "referrerpolicy", "fetchpriority", "media"];
|
|
625
|
+
function registerPreloadLink(tracking, headRegistry, link, nonce) {
|
|
626
|
+
if (!link || typeof link !== "object" || typeof link.href !== "string" || !link.href) {
|
|
627
|
+
return null;
|
|
628
|
+
}
|
|
629
|
+
if (typeof link.as !== "string") {
|
|
630
|
+
return null;
|
|
631
|
+
}
|
|
632
|
+
const as = asciiLowerCase(link.as);
|
|
633
|
+
let destination = null;
|
|
634
|
+
switch (as) {
|
|
635
|
+
case "script":
|
|
636
|
+
case "style":
|
|
637
|
+
destination = as;
|
|
638
|
+
break;
|
|
639
|
+
case "fetch":
|
|
640
|
+
case "font":
|
|
641
|
+
case "image":
|
|
642
|
+
case "track":
|
|
643
|
+
break;
|
|
644
|
+
default:
|
|
645
|
+
return null;
|
|
646
|
+
}
|
|
647
|
+
const props = {
|
|
648
|
+
rel: "preload",
|
|
649
|
+
href: link.href,
|
|
650
|
+
as
|
|
651
|
+
};
|
|
652
|
+
for (let i = 0; i < PRELOAD_LINK_ATTRIBUTES.length; i++) {
|
|
653
|
+
const name = PRELOAD_LINK_ATTRIBUTES[i];
|
|
654
|
+
const value = link[name];
|
|
655
|
+
if (value == null || value === false) continue;
|
|
656
|
+
props[name] = value === true ? "" : String(value);
|
|
657
|
+
}
|
|
658
|
+
const identity = resourceIdentity("link", props);
|
|
659
|
+
if (headRegistry.resources.has(identity)) return null;
|
|
660
|
+
const attrs = headAttrRecord(props);
|
|
661
|
+
const nonceValue = destination && nonce && nonce[destination];
|
|
662
|
+
if (typeof nonceValue === "string" && nonceValue) attrs.nonce = nonceValue;
|
|
663
|
+
const entry = {
|
|
664
|
+
href: props.href,
|
|
665
|
+
attrs,
|
|
666
|
+
attrHtml: renderHeadAttrHtml(props) + nonceAttr(nonce, destination)
|
|
667
|
+
};
|
|
668
|
+
headRegistry.resources.add(identity);
|
|
669
|
+
let links = tracking.preloadLinks;
|
|
670
|
+
if (!links) tracking.preloadLinks = links = [];
|
|
671
|
+
links.push(entry);
|
|
672
|
+
return entry;
|
|
673
|
+
}
|
|
576
674
|
function createHeadRegistry() {
|
|
577
675
|
return {
|
|
578
676
|
pending: [],
|
|
@@ -1049,6 +1147,10 @@ function renderToString(code, options = {}) {
|
|
|
1049
1147
|
serializer.write(id, p);
|
|
1050
1148
|
},
|
|
1051
1149
|
registerAsset(type, value) {
|
|
1150
|
+
if (type === "preload") {
|
|
1151
|
+
registerPreloadLink(tracking, headRegistry, value, nonce);
|
|
1152
|
+
return;
|
|
1153
|
+
}
|
|
1052
1154
|
if (type === "inline-style") {
|
|
1053
1155
|
tracking.registerInlineStyle(value);
|
|
1054
1156
|
return;
|
|
@@ -1076,7 +1178,7 @@ function renderToString(code, options = {}) {
|
|
|
1076
1178
|
solidJs.sharedConfig.context.noHydrate = true;
|
|
1077
1179
|
serializer.close();
|
|
1078
1180
|
const head = renderShellHead(headRegistry, nonce, null, noScripts);
|
|
1079
|
-
return assembleDocument(resolveSSRSelectValues(html), tracking.emittedAssets, tracking.inlineStyles, scripts.length ? scripts : "", nonce, head, onHead);
|
|
1181
|
+
return assembleDocument(resolveSSRSelectValues(html), tracking.emittedAssets, tracking.preloadLinks, tracking.inlineStyles, scripts.length ? scripts : "", nonce, head, onHead);
|
|
1080
1182
|
}
|
|
1081
1183
|
function renderToStream(code, options = {}) {
|
|
1082
1184
|
let {
|
|
@@ -1230,6 +1332,8 @@ function renderToStream(code, options = {}) {
|
|
|
1230
1332
|
asset(type, value) {
|
|
1231
1333
|
if (type === "module") {
|
|
1232
1334
|
buffer.write(`<link rel="modulepreload" href="${value}"${nonceAttr(nonce, "script")}>`);
|
|
1335
|
+
} else if (type === "preload") {
|
|
1336
|
+
buffer.write(`<link${value.attrHtml}>`);
|
|
1233
1337
|
} else if (type === "inline-style") {
|
|
1234
1338
|
buffer.write(renderInlineStyle(value, nonce));
|
|
1235
1339
|
} else if (type === "head-tag") {
|
|
@@ -1237,7 +1341,7 @@ function renderToStream(code, options = {}) {
|
|
|
1237
1341
|
}
|
|
1238
1342
|
},
|
|
1239
1343
|
shell(shellHtml, meta) {
|
|
1240
|
-
buffer.write(assembleDocument(shellHtml, meta.preloads, meta.inlineStyles, meta.tasks.length ? meta.tasks : "", nonce, meta.head, onHead));
|
|
1344
|
+
buffer.write(assembleDocument(shellHtml, meta.preloads, meta.preloadLinks, meta.inlineStyles, meta.tasks.length ? meta.tasks : "", nonce, meta.head, onHead));
|
|
1241
1345
|
},
|
|
1242
1346
|
...options.sink
|
|
1243
1347
|
};
|
|
@@ -1270,6 +1374,29 @@ function renderToStream(code, options = {}) {
|
|
|
1270
1374
|
}
|
|
1271
1375
|
};
|
|
1272
1376
|
const registry = new Map();
|
|
1377
|
+
const pendingSerialized = new Map();
|
|
1378
|
+
const trackSerialized = (id, p) => {
|
|
1379
|
+
let settle;
|
|
1380
|
+
const raced = Promise.race([p, new Promise(r => settle = r)]);
|
|
1381
|
+
pendingSerialized.set(id, settle);
|
|
1382
|
+
const drop = () => pendingSerialized.delete(id);
|
|
1383
|
+
p.then(drop, drop);
|
|
1384
|
+
return raced;
|
|
1385
|
+
};
|
|
1386
|
+
const abandonSubtree = key => {
|
|
1387
|
+
for (const [k, entry] of registry) {
|
|
1388
|
+
if (k.length > key.length && k.startsWith(key)) {
|
|
1389
|
+
registry.delete(k);
|
|
1390
|
+
entry.resolve();
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
for (const [id, settle] of pendingSerialized) {
|
|
1394
|
+
if (id.startsWith(key)) {
|
|
1395
|
+
pendingSerialized.delete(id);
|
|
1396
|
+
settle();
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
};
|
|
1273
1400
|
const writeTasks = () => {
|
|
1274
1401
|
if (tasks.length && !completed && firstFlushed) {
|
|
1275
1402
|
buffer.write(`<script${nonceAttr(nonce, "script")}>${tasks}</script>`);
|
|
@@ -1340,6 +1467,11 @@ function renderToStream(code, options = {}) {
|
|
|
1340
1467
|
}, nonce, tags);
|
|
1341
1468
|
},
|
|
1342
1469
|
registerAsset(type, value) {
|
|
1470
|
+
if (type === "preload") {
|
|
1471
|
+
const entry = registerPreloadLink(tracking, headRegistry, value, nonce);
|
|
1472
|
+
if (entry && firstFlushed) sink.asset("preload", entry);
|
|
1473
|
+
return;
|
|
1474
|
+
}
|
|
1343
1475
|
if (type === "inline-style") {
|
|
1344
1476
|
const entry = tracking.registerInlineStyle(value);
|
|
1345
1477
|
if (firstFlushed && !tracking.currentBoundaryId && !entry.emitted) {
|
|
@@ -1384,13 +1516,14 @@ function renderToStream(code, options = {}) {
|
|
|
1384
1516
|
},
|
|
1385
1517
|
serialize(id, p, deferStream) {
|
|
1386
1518
|
if (solidJs.sharedConfig.context.noHydrate) return;
|
|
1387
|
-
if (
|
|
1388
|
-
if (deferStream) {
|
|
1519
|
+
if (p && typeof p === "object" && typeof p.then === "function") {
|
|
1520
|
+
if (!firstFlushed && deferStream) {
|
|
1389
1521
|
blockingPromises.add(p);
|
|
1390
1522
|
p.then(d => serializer.write(id, d)).catch(e => serializer.write(id, e));
|
|
1391
1523
|
return;
|
|
1392
1524
|
}
|
|
1393
|
-
|
|
1525
|
+
p = trackSerialized(id, p);
|
|
1526
|
+
if (!firstFlushed && canBatchStubs && !shellCompleted) {
|
|
1394
1527
|
(stubBatch ||= new Map()).set(id, p);
|
|
1395
1528
|
return;
|
|
1396
1529
|
}
|
|
@@ -1435,6 +1568,7 @@ function renderToStream(code, options = {}) {
|
|
|
1435
1568
|
if (registry.has(key)) {
|
|
1436
1569
|
const item = registry.get(key);
|
|
1437
1570
|
registry.delete(key);
|
|
1571
|
+
if (error) abandonSubtree(key);
|
|
1438
1572
|
if (item.children) {
|
|
1439
1573
|
for (const k in item.children) {
|
|
1440
1574
|
value = replacePlaceholder(value, k, item.children[k]);
|
|
@@ -1559,6 +1693,7 @@ function renderToStream(code, options = {}) {
|
|
|
1559
1693
|
const head = renderShellHead(headRegistry, nonce, k => registry.has(k), noScripts);
|
|
1560
1694
|
sink.shell(resolveSSRSelectValues(html), {
|
|
1561
1695
|
preloads: tracking.emittedAssets,
|
|
1696
|
+
preloadLinks: tracking.preloadLinks,
|
|
1562
1697
|
inlineStyles: tracking.inlineStyles,
|
|
1563
1698
|
tasks,
|
|
1564
1699
|
head
|
|
@@ -2376,6 +2511,7 @@ function ssr(t) {
|
|
|
2376
2511
|
return result;
|
|
2377
2512
|
}
|
|
2378
2513
|
function ssrClassName(value) {
|
|
2514
|
+
if (typeof value === "number") return "" + value;
|
|
2379
2515
|
if (!value) return "";
|
|
2380
2516
|
if (typeof value === "string") return escape(value, true);
|
|
2381
2517
|
value = classListToObject(value);
|
|
@@ -2705,12 +2841,12 @@ function allSettled(promises) {
|
|
|
2705
2841
|
return;
|
|
2706
2842
|
});
|
|
2707
2843
|
}
|
|
2708
|
-
function assembleDocument(html, emittedAssets, inlineStyles, scripts, nonce, headTags, onHead) {
|
|
2844
|
+
function assembleDocument(html, emittedAssets, preloadLinks, inlineStyles, scripts, nonce, headTags, onHead) {
|
|
2709
2845
|
const scriptTag = scripts ? `<script${nonceAttr(nonce, "script")}>${scripts}</script>` : "";
|
|
2710
2846
|
const title = headTags ? headTags.title : null;
|
|
2711
2847
|
let headTagsHtml = headTags ? headTags.html : "";
|
|
2712
2848
|
const headPrelude = headTags ? headTags.prelude : "";
|
|
2713
|
-
if (!onHead && title == null && !headTagsHtml && !headPrelude && !(emittedAssets && emittedAssets.size) && !(inlineStyles && inlineStyles.size)) {
|
|
2849
|
+
if (!onHead && title == null && !headTagsHtml && !headPrelude && !(emittedAssets && emittedAssets.size) && !preloadLinks && !(inlineStyles && inlineStyles.size)) {
|
|
2714
2850
|
if (!scriptTag) return html;
|
|
2715
2851
|
const xs = html.indexOf("<!--xs-->");
|
|
2716
2852
|
return xs === -1 ? html + scriptTag : html.slice(0, xs) + scriptTag + html.slice(xs);
|
|
@@ -2729,7 +2865,7 @@ function assembleDocument(html, emittedAssets, inlineStyles, scripts, nonce, hea
|
|
|
2729
2865
|
if (title != null) {
|
|
2730
2866
|
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>`;
|
|
2731
2867
|
}
|
|
2732
|
-
onHead(headPrelude + headTagsHtml + titleHtml + renderHeadAssets(emittedAssets, inlineStyles, nonce));
|
|
2868
|
+
onHead(headPrelude + headTagsHtml + titleHtml + renderHeadAssets(emittedAssets, preloadLinks, inlineStyles, nonce));
|
|
2733
2869
|
}
|
|
2734
2870
|
if (!scriptTag) return html;
|
|
2735
2871
|
const xs = html.indexOf("<!--xs-->");
|
|
@@ -2749,13 +2885,13 @@ function assembleDocument(html, emittedAssets, inlineStyles, scripts, nonce, hea
|
|
|
2749
2885
|
headTagsHtml = `<title data-dh="title">${winner}</title>` + headTagsHtml;
|
|
2750
2886
|
}
|
|
2751
2887
|
}
|
|
2752
|
-
const head = headTagsHtml + renderHeadAssets(emittedAssets, inlineStyles, nonce);
|
|
2888
|
+
const head = headTagsHtml + renderHeadAssets(emittedAssets, preloadLinks, inlineStyles, nonce);
|
|
2753
2889
|
if (!scriptTag) return html.slice(0, headIdx) + head + html.slice(headIdx);
|
|
2754
2890
|
const xsIdx = html.indexOf("<!--xs-->");
|
|
2755
2891
|
if (xsIdx === -1) return html.slice(0, headIdx) + head + html.slice(headIdx) + scriptTag;
|
|
2756
2892
|
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);
|
|
2757
2893
|
}
|
|
2758
|
-
function renderHeadAssets(emittedAssets, inlineStyles, nonce) {
|
|
2894
|
+
function renderHeadAssets(emittedAssets, preloadLinks, inlineStyles, nonce) {
|
|
2759
2895
|
let head = "";
|
|
2760
2896
|
const styleAttr = nonceAttr(nonce, "style");
|
|
2761
2897
|
const scriptAttr = nonceAttr(nonce, "script");
|
|
@@ -2764,6 +2900,9 @@ function renderHeadAssets(emittedAssets, inlineStyles, nonce) {
|
|
|
2764
2900
|
head += isCssUrl(url) ? `<link rel="stylesheet" href="${url}"${styleAttr}>` : `<link rel="modulepreload" href="${url}"${scriptAttr}>`;
|
|
2765
2901
|
}
|
|
2766
2902
|
}
|
|
2903
|
+
if (preloadLinks) {
|
|
2904
|
+
for (const entry of preloadLinks) head += `<link${entry.attrHtml}>`;
|
|
2905
|
+
}
|
|
2767
2906
|
if (inlineStyles && inlineStyles.size) {
|
|
2768
2907
|
for (const entry of inlineStyles.values()) {
|
|
2769
2908
|
if (entry.emitted) continue;
|
|
@@ -2858,7 +2997,8 @@ function classListToObject(classList) {
|
|
|
2858
2997
|
function flattenClassList(list, result) {
|
|
2859
2998
|
for (let i = 0, len = list.length; i < len; i++) {
|
|
2860
2999
|
const item = list[i];
|
|
2861
|
-
if (Array.isArray(item)) flattenClassList(item, result);else if (typeof item === "object" && item != null) Object.assign(result, item);
|
|
3000
|
+
if (Array.isArray(item)) flattenClassList(item, result);else if (typeof item === "object" && item != null) Object.assign(result, item);
|
|
3001
|
+
else if (typeof item !== "boolean" && (item || item === 0)) result[item] = true;
|
|
2862
3002
|
}
|
|
2863
3003
|
}
|
|
2864
3004
|
function tryResolveString(node) {
|
|
@@ -3028,7 +3168,8 @@ function copyInitHeaders(init) {
|
|
|
3028
3168
|
for (const cookie of init.getSetCookie()) headers.append("Set-Cookie", cookie);
|
|
3029
3169
|
return headers;
|
|
3030
3170
|
}
|
|
3031
|
-
const STUB_GAP_FILL_EXCLUDED = /*#__PURE__*/new Set([ERROR_HEADER, BODY_FORMAT_HEADER, SINGLE_FLIGHT_HEADER, REVALIDATE_HEADER, "Location"
|
|
3171
|
+
const STUB_GAP_FILL_EXCLUDED = /*#__PURE__*/new Set([ERROR_HEADER, BODY_FORMAT_HEADER, SINGLE_FLIGHT_HEADER, REVALIDATE_HEADER, REDIRECT_HEADER, "Location",
|
|
3172
|
+
...COMPOSED_BODY_FRAMING].map(header => header.toLowerCase()));
|
|
3032
3173
|
function fillsStubGap(key, headers, response) {
|
|
3033
3174
|
if (key === "set-cookie" || STUB_GAP_FILL_EXCLUDED.has(key)) return false;
|
|
3034
3175
|
if (response.body === null && (key === "content-type" || key === "content-length")) return false;
|
|
@@ -3044,27 +3185,20 @@ function commitEventResponse(response, event = getRequestEvent()) {
|
|
|
3044
3185
|
if (fillsStubGap(key, response.headers, response)) hasGaps = true;
|
|
3045
3186
|
});
|
|
3046
3187
|
if (!cookies.length && !hasGaps) return response;
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
if (fillsStubGap(key, headers, response)) headers.set(key, value);
|
|
3058
|
-
});
|
|
3059
|
-
return new Response(response.body, {
|
|
3060
|
-
status: response.status,
|
|
3061
|
-
statusText: response.statusText,
|
|
3062
|
-
headers
|
|
3063
|
-
});
|
|
3064
|
-
}
|
|
3188
|
+
const headers = copyInitHeaders(response.headers);
|
|
3189
|
+
for (const cookie of cookies) headers.append("Set-Cookie", cookie);
|
|
3190
|
+
stub.headers.forEach((value, key) => {
|
|
3191
|
+
if (fillsStubGap(key, headers, response)) headers.set(key, value);
|
|
3192
|
+
});
|
|
3193
|
+
return new Response(response.body, {
|
|
3194
|
+
status: response.status,
|
|
3195
|
+
statusText: response.statusText,
|
|
3196
|
+
headers
|
|
3197
|
+
});
|
|
3065
3198
|
}
|
|
3066
3199
|
function deriveHead(stub, responseInit = {}) {
|
|
3067
3200
|
const headers = mergeStubHeaders(copyInitHeaders(responseInit.headers), stub);
|
|
3201
|
+
for (const header of COMPOSED_BODY_FRAMING) headers.delete(header);
|
|
3068
3202
|
const status = stub && stub.status || responseInit.status || 200;
|
|
3069
3203
|
const statusText = stub && stub.statusText || responseInit.statusText || undefined;
|
|
3070
3204
|
return {
|
|
@@ -3148,7 +3282,7 @@ function createSSRResponse(result, event, options = {}) {
|
|
|
3148
3282
|
end() {
|
|
3149
3283
|
if (closed || !controller) return;
|
|
3150
3284
|
const location = stub && stub.headers.get("Location");
|
|
3151
|
-
if (location) {
|
|
3285
|
+
if (location && isHttpNavigationTarget(location)) {
|
|
3152
3286
|
const attr = nonceAttr(nonce, "script");
|
|
3153
3287
|
enqueue(`<script${attr}>window.location=${JSON.stringify(location).replace(/</g, "\\u003c")}</script>`);
|
|
3154
3288
|
}
|
|
@@ -3227,6 +3361,11 @@ function registerClientOnlyPreload(moduleUrl) {
|
|
|
3227
3361
|
const css = assets.css[i];
|
|
3228
3362
|
if (typeof css === "string") registerAsset("style", css);else registerAsset("inline-style", css);
|
|
3229
3363
|
}
|
|
3364
|
+
if (assets.preloads) {
|
|
3365
|
+
for (let i = 0; i < assets.preloads.length; i++) {
|
|
3366
|
+
registerAsset("preload", assets.preloads[i]);
|
|
3367
|
+
}
|
|
3368
|
+
}
|
|
3230
3369
|
for (let i = 0; i < assets.js.length; i++) registerAsset("module", assets.js[i]);
|
|
3231
3370
|
};
|
|
3232
3371
|
const assets = resolve(moduleUrl);
|
|
@@ -3405,8 +3544,10 @@ exports.Dynamic = Dynamic;
|
|
|
3405
3544
|
exports.HREF = HREF;
|
|
3406
3545
|
exports.HydrationScript = HydrationScript;
|
|
3407
3546
|
exports.MathMLElements = MathMLElements;
|
|
3547
|
+
exports.NULL_BODY_STATUSES = NULL_BODY_STATUSES;
|
|
3408
3548
|
exports.Namespaces = Namespaces;
|
|
3409
3549
|
exports.Portal = Portal;
|
|
3550
|
+
exports.RESPONSE_HEADER_VALUE_LIMIT = RESPONSE_HEADER_VALUE_LIMIT;
|
|
3410
3551
|
exports.REVALIDATE_HEADER = REVALIDATE_HEADER;
|
|
3411
3552
|
exports.RawTextElements = RawTextElements;
|
|
3412
3553
|
exports.RequestContext = RequestContext;
|