@solidjs/web 2.0.0-beta.31 → 2.0.0-beta.32

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 (64) hide show
  1. package/README.md +1 -6
  2. package/dist/dev.cjs +234 -45
  3. package/dist/dev.js +221 -42
  4. package/dist/server.cjs +456 -123
  5. package/dist/server.js +445 -120
  6. package/dist/web.cjs +234 -45
  7. package/dist/web.js +221 -42
  8. package/frames/dist/client.cjs +217 -112
  9. package/frames/dist/client.dev.cjs +217 -112
  10. package/frames/dist/client.dev.js +218 -113
  11. package/frames/dist/client.js +218 -113
  12. package/frames/dist/server.cjs +488 -177
  13. package/frames/dist/server.js +489 -179
  14. package/package.json +55 -4
  15. package/serialization/dist/serialization.cjs +8 -0
  16. package/serialization/dist/serialization.js +1 -0
  17. package/serialization/types/index.d.ts +173 -6
  18. package/serialization/types-cjs/index.d.cts +173 -6
  19. package/server-functions/dist/client.cjs +46 -9
  20. package/server-functions/dist/client.js +47 -11
  21. package/server-functions/dist/rich-args.cjs +11 -0
  22. package/server-functions/dist/rich-args.js +9 -0
  23. package/server-functions/dist/server.cjs +275 -126
  24. package/server-functions/dist/server.dev.cjs +1053 -0
  25. package/server-functions/dist/server.dev.js +1021 -0
  26. package/server-functions/dist/server.js +273 -127
  27. package/server-functions/package.json +10 -0
  28. package/server-functions/rich-args/package.json +20 -0
  29. package/storage/types/index.d.ts +1 -1
  30. package/storage/types-cjs/index.d.cts +1 -1
  31. package/types/client.d.ts +127 -6
  32. package/types/core.d.ts +3 -1
  33. package/types/frames/client.d.ts +15 -1
  34. package/types/frames/frame-client.d.ts +37 -7
  35. package/types/frames/frame-sink.d.ts +26 -3
  36. package/types/frames/frame-transport.d.ts +39 -7
  37. package/types/frames/serializer.d.ts +173 -6
  38. package/types/frames/server.d.ts +22 -0
  39. package/types/index.d.ts +2 -3
  40. package/types/response.d.ts +45 -0
  41. package/types/serializer.d.ts +173 -6
  42. package/types/server-functions/client.d.ts +1 -0
  43. package/types/server-functions/rich-args.d.ts +10 -0
  44. package/types/server-functions/server.d.ts +98 -0
  45. package/types/server-functions/shared.d.ts +22 -0
  46. package/types/server-mock.d.ts +171 -59
  47. package/types/server.d.ts +188 -36
  48. package/types-cjs/client.d.cts +127 -6
  49. package/types-cjs/core.d.cts +3 -1
  50. package/types-cjs/frames/client.d.cts +15 -1
  51. package/types-cjs/frames/frame-client.d.cts +37 -7
  52. package/types-cjs/frames/frame-sink.d.cts +26 -3
  53. package/types-cjs/frames/frame-transport.d.cts +39 -7
  54. package/types-cjs/frames/serializer.d.cts +173 -6
  55. package/types-cjs/frames/server.d.cts +22 -0
  56. package/types-cjs/index.d.cts +2 -3
  57. package/types-cjs/response.d.cts +45 -0
  58. package/types-cjs/serializer.d.cts +173 -6
  59. package/types-cjs/server-functions/client.d.cts +1 -0
  60. package/types-cjs/server-functions/rich-args.d.cts +10 -0
  61. package/types-cjs/server-functions/server.d.cts +98 -0
  62. package/types-cjs/server-functions/shared.d.cts +22 -0
  63. package/types-cjs/server-mock.d.cts +171 -59
  64. package/types-cjs/server.d.cts +188 -36
@@ -7,6 +7,9 @@ var web = require('seroval-plugins/web');
7
7
  const runWithHydrationScope = (id, fn) => solidJs.runWithOwner(solidJs.createOwner({
8
8
  id
9
9
  }), fn);
10
+ const ssrAsyncValue = value => solidJs.createMemo(() => value, {
11
+ serialize: false
12
+ });
10
13
 
11
14
  const DEFAULT_DISABLED_FEATURES = seroval.Feature.AggregateError | seroval.Feature.BigIntTypedArray;
12
15
  const serializeOnlyDisabledFeatures = () => process.env.NODE_ENV === "development" ? 0 : seroval.Feature.ErrorPrototypeStack;
@@ -137,6 +140,143 @@ function createJSONSerializer({
137
140
  };
138
141
  }
139
142
 
