@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.
Files changed (57) hide show
  1. package/dist/dev.cjs +52 -7
  2. package/dist/dev.js +51 -8
  3. package/dist/server.cjs +162 -35
  4. package/dist/server.js +161 -36
  5. package/dist/web.cjs +32 -7
  6. package/dist/web.js +31 -8
  7. package/frames/dist/client.cjs +41 -8
  8. package/frames/dist/client.dev.cjs +41 -8
  9. package/frames/dist/client.dev.js +41 -8
  10. package/frames/dist/client.js +41 -8
  11. package/frames/dist/server.cjs +432 -44
  12. package/frames/dist/server.js +432 -44
  13. package/package.json +2 -2
  14. package/serialization/dist/decode.cjs +4 -2
  15. package/serialization/dist/decode.js +4 -2
  16. package/serialization/dist/serialization.cjs +12 -8
  17. package/serialization/dist/serialization.js +12 -8
  18. package/serialization/types/index.d.ts +7 -0
  19. package/serialization/types/serializer-decode.d.ts +14 -1
  20. package/serialization/types/serializer.d.ts +7 -0
  21. package/serialization/types-cjs/index.d.cts +7 -0
  22. package/serialization/types-cjs/serializer-decode.d.cts +14 -1
  23. package/serialization/types-cjs/serializer.d.cts +7 -0
  24. package/server-functions/dist/client.cjs +150 -33
  25. package/server-functions/dist/client.js +147 -34
  26. package/server-functions/dist/server.cjs +731 -118
  27. package/server-functions/dist/server.dev.cjs +751 -118
  28. package/server-functions/dist/server.dev.js +747 -119
  29. package/server-functions/dist/server.js +727 -119
  30. package/types/cookies.d.ts +6 -14
  31. package/types/frames/frame-client.d.ts +4 -0
  32. package/types/frames/serializer-decode.d.ts +14 -1
  33. package/types/frames/serializer.d.ts +7 -0
  34. package/types/jsx.d.ts +11 -16
  35. package/types/response.d.ts +11 -0
  36. package/types/serializer-decode.d.ts +14 -1
  37. package/types/serializer.d.ts +7 -0
  38. package/types/server-functions/client.d.ts +22 -2
  39. package/types/server-functions/flash.d.ts +9 -0
  40. package/types/server-functions/server.d.ts +58 -9
  41. package/types/server-functions/shared.d.ts +77 -14
  42. package/types/server-mock.d.ts +17 -2
  43. package/types/server.d.ts +16 -2
  44. package/types-cjs/cookies.d.cts +6 -14
  45. package/types-cjs/frames/frame-client.d.cts +4 -0
  46. package/types-cjs/frames/serializer-decode.d.cts +14 -1
  47. package/types-cjs/frames/serializer.d.cts +7 -0
  48. package/types-cjs/jsx.d.cts +11 -16
  49. package/types-cjs/response.d.cts +11 -0
  50. package/types-cjs/serializer-decode.d.cts +14 -1
  51. package/types-cjs/serializer.d.cts +7 -0
  52. package/types-cjs/server-functions/client.d.cts +22 -2
  53. package/types-cjs/server-functions/flash.d.cts +9 -0
  54. package/types-cjs/server-functions/server.d.cts +58 -9
  55. package/types-cjs/server-functions/shared.d.cts +77 -14
  56. package/types-cjs/server-mock.d.cts +17 -2
  57. package/types-cjs/server.d.cts +16 -2
@@ -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 = () => process.env.NODE_ENV === "development" ? 0 : seroval.Feature.ErrorPrototypeStack;
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.buffer = new Uint8Array(0);
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 (!chunk.done) {
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
- if (props[q] != null) id += ":" + q + "=" + props[q];
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
- return {
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 (!firstFlushed && p && typeof p === "object" && "then" in p) {
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
- if (canBatchStubs && !shellCompleted) {
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 (styles.length) chunk.styles = styles;
2798
- if (modules.length) chunk.modules = modules;
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, url) {
2911
- if (type !== "module") return;
2912
- emit({
2913
- type: "assets",
2914
- id,
2915
- version,
2916
- key: "",
2917
- modules: [url]
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",