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

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 (73) hide show
  1. package/README.md +1 -6
  2. package/dist/dev.cjs +285 -60
  3. package/dist/dev.js +267 -57
  4. package/dist/server.cjs +1148 -176
  5. package/dist/server.js +1133 -175
  6. package/dist/web.cjs +285 -60
  7. package/dist/web.js +267 -57
  8. package/frames/dist/client.cjs +397 -175
  9. package/frames/dist/client.dev.cjs +401 -175
  10. package/frames/dist/client.dev.js +399 -173
  11. package/frames/dist/client.js +395 -173
  12. package/frames/dist/server.cjs +1424 -277
  13. package/frames/dist/server.js +1426 -280
  14. package/package.json +69 -7
  15. package/serialization/decode/package.json +20 -0
  16. package/serialization/dist/decode.cjs +110 -0
  17. package/serialization/dist/decode.js +104 -0
  18. package/serialization/dist/serialization.cjs +106 -43
  19. package/serialization/dist/serialization.js +100 -44
  20. package/serialization/types/index.d.ts +85 -60
  21. package/serialization/types/serializer-decode.d.ts +182 -0
  22. package/serialization/types-cjs/index.d.cts +85 -60
  23. package/serialization/types-cjs/serializer-decode.d.cts +182 -0
  24. package/server-functions/dist/client.cjs +131 -98
  25. package/server-functions/dist/client.js +131 -99
  26. package/server-functions/dist/rich-args.cjs +11 -0
  27. package/server-functions/dist/rich-args.js +9 -0
  28. package/server-functions/dist/server.cjs +367 -194
  29. package/server-functions/dist/server.dev.cjs +1077 -0
  30. package/server-functions/dist/server.dev.js +1045 -0
  31. package/server-functions/dist/server.js +365 -195
  32. package/server-functions/package.json +10 -0
  33. package/server-functions/rich-args/package.json +20 -0
  34. package/storage/types/index.d.ts +1 -1
  35. package/storage/types-cjs/index.d.cts +1 -1
  36. package/types/client.d.ts +149 -6
  37. package/types/cookies.d.ts +93 -0
  38. package/types/core.d.ts +4 -2
  39. package/types/frames/client.d.ts +15 -1
  40. package/types/frames/frame-client.d.ts +63 -7
  41. package/types/frames/frame-sink.d.ts +26 -3
  42. package/types/frames/frame-transport.d.ts +40 -8
  43. package/types/frames/serializer.d.ts +85 -60
  44. package/types/frames/server.d.ts +22 -0
  45. package/types/index.d.ts +2 -3
  46. package/types/response.d.ts +45 -0
  47. package/types/serializer-decode.d.ts +182 -0
  48. package/types/serializer.d.ts +85 -60
  49. package/types/server-functions/client.d.ts +2 -1
  50. package/types/server-functions/rich-args.d.ts +10 -0
  51. package/types/server-functions/server.d.ts +99 -1
  52. package/types/server-functions/shared.d.ts +79 -1
  53. package/types/server-mock.d.ts +171 -59
  54. package/types/server.d.ts +209 -37
  55. package/types-cjs/client.d.cts +149 -6
  56. package/types-cjs/cookies.d.cts +93 -0
  57. package/types-cjs/core.d.cts +4 -2
  58. package/types-cjs/frames/client.d.cts +15 -1
  59. package/types-cjs/frames/frame-client.d.cts +63 -7
  60. package/types-cjs/frames/frame-sink.d.cts +26 -3
  61. package/types-cjs/frames/frame-transport.d.cts +40 -8
  62. package/types-cjs/frames/serializer.d.cts +85 -60
  63. package/types-cjs/frames/server.d.cts +22 -0
  64. package/types-cjs/index.d.cts +2 -3
  65. package/types-cjs/response.d.cts +45 -0
  66. package/types-cjs/serializer-decode.d.cts +182 -0
  67. package/types-cjs/serializer.d.cts +85 -60
  68. package/types-cjs/server-functions/client.d.cts +2 -1
  69. package/types-cjs/server-functions/rich-args.d.cts +10 -0
  70. package/types-cjs/server-functions/server.d.cts +99 -1
  71. package/types-cjs/server-functions/shared.d.cts +79 -1
  72. package/types-cjs/server-mock.d.cts +171 -59
  73. package/types-cjs/server.d.cts +209 -37
package/dist/server.cjs CHANGED
@@ -64,15 +64,74 @@ const effect = (fn, effectFn, options) => solidJs.createRenderEffect(fn, effectF
64
64
  } : transparentOptions);
65
65
  const memo = fn => solidJs.createMemo(() => fn(), syncOptions);
66
66
 
67
- const DEFAULT_DISABLED_FEATURES = seroval.Feature.AggregateError | seroval.Feature.BigIntTypedArray;
68
- const serializeOnlyDisabledFeatures = () => process.env.NODE_ENV === "development" ? 0 : seroval.Feature.ErrorPrototypeStack;
69
- const HYDRATION_GLOBAL = "_$HY.r";
67
+ const STATE = Symbol.for("dom-expressions.container-trace-state");
68
+ const state = globalThis[STATE] || (globalThis[STATE] = {
69
+ materialized: new WeakMap(),
70
+ materializedValues: new WeakSet()
71
+ });
72
+ function setContainerTraceResolver(fn) {
73
+ state.resolveTrace = fn;
74
+ }
75
+ const TRACE = Symbol.for("dom-expressions.container-trace");
76
+ function materialize(marker) {
77
+ let value = state.materialized.get(marker.$tr);
78
+ if (value === undefined) {
79
+ value = state.materializeTrace(marker);
80
+ state.materialized.set(marker.$tr, value);
81
+ if (value !== null && typeof value === "object") state.materializedValues.add(value);
82
+ }
83
+ return value;
84
+ }
85
+ function parseTrace(value, ctx) {
86
+ const trace = value[TRACE];
87
+ return {
88
+ a: trace.array ? 1 : 0,
89
+ i: ctx.parse(trace.subscribe())
90
+ };
91
+ }
92
+ const ContainerTracePlugin = {
93
+ tag: "dom-expressions/container-trace",
94
+ test(value) {
95
+ return value != null && typeof value === "object" && TRACE in value;
96
+ },
97
+ parse: {
98
+ sync() {
99
+ throw new Error("A reactive container can only be serialized by a streaming serializer.");
100
+ },
101
+ async async(value, ctx) {
102
+ const trace = value[TRACE];
103
+ return {
104
+ a: trace.array ? 1 : 0,
105
+ i: await ctx.parse(trace.subscribe())
106
+ };
107
+ },
108
+ stream: parseTrace
109
+ },
110
+ serialize(node, ctx) {
111
+ return "{$tr:" + ctx.serialize(node.i) + ",$ta:" + node.a + "}";
112
+ },
113
+ deserialize(node, ctx) {
114
+ const iterable = ctx.deserialize(node.i);
115
+ const marker = {
116
+ $tr: iterable,
117
+ $ta: node.a
118
+ };
119
+ return state.materializeTrace ? materialize(marker) : marker;
120
+ }
121
+ };
122
+
70
123
  const DEFAULT_WEB_PLUGINS = Object.freeze([web.AbortSignalPlugin,
71
124
  web.CustomEventPlugin, web.DOMExceptionPlugin, web.EventPlugin,
72
- web.FormDataPlugin, web.HeadersPlugin, web.ReadableStreamPlugin, web.RequestPlugin, web.ResponsePlugin, web.URLSearchParamsPlugin, web.URLPlugin]);
125
+ web.FormDataPlugin, web.HeadersPlugin, web.ReadableStreamPlugin, web.RequestPlugin, web.ResponsePlugin, web.URLSearchParamsPlugin, web.URLPlugin,
126
+ ContainerTracePlugin]);
73
127
  function resolveSerializerPlugins(customPlugins) {
74
128
  return customPlugins ? [...customPlugins, ...DEFAULT_WEB_PLUGINS] : [...DEFAULT_WEB_PLUGINS];
75
129
  }