143
+ const ENVELOPE = Symbol.for("solid.ResponseEnvelope");
144
+ function isResponseEnvelope(value) {
145
+ return !!(value && typeof value === "object" && value[ENVELOPE]);
146
+ }
147
+ const REVALIDATE_HEADER = "X-Revalidate";
148
+
149
+ function frameAddress(id, args) {
150
+ return args && args.length ? id + ":" + hashArguments(args) : id;
151
+ }
152
+ function hashArguments(args) {
153
+ let hash = 0;
154
+ const text = stableString(args);
155
+ for (let i = 0; i < text.length; i++) {
156
+ hash = (hash << 5) - hash + text.charCodeAt(i);
157
+ hash |= 0;
158
+ }
159
+ return (hash >>> 0).toString(36);
160
+ }
161
+ function stableString(value, seen) {
162
+ if (value === null || typeof value !== "object") {
163
+ return typeof value === "bigint" ? value + "n" : String(value);
164
+ }
165
+ if (value instanceof Date) return "Date:" + value.getTime();
166
+ seen || (seen = new Set());
167
+ if (seen.has(value)) return "~";
168
+ seen.add(value);
169
+ if (value instanceof Map) {
170
+ const entries = [];
171
+ for (const [k, v] of value) {
172
+ entries.push(stableString(k, seen) + "=>" + stableString(v, seen));
173
+ }
174
+ return "Map{" + entries.sort().join(",") + "}";
175
+ }
176
+ if (value instanceof Set) {
177
+ const members = [];
178
+ for (const v of value) members.push(stableString(v, seen));
179
+ return "Set{" + members.sort().join(",") + "}";
180
+ }
181
+ if (Array.isArray(value)) {
182
+ let out = "[";
183
+ for (let i = 0; i < value.length; i++) out += (i ? "," : "") + stableString(value[i], seen);
184
+ return out + "]";
185
+ }
186
+ const keys = Object.keys(value).sort();
187
+ let out = "{";
188
+ for (let i = 0; i < keys.length; i++) {
189
+ out += (i ? "," : "") + keys[i] + ":" + stableString(value[keys[i]], seen);
190
+ }
191
+ return out + "}";
192
+ }
193
+ const ERROR_HEADER = "X-Server-Function-Error";
194
+ const BODY_FORMAT_HEADER = "X-Server-Function-Format";
195
+ const SINGLE_FLIGHT_HEADER = "X-Single-Flight";
196
+ function createChunk(data) {
197
+ const encoder = new TextEncoder();
198
+ const encodeData = encoder.encode(data);
199
+ const bytes = encodeData.length;
200
+ const chunk = new Uint8Array(12 + bytes);
201
+ chunk.set(encoder.encode(`;0x${bytes.toString(16).padStart(8, "0")};`));
202
+ chunk.set(encodeData, 12);
203
+ return chunk;
204
+ }
205
+ class ChunkReader {
206
+ constructor(stream) {
207
+ this.reader = stream.getReader();
208
+ this.buffer = new Uint8Array(0);
209
+ this.done = false;
210
+ }
211
+ async readChunk() {
212
+ const chunk = await this.reader.read();
213
+ if (!chunk.done) {
214
+ const newBuffer = new Uint8Array(this.buffer.length + chunk.value.length);
215
+ newBuffer.set(this.buffer);
216
+ newBuffer.set(chunk.value, this.buffer.length);
217
+ this.buffer = newBuffer;
218
+ } else {
219
+ this.done = true;
220
+ }
221
+ }
222
+ async next() {
223
+ while (this.buffer.length < 12) {
224
+ if (this.done) {
225
+ if (this.buffer.length === 0) return {
226
+ done: true,
227
+ value: undefined
228
+ };
229
+ throw new Error("Malformed server function stream.");
230
+ }
231
+ await this.readChunk();
232
+ }
233
+ const decoder = new TextDecoder();
234
+ const bytes = Number.parseInt(decoder.decode(this.buffer.subarray(1, 11)), 16);
235
+ if (Number.isNaN(bytes)) {
236
+ throw new Error("Malformed server function stream.");
237
+ }
238
+ while (bytes > this.buffer.length - 12) {
239
+ if (this.done) {
240
+ throw new Error("Malformed server function stream.");
241
+ }
242
+ await this.readChunk();
243
+ }
244
+ const partial = decoder.decode(this.buffer.subarray(12, 12 + bytes));
245
+ this.buffer = this.buffer.subarray(12 + bytes);
246
+ return {
247
+ done: false,
248
+ value: partial
249
+ };
250
+ }
251
+ async drain(interpret) {
252
+ while (true) {
253
+ const result = await this.next();
254
+ if (result.done) {
255
+ break;
256
+ }
257
+ interpret(result.value);
258
+ }
259
+ }
260
+ }
261
+ function serializeStream(value, codecOptions) {
262
+ return new ReadableStream({
263
+ start(controller) {
264
+ serializeJSON(value, {
265
+ ...codecOptions,
266
+ onParse(node) {
267
+ controller.enqueue(createChunk(JSON.stringify(node)));
268
+ },
269
+ onDone() {
270
+ controller.close();
271
+ },
272
+ onError(error) {
273
+ controller.error(error);
274
+ }
275
+ });
276
+ }
277
+ });
278
+ }
279
+
140
280
  const HEAD_ELIGIBLE_TAGS = new Set(["title", "meta", "link", "style", "script", "base"]);
141
281
  const HEAD_ATTR_NAME = /^[a-zA-Z_][a-zA-Z0-9_:.-]*$/;
142
282
  const RESOURCE_LINK_RELS = new Set(["preload", "modulepreload", "prefetch", "preconnect", "dns-prefetch", "stylesheet"]);
@@ -377,7 +517,8 @@ function createHeadRegistry() {
377
517
  resources: new Set(),
378
518
  eagerHtml: "",
379
519
  flushed: null,
380
- shellFlushed: false
520
+ shellFlushed: false,
521
+ parkedResources: []
381
522
  };
382
523
  }
