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