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