383
524
  function registerHeadTags(registry, context, tracking, emitResource, nonce, tags) {
@@ -391,6 +532,7 @@ function registerHeadTags(registry, context, tracking, emitResource, nonce, tags
391
532
  return;
392
533
  }
393
534
  if (!Array.isArray(tags)) tags = [tags];
535
+ const probe = solidJs.sharedConfig.context && solidJs.sharedConfig.context._loadingPhase;
394
536
  let replaceable = null;
395
537
  for (let i = 0; i < tags.length; i++) {
396
538
  const desc = tags[i];
@@ -399,6 +541,16 @@ function registerHeadTags(registry, context, tracking, emitResource, nonce, tags
399
541
  continue;
400
542
  }
401
543
  const cls = classifyHeadTag(desc);
544
+ if (probe && !cls.resource) {
545
+ try {
546
+ evalHeadProps(desc.props || {}, cls.rel !== undefined ? {
547
+ rel: cls.rel
548
+ } : undefined);
549
+ evalHeadValue(desc.key);
550
+ } catch (err) {
551
+ if (solidJs.ssrHandleError(err)) throw err;
552
+ }
553
+ }
402
554
  if (cls.resource) {
403
555
  emitHeadResource(registry, context, tracking, emitResource, nonce, desc, cls.rel);
404
556
  } else {
@@ -415,6 +567,52 @@ function registerHeadTags(registry, context, tracking, emitResource, nonce, tags
415
567
  tags: replaceable
416
568
  });
417
569
  }
570
+ function headShellReady(registry, block) {
571
+ let ready = true;
572
+ const pends = err => {
573
+ const source = solidJs.ssrHandleError(err, true);
574
+ if (!source) return false;
575
+ block(source);
576
+ ready = false;
577
+ return true;
578
+ };
579
+ const parked = registry.parkedResources;
580
+ for (let i = parked.length - 1; i >= 0; i--) {
581
+ const {
582
+ desc,
583
+ rel,
584
+ emit
585
+ } = parked[i];
586
+ try {
587
+ evalHeadProps(desc.props || {}, rel !== undefined ? {
588
+ rel
589
+ } : undefined);
590
+ } catch (err) {
591
+ if (pends(err)) continue;
592
+ console.warn(`useHead: error evaluating resource tag props`, err);
593
+ parked.splice(i, 1);
594
+ continue;
595
+ }
596
+ parked.splice(i, 1);
597
+ emit();
598
+ }
599
+ for (let i = 0; i < registry.pending.length; i++) {
600
+ const reg = registry.pending[i];
601
+ if (reg.boundary !== "" || reg.list) continue;
602
+ for (let j = 0; j < reg.tags.length; j++) {
603
+ const desc = reg.tags[j];
604
+ try {
605
+ evalHeadProps(desc.props || {}, desc.rel !== undefined ? {
606
+ rel: desc.rel
607
+ } : undefined);
608
+ evalHeadValue(desc.key);
609
+ } catch (err) {
610
+ pends(err);
611
+ }
612
+ }
613
+ }
614
+ return ready;
615
+ }
418
616
  function emitHeadResource(registry, context, tracking, emitResource, nonce, desc, rel) {
419
617
  let props;
420
618
  try {
@@ -422,6 +620,16 @@ function emitHeadResource(registry, context, tracking, emitResource, nonce, desc
422
620
  rel
423
621
  } : undefined);
424
622
  } catch (err) {
623
+ const loadingPhase = solidJs.sharedConfig.context && solidJs.sharedConfig.context._loadingPhase;
624
+ if (loadingPhase && solidJs.ssrHandleError(err)) throw err;
625
+ if (!loadingPhase && !context._currentBoundaryId && !registry.shellFlushed && typeof context.block === "function" && solidJs.ssrHandleError(err, true)) {
626
+ registry.parkedResources.push({
627
+ desc,
628
+ rel,
629
+ emit: () => emitHeadResource(registry, context, tracking, emitResource, nonce, desc, rel)
630
+ });
631
+ return;
632
+ }
425
633
  console.warn(`useHead: error evaluating resource tag props`, err);
426
634
  return;
427
635
  }
@@ -764,7 +972,7 @@ function renderToStream(code, options = {}) {
764
972
  }
765
973
  },
766
974
  shell(shellHtml, meta) {
767
- buffer.write(assembleDocument(shellHtml, meta.assets, meta.preloads, meta.inlineStyles, meta.tasks.length ? meta.tasks : "", nonce, meta.head, onHead));
975
+ buffer.write(assembleDocument(shellHtml, meta.preloads, meta.inlineStyles, meta.tasks.length ? meta.tasks : "", nonce, meta.head, onHead));
768
976
  },
769
977
  ...options.sink
770
978
  };
@@ -844,7 +1052,6 @@ function renderToStream(code, options = {}) {
844
1052
  };