130
+ seroval.Feature.RegExp;
131
+
132
+ const DEFAULT_DISABLED_FEATURES = seroval.Feature.AggregateError | seroval.Feature.BigIntTypedArray;
133
+ const serializeOnlyDisabledFeatures = () => process.env.NODE_ENV === "development" ? 0 : seroval.Feature.ErrorPrototypeStack;
134
+ const HYDRATION_GLOBAL = "_$HY.r";
76
135
  function createSerializer(options) {
77
136
  return new seroval.Serializer({
78
137
  ...options,
@@ -99,7 +158,166 @@ function createHydrationSerializer({
99
158
  function getLocalHeaderScript(id) {
100
159
  return seroval.getCrossReferenceHeader(id) + ";";
101
160
  }
102
- seroval.Feature.RegExp;
161
+
162
+ const ENVELOPE = Symbol.for("solid.ResponseEnvelope");
163
+ // PURE-annotated factory (same convention as solid's MockPromise): the brand
164
+ const ResponseEnvelope = /* @__PURE__ */(() => {
165
+ class ResponseEnvelope {
166
+ constructor(response, value) {
167
+ this.response = response;
168
+ this.value = value;
169
+ }
170
+ }
171
+ ResponseEnvelope.prototype[ENVELOPE] = true;
172
+ return ResponseEnvelope;
173
+ })();
174
+ function isResponseEnvelope(value) {
175
+ return !!(value && typeof value === "object" && value[ENVELOPE]);
176
+ }
177
+ const HREF = Symbol.for("solid.Href");
178
+ function isHref(value) {
179
+ return !!(value && (typeof value === "object" || typeof value === "function") && value[HREF]);
180
+ }
181
+ const SAFE_ERROR = Symbol.for("solid.SafeError");
182
+ function markSafeError(error) {
183
+ if (error && (typeof error === "object" || typeof error === "function")) {
184
+ Object.defineProperty(error, SAFE_ERROR, {
185
+ value: true,
186
+ enumerable: false,
187
+ configurable: true
188
+ });
189
+ }
190
+ return error;
191
+ }
192
+ function isSafeError(value) {
193
+ return !!(value && (typeof value === "object" || typeof value === "function") && value[SAFE_ERROR]);
194
+ }
195
+ const REVALIDATE_HEADER = "X-Revalidate";
196
+ function initWithRevalidate(init) {
197
+ const {
198
+ revalidate,
199
+ ...responseInit
200
+ } = init;
201
+ let headers;
202
+ if (responseInit.headers && responseInit.headers.getSetCookie) {
203
+ headers = new Headers();
204
+ responseInit.headers.forEach((value, key) => {
205
+ if (key !== "set-cookie") headers.append(key, value);
206
+ });
207
+ for (const cookie of responseInit.headers.getSetCookie()) {
208
+ headers.append("Set-Cookie", cookie);
209
+ }
210
+ } else {
211
+ headers = new Headers(responseInit.headers);
212
+ }
213
+ revalidate !== undefined && headers.set(REVALIDATE_HEADER, revalidate.toString());
214
+ return {
215
+ responseInit,
216
+ headers
217
+ };
218
+ }
219
+ function redirect(url, init = 302) {
220
+ if (typeof url !== "string" && !isHref(url)) {
221
+ throw new TypeError("redirect() expects a string URL or an Href-branded value (Symbol.for('solid.Href')).");
222
+ }
223
+ const {
224
+ responseInit,
225
+ headers
226
+ } = initWithRevalidate(typeof init === "number" ? {
227
+ status: init
228
+ } : init);
229
+ if (responseInit.status === undefined) {
230
+ responseInit.status = 302;
231
+ }
232
+ headers.set("Location", String(url));
233
+ return new Response(null, {
234
+ ...responseInit,
235
+ headers
236
+ });
237
+ }
238
+ function reload(init = {}) {
239
+ const {
240
+ responseInit,
241
+ headers
242
+ } = initWithRevalidate(init);
243
+ return new Response(null, {
244
+ ...responseInit,
245
+ headers
246
+ });
247
+ }
248
+ function respond(value, init = {}) {
249
+ const {
250
+ responseInit,
251
+ headers
252
+ } = initWithRevalidate(init);
253
+ headers.set("Content-Type", "application/json");
254
+ return new ResponseEnvelope(new Response(JSON.stringify(value), {
255
+ ...responseInit,
256
+ headers
257
+ }), value);
258
+ }
259
+
260
+ const SERVER_FUNCTION_METADATA = Symbol.for("solid.ServerFunctionMetadata");
261
+ function getServerFunctionMetadata(fn) {
262
+ if (typeof fn !== "function") return undefined;
263
+ return fn[SERVER_FUNCTION_METADATA] || undefined;
264
+ }
265
+ function isServerFunction(fn) {
266
+ return typeof fn === "function" && !!fn[SERVER_FUNCTION_METADATA];
267
+ }
268
+ const SERVER_FUNCTION_RPC = Symbol.for("solid.ServerFunctionRPC");
269
+ function getServerFunctionRPC() {
270
+ return globalThis[SERVER_FUNCTION_RPC];
271
+ }
272
+
273
+ function parseCookieHeader(header) {
274
+ const cookies = {};
275
+ if (!header) return cookies;
276
+ for (const part of header.split(";")) {
277
+ const eq = part.indexOf("=");
278
+ if (eq < 0) continue;
279
+ const name = decodeSafe(part.slice(0, eq).trim());
280
+ let value = part.slice(eq + 1).trim();
281
+ if (value.length > 1 && value[0] === '"' && value[value.length - 1] === '"') {
282
+ value = value.slice(1, -1);
283
+ }
284
+ cookies[name] = decodeSafe(value);
285
+ }
286
+ return cookies;
287
+ }
288
+ function decodeSafe(text) {
289
+ try {
290
+ return decodeURIComponent(text);
291
+ } catch {
292
+ return text;
293
+ }
294
+ }
295
+ function serializeCookie(name, value, options = {}) {
296
+ let cookie = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;
297
+ cookie += `; Path=${options.path === undefined ? "/" : options.path}`;
298
+ if (options.domain) cookie += `; Domain=${options.domain}`;
299
+ if (options.maxAge !== undefined) cookie += `; Max-Age=${Math.trunc(options.maxAge)}`;
300
+ if (options.expires) cookie += `; Expires=${options.expires.toUTCString()}`;
301
+ if (options.httpOnly) cookie += "; HttpOnly";
302
+ if (options.secure) cookie += "; Secure";
303
+ if (options.sameSite) {
304
+ const sameSite = options.sameSite.toLowerCase();
305
+ cookie += `; SameSite=${sameSite === "none" ? "None" : sameSite === "strict" ? "Strict" : "Lax"}`;
306
+ }
307
+ return cookie;
308
+ }
309
+ const FLASH_COOKIE = "flash";
310
+ const FLASH_MATCHER = new RegExp(`(?:^|;\\s*)${FLASH_COOKIE}=([^;]+)`);
311
+ function hasFlashCookie(cookieHeader) {
312
+ return !!cookieHeader && FLASH_MATCHER.test(cookieHeader);
313
+ }
314
+ function clearFlashCookie() {
315
+ return `${FLASH_COOKIE}=; Max-Age=0; Path=/`;
316
+ }
317
+
318
+ const ERROR_HEADER = "X-Server-Function-Error";
319
+ const BODY_FORMAT_HEADER = "X-Server-Function-Format";
320
+ const SINGLE_FLIGHT_HEADER = "X-Single-Flight";
103
321
 
104
322
  const HEAD_ELIGIBLE_TAGS = new Set(["title", "meta", "link", "style", "script", "base"]);
105
323
  const HEAD_ATTR_NAME = /^[a-zA-Z_][a-zA-Z0-9_:.-]*$/;
@@ -171,7 +389,6 @@ function resolveHead(groups) {
171
389
  }
172
390
  for (const [identity, tags] of byIdentity) {
173
391
  if (identity === "title") {
174
- if (tags.length > 1) console.warn("Multiple <title> tags in one head group; the last one wins.");
175
392
  winners.set(identity, {
176
393
  seq: group.seq,
177
394
  tags: [tags[tags.length - 1]]
@@ -341,7 +558,8 @@ function createHeadRegistry() {
341
558
  resources: new Set(),
342
559
  eagerHtml: "",
343
560
  flushed: null,
344
- shellFlushed: false
561
+ shellFlushed: false,
562
+ parkedResources: []
345
563
  };
346
564
  }
347
565
  function registerHeadTags(registry, context, tracking, emitResource, nonce, tags) {
@@ -355,14 +573,24 @@ function registerHeadTags(registry, context, tracking, emitResource, nonce, tags
355
573
  return;
356
574
  }
357
575
  if (!Array.isArray(tags)) tags = [tags];
576
+ const probe = solidJs.sharedConfig.context && solidJs.sharedConfig.context._loadingPhase;
358
577
  let replaceable = null;
359
578
  for (let i = 0; i < tags.length; i++) {
360
579
  const desc = tags[i];
361
580
  if (!desc || !HEAD_ELIGIBLE_TAGS.has(desc.tag)) {
362
- console.warn(`useHead: ignoring non-head tag`, desc);
363
581
  continue;
364
582
  }
365
583
  const cls = classifyHeadTag(desc);
584
+ if (probe && !cls.resource) {
585
+ try {
586
+ evalHeadProps(desc.props || {}, cls.rel !== undefined ? {
587
+ rel: cls.rel
588
+ } : undefined);
589
+ evalHeadValue(desc.key);
590
+ } catch (err) {
591
+ if (solidJs.ssrHandleError(err)) throw err;
592
+ }
593
+ }
366
594
  if (cls.resource) {
367
595
  emitHeadResource(registry, context, tracking, emitResource, nonce, desc, cls.rel);
368
596
  } else {
@@ -379,6 +607,51 @@ function registerHeadTags(registry, context, tracking, emitResource, nonce, tags
379
607
  tags: replaceable
380
608
  });
381
609
  }
610
+ function headShellReady(registry, block) {
611
+ let ready = true;
612
+ const pends = err => {
613
+ const source = solidJs.ssrHandleError(err, true);
614
+ if (!source) return false;
615
+ block(source);
616
+ ready = false;
617
+ return true;
618
+ };
619
+ const parked = registry.parkedResources;
620
+ for (let i = parked.length - 1; i >= 0; i--) {
621
+ const {
622
+ desc,
623
+ rel,
624
+ emit
625
+ } = parked[i];
626
+ try {
627
+ evalHeadProps(desc.props || {}, rel !== undefined ? {
628
+ rel
629
+ } : undefined);
630
+ } catch (err) {
631
+ if (pends(err)) continue;
632
+ parked.splice(i, 1);
633
+ continue;
634
+ }
635
+ parked.splice(i, 1);
636
+ emit();
637
+ }
638
+ for (let i = 0; i < registry.pending.length; i++) {
639
+ const reg = registry.pending[i];
640
+ if (reg.boundary !== "" || reg.list) continue;
641
+ for (let j = 0; j < reg.tags.length; j++) {
642
+ const desc = reg.tags[j];
643
+ try {
644
+ evalHeadProps(desc.props || {}, desc.rel !== undefined ? {
645
+ rel: desc.rel
646
+ } : undefined);
647
+ evalHeadValue(desc.key);
648
+ } catch (err) {
649
+ pends(err);
650
+ }
651
+ }
652
+ }
653
+ return ready;
654
+ }
382
655
  function emitHeadResource(registry, context, tracking, emitResource, nonce, desc, rel) {
383
656
  let props;
384
657
  try {
@@ -386,7 +659,16 @@ function emitHeadResource(registry, context, tracking, emitResource, nonce, desc
386
659
  rel
387
660
  } : undefined);
388
661
  } catch (err) {
389
- console.warn(`useHead: error evaluating resource tag props`, err);
662
+ const loadingPhase = solidJs.sharedConfig.context && solidJs.sharedConfig.context._loadingPhase;
663
+ if (loadingPhase && solidJs.ssrHandleError(err)) throw err;
664
+ if (!loadingPhase && !context._currentBoundaryId && !registry.shellFlushed && typeof context.block === "function" && solidJs.ssrHandleError(err, true)) {
665
+ registry.parkedResources.push({
666
+ desc,
667
+ rel,
668
+ emit: () => emitHeadResource(registry, context, tracking, emitResource, nonce, desc, rel)
669
+ });
670
+ return;
671
+ }
390
672
  return;
391
673
  }
392
674
  const identity = resourceIdentity(desc.tag, props);
@@ -448,7 +730,6 @@ function commitHeadBoundary(registry, boundary, isPendingFragment) {
448
730
  try {
449
731
  resolved = reg.list();
450
732
  } catch (err) {
451
- console.warn(`useHead: error evaluating head group membership`, err);
452
733
  continue;
453
734
  }
454
735
  if (!Array.isArray(resolved)) resolved = [resolved];
@@ -456,7 +737,6 @@ function commitHeadBoundary(registry, boundary, isPendingFragment) {
456
737
  for (let j = 0; j < resolved.length; j++) {
457
738
  const desc = resolved[j];
458
739
  if (!desc || !HEAD_ELIGIBLE_TAGS.has(desc.tag)) {
459
- console.warn(`useHead: ignoring non-head tag`, desc);
460
740
  continue;
461
741
  }
462
742
  const cls = classifyHeadTag(desc);
@@ -482,12 +762,10 @@ function commitHeadBoundary(registry, boundary, isPendingFragment) {
482
762
  } : undefined);
483
763
  key = evalHeadValue(desc.key);
484
764
  } catch (err) {
485
- console.warn(`useHead: error evaluating tag props`, err);
486
765
  continue;
487
766
  }
488
767
  const identity = replaceableIdentity(desc.tag, props, key, "u:" + registry.uniq++);
489
768
  if ((identity === "base" || identity === "charset") && registry.shellFlushed) {
490
- console.warn(`useHead: <${desc.tag}> (${identity}) registered after shell flush is ignored`);
491
769
  continue;
492
770
  }
493
771
  tags.push({
@@ -569,7 +847,6 @@ function flushHeadFragment(registry, boundary) {
569
847
  for (const name in t.props) {
570
848
  if (name === "children" || name === "ref" || name.slice(0, 2) === "on") continue;
571
849
  if (!HEAD_ATTR_NAME.test(name)) {
572
- console.warn(`useHead: ignoring invalid attribute name "${name}"`);
573
850
  continue;
574
851
  }
575
852
  const v = t.props[name];
@@ -587,7 +864,6 @@ function renderHeadAttrHtml(props) {
587
864
  for (const name in props) {
588
865
  if (name === "children" || name === "ref" || name.slice(0, 2) === "on") continue;
589
866
  if (!HEAD_ATTR_NAME.test(name)) {
590
- console.warn(`useHead: ignoring invalid attribute name "${name}"`);
591
867
  continue;
592
868
  }
593
869
  const v = props[name];
@@ -620,7 +896,6 @@ function renderHeadTagMarkup(tag, props, identity, nonce) {
620
896
  function useHead(tags) {
621
897
  const ctx = solidJs.sharedConfig.context;
622
898
  if (!ctx || !ctx.registerHeadTags) {
623
- console.warn("useHead() called outside of a server render; registration ignored.");
624
899
  return;
625
900
  }
626
901
  ctx.registerHeadTags(tags);
@@ -652,7 +927,6 @@ function renderToString(code, options = {}) {
652
927
  const tracking = createAssetTracking();
653
928
  const headRegistry = createHeadRegistry();
654
929
  solidJs.sharedConfig.context = {
655
- assets: [],
656
930
  nonce,
657
931
  escape: escape,
658
932
  resolve: resolveSSRNode,
@@ -694,9 +968,8 @@ function renderToString(code, options = {}) {
694
968
  serializeFragmentAssets("", tracking.boundaryModules, solidJs.sharedConfig.context);
695
969
  solidJs.sharedConfig.context.noHydrate = true;
696
970
  serializer.close();
697
- const assetsHtml = resolveAssetsHtml(solidJs.sharedConfig.context.assets);
698
971
  const head = renderShellHead(headRegistry, nonce, null);
699
- return assembleDocument(html, assetsHtml, tracking.emittedAssets, tracking.inlineStyles, scripts.length ? scripts : "", nonce, head, onHead);
972
+ return assembleDocument(html, tracking.emittedAssets, tracking.inlineStyles, scripts.length ? scripts : "", nonce, head, onHead);
700
973
  }
701
974
  function renderToStream(code, options = {}) {
702
975
  let {
@@ -726,6 +999,12 @@ function renderToStream(code, options = {}) {
726
999
  d();
727
1000
  }
728
1001
  };
1002
+ const failRender = err => {
1003
+ try {
1004
+ options.onError ? options.onError(err) : console.error(err);
1005
+ } catch (_) {}
1006
+ abandon();
1007
+ };
729
1008
  const guardSink = w => ({
730
1009
  write(payload) {
731
1010
  if (dead) return;
@@ -807,7 +1086,7 @@ function renderToStream(code, options = {}) {
807
1086
  }
808
1087
  },
809
1088
  shell(shellHtml, meta) {
810
- buffer.write(assembleDocument(shellHtml, meta.assets, meta.preloads, meta.inlineStyles, meta.tasks.length ? meta.tasks : "", nonce, meta.head, onHead));
1089
+ buffer.write(assembleDocument(shellHtml, meta.preloads, meta.inlineStyles, meta.tasks.length ? meta.tasks : "", nonce, meta.head, onHead));
811
1090
  },
812
1091
  ...options.sink
813
1092
  };
@@ -824,10 +1103,18 @@ function renderToStream(code, options = {}) {
824
1103
  rootAssetsSerialized = true;
825
1104
  serializeFragmentAssets("", tracking.boundaryModules, context);
826
1105
  };
1106
+ let holds = 0;
827
1107
  const flushEnd = () => {
828
- if (!registry.size) {
1108
+ if (!registry.size && !holds) {
829
1109
  serializeRootAssets();
830
- queue(() => queue(() => serializer.flush()));
1110
+ queue(() => queue(() => {
1111
+ if (context.live.end) {
1112
+ const end = context.live.end;
1113
+ context.live.end = null;
1114
+ end();
1115
+ }
1116
+ serializer.flush();
1117
+ }));
831
1118
  }
832
1119
  };
833
1120
  const registry = new Map();
@@ -887,8 +1174,8 @@ function renderToStream(code, options = {}) {
887
1174
  };
888
1175
  solidJs.sharedConfig.context = context = {
889
1176
  async: true,
890
- assets: [],
891
1177
  nonce,
1178
+ live: {},
892
1179
  registerHeadTags(tags) {
893
1180
  registerHeadTags(headRegistry, context, tracking,
894
1181
  (markup, gateEntry) => {
@@ -925,6 +1212,16 @@ function renderToStream(code, options = {}) {
925
1212
  block(p) {
926
1213
  if (!firstFlushed) blockingPromises.add(p);
927
1214
  },
1215
+ hold() {
1216
+ holds++;
1217
+ let released = false;
1218
+ return () => {
1219
+ if (released) return;
1220
+ released = true;
1221
+ holds--;
1222
+ if (!holds) queue(flushEnd);
1223
+ };
1224
+ },
928
1225
  replace(id, payloadFn) {
929
1226
  if (firstFlushed) return;
930
1227
  const placeholder = `<!--!$${id}-->`;
@@ -1033,6 +1330,7 @@ function renderToStream(code, options = {}) {
1033
1330
  }
1034
1331
  };
1035
1332
  applyAssetTracking(context, tracking, manifest, noScripts);
1333
+ context.failRender = failRender;
1036
1334
  registerEntryAssets(manifest);
1037
1335
  let html = solidJs.createRoot(d => {
1038
1336
  dispose = d;
@@ -1089,7 +1387,7 @@ function renderToStream(code, options = {}) {
1089
1387
  if (shellCompleted) return;
1090
1388
  solidJs.sharedConfig.context = context;
1091
1389
  if (!resolveRootHoles()) return;
1092
- const assetsHtml = resolveAssetsHtml(context.assets);
1390
+ if (!headShellReady(headRegistry, p => blockingPromises.add(p))) return;
1093
1391
  headStyles = new Set();
1094
1392
  for (const url of tracking.emittedAssets) {
1095
1393
  if (isCssUrl(url)) headStyles.add(url);
@@ -1097,7 +1395,6 @@ function renderToStream(code, options = {}) {
1097
1395
  serializeRootAssets();
1098
1396
  const head = renderShellHead(headRegistry, nonce, k => registry.has(k));
1099
1397
  sink.shell(html, {
1100
- assets: assetsHtml,
1101
1398
  preloads: tracking.emittedAssets,
1102
1399
  inlineStyles: tracking.inlineStyles,
1103
1400
  tasks,
@@ -1146,7 +1443,12 @@ function renderToStream(code, options = {}) {
1146
1443
  allSettled(blockingPromises).then(() => {
1147
1444
  scheduleFlush(() => {
1148
1445
  if (dead) return resolve();
1149
- doShell();
1446
+ try {
1447
+ doShell();
1448
+ } catch (err) {
1449
+ failRender(err);
1450
+ return resolve();
1451
+ }
1150
1452
  if (!shellCompleted) return flush();
1151
1453
  const encoder = new TextEncoder();
1152
1454
  const writer = w.getWriter();
@@ -1187,27 +1489,35 @@ function renderToStream(code, options = {}) {
1187
1489
  return p;
1188
1490
  };
1189
1491
  return {
1190
- then(fn) {
1191
- function complete() {
1192
- dispose();
1193
- fn(tmp);
1194
- }
1195
- if (onCompleteAll) {
1196
- let ogComplete = onCompleteAll;
1197
- onCompleteAll = options => {
1198
- ogComplete(options);
1199
- complete();
1200
- };
1201
- } else onCompleteAll = complete;
1202
- function flush() {
1203
- allSettled(blockingPromises).then(() => {
1204
- scheduleFlush(() => {
1205
- if (!resolveRootHoles()) return flush();
1206
- queue(flushEnd);
1492
+ then(onFulfilled, onRejected) {
1493
+ const p = new Promise(resolve => {
1494
+ function complete() {
1495
+ dispose();
1496
+ resolve(tmp);
1497
+ }
1498
+ if (onCompleteAll) {
1499
+ let ogComplete = onCompleteAll;
1500
+ onCompleteAll = options => {
1501
+ ogComplete(options);
1502
+ complete();
1503
+ };
1504
+ } else onCompleteAll = complete;
1505
+ function flush() {
1506
+ allSettled(blockingPromises).then(() => {
1507
+ scheduleFlush(() => {
1508
+ try {
1509
+ if (!resolveRootHoles() || !headShellReady(headRegistry, p => blockingPromises.add(p))) return flush();
1510
+ } catch (err) {
1511
+ failRender(err);
1512
+ return resolve(tmp);
1513
+ }
1514
+ queue(flushEnd);
1515
+ });
1207
1516
  });
1208
- });
1209
- }
1210
- flush();
1517
+ }
1518
+ flush();
1519
+ });
1520
+ return p.then(onFulfilled, onRejected);
1211
1521
  },
1212
1522
  pipe(w) {
1213
1523
  claimConsumer("pipe");
@@ -1215,7 +1525,15 @@ function renderToStream(code, options = {}) {
1215
1525
  allSettled(blockingPromises).then(() => {
1216
1526
  scheduleFlush(() => {
1217
1527
  if (dead) return;
1218
- doShell();
1528
+ try {
1529
+ doShell();
1530
+ } catch (err) {
1531
+ failRender(err);
1532
+ try {
1533
+ w.end();
1534
+ } catch (_) {}
1535
+ return;
1536
+ }
1219
1537
  if (!shellCompleted) return flush();
1220
1538
  buffer = writable = guardSink(w);
1221
1539
  buffer.write(tmp);
@@ -1260,9 +1578,27 @@ function ssrGroup(fn, n) {
1260
1578
  function buildAsyncWrap(err, node) {
1261
1579
  const p = solidJs.ssrHandleError(err);
1262
1580
  if (!p) return null;
1581
+ if (node.$rw) return {
1582
+ fn: node,
1583
+ p
1584
+ };
1263
1585
  const owner = solidJs.getOwner();
1586
+ const live = solidJs.sharedConfig.context && solidJs.sharedConfig.context.liveHoles;
1587
+ const suppress = node.$lhSuppress || live && (live.suppressed || live.sweeping);
1588
+ if (!owner) {
1589
+ if (suppress) node.$lhSuppress = true;
1590
+ return {
1591
+ fn: node,
1592
+ p
1593
+ };
1594
+ }
1595
+ const fn = () => solidJs.runWithOwner(owner, node);
1596
+ fn.$rw = true;
1597
+ if (suppress) fn.$lhSuppress = true;
1598
+ if (node.$lhSkip) fn.$lhSkip = true;
1599
+ if (node.$lhBinding) fn.$lhBinding = node.$lhBinding;
1264
1600
  return {
1265
- fn: owner ? () => solidJs.runWithOwner(owner, node) : node,
1601
+ fn,
1266
1602
  p
1267
1603
  };
1268
1604
  }
@@ -1322,6 +1658,326 @@ function ssrGroupSlot(fn, idx) {
1322
1658
  }
1323
1659
  };
1324
1660
  }
1661
+ const holePositionCache = new WeakMap();
1662
+ function holeContentPositions(t) {
1663
+ let cached = holePositionCache.get(t);
1664
+ if (cached) return cached;
1665
+ const pos = [];
1666
+ const openOff = [];
1667
+ const closeOff = [];
1668
+ let inTag = false;
1669
+ let quote = "";
1670
+ let curOpen = null;
1671
+ let scanningName = false;
1672
+ for (let i = 0; i < t.length; i++) {
1673
+ const seg = t[i];
1674
+ let close = -1;
1675
+ const openAtStart = inTag;
1676
+ let reopened = false;
1677
+ for (let j = 0; j < seg.length; j++) {
1678
+ const ch = seg[j];
1679
+ if (quote) {
1680
+ if (ch === quote) quote = "";
1681
+ } else if (inTag) {
1682
+ if (scanningName && (ch === " " || ch === "\t" || ch === "\n" || ch === ">" || ch === "/")) {
1683
+ scanningName = false;
1684
+ curOpen = {
1685
+ seg: i,
1686
+ off: j
1687
+ };
1688
+ }
1689
+ if (ch === '"' || ch === "'") quote = ch;else if (ch === ">") {
1690
+ inTag = false;
1691
+ if (openAtStart && !reopened && close === -1) close = j;
1692
+ curOpen = null;
1693
+ }
1694
+ } else if (ch === "<") {
1695
+ inTag = true;
1696
+ scanningName = true;
1697
+ reopened = true;
1698
+ curOpen = null;
1699
+ }
1700
+ }
1701
+ if (inTag && scanningName) {
1702
+ scanningName = false;
1703
+ curOpen = {
1704
+ seg: i,
1705
+ off: seg.length
1706
+ };
1707
+ }
1708
+ closeOff.push(close);
1709
+ openOff.push(inTag && curOpen && curOpen.seg === i ? curOpen.off : -1);
1710
+ if (i < t.length - 1) pos.push(!inTag);
1711
+ }
1712
+ cached = {
1713
+ pos,
1714
+ openOff,
1715
+ closeOff
1716
+ };
1717
+ holePositionCache.set(t, cached);
1718
+ return cached;
1719
+ }
1720
+ function createLiveHoles(sink, scoped) {
1721
+ let nextId = 0;
1722
+ const stamp = typeof solidJs.creationStamp === "function" ? solidJs.creationStamp : () => 0;
1723
+ const inScope = scoped && typeof solidJs.inServerComponentScope === "function" ? solidJs.inServerComponentScope : null;
1724
+ const stripMarkers = html => html.replace(/<!--lh:\/?\d+-->/g, "");
1725
+ function resolveHoleValue(hole) {
1726
+ const result = {
1727
+ t: [""],
1728
+ h: [],
1729
+ p: []
1730
+ };
1731
+ try {
1732
+ resolveSSRNode(hole(), result);
1733
+ } catch (err) {
1734
+ const wrap = buildAsyncWrap(err, hole);
1735
+ if (!wrap) throw err;
1736
+ result.h.push(wrap.fn);
1737
+ result.p.push(wrap.p);
1738
+ result.t.push("");
1739
+ }
1740
+ return result;
1741
+ }
1742
+ function closeChildren(b) {
1743
+ for (const c of b.children) {
1744
+ c.closed = true;
1745
+ if (c.key) sink.closeBinding(c.key);
1746
+ closeChildren(c);
1747
+ }
1748
+ b.children.length = 0;
1749
+ }
1750
+ const engine = {
1751
+ suppressed: 0,
1752
+ sweeping: false,
1753
+ parent: null,
1754
+ recordStamp: 0,
1755
+ gateHit: false,
1756
+ content(hole) {
1757
+ if (hole.$lhSuppress) {
1758
+ const r = {
1759
+ t: [""],
1760
+ h: [],
1761
+ p: []
1762
+ };
1763
+ engine.suppressed++;
1764
+ try {
1765
+ try {
1766
+ resolveSSRNode(hole(), r);
1767
+ } catch (err) {
1768
+ const wrap = buildAsyncWrap(err, hole);
1769
+ if (wrap) {
1770
+ r.h.push(wrap.fn);
1771
+ r.p.push(wrap.p);
1772
+ r.t.push("");
1773
+ }
1774
+ }
1775
+ } finally {
1776
+ engine.suppressed--;
1777
+ }
1778
+ const b = hole.$lhBinding;
1779
+ if (b && !b.closed && !r.h.length && !engine.sweeping) {
1780
+ b.last = stripMarkers(r.t[0]);
1781
+ }
1782
+ return r.h.length ? r : r.t[0];
1783
+ }
1784
+ if (engine.suppressed || engine.sweeping) return null;
1785
+ if (hole.$lhSkip) return null;
1786
+ if (inScope && !inScope()) return null;
1787
+ const recordsBefore = engine.recordStamp;
1788
+ const ownersBefore = stamp();
1789
+ const owner = solidJs.getOwner();
1790
+ const b = {
1791
+ key: null,
1792
+ children: [],
1793
+ last: null,
1794
+ closed: false,
1795
+ sweep() {
1796
+ if (b.closed) return;
1797
+ const prevSweeping = engine.sweeping;
1798
+ engine.sweeping = true;
1799
+ engine.gateHit = false;
1800
+ const sweepOwnersBefore = stamp();
1801
+ let res;
1802
+ try {
1803
+ res = owner ? solidJs.runWithOwner(owner, () => resolveHoleValue(hole)) : resolveHoleValue(hole);
1804
+ } catch (err) {
1805
+ b.closed = true;
1806
+ sink.closeBinding(b.key);
1807
+ sink.error(b.key, String(err && err.message || err));
1808
+ return;
1809
+ } finally {
1810
+ engine.sweeping = prevSweeping;
1811
+ }
1812
+ if (engine.gateHit || stamp() !== sweepOwnersBefore) {
1813
+ b.closed = true;
1814
+ sink.closeBinding(b.key);
1815
+ return;
1816
+ }
1817
+ if (res.h.length) return;
1818
+ const html = res.t[0];
1819
+ if (b.last === null || html === b.last) return;
1820
+ b.last = html;
1821
+ closeChildren(b);
1822
+ sink.hole(b.key, html);
1823
+ }
1824
+ };
1825
+ if (engine.parent) engine.parent.children.push(b);
1826
+ const prevParent = engine.parent;
1827
+ engine.parent = b;
1828
+ let value;
1829
+ let escalated = null;
1830
+ try {
1831
+ value = hole();
1832
+ } catch (err) {
1833
+ const wrap = buildAsyncWrap(err, hole);
1834
+ if (!wrap) {
1835
+ engine.parent = prevParent;
1836
+ closeChildren(b);
1837
+ return "";
1838
+ }
1839
+ escalated = wrap;
1840
+ }
1841
+ if (!escalated && (typeof value === "function" && value.$lhSkip || value !== null && typeof value === "object" && value.$slot)) {
1842
+ engine.parent = prevParent;
1843
+ const r = {
1844
+ t: [""],
1845
+ h: [],
1846
+ p: []
1847
+ };
1848
+ engine.suppressed++;
1849
+ try {
1850
+ resolveSSRNode(value, r);
1851
+ } finally {
1852
+ engine.suppressed--;
1853
+ }
1854
+ return r.h.length ? r : r.t[0];
1855
+ }
1856
+ let res;
1857
+ if (escalated) {
1858
+ closeChildren(b);
1859
+ escalated.fn.$lhSuppress = true;
1860
+ escalated.fn.$lhBinding = b;
1861
+ res = {
1862
+ t: ["", ""],
1863
+ h: [escalated.fn],
1864
+ p: [escalated.p]
1865
+ };
1866
+ } else {
1867
+ res = {
1868
+ t: [""],
1869
+ h: [],
1870
+ p: []
1871
+ };
1872
+ try {
1873
+ resolveSSRNode(value, res);
1874
+ } catch (_) {
1875
+ engine.parent = prevParent;
1876
+ closeChildren(b);
1877
+ return "";
1878
+ }
1879
+ }
1880
+ engine.parent = prevParent;
1881
+ if (engine.recordStamp !== recordsBefore || stamp() !== ownersBefore) {
1882
+ return res.h.length ? res : res.t[0];
1883
+ }
1884
+ const id = nextId++;
1885
+ const key = b.key = "lh:" + id;
1886
+ const open = `<!--lh:${id}-->`;
1887
+ const close = `<!--lh:/${id}-->`;
1888
+ if (!res.h.length) {
1889
+ b.last = stripMarkers(res.t[0]);
1890
+ sink.openBinding(key, b);
1891
+ return open + res.t[0] + close;
1892
+ }
1893
+ const t = res.t.slice();
1894
+ t[0] = open + t[0];
1895
+ t[t.length - 1] += close;
1896
+ sink.openBinding(key, b);
1897
+ return {
1898
+ t,
1899
+ h: res.h,
1900
+ p: res.p
1901
+ };
1902
+ },
1903
+ mint() {
1904
+ return nextId++;
1905
+ },
1906
+ active() {
1907
+ return !inScope || inScope();
1908
+ },
1909
+ attr(cap) {
1910
+ const owner = solidJs.getOwner();
1911
+ const b = {
1912
+ key: "lha:" + cap.id,
1913
+ children: [],
1914
+ last: cap.base,
1915
+ closed: false,
1916
+ sweep() {
1917
+ if (b.closed) return;
1918
+ const prevSweeping = engine.sweeping;
1919
+ engine.sweeping = true;
1920
+ engine.gateHit = false;
1921
+ const sweepOwnersBefore = stamp();
1922
+ let html = "";
1923
+ try {
1924
+ let group = null;
1925
+ let groupVal = null;
1926
+ const run = () => {
1927
+ for (const part of cap.parts) {
1928
+ if (typeof part === "string") {
1929
+ html += part;
1930
+ continue;
1931
+ }
1932
+ let v;
1933
+ if (part.g) {
1934
+ if (group !== part.g) {
1935
+ group = part.g;
1936
+ groupVal = part.g();
1937
+ }
1938
+ v = groupVal[part.i];
1939
+ } else {
1940
+ v = part.f();
1941
+ }
1942
+ const vt = typeof v;
1943
+ if (vt === "string" || vt === "number") html += v;
1944
+ }
1945
+ };
1946
+ owner ? solidJs.runWithOwner(owner, run) : run();
1947
+ } catch (err) {
1948
+ if (solidJs.ssrHandleError(err, true)) return;
1949
+ b.closed = true;
1950
+ sink.closeBinding(b.key);
1951
+ sink.error("lha:" + cap.id, String(err && err.message || err));
1952
+ return;
1953
+ } finally {
1954
+ engine.sweeping = prevSweeping;
1955
+ }
1956
+ if (engine.gateHit || stamp() !== sweepOwnersBefore) {
1957
+ b.closed = true;
1958
+ sink.closeBinding(b.key);
1959
+ return;
1960
+ }
1961
+ if (html === b.last) return;
1962
+ const before = attrNames(b.last);
1963
+ const after = attrNames(html);
1964
+ const removed = before.filter(n => !after.includes(n));
1965
+ b.last = html;
1966
+ sink.attr(String(cap.id), html, removed);
1967
+ }
1968
+ };
1969
+ sink.openBinding(b.key, b);
1970
+ }
1971
+ };
1972
+ return engine;
1973
+ }
1974
+ function attrNames(text) {
1975
+ const names = [];
1976
+ const re = /(?:^|\s)([^\s=/>"']+)(?:="[^"]*")?/g;
1977
+ let m;
1978
+ while (m = re.exec(text)) names.push(m[1]);
1979
+ return names;
1980
+ }
1325
1981
  function ssr(t) {
1326
1982
  const len = arguments.length;
1327
1983
  if (len === 1) return {
@@ -1332,13 +1988,54 @@ function ssr(t) {
1332
1988
  let lastGroup = null;
1333
1989
  let lastGroupVal = null;
1334
1990
  let lastGroupIdx = 0;
1991
+ const live = solidJs.sharedConfig.context && solidJs.sharedConfig.context.liveHoles;
1992
+ const hp = live ? holeContentPositions(t) : null;
1993
+ let lastOpen = null;
1994
+ let cap = null;
1995
+ if (live && hp.openOff[0] >= 0) lastOpen = {
1996
+ r: null,
1997
+ seg: -1,
1998
+ off: hp.openOff[0]
1999
+ };
2000
+ const captureStart = () => {
2001
+ if (cap) return true;
2002
+ if (!lastOpen || live.suppressed || live.sweeping || !live.active()) return false;
2003
+ if (lastOpen.r !== result || result !== null && lastOpen.seg !== result.t.length - 1) {
2004
+ return false;
2005
+ }
2006
+ const id = live.mint();
2007
+ const inject = ` data-lha="${id}"`;
2008
+ let prefix;
2009
+ if (result === null) {
2010
+ s = s.slice(0, lastOpen.off) + inject + s.slice(lastOpen.off);
2011
+ prefix = s.slice(lastOpen.off + inject.length);
2012
+ } else {
2013
+ const seg = result.t[lastOpen.seg];
2014
+ result.t[lastOpen.seg] = seg.slice(0, lastOpen.off) + inject + seg.slice(lastOpen.off);
2015
+ prefix = result.t[lastOpen.seg].slice(lastOpen.off + inject.length);
2016
+ }
2017
+ cap = {
2018
+ id,
2019
+ parts: [prefix],
2020
+ base: prefix
2021
+ };
2022
+ return true;
2023
+ };
1335
2024
  for (let i = 1; i < len; i++) {
1336
2025
  const hole = arguments[i];
1337
2026
  const ht = typeof hole;
1338
2027
  if (ht === "string") {
1339
2028
  if (result === null) s += hole;else result.t[result.t.length - 1] += hole;
2029
+ if (cap) {
2030
+ cap.parts.push(hole);
2031
+ cap.base += hole;
2032
+ }
1340
2033
  } else if (ht === "number") {
1341
2034
  if (result === null) s += hole;else result.t[result.t.length - 1] += hole;
2035
+ if (cap) {
2036
+ cap.parts.push("" + hole);
2037
+ cap.base += hole;
2038
+ }
1342
2039
  } else if (hole == null || ht === "boolean") ; else if (ht === "function" && hole.$g) {
1343
2040
  let value;
1344
2041
  let hasValue = false;
@@ -1362,7 +2059,14 @@ function ssr(t) {
1362
2059
  if (Array.isArray(lastGroupVal)) {
1363
2060
  value = lastGroupVal[lastGroupIdx++];
1364
2061
  hasValue = true;
2062
+ if (live && !hp.pos[i - 1] && captureStart()) {
2063
+ cap.parts.push({
2064
+ g: hole,
2065
+ i: lastGroupIdx - 1
2066
+ });
2067
+ }
1365
2068
  } else {
2069
+ cap = null;
1366
2070
  result.h.push(ssrGroupSlot(lastGroupVal.fn, lastGroupIdx++));
1367
2071
  result.p.push(lastGroupVal.p);
1368
2072
  result.t.push("");
@@ -1372,6 +2076,7 @@ function ssr(t) {
1372
2076
  const vt = typeof value;
1373
2077
  if (vt === "string" || vt === "number") {
1374
2078
  if (result === null) s += value;else result.t[result.t.length - 1] += value;
2079
+ if (cap && !hp.pos[i - 1]) cap.base += value;
1375
2080
  } else if (value == null || vt === "boolean") ; else if (result !== null) {
1376
2081
  resolveSSRNode(value, result);
1377
2082
  } else {
@@ -1389,19 +2094,67 @@ function ssr(t) {
1389
2094
  }
1390
2095
  }
1391
2096
  }
1392
- } else if (result !== null) {
1393
- resolveSSRNode(hole, result);
1394
2097
  } else if (ht === "function") {
1395
- const r = tryResolveFunctionHole(hole);
1396
- if (typeof r === "string") s += r;else {
1397
- result = {
1398
- t: [s],
1399
- h: [],
1400
- p: []
1401
- };
1402
- s = "";
1403
- appendResolvedNode(result, r);
2098
+ let liveNode = null;
2099
+ if (live && hp.pos[i - 1] && (liveNode = live.content(hole)) !== null) {
2100
+ if (typeof liveNode === "string") {
2101
+ if (result === null) s += liveNode;else result.t[result.t.length - 1] += liveNode;
2102
+ } else {
2103
+ if (result === null) {
2104
+ result = {
2105
+ t: [s],
2106
+ h: [],
2107
+ p: []
2108
+ };
2109
+ s = "";
2110
+ }
2111
+ resolveSSRNode(liveNode, result);
2112
+ }
2113
+ } else if (result !== null) {
2114
+ const inTag = live && !hp.pos[i - 1];
2115
+ const capturing = inTag && captureStart();
2116
+ const li = capturing ? result.t.length - 1 : 0;
2117
+ const before = capturing ? result.t[li].length : 0;
2118
+ if (live) live.suppressed++;
2119
+ try {
2120
+ resolveSSRNode(hole, result);
2121
+ } finally {
2122
+ if (live) live.suppressed--;
2123
+ }
2124
+ if (capturing) {
2125
+ if (result.t.length - 1 === li) {
2126
+ cap.base += result.t[li].slice(before);
2127
+ cap.parts.push({
2128
+ f: hole
2129
+ });
2130
+ } else {
2131
+ cap = null;
2132
+ }
2133
+ }
2134
+ } else {
2135
+ const capturing = live && !hp.pos[i - 1] && captureStart();
2136
+ const r = tryResolveFunctionHole(hole);
2137
+ if (typeof r === "string") {
2138
+ s += r;
2139
+ if (capturing) {
2140
+ cap.base += r;
2141
+ cap.parts.push({
2142
+ f: hole
2143
+ });
2144
+ }
2145
+ } else {
2146
+ if (capturing) cap = null;
2147
+ result = {
2148
+ t: [s],
2149
+ h: [],
2150
+ p: []
2151
+ };
2152
+ s = "";
2153
+ appendResolvedNode(result, r);
2154
+ }
1404
2155
  }
2156
+ } else if (result !== null) {
2157
+ resolveSSRNode(hole, result);
1405
2158
  } else {
1406
2159
  const r = tryResolveString(hole);
1407
2160
  if (typeof r === "string") {
@@ -1417,6 +2170,32 @@ function ssr(t) {
1417
2170
  }
1418
2171
  }
1419
2172
  const next = t[i];
2173
+ if (live) {
2174
+ if (cap) {
2175
+ const co = hp.closeOff[i];
2176
+ if (co >= 0) {
2177
+ const tail = next.slice(0, co);
2178
+ cap.parts.push(tail);
2179
+ cap.base += tail;
2180
+ live.attr(cap);
2181
+ cap = null;
2182
+ } else {
2183
+ cap.parts.push(next);
2184
+ cap.base += next;
2185
+ }
2186
+ }
2187
+ if (hp.openOff[i] >= 0) {
2188
+ lastOpen = result === null ? {
2189
+ r: null,
2190
+ seg: -1,
2191
+ off: s.length + hp.openOff[i]
2192
+ } : {
2193
+ r: result,
2194
+ seg: result.t.length - 1,
2195
+ off: result.t[result.t.length - 1].length + hp.openOff[i]
2196
+ };
2197
+ }
2198
+ }
1420
2199
  if (result === null) s += next;else result.t[result.t.length - 1] += next;
1421
2200
  }
1422
2201
  if (result === null) return {
@@ -1578,18 +2357,6 @@ function getHydrationKey() {
1578
2357
  function applyRef(r, element) {
1579
2358
  Array.isArray(r) ? r.flat(Infinity).forEach(f => f && f(element)) : r(element);
1580
2359
  }
1581
- function useAssets(fn) {
1582
- solidJs.sharedConfig.context.assets.push(() => resolveSSRSync(escape(fn())));
1583
- }
1584
- function getAssets() {
1585
- const assets = solidJs.sharedConfig.context.assets;
1586
- let out = "";
1587
- for (let i = 0, len = assets.length; i < len; i++) out += assets[i]();
1588
- return out;
1589
- }
1590
- function Assets(props) {
1591
- useAssets(() => props.children);
1592
- }
1593
2360
  function generateHydrationScript({
1594
2361
  eventNames = ["click", "input"],
1595
2362
  nonce
@@ -1606,17 +2373,11 @@ function allSettled(promises) {
1606
2373
  return;
1607
2374
  });
1608
2375
  }
1609
- function resolveAssetsHtml(assets) {
1610
- if (!assets || !assets.length) return "";
1611
- let out = "";
1612
- for (let i = 0, len = assets.length; i < len; i++) out += assets[i]();
1613
- return out;
1614
- }
1615
- function assembleDocument(html, assetsHtml, emittedAssets, inlineStyles, scripts, nonce, headTags, onHead) {
2376
+ function assembleDocument(html, emittedAssets, inlineStyles, scripts, nonce, headTags, onHead) {
1616
2377
  const scriptTag = scripts ? `<script${nonce ? ` nonce="${nonce}"` : ""}>${scripts}</script>` : "";
1617
2378
  const headTagsHtml = headTags ? headTags.html : "";
1618
2379
  const headPrelude = headTags ? headTags.prelude : "";
1619
- if (!onHead && !assetsHtml && !headTagsHtml && !headPrelude && !(emittedAssets && emittedAssets.size) && !(inlineStyles && inlineStyles.size)) {
2380
+ if (!onHead && !headTagsHtml && !headPrelude && !(emittedAssets && emittedAssets.size) && !(inlineStyles && inlineStyles.size)) {
1620
2381
  if (!scriptTag) return html;
1621
2382
  const xs = html.indexOf("<!--xs-->");
1622
2383
  return xs === -1 ? html + scriptTag : html.slice(0, xs) + scriptTag + html.slice(xs);
@@ -1631,13 +2392,13 @@ function assembleDocument(html, assetsHtml, emittedAssets, inlineStyles, scripts
1631
2392
  const headIdx = html.indexOf("</head>");
1632
2393
  if (headIdx === -1) {
1633
2394
  if (onHead) {
1634
- onHead(headPrelude + headTagsHtml + (assetsHtml || "") + renderHeadAssets(emittedAssets, inlineStyles, nonce));
2395
+ onHead(headPrelude + headTagsHtml + renderHeadAssets(emittedAssets, inlineStyles, nonce));
1635
2396
  }
1636
2397
  if (!scriptTag) return html;
1637
2398
  const xs = html.indexOf("<!--xs-->");
1638
2399
  return xs === -1 ? html + scriptTag : html.slice(0, xs) + scriptTag + html.slice(xs);
1639
2400
  }
1640
- const head = headTagsHtml + (assetsHtml || "") + renderHeadAssets(emittedAssets, inlineStyles, nonce);
2401
+ const head = headTagsHtml + renderHeadAssets(emittedAssets, inlineStyles, nonce);
1641
2402
  if (!scriptTag) return html.slice(0, headIdx) + head + html.slice(headIdx);
1642
2403
  const xsIdx = html.indexOf("<!--xs-->");
1643
2404
  if (xsIdx === -1) return html.slice(0, headIdx) + head + html.slice(headIdx) + scriptTag;
@@ -1770,7 +2531,6 @@ function tryResolveString(node) {
1770
2531
  merge: node
1771
2532
  };
1772
2533
  if (node.t === undefined) {
1773
- console.warn(`Unrecognized value. Skipped inserting`, node);
1774
2534
  return "";
1775
2535
  }
1776
2536
  return Array.isArray(node.t) ? node.t[0] : node.t;
@@ -1795,13 +2555,19 @@ function resolveSSRNode(node, result = {
1795
2555
  if (t === "string" || t === "number") {
1796
2556
  result.t[result.t.length - 1] += node;
1797
2557
  } else if (node == null || t === "boolean") ; else if (Array.isArray(node)) {
1798
- let prevNonObj = false;
1799
- for (let i = 0, len = node.length; i < len; i++) {
1800
- const item = node[i];
1801
- const itemNonObj = item !== null && typeof item !== "object";
1802
- if (!top && prevNonObj && itemNonObj) result.t[result.t.length - 1] += `<!--!$-->`;
1803
- prevNonObj = itemNonObj;
1804
- resolveSSRNode(item, result);
2558
+ const slotLive = node.$slot && solidJs.sharedConfig.context && solidJs.sharedConfig.context.liveHoles;
2559
+ if (slotLive) slotLive.suppressed++;
2560
+ try {
2561
+ let prevNonObj = false;
2562
+ for (let i = 0, len = node.length; i < len; i++) {
2563
+ const item = node[i];
2564
+ const itemNonObj = item !== null && typeof item !== "object";
2565
+ if (!top && prevNonObj && itemNonObj) result.t[result.t.length - 1] += `<!--!$-->`;
2566
+ prevNonObj = itemNonObj;
2567
+ resolveSSRNode(item, result);
2568
+ }
2569
+ } finally {
2570
+ if (slotLive) slotLive.suppressed--;
1805
2571
  }
1806
2572
  } else if (t === "object") {
1807
2573
  if (node.h) {
@@ -1813,16 +2579,22 @@ function resolveSSRNode(node, result = {
1813
2579
  }
1814
2580
  } else if (node.t !== undefined) {
1815
2581
  result.t[result.t.length - 1] += node.t;
1816
- } else console.warn(`Unrecognized value. Skipped inserting`, node);
2582
+ } else ;
1817
2583
  } else if (t === "function") {
1818
- try {
1819
- resolveSSRNode(node(), result);
1820
- } catch (err) {
1821
- const wrap = buildAsyncWrap(err, node);
1822
- if (wrap) {
1823
- result.h.push(wrap.fn);
1824
- result.p.push(wrap.p);
1825
- result.t.push("");
2584
+ const live = solidJs.sharedConfig.context && solidJs.sharedConfig.context.liveHoles;
2585
+ let liveNode = null;
2586
+ if (live && (liveNode = live.content(node)) !== null) {
2587
+ if (typeof liveNode === "string") result.t[result.t.length - 1] += liveNode;else resolveSSRNode(liveNode, result);
2588
+ } else {
2589
+ try {
2590
+ resolveSSRNode(node(), result);
2591
+ } catch (err) {
2592
+ const wrap = buildAsyncWrap(err, node);
2593
+ if (wrap) {
2594
+ result.h.push(wrap.fn);
2595
+ result.p.push(wrap.p);
2596
+ result.t.push("");
2597
+ }
1826
2598
  }
1827
2599
  }
1828
2600
  }
@@ -1837,92 +2609,229 @@ const RequestContext = Symbol.for("solid.RequestContext");
1837
2609
  function getRequestEvent() {
1838
2610
  return globalThis[RequestContext] ? globalThis[RequestContext].getStore() || solidJs.sharedConfig.context && solidJs.sharedConfig.context.event || console.warn("RequestEvent is missing. This is most likely due to accessing `getRequestEvent` non-managed async scope in a partially polyfilled environment. Try moving it above all `await` calls.") : undefined;
1839
2611
  }
1840
- function renderToStringAsync(code, options = {}) {
1841
- return new Promise(resolve => renderToStream(code, options).then(resolve));
1842
- }
1843
- function registerElementClaim() {
1844
- return noopCleanup;
1845
- }
1846
- function noopCleanup() {}
1847
- function claimElement(node) {
1848
- return node;
2612
+ function createResponseStub() {
2613
+ return {
2614
+ status: undefined,
2615
+ statusText: undefined,
2616
+ headers: new Headers(),
2617
+ committed: false
2618
+ };
1849
2619
  }
1850
- function claimElementTree(root) {
1851
- return root;
2620
+ function createRequestEvent(request, init) {
2621
+ return {
2622
+ request,
2623
+ locals: {},
2624
+ response: createResponseStub(),
2625
+ ...init
2626
+ };
1852
2627
  }
1853
- function notSup() {
1854
- throw new Error("Client-only API called on the server side. Run client-only code in onMount, or conditionally run client-only component with <Show>.");
2628
+ function reportLostHeaderWrite(method, name) {
2629
+ const message = `Response header write dropped: headers.${method}(${JSON.stringify(String(name))}) ` + "ran after the response head was sent. Write headers before the shell flushes " + "(or before the handler returns).";
2630
+ console.error(message);
1855
2631
  }
1856
-
1857
- const ENVELOPE = Symbol.for("solid.ResponseEnvelope");
1858
- class ResponseEnvelope {
1859
- constructor(response, value) {
1860
- this.response = response;
1861
- this.value = value;
2632
+ function commitResponseStub(stub, {
2633
+ allowLateLocation = false
2634
+ } = {}) {
2635
+ if (!stub || stub.committed) return stub;
2636
+ stub.committed = true;
2637
+ const headers = stub.headers;
2638
+ if (!headers || typeof headers.set !== "function") return stub;
2639
+ for (const method of ["set", "append", "delete"]) {
2640
+ const original = headers[method].bind(headers);
2641
+ headers[method] = function (name, ...rest) {
2642
+ if (allowLateLocation && method === "set" && String(name).toLowerCase() === "location") {
2643
+ return original(name, ...rest);
2644
+ }
2645
+ reportLostHeaderWrite(method, name);
2646
+ };
1862
2647
  }
2648
+ return stub;
1863
2649
  }
1864
- ResponseEnvelope.prototype[ENVELOPE] = true;
1865
- function isResponseEnvelope(value) {
1866
- return !!(value && typeof value === "object" && value[ENVELOPE]);
2650
+ const validRedirectStatuses = /*#__PURE__*/new Set([301, 302, 303, 307, 308]);
2651
+ function getExpectedRedirectStatus(response) {
2652
+ if (response.status && validRedirectStatuses.has(response.status)) return response.status;
2653
+ return 302;
1867
2654
  }
1868
- const HREF = Symbol.for("solid.Href");
1869
- function isHref(value) {
1870
- return !!(value && (typeof value === "object" || typeof value === "function") && value[HREF]);
2655
+ function mergeStubHeaders(target, stub) {
2656
+ if (!stub) return target;
2657
+ stub.headers.forEach((value, key) => {
2658
+ if (key !== "set-cookie") target.set(key, value);
2659
+ });
2660
+ const setCookies = stub.headers.getSetCookie ? stub.headers.getSetCookie() : [];
2661
+ for (const cookie of setCookies) target.append("set-cookie", cookie);
2662
+ return target;
2663
+ }
2664
+ function copyInitHeaders(init) {
2665
+ if (!init || !init.getSetCookie) return new Headers(init);
2666
+ const headers = new Headers();
2667
+ init.forEach((value, key) => {
2668
+ if (key !== "set-cookie") headers.append(key, value);
2669
+ });
2670
+ for (const cookie of init.getSetCookie()) headers.append("Set-Cookie", cookie);
2671
+ return headers;
2672
+ }
2673
+ const STUB_GAP_FILL_EXCLUDED = /*#__PURE__*/new Set([ERROR_HEADER, BODY_FORMAT_HEADER, SINGLE_FLIGHT_HEADER, REVALIDATE_HEADER, "Location"].map(header => header.toLowerCase()));
2674
+ function fillsStubGap(key, headers, response) {
2675
+ if (key === "set-cookie" || STUB_GAP_FILL_EXCLUDED.has(key)) return false;
2676
+ if (response.body === null && (key === "content-type" || key === "content-length")) return false;
2677
+ return !headers.has(key);
2678
+ }
2679
+ function commitEventResponse(response, event = getRequestEvent()) {
2680
+ const stub = event && event.response;
2681
+ if (!stub || !stub.headers || stub.committed) return response;
2682
+ const cookies = stub.headers.getSetCookie ? stub.headers.getSetCookie() : [];
2683
+ commitResponseStub(stub);
2684
+ let hasGaps = false;
2685
+ stub.headers.forEach((value, key) => {
2686
+ if (fillsStubGap(key, response.headers, response)) hasGaps = true;
2687
+ });
2688
+ if (!cookies.length && !hasGaps) return response;
2689
+ try {
2690
+ for (const cookie of cookies) response.headers.append("Set-Cookie", cookie);
2691
+ stub.headers.forEach((value, key) => {
2692
+ if (fillsStubGap(key, response.headers, response)) response.headers.set(key, value);
2693
+ });
2694
+ return response;
2695
+ } catch {
2696
+ const headers = copyInitHeaders(response.headers);
2697
+ for (const cookie of cookies) headers.append("Set-Cookie", cookie);
2698
+ stub.headers.forEach((value, key) => {
2699
+ if (fillsStubGap(key, headers, response)) headers.set(key, value);
2700
+ });
2701
+ return new Response(response.body, {
2702
+ status: response.status,
2703
+ statusText: response.statusText,
2704
+ headers
2705
+ });
2706
+ }
1871
2707
  }
1872
- const REVALIDATE_HEADER = "X-Revalidate";
1873
- function initWithRevalidate(init) {
1874
- const {
1875
- revalidate,
1876
- ...responseInit
1877
- } = init;
1878
- const headers = new Headers(responseInit.headers);
1879
- revalidate !== undefined && headers.set(REVALIDATE_HEADER, revalidate.toString());
2708
+ function deriveHead(stub, responseInit = {}) {
2709
+ const headers = mergeStubHeaders(copyInitHeaders(responseInit.headers), stub);
2710
+ const status = stub && stub.status || responseInit.status || 200;
2711
+ const statusText = stub && stub.statusText || responseInit.statusText || undefined;
1880
2712
  return {
1881
- responseInit,
2713
+ status,
2714
+ statusText,
1882
2715
  headers
1883
2716
  };
1884
2717
  }
1885
- function redirect(url, init = 302) {
1886
- if (typeof url !== "string" && !isHref(url)) {
1887
- throw new TypeError("redirect() expects a string URL or an Href-branded value (Symbol.for('solid.Href')).");
1888
- }
2718
+ function escapeAttribute(value) {
2719
+ return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;");
2720
+ }
2721
+ function createSSRResponse(result, event, options = {}) {
2722
+ const stub = event && event.response;
1889
2723
  const {
1890
2724
  responseInit,
1891
- headers
1892
- } = initWithRevalidate(typeof init === "number" ? {
1893
- status: init
1894
- } : init);
1895
- if (responseInit.status === undefined) {
1896
- responseInit.status = 302;
2725
+ nonce,
2726
+ transformChunk
2727
+ } = options;
2728
+ if (typeof result === "string") {
2729
+ if (stub) commitResponseStub(stub);
2730
+ const head = deriveHead(stub, responseInit);
2731
+ if (stub && stub.headers.get("Location")) {
2732
+ return new Response(null, {
2733
+ status: getExpectedRedirectStatus(stub),
2734
+ headers: head.headers
2735
+ });
2736
+ }
2737
+ if (!head.headers.has("content-type")) {
2738
+ head.headers.set("content-type", "text/html; charset=utf-8");
2739
+ }
2740
+ return new Response(transformChunk ? transformChunk(result) : result, {
2741
+ status: head.status,
2742
+ statusText: head.statusText,
2743
+ headers: head.headers
2744
+ });
1897
2745
  }
1898
- headers.set("Location", String(url));
1899
- return new Response(null, {
1900
- ...responseInit,
1901
- headers
2746
+ const encoder = new TextEncoder();
2747
+ return new Promise(resolve => {
2748
+ let controller;
2749
+ let closed = false;
2750
+ let flushed = false;
2751
+ const enqueue = value => {
2752
+ if (closed || !controller) return;
2753
+ try {
2754
+ controller.enqueue(encoder.encode(value));
2755
+ } catch {
2756
+ closed = true;
2757
+ }
2758
+ };
2759
+ result.pipe({
2760
+ write(chunk) {
2761
+ if (!flushed) {
2762
+ flushed = true;
2763
+ if (stub) commitResponseStub(stub, {
2764
+ allowLateLocation: true
2765
+ });
2766
+ const head = deriveHead(stub, responseInit);
2767
+ if (stub && stub.headers.get("Location")) {
2768
+ closed = true;
2769
+ resolve(new Response(null, {
2770
+ status: getExpectedRedirectStatus(stub),
2771
+ headers: head.headers
2772
+ }));
2773
+ return;
2774
+ }
2775
+ if (!head.headers.has("content-type")) {
2776
+ head.headers.set("content-type", "text/html; charset=utf-8");
2777
+ }
2778
+ resolve(new Response(new ReadableStream({
2779
+ start(c) {
2780
+ controller = c;
2781
+ },
2782
+ cancel() {
2783
+ closed = true;
2784
+ }
2785
+ }), {
2786
+ status: head.status,
2787
+ statusText: head.statusText,
2788
+ headers: head.headers
2789
+ }));
2790
+ }
2791
+ enqueue(transformChunk ? transformChunk(chunk) : chunk);
2792
+ },
2793
+ end() {
2794
+ if (closed || !controller) return;
2795
+ const location = stub && stub.headers.get("Location");
2796
+ if (location) {
2797
+ const attr = nonce ? ` nonce="${escapeAttribute(nonce)}"` : "";
2798
+ enqueue(`<script${attr}>window.location=${JSON.stringify(location).replace(/</g, "\\u003c")}</script>`);
2799
+ }
2800
+ closed = true;
2801
+ try {
2802
+ controller.close();
2803
+ } catch {}
2804
+ }
2805
+ });
1902
2806
  });
1903
2807
  }
1904
- function reload(init = {}) {
1905
- const {
1906
- responseInit,
1907
- headers
1908
- } = initWithRevalidate(init);
1909
- return new Response(null, {
1910
- ...responseInit,
1911
- headers
1912
- });
2808
+ function composeMiddleware(middlewares) {
2809
+ return function run(request, next) {
2810
+ let index = -1;
2811
+ function dispatch(i, req) {
2812
+ if (i <= index) return Promise.reject(new Error("next() called multiple times"));
2813
+ index = i;
2814
+ if (i === middlewares.length) return Promise.resolve(next(req));
2815
+ return Promise.resolve(middlewares[i](req, override => dispatch(i + 1, override || req)));
2816
+ }
2817
+ return dispatch(0, request);
2818
+ };
1913
2819
  }
1914
- function respond(value, init = {}) {
1915
- const {
1916
- responseInit,
1917
- headers
1918
- } = initWithRevalidate(init);
1919
- headers.set("Content-Type", "application/json");
1920
- return new ResponseEnvelope(new Response(JSON.stringify(value), {
1921
- ...responseInit,
1922
- headers
1923
- }), value);
2820
+ function registerElementClaim() {
2821
+ return noopCleanup;
2822
+ }
2823
+ function noopCleanup() {}
2824
+ function claimElement(node) {
2825
+ return node;
2826
+ }
2827
+ function claimElementTree(root) {
2828
+ return root;
2829
+ }
2830
+ function notSup() {
2831
+ throw new Error("Client-only API called on the server side. Run client-only code in onMount, or conditionally run client-only component with <Show>.");
1924
2832
  }
1925
2833
 
2834
+ setContainerTraceResolver(solidJs.getProjectionTrace);
1926
2835
  const isServer = true;
1927
2836
  const isDev = false;
1928
2837
  function dynamic(source) {
@@ -1988,18 +2897,39 @@ function clientOnly(_fn, _options = {}, moduleUrl) {
1988
2897
  return solidJs.createMemo(() => props.fallback);
1989
2898
  };
1990
2899
  }
2900
+ const statusLedgers = /* @__PURE__ */new WeakMap();
2901
+ const headerLedgers = /* @__PURE__ */new WeakMap();
1991
2902
  function httpStatus(code, text) {
1992
2903
  const event = getRequestEvent();
1993
2904
  const response = event && event.response;
1994
2905
  if (response && !response.committed) {
1995
- const prevStatus = response.status;
1996
- const prevStatusText = response.statusText;
2906
+ let ledger = statusLedgers.get(response);
2907
+ if (!ledger) {
2908
+ ledger = {
2909
+ base: {
2910
+ status: response.status,
2911
+ statusText: response.statusText
2912
+ },
2913
+ live: []
2914
+ };
2915
+ statusLedgers.set(response, ledger);
2916
+ }
2917
+ const declaration = {
2918
+ status: code,
2919
+ statusText: text
2920
+ };
2921
+ ledger.live.push(declaration);
1997
2922
  response.status = code;
1998
2923
  response.statusText = text;
1999
2924
  solidJs.onCleanup(() => {
2000
2925
  if (response.committed) return;
2001
- response.status = prevStatus;
2002
- response.statusText = prevStatusText;
2926
+ const index = ledger.live.indexOf(declaration);
2927
+ if (index < 0) return;
2928
+ ledger.live.splice(index, 1);
2929
+ const effective = ledger.live.length ? ledger.live[ledger.live.length - 1] : ledger.base;
2930
+ response.status = effective.status;
2931
+ response.statusText = effective.statusText;
2932
+ if (!ledger.live.length) statusLedgers.delete(response);
2003
2933
  });
2004
2934
  }
2005
2935
  }
@@ -2008,11 +2938,39 @@ function httpHeader(name, value, options) {
2008
2938
  const response = event && event.response;
2009
2939
  if (response && !response.committed) {
2010
2940
  const headers = response.headers;
2011
- const prev = headers.get(name);
2012
- if (options && options.append) headers.append(name, value);else headers.set(name, value);
2941
+ const key = name.toLowerCase();
2942
+ const setCookie = key === "set-cookie";
2943
+ let ledgers = headerLedgers.get(response);
2944
+ if (!ledgers) headerLedgers.set(response, ledgers = new Map());
2945
+ let ledger = ledgers.get(key);
2946
+ if (!ledger) {
2947
+ ledger = {
2948
+ base: setCookie ? headers.getSetCookie() : headers.get(name),
2949
+ live: []
2950
+ };
2951
+ ledgers.set(key, ledger);
2952
+ }
2953
+ const declaration = {
2954
+ value,
2955
+ append: !!(options && options.append)
2956
+ };
2957
+ ledger.live.push(declaration);
2958
+ if (declaration.append) headers.append(name, value);else headers.set(name, value);
2013
2959
  solidJs.onCleanup(() => {
2014
2960
  if (response.committed) return;
2015
- if (prev === null) headers.delete(name);else headers.set(name, prev);
2961
+ const index = ledger.live.indexOf(declaration);
2962
+ if (index < 0) return;
2963
+ ledger.live.splice(index, 1);
2964
+ headers.delete(name);
2965
+ if (setCookie) {
2966
+ for (const cookie of ledger.base) headers.append(name, cookie);
2967
+ } else if (ledger.base !== null) {
2968
+ headers.set(name, ledger.base);
2969
+ }
2970
+ for (const d of ledger.live) {
2971
+ if (d.append) headers.append(name, d.value);else headers.set(name, d.value);
2972
+ }
2973
+ if (!ledger.live.length) ledgers.delete(key);
2016
2974
  });
2017
2975
  }
2018
2976
  }
@@ -2077,7 +3035,6 @@ Object.defineProperty(exports, "untrack", {
2077
3035
  enumerable: true,
2078
3036
  get: function () { return solidJs.untrack; }
2079
3037
  });
2080
- exports.Assets = Assets;
2081
3038
  exports.ChildProperties = ChildProperties;
2082
3039
  exports.DOMElements = DOMElements;
2083
3040
  exports.DOMWithState = DOMWithState;
@@ -2092,6 +3049,7 @@ exports.REVALIDATE_HEADER = REVALIDATE_HEADER;
2092
3049
  exports.RawTextElements = RawTextElements;
2093
3050
  exports.RequestContext = RequestContext;
2094
3051
  exports.ResponseEnvelope = ResponseEnvelope;
3052
+ exports.SAFE_ERROR = SAFE_ERROR;
2095
3053
  exports.SVGElements = SVGElements;
2096
3054
  exports.VoidElements = VoidElements;
2097
3055
  exports.acquireAsset = notSup;
@@ -2101,20 +3059,31 @@ exports.assign = notSup;
2101
3059
  exports.claimElement = claimElement;
2102
3060
  exports.claimElementTree = claimElementTree;
2103
3061
  exports.className = notSup;
3062
+ exports.clearFlashCookie = clearFlashCookie;
2104
3063
  exports.clientOnly = clientOnly;
3064
+ exports.commitEventResponse = commitEventResponse;
3065
+ exports.commitResponseStub = commitResponseStub;
3066
+ exports.composeMiddleware = composeMiddleware;
3067
+ exports.createLiveHoles = createLiveHoles;
3068
+ exports.createRequestEvent = createRequestEvent;
3069
+ exports.createResponseStub = createResponseStub;
3070
+ exports.createSSRResponse = createSSRResponse;
2105
3071
  exports.delegateEvents = notSup;
2106
3072
  exports.dynamic = dynamic;
2107
3073
  exports.dynamicProperty = notSup;
2108
3074
  exports.effect = effect;
2109
3075
  exports.escape = escape;
2110
3076
  exports.generateHydrationScript = generateHydrationScript;
2111
- exports.getAssets = getAssets;
2112
3077
  exports.getDelegatedRoot = notSup;
3078
+ exports.getExpectedRedirectStatus = getExpectedRedirectStatus;
2113
3079
  exports.getHydrationKey = getHydrationKey;
2114
3080
  exports.getNextElement = notSup;
2115
3081
  exports.getNextMarker = notSup;
2116
3082
  exports.getNextMatch = notSup;
2117
3083
  exports.getRequestEvent = getRequestEvent;
3084
+ exports.getServerFunctionMetadata = getServerFunctionMetadata;
3085
+ exports.getServerFunctionRPC = getServerFunctionRPC;
3086
+ exports.hasFlashCookie = hasFlashCookie;
2118
3087
  exports.httpHeader = httpHeader;
2119
3088
  exports.httpStatus = httpStatus;
2120
3089
  exports.hydrate = notSup;
@@ -2122,8 +3091,12 @@ exports.insert = notSup;
2122
3091
  exports.isDev = isDev;
2123
3092
  exports.isHref = isHref;
2124
3093
  exports.isResponseEnvelope = isResponseEnvelope;
3094
+ exports.isSafeError = isSafeError;
2125
3095
  exports.isServer = isServer;
3096
+ exports.isServerFunction = isServerFunction;
3097
+ exports.markSafeError = markSafeError;
2126
3098
  exports.memo = memo;
3099
+ exports.parseCookieHeader = parseCookieHeader;
2127
3100
  exports.redirect = redirect;
2128
3101
  exports.ref = notSup;
2129
3102
  exports.registerDelegatedContainer = notSup;
@@ -2133,9 +3106,9 @@ exports.reload = reload;
2133
3106
  exports.render = notSup;
2134
3107
  exports.renderToStream = renderToStream;
2135
3108
  exports.renderToString = renderToString;
2136
- exports.renderToStringAsync = renderToStringAsync;
2137
3109
  exports.respond = respond;
2138
3110
  exports.runHydrationEvents = notSup;
3111
+ exports.serializeCookie = serializeCookie;
2139
3112
  exports.setAttribute = notSup;
2140
3113
  exports.setAttributeNS = notSup;
2141
3114
  exports.setProperty = notSup;
@@ -2153,5 +3126,4 @@ exports.style = notSup;
2153
3126
  exports.template = notSup;
2154
3127
  exports.unregisterDelegatedContainer = notSup;
2155
3128
  exports.unregisterDelegatedRoot = notSup;
2156
- exports.useAssets = useAssets;
2157
3129
  exports.useHead = useHead;