@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.js
CHANGED
|
@@ -48,6 +48,15 @@ const Namespaces = {
|
|
|
48
48
|
const VoidElements = /*#__PURE__*/new Set(["area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr"]);
|
|
49
49
|
const RawTextElements = /*#__PURE__*/new Set(["style", "script", "noscript", "template", "textarea", "title"]);
|
|
50
50
|
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(","));
|
|
51
|
+
const COMPOSED_BODY_FRAMING = /*#__PURE__*/new Set(["content-length", "content-encoding", "transfer-encoding"]);
|
|
52
|
+
function isHttpNavigationTarget(target) {
|
|
53
|
+
try {
|
|
54
|
+
const protocol = new URL(target, "http://base.invalid").protocol;
|
|
55
|
+
return protocol === "http:" || protocol === "https:";
|
|
56
|
+
} catch {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
51
60
|
|
|
52
61
|
const transparentOptions = {
|
|
53
62
|
transparent: true,
|
|
@@ -150,13 +159,13 @@ function resolveSerializerPlugins(customPlugins) {
|
|
|
150
159
|
Feature.RegExp;
|
|
151
160
|
|
|
152
161
|
const DEFAULT_DISABLED_FEATURES = Feature.AggregateError | Feature.BigIntTypedArray;
|
|
153
|
-
const serializeOnlyDisabledFeatures =
|
|
162
|
+
const serializeOnlyDisabledFeatures = serializeErrorStacks => (serializeErrorStacks === undefined ? process.env.NODE_ENV === "development" : serializeErrorStacks) ? 0 : Feature.ErrorPrototypeStack;
|
|
154
163
|
const HYDRATION_GLOBAL = "_$HY.r";
|
|
155
164
|
function createSerializer(options) {
|
|
156
165
|
return new Serializer({
|
|
157
166
|
...options,
|
|
158
167
|
plugins: resolveSerializerPlugins(options.plugins),
|
|
159
|
-
disabledFeatures: (options.disabledFeatures === undefined ? DEFAULT_DISABLED_FEATURES : options.disabledFeatures) | serializeOnlyDisabledFeatures()
|
|
168
|
+
disabledFeatures: (options.disabledFeatures === undefined ? DEFAULT_DISABLED_FEATURES : options.disabledFeatures) | serializeOnlyDisabledFeatures(options.serializeErrorStacks)
|
|
160
169
|
});
|
|
161
170
|
}
|
|
162
171
|
function createHydrationSerializer({
|
|
@@ -213,6 +222,7 @@ function isSafeError(value) {
|
|
|
213
222
|
return !!(value && (typeof value === "object" || typeof value === "function") && value[SAFE_ERROR]);
|
|
214
223
|
}
|
|
215
224
|
const REVALIDATE_HEADER = "X-Revalidate";
|
|
225
|
+
const RESPONSE_HEADER_VALUE_LIMIT = 4096;
|
|
216
226
|
function initWithRevalidate(init = {}) {
|
|
217
227
|
const resolved = typeof init === "number" ? {
|
|
218
228
|
status: init
|
|
@@ -233,7 +243,13 @@ function initWithRevalidate(init = {}) {
|
|
|
233
243
|
} else {
|
|
234
244
|
headers = new Headers(responseInit.headers);
|
|
235
245
|
}
|
|
236
|
-
revalidate !== undefined
|
|
246
|
+
if (revalidate !== undefined) {
|
|
247
|
+
const keys = revalidate.toString();
|
|
248
|
+
if (keys.length > RESPONSE_HEADER_VALUE_LIMIT) {
|
|
249
|
+
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.`);
|
|
250
|
+
}
|
|
251
|
+
headers.set(REVALIDATE_HEADER, keys);
|
|
252
|
+
}
|
|
237
253
|
return {
|
|
238
254
|
responseInit,
|
|
239
255
|
headers
|
|
@@ -251,7 +267,12 @@ function redirect(url, init = 302) {
|
|
|
251
267
|
responseInit.status = 302;
|
|
252
268
|
}
|
|
253
269
|
const target = typeof url === "string" ? url : url[HREF];
|
|
254
|
-
|
|
270
|
+
const location = typeof target === "string" ? target : String(url);
|
|
271
|
+
const encoded = location.replace(/[^\x00-\x7f]/gu, encodeURIComponent);
|
|
272
|
+
if (encoded.length > RESPONSE_HEADER_VALUE_LIMIT) {
|
|
273
|
+
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.`);
|
|
274
|
+
}
|
|
275
|
+
headers.set("Location", encoded);
|
|
255
276
|
return new Response(null, {
|
|
256
277
|
...responseInit,
|
|
257
278
|
headers
|
|
@@ -267,11 +288,19 @@ function reload(init = {}) {
|
|
|
267
288
|
headers
|
|
268
289
|
});
|
|
269
290
|
}
|
|
291
|
+
const NULL_BODY_STATUSES = new Set([204, 205, 304]);
|
|
270
292
|
function respond(value, init = {}) {
|
|
271
293
|
const {
|
|
272
294
|
responseInit,
|
|
273
295
|
headers
|
|
274
296
|
} = initWithRevalidate(init);
|
|
297
|
+
for (const header of COMPOSED_BODY_FRAMING) headers.delete(header);
|
|
298
|
+
if (NULL_BODY_STATUSES.has(responseInit.status)) {
|
|
299
|
+
return new ResponseEnvelope(new Response(null, {
|
|
300
|
+
...responseInit,
|
|
301
|
+
headers
|
|
302
|
+
}), value);
|
|
303
|
+
}
|
|
275
304
|
headers.set("Content-Type", "application/json");
|
|
276
305
|
return new ResponseEnvelope(new Response(JSON.stringify(value), {
|
|
277
306
|
...responseInit,
|
|
@@ -322,6 +351,7 @@ function serializeCookie(name, value, options = {}) {
|
|
|
322
351
|
if (options.expires) cookie += `; Expires=${options.expires.toUTCString()}`;
|
|
323
352
|
if (options.httpOnly) cookie += "; HttpOnly";
|
|
324
353
|
if (options.secure) cookie += "; Secure";
|
|
354
|
+
if (options.partitioned) cookie += "; Partitioned";
|
|
325
355
|
if (options.sameSite) {
|
|
326
356
|
const sameSite = options.sameSite.toLowerCase();
|
|
327
357
|
cookie += `; SameSite=${sameSite === "none" ? "None" : sameSite === "strict" ? "Strict" : "Lax"}`;
|
|
@@ -339,6 +369,7 @@ function clearFlashCookie() {
|
|
|
339
369
|
|
|
340
370
|
const ERROR_HEADER = "X-Server-Function-Error";
|
|
341
371
|
const BODY_FORMAT_HEADER = "X-Server-Function-Format";
|
|
372
|
+
const REDIRECT_HEADER = "X-Server-Function-Redirect";
|
|
342
373
|
const SINGLE_FLIGHT_HEADER = "X-Single-Flight";
|
|
343
374
|
|
|
344
375
|
const HEAD_ELIGIBLE_TAGS = new Set(["title", "meta", "link", "style", "script", "base"]);
|
|
@@ -377,7 +408,8 @@ function resourceIdentity(tag, props) {
|
|
|
377
408
|
let id = "res:" + tag + ":" + (props.rel || "") + ":" + (props.href || props.src || "");
|
|
378
409
|
for (let i = 0; i < RESOURCE_QUALIFIERS.length; i++) {
|
|
379
410
|
const q = RESOURCE_QUALIFIERS[i];
|
|
380
|
-
|
|
411
|
+
const value = props[q];
|
|
412
|
+
if (value != null) id += ":" + q + "=" + (value === true ? "" : value);
|
|
381
413
|
}
|
|
382
414
|
return id;
|
|
383
415
|
}
|
|
@@ -439,6 +471,7 @@ function resolveAssets(moduleUrl, manifest) {
|
|
|
439
471
|
if (!entry) return null;
|
|
440
472
|
const css = [];
|
|
441
473
|
const js = [];
|
|
474
|
+
let preloads;
|
|
442
475
|
const visited = new Set();
|
|
443
476
|
const walk = key => {
|
|
444
477
|
if (visited.has(key)) return;
|
|
@@ -447,13 +480,26 @@ function resolveAssets(moduleUrl, manifest) {
|
|
|
447
480
|
if (!e) return;
|
|
448
481
|
js.push(joinAssetPath(base, e.file));
|
|
449
482
|
if (e.css) for (let i = 0; i < e.css.length; i++) css.push(joinAssetPath(base, e.css[i]));
|
|
483
|
+
if (e.preloads) {
|
|
484
|
+
for (let i = 0; i < e.preloads.length; i++) {
|
|
485
|
+
const link = e.preloads[i];
|
|
486
|
+
if (!link || typeof link.href !== "string" || !link.href) continue;
|
|
487
|
+
if (!preloads) preloads = [];
|
|
488
|
+
preloads.push({
|
|
489
|
+
...link,
|
|
490
|
+
href: joinAssetPath(base, link.href)
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
}
|
|
450
494
|
if (e.imports) for (let i = 0; i < e.imports.length; i++) walk(e.imports[i]);
|
|
451
495
|
};
|
|
452
496
|
walk(moduleUrl);
|
|
453
|
-
|
|
497
|
+
const assets = {
|
|
454
498
|
js,
|
|
455
499
|
css
|
|
456
500
|
};
|
|
501
|
+
if (preloads) assets.preloads = preloads;
|
|
502
|
+
return assets;
|
|
457
503
|
}
|
|
458
504
|
function registerEntryAssets(manifest) {
|
|
459
505
|
if (!manifest || typeof manifest === "function" || typeof manifest.resolve === "function") return;
|
|
@@ -463,6 +509,7 @@ function registerEntryAssets(manifest) {
|
|
|
463
509
|
if (manifest[key].isEntry) {
|
|
464
510
|
const assets = resolveAssets(key, manifest);
|
|
465
511
|
if (assets) {
|
|
512
|
+
if (assets.preloads) for (let i = 0; i < assets.preloads.length; i++) ctx.registerAsset("preload", assets.preloads[i]);
|
|
466
513
|
for (let i = 0; i < assets.css.length; i++) ctx.registerAsset("style", assets.css[i]);
|
|
467
514
|
for (let i = 1; i < assets.js.length; i++) ctx.registerAsset("module", assets.js[i]);
|
|
468
515
|
}
|
|
@@ -481,6 +528,7 @@ function createAssetTracking() {
|
|
|
481
528
|
boundaryStyles,
|
|
482
529
|
emittedAssets,
|
|
483
530
|
inlineStyles,
|
|
531
|
+
preloadLinks: null,
|
|
484
532
|
registerInlineStyle(desc) {
|
|
485
533
|
let entry = inlineStyles.get(desc.id);
|
|
486
534
|
if (!entry) {
|
|
@@ -572,6 +620,56 @@ function isCssUrl(url) {
|
|
|
572
620
|
const q = url.search(/[?#]/);
|
|
573
621
|
return (q === -1 ? url : url.slice(0, q)).endsWith(".css");
|
|
574
622
|
}
|
|
623
|
+
const PRELOAD_LINK_ATTRIBUTES = ["type", "crossorigin", "integrity", "referrerpolicy", "fetchpriority", "media"];
|
|
624
|
+
function registerPreloadLink(tracking, headRegistry, link, nonce) {
|
|
625
|
+
if (!link || typeof link !== "object" || typeof link.href !== "string" || !link.href) {
|
|
626
|
+
return null;
|
|
627
|
+
}
|
|
628
|
+
if (typeof link.as !== "string") {
|
|
629
|
+
return null;
|
|
630
|
+
}
|
|
631
|
+
const as = asciiLowerCase(link.as);
|
|
632
|
+
let destination = null;
|
|
633
|
+
switch (as) {
|
|
634
|
+
case "script":
|
|
635
|
+
case "style":
|
|
636
|
+
destination = as;
|
|
637
|
+
break;
|
|
638
|
+
case "fetch":
|
|
639
|
+
case "font":
|
|
640
|
+
case "image":
|
|
641
|
+
case "track":
|
|
642
|
+
break;
|
|
643
|
+
default:
|
|
644
|
+
return null;
|
|
645
|
+
}
|
|
646
|
+
const props = {
|
|
647
|
+
rel: "preload",
|
|
648
|
+
href: link.href,
|
|
649
|
+
as
|
|
650
|
+
};
|
|
651
|
+
for (let i = 0; i < PRELOAD_LINK_ATTRIBUTES.length; i++) {
|
|
652
|
+
const name = PRELOAD_LINK_ATTRIBUTES[i];
|
|
653
|
+
const value = link[name];
|
|
654
|
+
if (value == null || value === false) continue;
|
|
655
|
+
props[name] = value === true ? "" : String(value);
|
|
656
|
+
}
|
|
657
|
+
const identity = resourceIdentity("link", props);
|
|
658
|
+
if (headRegistry.resources.has(identity)) return null;
|
|
659
|
+
const attrs = headAttrRecord(props);
|
|
660
|
+
const nonceValue = destination && nonce && nonce[destination];
|
|
661
|
+
if (typeof nonceValue === "string" && nonceValue) attrs.nonce = nonceValue;
|
|
662
|
+
const entry = {
|
|
663
|
+
href: props.href,
|
|
664
|
+
attrs,
|
|
665
|
+
attrHtml: renderHeadAttrHtml(props) + nonceAttr(nonce, destination)
|
|
666
|
+
};
|
|
667
|
+
headRegistry.resources.add(identity);
|
|
668
|
+
let links = tracking.preloadLinks;
|
|
669
|
+
if (!links) tracking.preloadLinks = links = [];
|
|
670
|
+
links.push(entry);
|
|
671
|
+
return entry;
|
|
672
|
+
}
|
|
575
673
|
function createHeadRegistry() {
|
|
576
674
|
return {
|
|
577
675
|
pending: [],
|
|
@@ -1048,6 +1146,10 @@ function renderToString(code, options = {}) {
|
|
|
1048
1146
|
serializer.write(id, p);
|
|
1049
1147
|
},
|
|
1050
1148
|
registerAsset(type, value) {
|
|
1149
|
+
if (type === "preload") {
|
|
1150
|
+
registerPreloadLink(tracking, headRegistry, value, nonce);
|
|
1151
|
+
return;
|
|
1152
|
+
}
|
|
1051
1153
|
if (type === "inline-style") {
|
|
1052
1154
|
tracking.registerInlineStyle(value);
|
|
1053
1155
|
return;
|
|
@@ -1075,7 +1177,7 @@ function renderToString(code, options = {}) {
|
|
|
1075
1177
|
sharedConfig.context.noHydrate = true;
|
|
1076
1178
|
serializer.close();
|
|
1077
1179
|
const head = renderShellHead(headRegistry, nonce, null, noScripts);
|
|
1078
|
-
return assembleDocument(resolveSSRSelectValues(html), tracking.emittedAssets, tracking.inlineStyles, scripts.length ? scripts : "", nonce, head, onHead);
|
|
1180
|
+
return assembleDocument(resolveSSRSelectValues(html), tracking.emittedAssets, tracking.preloadLinks, tracking.inlineStyles, scripts.length ? scripts : "", nonce, head, onHead);
|
|
1079
1181
|
}
|
|
1080
1182
|
function renderToStream(code, options = {}) {
|
|
1081
1183
|
let {
|
|
@@ -1229,6 +1331,8 @@ function renderToStream(code, options = {}) {
|
|
|
1229
1331
|
asset(type, value) {
|
|
1230
1332
|
if (type === "module") {
|
|
1231
1333
|
buffer.write(`<link rel="modulepreload" href="${value}"${nonceAttr(nonce, "script")}>`);
|
|
1334
|
+
} else if (type === "preload") {
|
|
1335
|
+
buffer.write(`<link${value.attrHtml}>`);
|
|
1232
1336
|
} else if (type === "inline-style") {
|
|
1233
1337
|
buffer.write(renderInlineStyle(value, nonce));
|
|
1234
1338
|
} else if (type === "head-tag") {
|
|
@@ -1236,7 +1340,7 @@ function renderToStream(code, options = {}) {
|
|
|
1236
1340
|
}
|
|
1237
1341
|
},
|
|
1238
1342
|
shell(shellHtml, meta) {
|
|
1239
|
-
buffer.write(assembleDocument(shellHtml, meta.preloads, meta.inlineStyles, meta.tasks.length ? meta.tasks : "", nonce, meta.head, onHead));
|
|
1343
|
+
buffer.write(assembleDocument(shellHtml, meta.preloads, meta.preloadLinks, meta.inlineStyles, meta.tasks.length ? meta.tasks : "", nonce, meta.head, onHead));
|
|
1240
1344
|
},
|
|
1241
1345
|
...options.sink
|
|
1242
1346
|
};
|
|
@@ -1269,6 +1373,29 @@ function renderToStream(code, options = {}) {
|
|
|
1269
1373
|
}
|
|
1270
1374
|
};
|
|
1271
1375
|
const registry = new Map();
|
|
1376
|
+
const pendingSerialized = new Map();
|
|
1377
|
+
const trackSerialized = (id, p) => {
|
|
1378
|
+
let settle;
|
|
1379
|
+
const raced = Promise.race([p, new Promise(r => settle = r)]);
|
|
1380
|
+
pendingSerialized.set(id, settle);
|
|
1381
|
+
const drop = () => pendingSerialized.delete(id);
|
|
1382
|
+
p.then(drop, drop);
|
|
1383
|
+
return raced;
|
|
1384
|
+
};
|
|
1385
|
+
const abandonSubtree = key => {
|
|
1386
|
+
for (const [k, entry] of registry) {
|
|
1387
|
+
if (k.length > key.length && k.startsWith(key)) {
|
|
1388
|
+
registry.delete(k);
|
|
1389
|
+
entry.resolve();
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
for (const [id, settle] of pendingSerialized) {
|
|
1393
|
+
if (id.startsWith(key)) {
|
|
1394
|
+
pendingSerialized.delete(id);
|
|
1395
|
+
settle();
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
};
|
|
1272
1399
|
const writeTasks = () => {
|
|
1273
1400
|
if (tasks.length && !completed && firstFlushed) {
|
|
1274
1401
|
buffer.write(`<script${nonceAttr(nonce, "script")}>${tasks}</script>`);
|
|
@@ -1339,6 +1466,11 @@ function renderToStream(code, options = {}) {
|
|
|
1339
1466
|
}, nonce, tags);
|
|
1340
1467
|
},
|
|
1341
1468
|
registerAsset(type, value) {
|
|
1469
|
+
if (type === "preload") {
|
|
1470
|
+
const entry = registerPreloadLink(tracking, headRegistry, value, nonce);
|
|
1471
|
+
if (entry && firstFlushed) sink.asset("preload", entry);
|
|
1472
|
+
return;
|
|
1473
|
+
}
|
|
1342
1474
|
if (type === "inline-style") {
|
|
1343
1475
|
const entry = tracking.registerInlineStyle(value);
|
|
1344
1476
|
if (firstFlushed && !tracking.currentBoundaryId && !entry.emitted) {
|
|
@@ -1383,13 +1515,14 @@ function renderToStream(code, options = {}) {
|
|
|
1383
1515
|
},
|
|
1384
1516
|
serialize(id, p, deferStream) {
|
|
1385
1517
|
if (sharedConfig.context.noHydrate) return;
|
|
1386
|
-
if (
|
|
1387
|
-
if (deferStream) {
|
|
1518
|
+
if (p && typeof p === "object" && typeof p.then === "function") {
|
|
1519
|
+
if (!firstFlushed && deferStream) {
|
|
1388
1520
|
blockingPromises.add(p);
|
|
1389
1521
|
p.then(d => serializer.write(id, d)).catch(e => serializer.write(id, e));
|
|
1390
1522
|
return;
|
|
1391
1523
|
}
|
|
1392
|
-
|
|
1524
|
+
p = trackSerialized(id, p);
|
|
1525
|
+
if (!firstFlushed && canBatchStubs && !shellCompleted) {
|
|
1393
1526
|
(stubBatch ||= new Map()).set(id, p);
|
|
1394
1527
|
return;
|
|
1395
1528
|
}
|
|
@@ -1434,6 +1567,7 @@ function renderToStream(code, options = {}) {
|
|
|
1434
1567
|
if (registry.has(key)) {
|
|
1435
1568
|
const item = registry.get(key);
|
|
1436
1569
|
registry.delete(key);
|
|
1570
|
+
if (error) abandonSubtree(key);
|
|
1437
1571
|
if (item.children) {
|
|
1438
1572
|
for (const k in item.children) {
|
|
1439
1573
|
value = replacePlaceholder(value, k, item.children[k]);
|
|
@@ -1558,6 +1692,7 @@ function renderToStream(code, options = {}) {
|
|
|
1558
1692
|
const head = renderShellHead(headRegistry, nonce, k => registry.has(k), noScripts);
|
|
1559
1693
|
sink.shell(resolveSSRSelectValues(html), {
|
|
1560
1694
|
preloads: tracking.emittedAssets,
|
|
1695
|
+
preloadLinks: tracking.preloadLinks,
|
|
1561
1696
|
inlineStyles: tracking.inlineStyles,
|
|
1562
1697
|
tasks,
|
|
1563
1698
|
head
|
|
@@ -2375,6 +2510,7 @@ function ssr(t) {
|
|
|
2375
2510
|
return result;
|
|
2376
2511
|
}
|
|
2377
2512
|
function ssrClassName(value) {
|
|
2513
|
+
if (typeof value === "number") return "" + value;
|
|
2378
2514
|
if (!value) return "";
|
|
2379
2515
|
if (typeof value === "string") return escape(value, true);
|
|
2380
2516
|
value = classListToObject(value);
|
|
@@ -2704,12 +2840,12 @@ function allSettled(promises) {
|
|
|
2704
2840
|
return;
|
|
2705
2841
|
});
|
|
2706
2842
|
}
|
|
2707
|
-
function assembleDocument(html, emittedAssets, inlineStyles, scripts, nonce, headTags, onHead) {
|
|
2843
|
+
function assembleDocument(html, emittedAssets, preloadLinks, inlineStyles, scripts, nonce, headTags, onHead) {
|
|
2708
2844
|
const scriptTag = scripts ? `<script${nonceAttr(nonce, "script")}>${scripts}</script>` : "";
|
|
2709
2845
|
const title = headTags ? headTags.title : null;
|
|
2710
2846
|
let headTagsHtml = headTags ? headTags.html : "";
|
|
2711
2847
|
const headPrelude = headTags ? headTags.prelude : "";
|
|
2712
|
-
if (!onHead && title == null && !headTagsHtml && !headPrelude && !(emittedAssets && emittedAssets.size) && !(inlineStyles && inlineStyles.size)) {
|
|
2848
|
+
if (!onHead && title == null && !headTagsHtml && !headPrelude && !(emittedAssets && emittedAssets.size) && !preloadLinks && !(inlineStyles && inlineStyles.size)) {
|
|
2713
2849
|
if (!scriptTag) return html;
|
|
2714
2850
|
const xs = html.indexOf("<!--xs-->");
|
|
2715
2851
|
return xs === -1 ? html + scriptTag : html.slice(0, xs) + scriptTag + html.slice(xs);
|
|
@@ -2728,7 +2864,7 @@ function assembleDocument(html, emittedAssets, inlineStyles, scripts, nonce, hea
|
|
|
2728
2864
|
if (title != null) {
|
|
2729
2865
|
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>`;
|
|
2730
2866
|
}
|
|
2731
|
-
onHead(headPrelude + headTagsHtml + titleHtml + renderHeadAssets(emittedAssets, inlineStyles, nonce));
|
|
2867
|
+
onHead(headPrelude + headTagsHtml + titleHtml + renderHeadAssets(emittedAssets, preloadLinks, inlineStyles, nonce));
|
|
2732
2868
|
}
|
|
2733
2869
|
if (!scriptTag) return html;
|
|
2734
2870
|
const xs = html.indexOf("<!--xs-->");
|
|
@@ -2748,13 +2884,13 @@ function assembleDocument(html, emittedAssets, inlineStyles, scripts, nonce, hea
|
|
|
2748
2884
|
headTagsHtml = `<title data-dh="title">${winner}</title>` + headTagsHtml;
|
|
2749
2885
|
}
|
|
2750
2886
|
}
|
|
2751
|
-
const head = headTagsHtml + renderHeadAssets(emittedAssets, inlineStyles, nonce);
|
|
2887
|
+
const head = headTagsHtml + renderHeadAssets(emittedAssets, preloadLinks, inlineStyles, nonce);
|
|
2752
2888
|
if (!scriptTag) return html.slice(0, headIdx) + head + html.slice(headIdx);
|
|
2753
2889
|
const xsIdx = html.indexOf("<!--xs-->");
|
|
2754
2890
|
if (xsIdx === -1) return html.slice(0, headIdx) + head + html.slice(headIdx) + scriptTag;
|
|
2755
2891
|
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);
|
|
2756
2892
|
}
|
|
2757
|
-
function renderHeadAssets(emittedAssets, inlineStyles, nonce) {
|
|
2893
|
+
function renderHeadAssets(emittedAssets, preloadLinks, inlineStyles, nonce) {
|
|
2758
2894
|
let head = "";
|
|
2759
2895
|
const styleAttr = nonceAttr(nonce, "style");
|
|
2760
2896
|
const scriptAttr = nonceAttr(nonce, "script");
|
|
@@ -2763,6 +2899,9 @@ function renderHeadAssets(emittedAssets, inlineStyles, nonce) {
|
|
|
2763
2899
|
head += isCssUrl(url) ? `<link rel="stylesheet" href="${url}"${styleAttr}>` : `<link rel="modulepreload" href="${url}"${scriptAttr}>`;
|
|
2764
2900
|
}
|
|
2765
2901
|
}
|
|
2902
|
+
if (preloadLinks) {
|
|
2903
|
+
for (const entry of preloadLinks) head += `<link${entry.attrHtml}>`;
|
|
2904
|
+
}
|
|
2766
2905
|
if (inlineStyles && inlineStyles.size) {
|
|
2767
2906
|
for (const entry of inlineStyles.values()) {
|
|
2768
2907
|
if (entry.emitted) continue;
|
|
@@ -2857,7 +2996,8 @@ function classListToObject(classList) {
|
|
|
2857
2996
|
function flattenClassList(list, result) {
|
|
2858
2997
|
for (let i = 0, len = list.length; i < len; i++) {
|
|
2859
2998
|
const item = list[i];
|
|
2860
|
-
if (Array.isArray(item)) flattenClassList(item, result);else if (typeof item === "object" && item != null) Object.assign(result, item);
|
|
2999
|
+
if (Array.isArray(item)) flattenClassList(item, result);else if (typeof item === "object" && item != null) Object.assign(result, item);
|
|
3000
|
+
else if (typeof item !== "boolean" && (item || item === 0)) result[item] = true;
|
|
2861
3001
|
}
|
|
2862
3002
|
}
|
|
2863
3003
|
function tryResolveString(node) {
|
|
@@ -3027,7 +3167,8 @@ function copyInitHeaders(init) {
|
|
|
3027
3167
|
for (const cookie of init.getSetCookie()) headers.append("Set-Cookie", cookie);
|
|
3028
3168
|
return headers;
|
|
3029
3169
|
}
|
|
3030
|
-
const STUB_GAP_FILL_EXCLUDED = /*#__PURE__*/new Set([ERROR_HEADER, BODY_FORMAT_HEADER, SINGLE_FLIGHT_HEADER, REVALIDATE_HEADER, "Location"
|
|
3170
|
+
const STUB_GAP_FILL_EXCLUDED = /*#__PURE__*/new Set([ERROR_HEADER, BODY_FORMAT_HEADER, SINGLE_FLIGHT_HEADER, REVALIDATE_HEADER, REDIRECT_HEADER, "Location",
|
|
3171
|
+
...COMPOSED_BODY_FRAMING].map(header => header.toLowerCase()));
|
|
3031
3172
|
function fillsStubGap(key, headers, response) {
|
|
3032
3173
|
if (key === "set-cookie" || STUB_GAP_FILL_EXCLUDED.has(key)) return false;
|
|
3033
3174
|
if (response.body === null && (key === "content-type" || key === "content-length")) return false;
|
|
@@ -3043,27 +3184,20 @@ function commitEventResponse(response, event = getRequestEvent()) {
|
|
|
3043
3184
|
if (fillsStubGap(key, response.headers, response)) hasGaps = true;
|
|
3044
3185
|
});
|
|
3045
3186
|
if (!cookies.length && !hasGaps) return response;
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
if (fillsStubGap(key, headers, response)) headers.set(key, value);
|
|
3057
|
-
});
|
|
3058
|
-
return new Response(response.body, {
|
|
3059
|
-
status: response.status,
|
|
3060
|
-
statusText: response.statusText,
|
|
3061
|
-
headers
|
|
3062
|
-
});
|
|
3063
|
-
}
|
|
3187
|
+
const headers = copyInitHeaders(response.headers);
|
|
3188
|
+
for (const cookie of cookies) headers.append("Set-Cookie", cookie);
|
|
3189
|
+
stub.headers.forEach((value, key) => {
|
|
3190
|
+
if (fillsStubGap(key, headers, response)) headers.set(key, value);
|
|
3191
|
+
});
|
|
3192
|
+
return new Response(response.body, {
|
|
3193
|
+
status: response.status,
|
|
3194
|
+
statusText: response.statusText,
|
|
3195
|
+
headers
|
|
3196
|
+
});
|
|
3064
3197
|
}
|
|
3065
3198
|
function deriveHead(stub, responseInit = {}) {
|
|
3066
3199
|
const headers = mergeStubHeaders(copyInitHeaders(responseInit.headers), stub);
|
|
3200
|
+
for (const header of COMPOSED_BODY_FRAMING) headers.delete(header);
|
|
3067
3201
|
const status = stub && stub.status || responseInit.status || 200;
|
|
3068
3202
|
const statusText = stub && stub.statusText || responseInit.statusText || undefined;
|
|
3069
3203
|
return {
|
|
@@ -3147,7 +3281,7 @@ function createSSRResponse(result, event, options = {}) {
|
|
|
3147
3281
|
end() {
|
|
3148
3282
|
if (closed || !controller) return;
|
|
3149
3283
|
const location = stub && stub.headers.get("Location");
|
|
3150
|
-
if (location) {
|
|
3284
|
+
if (location && isHttpNavigationTarget(location)) {
|
|
3151
3285
|
const attr = nonceAttr(nonce, "script");
|
|
3152
3286
|
enqueue(`<script${attr}>window.location=${JSON.stringify(location).replace(/</g, "\\u003c")}</script>`);
|
|
3153
3287
|
}
|
|
@@ -3226,6 +3360,11 @@ function registerClientOnlyPreload(moduleUrl) {
|
|
|
3226
3360
|
const css = assets.css[i];
|
|
3227
3361
|
if (typeof css === "string") registerAsset("style", css);else registerAsset("inline-style", css);
|
|
3228
3362
|
}
|
|
3363
|
+
if (assets.preloads) {
|
|
3364
|
+
for (let i = 0; i < assets.preloads.length; i++) {
|
|
3365
|
+
registerAsset("preload", assets.preloads[i]);
|
|
3366
|
+
}
|
|
3367
|
+
}
|
|
3229
3368
|
for (let i = 0; i < assets.js.length; i++) registerAsset("module", assets.js[i]);
|
|
3230
3369
|
};
|
|
3231
3370
|
const assets = resolve(moduleUrl);
|
|
@@ -3329,4 +3468,4 @@ function httpHeader(name, value, options) {
|
|
|
3329
3468
|
}
|
|
3330
3469
|
}
|
|
3331
3470
|
|
|
3332
|
-
export { CLAIMS_DOCUMENT, CLAIMS_STREAM, CLAIM_PROP, ChildProperties, DOMElements, DOMWithState, DelegatedEvents, Dynamic, HREF, HydrationScript, MathMLElements, Namespaces, Portal, REVALIDATE_HEADER, RawTextElements, RequestContext, ResponseEnvelope, SAFE_ERROR, SVGElements, VoidElements, notSup as acquireAsset, notSup as addEvent, applyRef, notSup as assign, claimElement, claimElementTree, notSup as className, clearFlashCookie, clientOnly, commitEventResponse, commitResponseStub, composeMiddleware, createLiveHoles, createRequestEvent, createResponseStub, createSSRResponse, notSup as delegateEvents, dynamic, notSup as dynamicProperty, effect, escape, generateHydrationScript, notSup as getDelegatedRoot, getExpectedRedirectStatus, getHydrationKey, notSup as getNextElement, notSup as getNextMarker, notSup as getNextMatch, getRequestEvent, getServerFunctionMetadata, getServerFunctionRPC, hasFlashCookie, httpHeader, httpStatus, notSup as hydrate, notSup as insert, isDev, isHref, isResponseEnvelope, isSafeError, isServer, isServerFunction, markSafeError, memo, parseCookieHeader, redirect, notSup as ref, notSup as registerDelegatedContainer, notSup as registerDelegatedRoot, registerElementClaim, reload, notSup as render, renderToStream, renderToString, resolveSSRNode, resolveSSRSelectValues, respond, notSup as runHydrationEvents, scriptNonce, serializeCookie, notSup as setAttribute, notSup as setAttributeNS, notSup as setProperty, notSup as setStyleProperty, notSup as spread, ssr, ssrAttribute, ssrClaim, ssrClassName, ssrElement, ssrGroup, ssrHydrationKey, ssrSelectValues, ssrStyle, ssrStyleProperty, notSup as style, styleNonce, notSup as template, notSup as unregisterDelegatedContainer, notSup as unregisterDelegatedRoot, useHead };
|
|
3471
|
+
export { CLAIMS_DOCUMENT, CLAIMS_STREAM, CLAIM_PROP, ChildProperties, DOMElements, DOMWithState, DelegatedEvents, Dynamic, HREF, HydrationScript, MathMLElements, NULL_BODY_STATUSES, Namespaces, Portal, RESPONSE_HEADER_VALUE_LIMIT, REVALIDATE_HEADER, RawTextElements, RequestContext, ResponseEnvelope, SAFE_ERROR, SVGElements, VoidElements, notSup as acquireAsset, notSup as addEvent, applyRef, notSup as assign, claimElement, claimElementTree, notSup as className, clearFlashCookie, clientOnly, commitEventResponse, commitResponseStub, composeMiddleware, createLiveHoles, createRequestEvent, createResponseStub, createSSRResponse, notSup as delegateEvents, dynamic, notSup as dynamicProperty, effect, escape, generateHydrationScript, notSup as getDelegatedRoot, getExpectedRedirectStatus, getHydrationKey, notSup as getNextElement, notSup as getNextMarker, notSup as getNextMatch, getRequestEvent, getServerFunctionMetadata, getServerFunctionRPC, hasFlashCookie, httpHeader, httpStatus, notSup as hydrate, notSup as insert, isDev, isHref, isResponseEnvelope, isSafeError, isServer, isServerFunction, markSafeError, memo, parseCookieHeader, redirect, notSup as ref, notSup as registerDelegatedContainer, notSup as registerDelegatedRoot, registerElementClaim, reload, notSup as render, renderToStream, renderToString, resolveSSRNode, resolveSSRSelectValues, respond, notSup as runHydrationEvents, scriptNonce, serializeCookie, notSup as setAttribute, notSup as setAttributeNS, notSup as setProperty, notSup as setStyleProperty, notSup as spread, ssr, ssrAttribute, ssrClaim, ssrClassName, ssrElement, ssrGroup, ssrHydrationKey, ssrSelectValues, ssrStyle, ssrStyleProperty, notSup as style, styleNonce, notSup as template, notSup as unregisterDelegatedContainer, notSup as unregisterDelegatedRoot, useHead };
|