845
1053
  solidJs.sharedConfig.context = context = {
846
1054
  async: true,
847
- assets: [],
848
1055
  nonce,
849
1056
  registerHeadTags(tags) {
850
1057
  registerHeadTags(headRegistry, context, tracking,
@@ -1046,7 +1253,7 @@ function renderToStream(code, options = {}) {
1046
1253
  if (shellCompleted) return;
1047
1254
  solidJs.sharedConfig.context = context;
1048
1255
  if (!resolveRootHoles()) return;
1049
- const assetsHtml = resolveAssetsHtml(context.assets);
1256
+ if (!headShellReady(headRegistry, p => blockingPromises.add(p))) return;
1050
1257
  headStyles = new Set();
1051
1258
  for (const url of tracking.emittedAssets) {
1052
1259
  if (isCssUrl(url)) headStyles.add(url);
@@ -1054,7 +1261,6 @@ function renderToStream(code, options = {}) {
1054
1261
  serializeRootAssets();
1055
1262
  const head = renderShellHead(headRegistry, nonce, k => registry.has(k));
1056
1263
  sink.shell(html, {
1057
- assets: assetsHtml,
1058
1264
  preloads: tracking.emittedAssets,
1059
1265
  inlineStyles: tracking.inlineStyles,
1060
1266
  tasks,
@@ -1144,27 +1350,30 @@ function renderToStream(code, options = {}) {
1144
1350
  return p;
1145
1351
  };
1146
1352
  return {
1147
- then(fn) {
1148
- function complete() {
1149
- dispose();
1150
- fn(tmp);
1151
- }
1152
- if (onCompleteAll) {
1153
- let ogComplete = onCompleteAll;
1154
- onCompleteAll = options => {
1155
- ogComplete(options);
1156
- complete();
1157
- };
1158
- } else onCompleteAll = complete;
1159
- function flush() {
1160
- allSettled(blockingPromises).then(() => {
1161
- scheduleFlush(() => {
1162
- if (!resolveRootHoles()) return flush();
1163
- queue(flushEnd);
1353
+ then(onFulfilled, onRejected) {
1354
+ const p = new Promise(resolve => {
1355
+ function complete() {
1356
+ dispose();
1357
+ resolve(tmp);
1358
+ }
1359
+ if (onCompleteAll) {
1360
+ let ogComplete = onCompleteAll;
1361
+ onCompleteAll = options => {
1362
+ ogComplete(options);
1363
+ complete();
1364
+ };
1365
+ } else onCompleteAll = complete;
1366
+ function flush() {
1367
+ allSettled(blockingPromises).then(() => {
1368
+ scheduleFlush(() => {
1369
+ if (!resolveRootHoles() || !headShellReady(headRegistry, p => blockingPromises.add(p))) return flush();
1370
+ queue(flushEnd);
1371
+ });
1164
1372
  });
1165
- });
1166
- }
1167
- flush();
1373
+ }
1374
+ flush();
1375
+ });
1376
+ return p.then(onFulfilled, onRejected);
1168
1377
  },
1169
1378
  pipe(w) {
1170
1379
  claimConsumer("pipe");
@@ -1449,17 +1658,11 @@ function allSettled(promises) {
1449
1658
  return;
1450
1659
  });
1451
1660
  }
1452
- function resolveAssetsHtml(assets) {
1453
- if (!assets || !assets.length) return "";
1454
- let out = "";
1455
- for (let i = 0, len = assets.length; i < len; i++) out += assets[i]();
1456
- return out;
1457
- }
1458
- function assembleDocument(html, assetsHtml, emittedAssets, inlineStyles, scripts, nonce, headTags, onHead) {
1661
+ function assembleDocument(html, emittedAssets, inlineStyles, scripts, nonce, headTags, onHead) {
1459
1662
  const scriptTag = scripts ? `<script${nonce ? ` nonce="${nonce}"` : ""}>${scripts}</script>` : "";
1460
1663
  const headTagsHtml = headTags ? headTags.html : "";
1461
1664
  const headPrelude = headTags ? headTags.prelude : "";
1462
- if (!onHead && !assetsHtml && !headTagsHtml && !headPrelude && !(emittedAssets && emittedAssets.size) && !(inlineStyles && inlineStyles.size)) {
1665
+ if (!onHead && !headTagsHtml && !headPrelude && !(emittedAssets && emittedAssets.size) && !(inlineStyles && inlineStyles.size)) {
1463
1666
  if (!scriptTag) return html;
1464
1667
  const xs = html.indexOf("<!--xs-->");
1465
1668
  return xs === -1 ? html + scriptTag : html.slice(0, xs) + scriptTag + html.slice(xs);
@@ -1474,13 +1677,13 @@ function assembleDocument(html, assetsHtml, emittedAssets, inlineStyles, scripts
1474
1677
  const headIdx = html.indexOf("</head>");
1475
1678
  if (headIdx === -1) {
1476
1679
  if (onHead) {
1477
- onHead(headPrelude + headTagsHtml + (assetsHtml || "") + renderHeadAssets(emittedAssets, inlineStyles, nonce));
1680
+ onHead(headPrelude + headTagsHtml + renderHeadAssets(emittedAssets, inlineStyles, nonce));
1478
1681
  }
1479
1682
  if (!scriptTag) return html;
1480
1683
  const xs = html.indexOf("<!--xs-->");
1481
1684
  return xs === -1 ? html + scriptTag : html.slice(0, xs) + scriptTag + html.slice(xs);
1482
1685
  }
1483
- const head = headTagsHtml + (assetsHtml || "") + renderHeadAssets(emittedAssets, inlineStyles, nonce);
1686
+ const head = headTagsHtml + renderHeadAssets(emittedAssets, inlineStyles, nonce);
1484
1687
  if (!scriptTag) return html.slice(0, headIdx) + head + html.slice(headIdx);
1485
1688
  const xsIdx = html.indexOf("<!--xs-->");
1486
1689
  if (xsIdx === -1) return html.slice(0, headIdx) + head + html.slice(headIdx) + scriptTag;
@@ -1662,142 +1865,7 @@ function resolveSSRSync(node) {
1662
1865
  if (!res.h.length) return res.t[0];
1663
1866
  throw new Error("This value cannot be rendered synchronously. Are you missing a boundary?");
1664
1867
  }
1665
-
1666
- function frameAddress(id, args) {
1667
- return args && args.length ? id + ":" + hashArguments(args) : id;
1668
- }
1669
- function hashArguments(args) {
1670
- let hash = 0;
1671
- const text = stableString(args);
1672
- for (let i = 0; i < text.length; i++) {
1673
- hash = (hash << 5) - hash + text.charCodeAt(i);
1674
- hash |= 0;
1675
- }
1676
- return (hash >>> 0).toString(36);
1677
- }
1678
- function stableString(value, seen) {
1679
- if (value === null || typeof value !== "object") {
1680
- return typeof value === "bigint" ? value + "n" : String(value);
1681
- }
1682
- if (value instanceof Date) return "Date:" + value.getTime();
1683
- seen || (seen = new Set());
1684
- if (seen.has(value)) return "~";
1685
- seen.add(value);
1686
- if (value instanceof Map) {
1687
- const entries = [];
1688
- for (const [k, v] of value) {
1689
- entries.push(stableString(k, seen) + "=>" + stableString(v, seen));
1690
- }
1691
- return "Map{" + entries.sort().join(",") + "}";
1692
- }
1693
- if (value instanceof Set) {
1694
- const members = [];
1695
- for (const v of value) members.push(stableString(v, seen));
1696
- return "Set{" + members.sort().join(",") + "}";
1697
- }
1698
- if (Array.isArray(value)) {
1699
- let out = "[";
1700
- for (let i = 0; i < value.length; i++) out += (i ? "," : "") + stableString(value[i], seen);
1701
- return out + "]";
1702
- }
1703
- const keys = Object.keys(value).sort();
1704
- let out = "{";
1705
- for (let i = 0; i < keys.length; i++) {
1706
- out += (i ? "," : "") + keys[i] + ":" + stableString(value[keys[i]], seen);
1707
- }
1708
- return out + "}";
1709
- }
1710
- const SINGLE_FLIGHT_HEADER = "X-Single-Flight";
1711
- function createChunk(data) {
1712
- const encodeData = new TextEncoder().encode(data);
1713
- const bytes = encodeData.length;
1714
- const baseHex = bytes.toString(16);
1715
- const totalHex = "00000000".substring(0, 8 - baseHex.length) + baseHex;
1716
- const head = new TextEncoder().encode(`;0x${totalHex};`);
1717
- const chunk = new Uint8Array(12 + bytes);
1718
- chunk.set(head);
1719
- chunk.set(encodeData, 12);
1720
- return chunk;
1721
- }
1722
- class ChunkReader {
1723
- constructor(stream) {
1724
- this.reader = stream.getReader();
1725
- this.buffer = new Uint8Array(0);
1726
- this.done = false;
1727
- }
1728
- async readChunk() {
1729
- const chunk = await this.reader.read();
1730
- if (!chunk.done) {
1731
- const newBuffer = new Uint8Array(this.buffer.length + chunk.value.length);
1732
- newBuffer.set(this.buffer);
1733
- newBuffer.set(chunk.value, this.buffer.length);
1734
- this.buffer = newBuffer;
1735
- } else {
1736
- this.done = true;
1737
- }
1738
- }
1739
- async next() {
1740
- while (this.buffer.length < 12) {
1741
- if (this.done) {
1742
- if (this.buffer.length === 0) return {
1743
- done: true,
1744
- value: undefined
1745
- };
1746
- throw new Error("Malformed server function stream.");
1747
- }
1748
- await this.readChunk();
1749
- }
1750
- const head = new TextDecoder().decode(this.buffer.subarray(1, 11));
1751
- const bytes = Number.parseInt(head, 16);
1752
- if (Number.isNaN(bytes)) {
1753
- throw new Error("Malformed server function stream.");
1754
- }
1755
- while (bytes > this.buffer.length - 12) {
1756
- if (this.done) {
1757
- throw new Error("Malformed server function stream.");
1758
- }
1759
- await this.readChunk();
1760
- }
1761
- const partial = new TextDecoder().decode(this.buffer.subarray(12, 12 + bytes));
1762
- this.buffer = this.buffer.subarray(12 + bytes);
1763
- return {
1764
- done: false,
1765
- value: partial
1766
- };
1767
- }
1768
- async drain(interpret) {
1769
- while (true) {
1770
- const result = await this.next();
1771
- if (result.done) {
1772
- break;
1773
- }
1774
- interpret(result.value);
1775
- }
1776
- }
1777
- }
1778
- function serializeStream(value, codecOptions) {
1779
- return new ReadableStream({
1780
- start(controller) {
1781
- serializeJSON(value, {
1782
- ...codecOptions,
1783
- onParse(node) {
1784
- controller.enqueue(createChunk(JSON.stringify(node)));
1785
- },
1786
- onDone() {
1787
- controller.close();
1788
- },
1789
- onError(error) {
1790
- controller.error(error);
1791
- }
1792
- });
1793
- }
1794
- });
1795
- }
1796
-
1797
- const ENVELOPE = Symbol.for("solid.ResponseEnvelope");
1798
- function isResponseEnvelope(value) {
1799
- return !!(value && typeof value === "object" && value[ENVELOPE]);
1800
- }
1868
+ /*#__PURE__*/new Set([ERROR_HEADER, BODY_FORMAT_HEADER, SINGLE_FLIGHT_HEADER, REVALIDATE_HEADER, "Location"].map(header => header.toLowerCase()));
1801
1869
 
1802
1870
  const INVOCATIONS = new WeakMap();
1803
1871
  function getEventServerFunctionInvocation(event) {
@@ -1881,6 +1949,29 @@ function createFrameSink(emit, frame) {
1881
1949
  version
1882
1950
  } = frame;
1883
1951
  const styledKeys = new Set();
1952
+ const bindings = new Map();
1953
+ const sweepMinted = new Set();
1954
+ const argRefVersions = new Map();
1955
+ let sweepScheduled = false;
1956
+ let closed = false;
1957
+ let epoch = 0;
1958
+ const sweep = () => {
1959
+ epoch++;
1960
+ for (const b of [...bindings.values()]) {
1961
+ try {
1962
+ b.sweep();
1963
+ } catch (_) {
1964
+ }
1965
+ }
1966
+ };
1967
+ const scheduleSweep = () => {
1968
+ if (closed || sweepScheduled || !bindings.size) return;
1969
+ sweepScheduled = true;
1970
+ queueMicrotask(() => {
1971
+ sweepScheduled = false;
1972
+ if (!closed) sweep();
1973
+ });
1974
+ };
1884
1975
  const regionKeys = new Map();
1885
1976
  const frameOf = key => regionKeys.get(key) || id;
1886
1977
  return {
@@ -1922,6 +2013,7 @@ function createFrameSink(emit, frame) {
1922
2013
  version,
1923
2014
  payload: record
1924
2015
  });
2016
+ scheduleSweep();
1925
2017
  } else {
1926
2018
  emit({
1927
2019
  type: "data",
@@ -1931,6 +2023,7 @@ function createFrameSink(emit, frame) {
1931
2023
  node: record.node,
1932
2024
  initial: record.initial
1933
2025
  });
2026
+ if (!sweepMinted.has(record.key)) scheduleSweep();
1934
2027
  }
1935
2028
  },
1936
2029
  fragment(key, value, meta = {}) {
@@ -1967,6 +2060,7 @@ function createFrameSink(emit, frame) {
1967
2060
  key,
1968
2061
  html: value
1969
2062
  });
2063
+ scheduleSweep();
1970
2064
  if (meta.error) {
1971
2065
  emit({
1972
2066
  type: "error",
@@ -2021,6 +2115,8 @@ function createFrameSink(emit, frame) {
2021
2115
  });
2022
2116
  },
2023
2117
  end() {
2118
+ if (bindings.size) sweep();
2119
+ closed = true;
2024
2120
  emit({
2025
2121
  type: "complete",
2026
2122
  id,
@@ -2052,6 +2148,24 @@ function createFrameSink(emit, frame) {
2052
2148
  version,
2053
2149
  html
2054
2150
  });
2151
+ },
2152
+ openBinding(key, b) {
2153
+ bindings.set(key, b);
2154
+ },
2155
+ closeBinding(key) {
2156
+ bindings.delete(key);
2157
+ },
2158
+ mintRef(ref) {
2159
+ sweepMinted.add(ref);
2160
+ },
2161
+ nextArgRef(ledgerKey) {
2162
+ const n = (argRefVersions.get(ledgerKey) || 0) + 1;
2163
+ argRefVersions.set(ledgerKey, n);
2164
+ return n;
2165
+ },
2166
+ commit: scheduleSweep,
2167
+ get epoch() {
2168
+ return epoch;
2055
2169
  }
2056
2170
  };
2057
2171
  }
@@ -2061,7 +2175,14 @@ function renderToFrameStream(code, options = {}) {
2061
2175
  function renderServerComponent(component, options = {}) {
2062
2176
  return frameStream((sink, frame) => {
2063
2177
  const props = createSlotProps(sink, frame);
2064
- return () => serverComponentScope(() => component(props));
2178
+ return () => {
2179
+ const ctx = solidJs.sharedConfig.context;
2180
+ if (ctx) {
2181
+ ctx.commit = sink.commit;
2182
+ ctx.commitEpoch = () => sink.epoch;
2183
+ }
2184
+ return serverComponentScope(() => component(props));
2185
+ };
2065
2186
  }, options);
2066
2187
  }
2067
2188
  function frameStream(makeCode, options) {
@@ -2138,6 +2259,35 @@ function occurrenceId(prop, raw, counts) {
2138
2259
  counts[prop] = n + 1;
2139
2260
  return `${prop}#${n}`;
2140
2261
  }
2262
+ function isAsyncValue(v) {
2263
+ return !!v && typeof v === "object" && (typeof v.then === "function" || typeof v[Symbol.asyncIterator] === "function");
2264
+ }
2265
+ function tapFirstYield(iterable) {
2266
+ const iter = iterable[Symbol.asyncIterator]();
2267
+ const firstStep = Promise.resolve(iter.next());
2268
+ return {
2269
+ first: firstStep.then(r => r.done ? undefined : r.value),
2270
+ rest: {
2271
+ [Symbol.asyncIterator]() {
2272
+ let replayed = false;
2273
+ return {
2274
+ next: () => {
2275
+ if (!replayed) {
2276
+ replayed = true;
2277
+ return firstStep;
2278
+ }
2279
+ return iter.next();
2280
+ },
2281
+ return: v => iter.return ? iter.return(v) : Promise.resolve({
2282
+ done: true,
2283
+ value: v
2284
+ }),
2285
+ throw: e => iter.throw ? iter.throw(e) : Promise.reject(e)
2286
+ };
2287
+ }
2288
+ }
2289
+ };
2290
+ }
2141
2291
  function createDocumentSlotProps(clientProps, frameId) {
2142
2292
  const counts = Object.create(null);
2143
2293
  const getters = new Map();
@@ -2207,6 +2357,22 @@ function createDocumentSlotProps(clientProps, frameId) {
2207
2357
  t: FRAME_ELEMENT_CLOSE
2208
2358
  }];
2209
2359
  };
2360
+ } else if (ssrAsyncValue && isAsyncValue(value)) {
2361
+ let readable = value;
2362
+ if (typeof value.then !== "function") {
2363
+ const {
2364
+ first,
2365
+ rest
2366
+ } = tapFirstYield(value);
2367
+ readable = first;
2368
+ vals[key] = rest;
2369
+ }
2370
+ const read = ssrAsyncValue(readable);
2371
+ Object.defineProperty(resolved, key, {
2372
+ get: read,
2373
+ enumerable: true,
2374
+ configurable: true
2375
+ });
2210
2376
  } else {
2211
2377
  resolved[key] = value;
2212
2378
  }
@@ -2294,6 +2460,88 @@ function isServerContent(value) {
2294
2460
  }
2295
2461
  return false;
2296
2462
  }
2463
+ function unwrapThunks(value) {
2464
+ for (let d = 0; typeof value === "function" && d < 16; d++) value = value();
2465
+ return value;
2466
+ }
2467
+ function contentArgError(key, occurrence) {
2468
+ return new Error("Async slot arg resolved to JSX (arg '" + key + "' of " + occurrence + "). Async args must resolve to serializable values; render async content through a boundary instead.");
2469
+ }
2470
+ function retryArgUntilSettled(evaluate, blocked, key, occurrence, onSettle) {
2471
+ const owner = solidJs.getOwner();
2472
+ return new Promise((resolve, reject) => {
2473
+ const retry = () => {
2474
+ try {
2475
+ const value = owner ? solidJs.runWithOwner(owner, evaluate) : evaluate();
2476
+ if (isServerContent(value)) {
2477
+ reject(contentArgError(key, occurrence));
2478
+ return;
2479
+ }
2480
+ if (onSettle) onSettle(value);
2481
+ resolve(value);
2482
+ } catch (err) {
2483
+ const next = solidJs.ssrHandleError && solidJs.ssrHandleError(err);
2484
+ if (next) next.then(retry, retry);else reject(err);
2485
+ }
2486
+ };
2487
+ blocked.then(retry, retry);
2488
+ });
2489
+ }
2490
+ function openArgBinding(sink, ctx, occurrence, key, evaluate, args, state) {
2491
+ const owner = solidJs.getOwner();
2492
+ const ledgerKey = `${occurrence}:${key}`;
2493
+ const reEmit = value => {
2494
+ const ref = `arg:${occurrence}:${key}@${sink.nextArgRef(ledgerKey)}`;
2495
+ sink.mintRef(ref);
2496
+ ctx.serialize(ref, value);
2497
+ args[key] = {
2498
+ $ref: ref
2499
+ };
2500
+ sink.slot(occurrence, {
2501
+ ...args
2502
+ });
2503
+ };
2504
+ const binding = {
2505
+ sweep() {
2506
+ if (!state.settled) return;
2507
+ let value;
2508
+ try {
2509
+ value = owner ? solidJs.runWithOwner(owner, evaluate) : evaluate();
2510
+ } catch (err) {
2511
+ const blocked = solidJs.ssrHandleError && solidJs.ssrHandleError(err);
2512
+ if (!blocked) {
2513
+ sink.closeBinding(ledgerKey);
2514
+ reEmit(Promise.reject(err instanceof Error ? err : new Error(String(err))));
2515
+ return;
2516
+ }
2517
+ state.settled = false;
2518
+ reEmit(retryArgUntilSettled(evaluate, blocked, key, occurrence, v => {
2519
+ state.settled = true;
2520
+ state.last = v;
2521
+ sink.commit();
2522
+ }));
2523
+ return;
2524
+ }
2525
+ if (value === state.last) return;
2526
+ state.last = value;
2527
+ if (isServerContent(value)) {
2528
+ sink.closeBinding(ledgerKey);
2529
+ reEmit(Promise.reject(contentArgError(key, occurrence)));
2530
+ return;
2531
+ }
2532
+ const t = typeof value;
2533
+ if (value == null || t === "string" || t === "number" || t === "boolean") {
2534
+ args[key] = value;
2535
+ sink.slot(occurrence, {
2536
+ ...args
2537
+ });
2538
+ } else {
2539
+ reEmit(value);
2540
+ }
2541
+ }
2542
+ };
2543
+ sink.openBinding(ledgerKey, binding);
2544
+ }
2297
2545
  function createSlotProps(sink, frame) {
2298
2546
  const counts = Object.create(null);
2299
2547
  const getters = new Map();
@@ -2313,6 +2561,7 @@ function createSlotProps(sink, frame) {
2313
2561
  const raw = callArgs[0];
2314
2562
  const occurrence = occurrenceId(prop, raw, counts);
2315
2563
  const args = {};
2564
+ const opened = [];
2316
2565
  for (const key of Object.keys(raw)) {
2317
2566
  if (key === "$key") continue;
2318
2567
  const childId = `${frame.id}.${occurrence}.${key}`;
@@ -2323,11 +2572,44 @@ function createSlotProps(sink, frame) {
2323
2572
  return origRegister.call(ctx, fragKey, fragOptions);
2324
2573
  };
2325
2574
  try {
2326
- let value = raw[key];
2327
- for (let d = 0; typeof value === "function" && d < 16; d++) value = value();
2575
+ const desc = Object.getOwnPropertyDescriptor(raw, key);
2576
+ let evaluate = null;
2577
+ let value;
2578
+ let state = null;
2579
+ try {
2580
+ if (desc.get) {
2581
+ const get = desc.get;
2582
+ evaluate = () => unwrapThunks(get.call(raw));
2583
+ value = evaluate();
2584
+ } else {
2585
+ value = desc.value;
2586
+ if (typeof value === "function") {
2587
+ const fn = value;
2588
+ evaluate = () => unwrapThunks(fn);
2589
+ value = evaluate();
2590
+ }
2591
+ }
2592
+ } catch (err) {
2593
+ const blocked = solidJs.ssrHandleError && solidJs.ssrHandleError(err);
2594
+ if (!blocked) throw err;
2595
+ state = {
2596
+ settled: false,
2597
+ last: undefined
2598
+ };
2599
+ const pendingState = state;
2600
+ value = retryArgUntilSettled(evaluate, blocked, key, occurrence, v => {
2601
+ pendingState.settled = true;
2602
+ pendingState.last = v;
2603
+ sink.commit();
2604
+ });
2605
+ }
2328
2606
  const t = typeof value;
2329
2607
  if (value == null || t === "string" || t === "number" || t === "boolean") {
2330
2608
  args[key] = value;
2609
+ if (evaluate) state = {
2610
+ settled: true,
2611
+ last: value
2612
+ };
2331
2613
  } else if (isServerContent(value)) {
2332
2614
  const resolved = ctx.resolve(value);
2333
2615
  if (resolved.h.length) {
@@ -2343,12 +2625,27 @@ function createSlotProps(sink, frame) {
2343
2625
  args[key] = {
2344
2626
  $ref: ref
2345
2627
  };
2628
+ if (evaluate && !state) state = {
2629
+ settled: true,
2630
+ last: value
2631
+ };
2346
2632
  }
2633
+ if (evaluate && state) opened.push({
2634
+ key,
2635
+ evaluate,
2636
+ state
2637
+ });
2347
2638
  } finally {
2348
2639
  ctx.registerFragment = origRegister;
2349
2640
  }
2350
2641
  }
2351
- sink.slot(occurrence, args);
2642
+ sink.slot(occurrence, {
2643
+ ...args
2644
+ });
2645
+ const ctx = solidJs.sharedConfig.context;
2646
+ for (const b of opened) {
2647
+ openArgBinding(sink, ctx, occurrence, b.key, b.evaluate, args, b.state);
2648
+ }
2352
2649
  return slotRange(occurrence);
2353
2650
  };
2354
2651
  getters.set(prop, fn);
@@ -2357,12 +2654,21 @@ function createSlotProps(sink, frame) {
2357
2654
  }
2358
2655
  });
2359
2656
  }
2657
+ function copyInitHeaders(init) {
2658
+ if (!init || !init.getSetCookie) return new Headers(init);
2659
+ const headers = new Headers();
2660
+ init.forEach((value, key) => {
2661
+ if (key !== "set-cookie") headers.append(key, value);
2662
+ });
2663
+ for (const cookie of init.getSetCookie()) headers.append("Set-Cookie", cookie);
2664
+ return headers;
2665
+ }
2360
2666
  function serverComponentResponse(component, options = {}, init = {}) {
2361
2667
  const {
2362
2668
  id = "",
2363
2669
  version = 1
2364
2670
  } = options.frame || {};
2365
- const headers = new Headers(init.headers);
2671
+ const headers = copyInitHeaders(init.headers);
2366
2672
  headers.set("Content-Type", "application/x-frame-stream");
2367
2673
  headers.set(FRAME_STREAM_HEADER, id);
2368
2674
  headers.set("X-Content-Raw", "1");
@@ -2461,7 +2767,7 @@ function frameFlightResponse({
2461
2767
  codec
2462
2768
  }, init = {}) {
2463
2769
  const frames = primary ? [primary, ...regions] : regions;
2464
- const headers = new Headers(init.headers);
2770
+ const headers = copyInitHeaders(init.headers);
2465
2771
  headers.set("Content-Type", "application/x-frame-stream");
2466
2772
  headers.set(FRAME_STREAM_HEADER, primary ? primary.id : "");
2467
2773
  headers.set("X-Content-Raw", "1");
@@ -2507,9 +2813,14 @@ function frameFlightResponse({
2507
2813
  });
2508
2814
  }
2509
2815
 
2816
+ function asyncArg(value) {
2817
+ return value;
2818
+ }
2819
+
2510
2820
  exports.FRAME_STREAM_HEADER = FRAME_STREAM_HEADER;
2511
2821
  exports.SERVER_COMPONENT_BOOTSTRAP = SERVER_COMPONENT_BOOTSTRAP;
2512
2822
  exports.ServerComponentPlugin = ServerComponentPlugin;
2823
+ exports.asyncArg = asyncArg;
2513
2824
  exports.createFrameSink = createFrameSink;
2514
2825
  exports.frameTransformDirectResult = frameTransformDirectResult;
2515
2826
  exports.frameTransformFlightResult = frameTransformFlightResult;