@solidjs/web 2.0.0-beta.32 → 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 (52) hide show
  1. package/dist/dev.cjs +51 -15
  2. package/dist/dev.js +47 -16
  3. package/dist/server.cjs +710 -71
  4. package/dist/server.js +707 -74
  5. package/dist/web.cjs +51 -15
  6. package/dist/web.js +47 -16
  7. package/frames/dist/client.cjs +181 -64
  8. package/frames/dist/client.dev.cjs +185 -64
  9. package/frames/dist/client.dev.js +183 -62
  10. package/frames/dist/client.js +179 -62
  11. package/frames/dist/server.cjs +969 -133
  12. package/frames/dist/server.js +971 -135
  13. package/package.json +17 -6
  14. package/serialization/decode/package.json +20 -0
  15. package/serialization/dist/decode.cjs +110 -0
  16. package/serialization/dist/decode.js +104 -0
  17. package/serialization/dist/serialization.cjs +98 -43
  18. package/serialization/dist/serialization.js +99 -44
  19. package/serialization/types/index.d.ts +18 -160
  20. package/serialization/types/serializer-decode.d.ts +182 -0
  21. package/serialization/types-cjs/index.d.cts +18 -160
  22. package/serialization/types-cjs/serializer-decode.d.cts +182 -0
  23. package/server-functions/dist/client.cjs +101 -105
  24. package/server-functions/dist/client.js +101 -105
  25. package/server-functions/dist/server.cjs +131 -107
  26. package/server-functions/dist/server.dev.cjs +131 -107
  27. package/server-functions/dist/server.dev.js +132 -108
  28. package/server-functions/dist/server.js +132 -108
  29. package/types/client.d.ts +23 -1
  30. package/types/cookies.d.ts +93 -0
  31. package/types/core.d.ts +1 -1
  32. package/types/frames/frame-client.d.ts +26 -0
  33. package/types/frames/frame-transport.d.ts +1 -1
  34. package/types/frames/serializer.d.ts +18 -160
  35. package/types/serializer-decode.d.ts +182 -0
  36. package/types/serializer.d.ts +18 -160
  37. package/types/server-functions/client.d.ts +1 -1
  38. package/types/server-functions/server.d.ts +1 -1
  39. package/types/server-functions/shared.d.ts +57 -1
  40. package/types/server.d.ts +21 -1
  41. package/types-cjs/client.d.cts +23 -1
  42. package/types-cjs/cookies.d.cts +93 -0
  43. package/types-cjs/core.d.cts +1 -1
  44. package/types-cjs/frames/frame-client.d.cts +26 -0
  45. package/types-cjs/frames/frame-transport.d.cts +1 -1
  46. package/types-cjs/frames/serializer.d.cts +18 -160
  47. package/types-cjs/serializer-decode.d.cts +182 -0
  48. package/types-cjs/serializer.d.cts +18 -160
  49. package/types-cjs/server-functions/client.d.cts +1 -1
  50. package/types-cjs/server-functions/server.d.cts +1 -1
  51. package/types-cjs/server-functions/shared.d.cts +57 -1
  52. package/types-cjs/server.d.cts +21 -1
@@ -4,6 +4,98 @@ var solidJs = require('solid-js');
4
4
  var seroval = require('seroval');
5
5
  var web = require('seroval-plugins/web');
6
6
 
7
+ const STATE = Symbol.for("dom-expressions.container-trace-state");
8
+ const state = globalThis[STATE] || (globalThis[STATE] = {
9
+ materialized: new WeakMap(),
10
+ materializedValues: new WeakSet()
11
+ });
12
+ function setContainerTraceResolver(fn) {
13
+ state.resolveTrace = fn;
14
+ }
15
+ function isContainerTraced(value) {
16
+ const resolve = state.resolveTrace;
17
+ return !!(resolve && value && typeof value === "object" && resolve(value));
18
+ }
19
+ const TRACE = Symbol.for("dom-expressions.container-trace");
20
+ function envelopeContainerTraces(value) {
21
+ if (!state.resolveTrace || value == null || typeof value !== "object") return value;
22
+ const trace = state.resolveTrace(value);
23
+ if (trace) return {
24
+ [TRACE]: trace
25
+ };
26
+ if (Array.isArray(value)) {
27
+ let out = value;
28
+ for (let i = 0; i < value.length; i++) {
29
+ const next = envelopeContainerTraces(value[i]);
30
+ if (next !== value[i]) {
31
+ if (out === value) out = value.slice();
32
+ out[i] = next;
33
+ }
34
+ }
35
+ return out;
36
+ }
37
+ if (Object.getPrototypeOf(value) === Object.prototype) {
38
+ let out = value;
39
+ for (const key of Object.keys(value)) {
40
+ const next = envelopeContainerTraces(value[key]);
41
+ if (next !== value[key]) {
42
+ if (out === value) out = {
43
+ ...value
44
+ };
45
+ out[key] = next;
46
+ }
47
+ }
48
+ return out;
49
+ }
50
+ return value;
51
+ }
52
+ function materialize(marker) {
53
+ let value = state.materialized.get(marker.$tr);
54
+ if (value === undefined) {
55
+ value = state.materializeTrace(marker);
56
+ state.materialized.set(marker.$tr, value);
57
+ if (value !== null && typeof value === "object") state.materializedValues.add(value);
58
+ }
59
+ return value;
60
+ }
61
+ function parseTrace(value, ctx) {
62
+ const trace = value[TRACE];
63
+ return {
64
+ a: trace.array ? 1 : 0,
65
+ i: ctx.parse(trace.subscribe())
66
+ };
67
+ }
68
+ const ContainerTracePlugin = {
69
+ tag: "dom-expressions/container-trace",
70
+ test(value) {
71
+ return value != null && typeof value === "object" && TRACE in value;
72
+ },
73
+ parse: {
74
+ sync() {
75
+ throw new Error("A reactive container can only be serialized by a streaming serializer.");
76
+ },
77
+ async async(value, ctx) {
78
+ const trace = value[TRACE];
79
+ return {
80
+ a: trace.array ? 1 : 0,
81
+ i: await ctx.parse(trace.subscribe())
82
+ };
83
+ },
84
+ stream: parseTrace
85
+ },
86
+ serialize(node, ctx) {
87
+ return "{$tr:" + ctx.serialize(node.i) + ",$ta:" + node.a + "}";
88
+ },
89
+ deserialize(node, ctx) {
90
+ const iterable = ctx.deserialize(node.i);
91
+ const marker = {
92
+ $tr: iterable,
93
+ $ta: node.a
94
+ };
95
+ return state.materializeTrace ? materialize(marker) : marker;
96
+ }
97
+ };
98
+
7
99
  const runWithHydrationScope = (id, fn) => solidJs.runWithOwner(solidJs.createOwner({
8
100
  id
9
101
  }), fn);
@@ -11,15 +103,30 @@ const ssrAsyncValue = value => solidJs.createMemo(() => value, {
11
103
  serialize: false
12
104
  });
13
105
 
14
- const DEFAULT_DISABLED_FEATURES = seroval.Feature.AggregateError | seroval.Feature.BigIntTypedArray;
15
- const serializeOnlyDisabledFeatures = () => process.env.NODE_ENV === "development" ? 0 : seroval.Feature.ErrorPrototypeStack;
16
- const HYDRATION_GLOBAL = "_$HY.r";
17
106
  const DEFAULT_WEB_PLUGINS = Object.freeze([web.AbortSignalPlugin,
18
107
  web.CustomEventPlugin, web.DOMExceptionPlugin, web.EventPlugin,
19
- web.FormDataPlugin, web.HeadersPlugin, web.ReadableStreamPlugin, web.RequestPlugin, web.ResponsePlugin, web.URLSearchParamsPlugin, web.URLPlugin]);
108
+ web.FormDataPlugin, web.HeadersPlugin, web.ReadableStreamPlugin, web.RequestPlugin, web.ResponsePlugin, web.URLSearchParamsPlugin, web.URLPlugin,
109
+ ContainerTracePlugin]);
20
110
  function resolveSerializerPlugins(customPlugins) {
21
111
  return customPlugins ? [...customPlugins, ...DEFAULT_WEB_PLUGINS] : [...DEFAULT_WEB_PLUGINS];
22
112
  }
113
+ const JSON_CODEC_DISABLED_FEATURES = seroval.Feature.RegExp;
114
+ const JSON_CODEC_DEPTH_LIMIT = 64;
115
+ function resolveCodecOptions({
116
+ plugins,
117
+ disabledFeatures,
118
+ depthLimit
119
+ } = {}) {
120
+ return {
121
+ plugins: resolveSerializerPlugins(plugins),
122
+ disabledFeatures: disabledFeatures === undefined ? JSON_CODEC_DISABLED_FEATURES : disabledFeatures,
123
+ depthLimit: depthLimit === undefined ? JSON_CODEC_DEPTH_LIMIT : depthLimit
124
+ };
125
+ }
126
+
127
+ const DEFAULT_DISABLED_FEATURES = seroval.Feature.AggregateError | seroval.Feature.BigIntTypedArray;
128
+ const serializeOnlyDisabledFeatures = () => process.env.NODE_ENV === "development" ? 0 : seroval.Feature.ErrorPrototypeStack;
129
+ const HYDRATION_GLOBAL = "_$HY.r";
23
130
  function createSerializer(options) {
24
131
  return new seroval.Serializer({
25
132
  ...options,
@@ -46,34 +153,6 @@ function createHydrationSerializer({
46
153
  function getLocalHeaderScript(id) {
47
154
  return seroval.getCrossReferenceHeader(id) + ";";
48
155
  }
49
- const JSON_CODEC_DISABLED_FEATURES = seroval.Feature.RegExp;
50
- const JSON_CODEC_DEPTH_LIMIT = 64;
51
- function resolveCodecOptions({
52
- plugins,
53
- disabledFeatures,
54
- depthLimit
55
- } = {}) {
56
- return {
57
- plugins: resolveSerializerPlugins(plugins),
58
- disabledFeatures: disabledFeatures === undefined ? JSON_CODEC_DISABLED_FEATURES : disabledFeatures,
59
- depthLimit: depthLimit === undefined ? JSON_CODEC_DEPTH_LIMIT : depthLimit
60
- };
61
- }
62
- function serializeJSON(value, {
63
- onParse,
64
- onDone,
65
- onError,
66
- ...codecOptions
67
- }) {
68
- const resolved = resolveCodecOptions(codecOptions);
69
- return seroval.toCrossJSONStream(value, {
70
- onParse,
71
- onDone,
72
- onError,
73
- ...resolved,
74
- disabledFeatures: resolved.disabledFeatures | serializeOnlyDisabledFeatures()
75
- });
76
- }
77
156
  function createJSONSerializer({
78
157
  onData,
79
158
  onDone,
@@ -260,7 +339,10 @@ class ChunkReader {
260
339
  }
261
340
  function serializeStream(value, codecOptions) {
262
341
  return new ReadableStream({
263
- start(controller) {
342
+ async start(controller) {
343
+ const {
344
+ serializeJSON
345
+ } = await import('@solidjs/web/serialization');
264
346
  serializeJSON(value, {
265
347
  ...codecOptions,
266
348
  onParse(node) {
@@ -347,7 +429,6 @@ function resolveHead(groups) {
347
429
  }
348
430
  for (const [identity, tags] of byIdentity) {
349
431
  if (identity === "title") {
350
- if (tags.length > 1) console.warn("Multiple <title> tags in one head group; the last one wins.");
351
432
  winners.set(identity, {
352
433
  seq: group.seq,
353
434
  tags: [tags[tags.length - 1]]
@@ -537,7 +618,6 @@ function registerHeadTags(registry, context, tracking, emitResource, nonce, tags
537
618
  for (let i = 0; i < tags.length; i++) {
538
619
  const desc = tags[i];
539
620
  if (!desc || !HEAD_ELIGIBLE_TAGS.has(desc.tag)) {
540
- console.warn(`useHead: ignoring non-head tag`, desc);
541
621
  continue;
542
622
  }
543
623
  const cls = classifyHeadTag(desc);
@@ -589,7 +669,6 @@ function headShellReady(registry, block) {
589
669
  } : undefined);
590
670
  } catch (err) {
591
671
  if (pends(err)) continue;
592
- console.warn(`useHead: error evaluating resource tag props`, err);
593
672
  parked.splice(i, 1);
594
673
  continue;
595
674
  }
@@ -630,7 +709,6 @@ function emitHeadResource(registry, context, tracking, emitResource, nonce, desc
630
709
  });
631
710
  return;
632
711
  }
633
- console.warn(`useHead: error evaluating resource tag props`, err);
634
712
  return;
635
713
  }
636
714
  const identity = resourceIdentity(desc.tag, props);
@@ -692,7 +770,6 @@ function commitHeadBoundary(registry, boundary, isPendingFragment) {
692
770
  try {
693
771
  resolved = reg.list();
694
772
  } catch (err) {
695
- console.warn(`useHead: error evaluating head group membership`, err);
696
773
  continue;
697
774
  }
698
775
  if (!Array.isArray(resolved)) resolved = [resolved];
@@ -700,7 +777,6 @@ function commitHeadBoundary(registry, boundary, isPendingFragment) {
700
777
  for (let j = 0; j < resolved.length; j++) {
701
778
  const desc = resolved[j];
702
779
  if (!desc || !HEAD_ELIGIBLE_TAGS.has(desc.tag)) {
703
- console.warn(`useHead: ignoring non-head tag`, desc);
704
780
  continue;
705
781
  }
706
782
  const cls = classifyHeadTag(desc);
@@ -726,12 +802,10 @@ function commitHeadBoundary(registry, boundary, isPendingFragment) {
726
802
  } : undefined);
727
803
  key = evalHeadValue(desc.key);
728
804
  } catch (err) {
729
- console.warn(`useHead: error evaluating tag props`, err);
730
805
  continue;
731
806
  }
732
807
  const identity = replaceableIdentity(desc.tag, props, key, "u:" + registry.uniq++);
733
808
  if ((identity === "base" || identity === "charset") && registry.shellFlushed) {
734
- console.warn(`useHead: <${desc.tag}> (${identity}) registered after shell flush is ignored`);
735
809
  continue;
736
810
  }
737
811
  tags.push({
@@ -813,7 +887,6 @@ function flushHeadFragment(registry, boundary) {
813
887
  for (const name in t.props) {
814
888
  if (name === "children" || name === "ref" || name.slice(0, 2) === "on") continue;
815
889
  if (!HEAD_ATTR_NAME.test(name)) {
816
- console.warn(`useHead: ignoring invalid attribute name "${name}"`);
817
890
  continue;
818
891
  }
819
892
  const v = t.props[name];
@@ -831,7 +904,6 @@ function renderHeadAttrHtml(props) {
831
904
  for (const name in props) {
832
905
  if (name === "children" || name === "ref" || name.slice(0, 2) === "on") continue;
833
906
  if (!HEAD_ATTR_NAME.test(name)) {
834
- console.warn(`useHead: ignoring invalid attribute name "${name}"`);
835
907
  continue;
836
908
  }
837
909
  const v = props[name];
@@ -891,6 +963,12 @@ function renderToStream(code, options = {}) {
891
963
  d();
892
964
  }
893
965
  };
966
+ const failRender = err => {
967
+ try {
968
+ options.onError ? options.onError(err) : console.error(err);
969
+ } catch (_) {}
970
+ abandon();
971
+ };
894
972
  const guardSink = w => ({
895
973
  write(payload) {
896
974
  if (dead) return;
@@ -989,10 +1067,18 @@ function renderToStream(code, options = {}) {
989
1067
  rootAssetsSerialized = true;
990
1068
  serializeFragmentAssets("", tracking.boundaryModules, context);
991
1069
  };
1070
+ let holds = 0;
992
1071
  const flushEnd = () => {
993
- if (!registry.size) {
1072
+ if (!registry.size && !holds) {
994
1073
  serializeRootAssets();
995
- queue(() => queue(() => serializer.flush()));
1074
+ queue(() => queue(() => {
1075
+ if (context.live.end) {
1076
+ const end = context.live.end;
1077
+ context.live.end = null;
1078
+ end();
1079
+ }
1080
+ serializer.flush();
1081
+ }));
996
1082
  }
997
1083
  };
998
1084
  const registry = new Map();
@@ -1053,6 +1139,7 @@ function renderToStream(code, options = {}) {
1053
1139
  solidJs.sharedConfig.context = context = {
1054
1140
  async: true,
1055
1141
  nonce,
1142
+ live: {},
1056
1143
  registerHeadTags(tags) {
1057
1144
  registerHeadTags(headRegistry, context, tracking,
1058
1145
  (markup, gateEntry) => {
@@ -1089,6 +1176,16 @@ function renderToStream(code, options = {}) {
1089
1176
  block(p) {
1090
1177
  if (!firstFlushed) blockingPromises.add(p);
1091
1178
  },
1179
+ hold() {
1180
+ holds++;
1181
+ let released = false;
1182
+ return () => {
1183
+ if (released) return;
1184
+ released = true;
1185
+ holds--;
1186
+ if (!holds) queue(flushEnd);
1187
+ };
1188
+ },
1092
1189
  replace(id, payloadFn) {
1093
1190
  if (firstFlushed) return;
1094
1191
  const placeholder = `<!--!$${id}-->`;
@@ -1197,6 +1294,7 @@ function renderToStream(code, options = {}) {
1197
1294
  }
1198
1295
  };
1199
1296
  applyAssetTracking(context, tracking, manifest, noScripts);
1297
+ context.failRender = failRender;
1200
1298
  registerEntryAssets(manifest);
1201
1299
  let html = solidJs.createRoot(d => {
1202
1300
  dispose = d;
@@ -1309,7 +1407,12 @@ function renderToStream(code, options = {}) {
1309
1407
  allSettled(blockingPromises).then(() => {
1310
1408
  scheduleFlush(() => {
1311
1409
  if (dead) return resolve();
1312
- doShell();
1410
+ try {
1411
+ doShell();
1412
+ } catch (err) {
1413
+ failRender(err);
1414
+ return resolve();
1415
+ }
1313
1416
  if (!shellCompleted) return flush();
1314
1417
  const encoder = new TextEncoder();
1315
1418
  const writer = w.getWriter();
@@ -1366,7 +1469,12 @@ function renderToStream(code, options = {}) {
1366
1469
  function flush() {
1367
1470
  allSettled(blockingPromises).then(() => {
1368
1471
  scheduleFlush(() => {
1369
- if (!resolveRootHoles() || !headShellReady(headRegistry, p => blockingPromises.add(p))) return flush();
1472
+ try {
1473
+ if (!resolveRootHoles() || !headShellReady(headRegistry, p => blockingPromises.add(p))) return flush();
1474
+ } catch (err) {
1475
+ failRender(err);
1476
+ return resolve(tmp);
1477
+ }
1370
1478
  queue(flushEnd);
1371
1479
  });
1372
1480
  });
@@ -1381,7 +1489,15 @@ function renderToStream(code, options = {}) {
1381
1489
  allSettled(blockingPromises).then(() => {
1382
1490
  scheduleFlush(() => {
1383
1491
  if (dead) return;
1384
- doShell();
1492
+ try {
1493
+ doShell();
1494
+ } catch (err) {
1495
+ failRender(err);
1496
+ try {
1497
+ w.end();
1498
+ } catch (_) {}
1499
+ return;
1500
+ }
1385
1501
  if (!shellCompleted) return flush();
1386
1502
  buffer = writable = guardSink(w);
1387
1503
  buffer.write(tmp);
@@ -1413,9 +1529,27 @@ function renderToStream(code, options = {}) {
1413
1529
  function buildAsyncWrap(err, node) {
1414
1530
  const p = solidJs.ssrHandleError(err);
1415
1531
  if (!p) return null;
1532
+ if (node.$rw) return {
1533
+ fn: node,
1534
+ p
1535
+ };
1416
1536
  const owner = solidJs.getOwner();
1537
+ const live = solidJs.sharedConfig.context && solidJs.sharedConfig.context.liveHoles;
1538
+ const suppress = node.$lhSuppress || live && (live.suppressed || live.sweeping);
1539
+ if (!owner) {
1540
+ if (suppress) node.$lhSuppress = true;
1541
+ return {
1542
+ fn: node,
1543
+ p
1544
+ };
1545
+ }
1546
+ const fn = () => solidJs.runWithOwner(owner, node);
1547
+ fn.$rw = true;
1548
+ if (suppress) fn.$lhSuppress = true;
1549
+ if (node.$lhSkip) fn.$lhSkip = true;
1550
+ if (node.$lhBinding) fn.$lhBinding = node.$lhBinding;
1417
1551
  return {
1418
- fn: owner ? () => solidJs.runWithOwner(owner, node) : node,
1552
+ fn,
1419
1553
  p
1420
1554
  };
1421
1555
  }
@@ -1475,6 +1609,326 @@ function ssrGroupSlot(fn, idx) {
1475
1609
  }
1476
1610
  };
1477
1611
  }
1612
+ const holePositionCache = new WeakMap();
1613
+ function holeContentPositions(t) {
1614
+ let cached = holePositionCache.get(t);
1615
+ if (cached) return cached;
1616
+ const pos = [];
1617
+ const openOff = [];
1618
+ const closeOff = [];
1619
+ let inTag = false;
1620
+ let quote = "";
1621
+ let curOpen = null;
1622
+ let scanningName = false;
1623
+ for (let i = 0; i < t.length; i++) {
1624
+ const seg = t[i];
1625
+ let close = -1;
1626
+ const openAtStart = inTag;
1627
+ let reopened = false;
1628
+ for (let j = 0; j < seg.length; j++) {
1629
+ const ch = seg[j];
1630
+ if (quote) {
1631
+ if (ch === quote) quote = "";
1632
+ } else if (inTag) {
1633
+ if (scanningName && (ch === " " || ch === "\t" || ch === "\n" || ch === ">" || ch === "/")) {
1634
+ scanningName = false;
1635
+ curOpen = {
1636
+ seg: i,
1637
+ off: j
1638
+ };
1639
+ }
1640
+ if (ch === '"' || ch === "'") quote = ch;else if (ch === ">") {
1641
+ inTag = false;
1642
+ if (openAtStart && !reopened && close === -1) close = j;
1643
+ curOpen = null;
1644
+ }
1645
+ } else if (ch === "<") {
1646
+ inTag = true;
1647
+ scanningName = true;
1648
+ reopened = true;
1649
+ curOpen = null;
1650
+ }
1651
+ }
1652
+ if (inTag && scanningName) {
1653
+ scanningName = false;
1654
+ curOpen = {
1655
+ seg: i,
1656
+ off: seg.length
1657
+ };
1658
+ }
1659
+ closeOff.push(close);
1660
+ openOff.push(inTag && curOpen && curOpen.seg === i ? curOpen.off : -1);
1661
+ if (i < t.length - 1) pos.push(!inTag);
1662
+ }
1663
+ cached = {
1664
+ pos,
1665
+ openOff,
1666
+ closeOff
1667
+ };
1668
+ holePositionCache.set(t, cached);
1669
+ return cached;
1670
+ }
1671
+ function createLiveHoles(sink, scoped) {
1672
+ let nextId = 0;
1673
+ const stamp = typeof solidJs.creationStamp === "function" ? solidJs.creationStamp : () => 0;
1674
+ const inScope = scoped && typeof solidJs.inServerComponentScope === "function" ? solidJs.inServerComponentScope : null;
1675
+ const stripMarkers = html => html.replace(/<!--lh:\/?\d+-->/g, "");
1676
+ function resolveHoleValue(hole) {
1677
+ const result = {
1678
+ t: [""],
1679
+ h: [],
1680
+ p: []
1681
+ };
1682
+ try {
1683
+ resolveSSRNode(hole(), result);
1684
+ } catch (err) {
1685
+ const wrap = buildAsyncWrap(err, hole);
1686
+ if (!wrap) throw err;
1687
+ result.h.push(wrap.fn);
1688
+ result.p.push(wrap.p);
1689
+ result.t.push("");
1690
+ }
1691
+ return result;
1692
+ }
1693
+ function closeChildren(b) {
1694
+ for (const c of b.children) {
1695
+ c.closed = true;
1696
+ if (c.key) sink.closeBinding(c.key);
1697
+ closeChildren(c);
1698
+ }
1699
+ b.children.length = 0;
1700
+ }
1701
+ const engine = {
1702
+ suppressed: 0,
1703
+ sweeping: false,
1704
+ parent: null,
1705
+ recordStamp: 0,
1706
+ gateHit: false,
1707
+ content(hole) {
1708
+ if (hole.$lhSuppress) {
1709
+ const r = {
1710
+ t: [""],
1711
+ h: [],
1712
+ p: []
1713
+ };
1714
+ engine.suppressed++;
1715
+ try {
1716
+ try {
1717
+ resolveSSRNode(hole(), r);
1718
+ } catch (err) {
1719
+ const wrap = buildAsyncWrap(err, hole);
1720
+ if (wrap) {
1721
+ r.h.push(wrap.fn);
1722
+ r.p.push(wrap.p);
1723
+ r.t.push("");
1724
+ }
1725
+ }
1726
+ } finally {
1727
+ engine.suppressed--;
1728
+ }
1729
+ const b = hole.$lhBinding;
1730
+ if (b && !b.closed && !r.h.length && !engine.sweeping) {
1731
+ b.last = stripMarkers(r.t[0]);
1732
+ }
1733
+ return r.h.length ? r : r.t[0];
1734
+ }
1735
+ if (engine.suppressed || engine.sweeping) return null;
1736
+ if (hole.$lhSkip) return null;
1737
+ if (inScope && !inScope()) return null;
1738
+ const recordsBefore = engine.recordStamp;
1739
+ const ownersBefore = stamp();
1740
+ const owner = solidJs.getOwner();
1741
+ const b = {
1742
+ key: null,
1743
+ children: [],
1744
+ last: null,
1745
+ closed: false,
1746
+ sweep() {
1747
+ if (b.closed) return;
1748
+ const prevSweeping = engine.sweeping;
1749
+ engine.sweeping = true;
1750
+ engine.gateHit = false;
1751
+ const sweepOwnersBefore = stamp();
1752
+ let res;
1753
+ try {
1754
+ res = owner ? solidJs.runWithOwner(owner, () => resolveHoleValue(hole)) : resolveHoleValue(hole);
1755
+ } catch (err) {
1756
+ b.closed = true;
1757
+ sink.closeBinding(b.key);
1758
+ sink.error(b.key, String(err && err.message || err));
1759
+ return;
1760
+ } finally {
1761
+ engine.sweeping = prevSweeping;
1762
+ }
1763
+ if (engine.gateHit || stamp() !== sweepOwnersBefore) {
1764
+ b.closed = true;
1765
+ sink.closeBinding(b.key);
1766
+ return;
1767
+ }
1768
+ if (res.h.length) return;
1769
+ const html = res.t[0];
1770
+ if (b.last === null || html === b.last) return;
1771
+ b.last = html;
1772
+ closeChildren(b);
1773
+ sink.hole(b.key, html);
1774
+ }
1775
+ };
1776
+ if (engine.parent) engine.parent.children.push(b);
1777
+ const prevParent = engine.parent;
1778
+ engine.parent = b;
1779
+ let value;
1780
+ let escalated = null;
1781
+ try {
1782
+ value = hole();
1783
+ } catch (err) {
1784
+ const wrap = buildAsyncWrap(err, hole);
1785
+ if (!wrap) {
1786
+ engine.parent = prevParent;
1787
+ closeChildren(b);
1788
+ return "";
1789
+ }
1790
+ escalated = wrap;
1791
+ }
1792
+ if (!escalated && (typeof value === "function" && value.$lhSkip || value !== null && typeof value === "object" && value.$slot)) {
1793
+ engine.parent = prevParent;
1794
+ const r = {
1795
+ t: [""],
1796
+ h: [],
1797
+ p: []
1798
+ };
1799
+ engine.suppressed++;
1800
+ try {
1801
+ resolveSSRNode(value, r);
1802
+ } finally {
1803
+ engine.suppressed--;
1804
+ }
1805
+ return r.h.length ? r : r.t[0];
1806
+ }
1807
+ let res;
1808
+ if (escalated) {
1809
+ closeChildren(b);
1810
+ escalated.fn.$lhSuppress = true;
1811
+ escalated.fn.$lhBinding = b;
1812
+ res = {
1813
+ t: ["", ""],
1814
+ h: [escalated.fn],
1815
+ p: [escalated.p]
1816
+ };
1817
+ } else {
1818
+ res = {
1819
+ t: [""],
1820
+ h: [],
1821
+ p: []
1822
+ };
1823
+ try {
1824
+ resolveSSRNode(value, res);
1825
+ } catch (_) {
1826
+ engine.parent = prevParent;
1827
+ closeChildren(b);
1828
+ return "";
1829
+ }
1830
+ }
1831
+ engine.parent = prevParent;
1832
+ if (engine.recordStamp !== recordsBefore || stamp() !== ownersBefore) {
1833
+ return res.h.length ? res : res.t[0];
1834
+ }
1835
+ const id = nextId++;
1836
+ const key = b.key = "lh:" + id;
1837
+ const open = `<!--lh:${id}-->`;
1838
+ const close = `<!--lh:/${id}-->`;
1839
+ if (!res.h.length) {
1840
+ b.last = stripMarkers(res.t[0]);
1841
+ sink.openBinding(key, b);
1842
+ return open + res.t[0] + close;
1843
+ }
1844
+ const t = res.t.slice();
1845
+ t[0] = open + t[0];
1846
+ t[t.length - 1] += close;
1847
+ sink.openBinding(key, b);
1848
+ return {
1849
+ t,
1850
+ h: res.h,
1851
+ p: res.p
1852
+ };
1853
+ },
1854
+ mint() {
1855
+ return nextId++;
1856
+ },
1857
+ active() {
1858
+ return !inScope || inScope();
1859
+ },
1860
+ attr(cap) {
1861
+ const owner = solidJs.getOwner();
1862
+ const b = {
1863
+ key: "lha:" + cap.id,
1864
+ children: [],
1865
+ last: cap.base,
1866
+ closed: false,
1867
+ sweep() {
1868
+ if (b.closed) return;
1869
+ const prevSweeping = engine.sweeping;
1870
+ engine.sweeping = true;
1871
+ engine.gateHit = false;
1872
+ const sweepOwnersBefore = stamp();
1873
+ let html = "";
1874
+ try {
1875
+ let group = null;
1876
+ let groupVal = null;
1877
+ const run = () => {
1878
+ for (const part of cap.parts) {
1879
+ if (typeof part === "string") {
1880
+ html += part;
1881
+ continue;
1882
+ }
1883
+ let v;
1884
+ if (part.g) {
1885
+ if (group !== part.g) {
1886
+ group = part.g;
1887
+ groupVal = part.g();
1888
+ }
1889
+ v = groupVal[part.i];
1890
+ } else {
1891
+ v = part.f();
1892
+ }
1893
+ const vt = typeof v;
1894
+ if (vt === "string" || vt === "number") html += v;
1895
+ }
1896
+ };
1897
+ owner ? solidJs.runWithOwner(owner, run) : run();
1898
+ } catch (err) {
1899
+ if (solidJs.ssrHandleError(err, true)) return;
1900
+ b.closed = true;
1901
+ sink.closeBinding(b.key);
1902
+ sink.error("lha:" + cap.id, String(err && err.message || err));
1903
+ return;
1904
+ } finally {
1905
+ engine.sweeping = prevSweeping;
1906
+ }
1907
+ if (engine.gateHit || stamp() !== sweepOwnersBefore) {
1908
+ b.closed = true;
1909
+ sink.closeBinding(b.key);
1910
+ return;
1911
+ }
1912
+ if (html === b.last) return;
1913
+ const before = attrNames(b.last);
1914
+ const after = attrNames(html);
1915
+ const removed = before.filter(n => !after.includes(n));
1916
+ b.last = html;
1917
+ sink.attr(String(cap.id), html, removed);
1918
+ }
1919
+ };
1920
+ sink.openBinding(b.key, b);
1921
+ }
1922
+ };
1923
+ return engine;
1924
+ }
1925
+ function attrNames(text) {
1926
+ const names = [];
1927
+ const re = /(?:^|\s)([^\s=/>"']+)(?:="[^"]*")?/g;
1928
+ let m;
1929
+ while (m = re.exec(text)) names.push(m[1]);
1930
+ return names;
1931
+ }
1478
1932
  function ssr(t) {
1479
1933
  const len = arguments.length;
1480
1934
  if (len === 1) return {
@@ -1485,13 +1939,54 @@ function ssr(t) {
1485
1939
  let lastGroup = null;
1486
1940
  let lastGroupVal = null;
1487
1941
  let lastGroupIdx = 0;
1942
+ const live = solidJs.sharedConfig.context && solidJs.sharedConfig.context.liveHoles;
1943
+ const hp = live ? holeContentPositions(t) : null;
1944
+ let lastOpen = null;
1945
+ let cap = null;
1946
+ if (live && hp.openOff[0] >= 0) lastOpen = {
1947
+ r: null,
1948
+ seg: -1,
1949
+ off: hp.openOff[0]
1950
+ };
1951
+ const captureStart = () => {
1952
+ if (cap) return true;
1953
+ if (!lastOpen || live.suppressed || live.sweeping || !live.active()) return false;
1954
+ if (lastOpen.r !== result || result !== null && lastOpen.seg !== result.t.length - 1) {
1955
+ return false;
1956
+ }
1957
+ const id = live.mint();
1958
+ const inject = ` data-lha="${id}"`;
1959
+ let prefix;
1960
+ if (result === null) {
1961
+ s = s.slice(0, lastOpen.off) + inject + s.slice(lastOpen.off);
1962
+ prefix = s.slice(lastOpen.off + inject.length);
1963
+ } else {
1964
+ const seg = result.t[lastOpen.seg];
1965
+ result.t[lastOpen.seg] = seg.slice(0, lastOpen.off) + inject + seg.slice(lastOpen.off);
1966
+ prefix = result.t[lastOpen.seg].slice(lastOpen.off + inject.length);
1967
+ }
1968
+ cap = {
1969
+ id,
1970
+ parts: [prefix],
1971
+ base: prefix
1972
+ };
1973
+ return true;
1974
+ };
1488
1975
  for (let i = 1; i < len; i++) {
1489
1976
  const hole = arguments[i];
1490
1977
  const ht = typeof hole;
1491
1978
  if (ht === "string") {
1492
1979
  if (result === null) s += hole;else result.t[result.t.length - 1] += hole;
1980
+ if (cap) {
1981
+ cap.parts.push(hole);
1982
+ cap.base += hole;
1983
+ }
1493
1984
  } else if (ht === "number") {
1494
1985
  if (result === null) s += hole;else result.t[result.t.length - 1] += hole;
1986
+ if (cap) {
1987
+ cap.parts.push("" + hole);
1988
+ cap.base += hole;
1989
+ }
1495
1990
  } else if (hole == null || ht === "boolean") ; else if (ht === "function" && hole.$g) {
1496
1991
  let value;
1497
1992
  let hasValue = false;
@@ -1515,7 +2010,14 @@ function ssr(t) {
1515
2010
  if (Array.isArray(lastGroupVal)) {
1516
2011
  value = lastGroupVal[lastGroupIdx++];
1517
2012
  hasValue = true;
2013
+ if (live && !hp.pos[i - 1] && captureStart()) {
2014
+ cap.parts.push({
2015
+ g: hole,
2016
+ i: lastGroupIdx - 1
2017
+ });
2018
+ }
1518
2019
  } else {
2020
+ cap = null;
1519
2021
  result.h.push(ssrGroupSlot(lastGroupVal.fn, lastGroupIdx++));
1520
2022
  result.p.push(lastGroupVal.p);
1521
2023
  result.t.push("");
@@ -1525,6 +2027,7 @@ function ssr(t) {
1525
2027
  const vt = typeof value;
1526
2028
  if (vt === "string" || vt === "number") {
1527
2029
  if (result === null) s += value;else result.t[result.t.length - 1] += value;
2030
+ if (cap && !hp.pos[i - 1]) cap.base += value;
1528
2031
  } else if (value == null || vt === "boolean") ; else if (result !== null) {
1529
2032
  resolveSSRNode(value, result);
1530
2033
  } else {
@@ -1542,19 +2045,67 @@ function ssr(t) {
1542
2045
  }
1543
2046
  }
1544
2047
  }
1545
- } else if (result !== null) {
1546
- resolveSSRNode(hole, result);
1547
2048
  } else if (ht === "function") {
1548
- const r = tryResolveFunctionHole(hole);
1549
- if (typeof r === "string") s += r;else {
1550
- result = {
1551
- t: [s],
1552
- h: [],
1553
- p: []
1554
- };
1555
- s = "";
1556
- appendResolvedNode(result, r);
2049
+ let liveNode = null;
2050
+ if (live && hp.pos[i - 1] && (liveNode = live.content(hole)) !== null) {
2051
+ if (typeof liveNode === "string") {
2052
+ if (result === null) s += liveNode;else result.t[result.t.length - 1] += liveNode;
2053
+ } else {
2054
+ if (result === null) {
2055
+ result = {
2056
+ t: [s],
2057
+ h: [],
2058
+ p: []
2059
+ };
2060
+ s = "";
2061
+ }
2062
+ resolveSSRNode(liveNode, result);
2063
+ }
2064
+ } else if (result !== null) {
2065
+ const inTag = live && !hp.pos[i - 1];
2066
+ const capturing = inTag && captureStart();
2067
+ const li = capturing ? result.t.length - 1 : 0;
2068
+ const before = capturing ? result.t[li].length : 0;
2069
+ if (live) live.suppressed++;
2070
+ try {
2071
+ resolveSSRNode(hole, result);
2072
+ } finally {
2073
+ if (live) live.suppressed--;
2074
+ }
2075
+ if (capturing) {
2076
+ if (result.t.length - 1 === li) {
2077
+ cap.base += result.t[li].slice(before);
2078
+ cap.parts.push({
2079
+ f: hole
2080
+ });
2081
+ } else {
2082
+ cap = null;
2083
+ }
2084
+ }
2085
+ } else {
2086
+ const capturing = live && !hp.pos[i - 1] && captureStart();
2087
+ const r = tryResolveFunctionHole(hole);
2088
+ if (typeof r === "string") {
2089
+ s += r;
2090
+ if (capturing) {
2091
+ cap.base += r;
2092
+ cap.parts.push({
2093
+ f: hole
2094
+ });
2095
+ }
2096
+ } else {
2097
+ if (capturing) cap = null;
2098
+ result = {
2099
+ t: [s],
2100
+ h: [],
2101
+ p: []
2102
+ };
2103
+ s = "";
2104
+ appendResolvedNode(result, r);
2105
+ }
1557
2106
  }
2107
+ } else if (result !== null) {
2108
+ resolveSSRNode(hole, result);
1558
2109
  } else {
1559
2110
  const r = tryResolveString(hole);
1560
2111
  if (typeof r === "string") {
@@ -1570,6 +2121,32 @@ function ssr(t) {
1570
2121
  }
1571
2122
  }
1572
2123
  const next = t[i];
2124
+ if (live) {
2125
+ if (cap) {
2126
+ const co = hp.closeOff[i];
2127
+ if (co >= 0) {
2128
+ const tail = next.slice(0, co);
2129
+ cap.parts.push(tail);
2130
+ cap.base += tail;
2131
+ live.attr(cap);
2132
+ cap = null;
2133
+ } else {
2134
+ cap.parts.push(next);
2135
+ cap.base += next;
2136
+ }
2137
+ }
2138
+ if (hp.openOff[i] >= 0) {
2139
+ lastOpen = result === null ? {
2140
+ r: null,
2141
+ seg: -1,
2142
+ off: s.length + hp.openOff[i]
2143
+ } : {
2144
+ r: result,
2145
+ seg: result.t.length - 1,
2146
+ off: result.t[result.t.length - 1].length + hp.openOff[i]
2147
+ };
2148
+ }
2149
+ }
1573
2150
  if (result === null) s += next;else result.t[result.t.length - 1] += next;
1574
2151
  }
1575
2152
  if (result === null) return {
@@ -1802,7 +2379,6 @@ function tryResolveString(node) {
1802
2379
  merge: node
1803
2380
  };
1804
2381
  if (node.t === undefined) {
1805
- console.warn(`Unrecognized value. Skipped inserting`, node);
1806
2382
  return "";
1807
2383
  }
1808
2384
  return Array.isArray(node.t) ? node.t[0] : node.t;
@@ -1827,13 +2403,19 @@ function resolveSSRNode(node, result = {
1827
2403
  if (t === "string" || t === "number") {
1828
2404
  result.t[result.t.length - 1] += node;
1829
2405
  } else if (node == null || t === "boolean") ; else if (Array.isArray(node)) {
1830
- let prevNonObj = false;
1831
- for (let i = 0, len = node.length; i < len; i++) {
1832
- const item = node[i];
1833
- const itemNonObj = item !== null && typeof item !== "object";
1834
- if (!top && prevNonObj && itemNonObj) result.t[result.t.length - 1] += `<!--!$-->`;
1835
- prevNonObj = itemNonObj;
1836
- resolveSSRNode(item, result);
2406
+ const slotLive = node.$slot && solidJs.sharedConfig.context && solidJs.sharedConfig.context.liveHoles;
2407
+ if (slotLive) slotLive.suppressed++;
2408
+ try {
2409
+ let prevNonObj = false;
2410
+ for (let i = 0, len = node.length; i < len; i++) {
2411
+ const item = node[i];
2412
+ const itemNonObj = item !== null && typeof item !== "object";
2413
+ if (!top && prevNonObj && itemNonObj) result.t[result.t.length - 1] += `<!--!$-->`;
2414
+ prevNonObj = itemNonObj;
2415
+ resolveSSRNode(item, result);
2416
+ }
2417
+ } finally {
2418
+ if (slotLive) slotLive.suppressed--;
1837
2419
  }
1838
2420
  } else if (t === "object") {
1839
2421
  if (node.h) {
@@ -1845,16 +2427,22 @@ function resolveSSRNode(node, result = {
1845
2427
  }
1846
2428
  } else if (node.t !== undefined) {
1847
2429
  result.t[result.t.length - 1] += node.t;
1848
- } else console.warn(`Unrecognized value. Skipped inserting`, node);
2430
+ } else ;
1849
2431
  } else if (t === "function") {
1850
- try {
1851
- resolveSSRNode(node(), result);
1852
- } catch (err) {
1853
- const wrap = buildAsyncWrap(err, node);
1854
- if (wrap) {
1855
- result.h.push(wrap.fn);
1856
- result.p.push(wrap.p);
1857
- result.t.push("");
2432
+ const live = solidJs.sharedConfig.context && solidJs.sharedConfig.context.liveHoles;
2433
+ let liveNode = null;
2434
+ if (live && (liveNode = live.content(node)) !== null) {
2435
+ if (typeof liveNode === "string") result.t[result.t.length - 1] += liveNode;else resolveSSRNode(liveNode, result);
2436
+ } else {
2437
+ try {
2438
+ resolveSSRNode(node(), result);
2439
+ } catch (err) {
2440
+ const wrap = buildAsyncWrap(err, node);
2441
+ if (wrap) {
2442
+ result.h.push(wrap.fn);
2443
+ result.p.push(wrap.p);
2444
+ result.t.push("");
2445
+ }
1858
2446
  }
1859
2447
  }
1860
2448
  }
@@ -1889,7 +2477,7 @@ function parseServerComponent(value, ctx) {
1889
2477
  address: ctx.parse(value[SERVER_COMPONENT_ADDRESS])
1890
2478
  };
1891
2479
  }
1892
- const ServerComponentPlugin = /*#__PURE__*/seroval.createPlugin({
2480
+ const ServerComponentPlugin = {
1893
2481
  tag: "dom-expressions/server-component",
1894
2482
  test(value) {
1895
2483
  return typeof value === "function" && SERVER_COMPONENT in value;
@@ -1913,18 +2501,17 @@ const ServerComponentPlugin = /*#__PURE__*/seroval.createPlugin({
1913
2501
  ctx.deserialize(node.address);
1914
2502
  return globalThis._$SC.r(id);
1915
2503
  }
1916
- });
2504
+ };
1917
2505
  function flightCodec(codec) {
1918
2506
  const plugins = codec && codec.plugins || [];
1919
- for (const plugin of plugins) {
1920
- if (plugin && plugin.tag === "dom-expressions/server-component") return codec;
1921
- }
2507
+ if (plugins.some(plugin => plugin && plugin.tag === ServerComponentPlugin.tag)) return codec;
1922
2508
  return {
1923
2509
  ...codec,
1924
2510
  plugins: [...plugins, ServerComponentPlugin]
1925
2511
  };
1926
2512
  }
1927
2513
 
2514
+ const scopeStamp = typeof solidJs.creationStamp === "function" ? solidJs.creationStamp : () => 0;
1928
2515
  function serverOwned(render) {
1929
2516
  return solidJs.NoHydration ? solidJs.NoHydration({
1930
2517
  get children() {
@@ -2149,6 +2736,26 @@ function createFrameSink(emit, frame) {
2149
2736
  html
2150
2737
  });
2151
2738
  },
2739
+ hole(key, html) {
2740
+ emit({
2741
+ type: "hole",
2742
+ id,
2743
+ version,
2744
+ key,
2745
+ html
2746
+ });
2747
+ },
2748
+ attr(key, attrs, removed) {
2749
+ const chunk = {
2750
+ type: "attr",
2751
+ id,
2752
+ version,
2753
+ key,
2754
+ attrs
2755
+ };
2756
+ if (removed && removed.length) chunk.removed = removed;
2757
+ emit(chunk);
2758
+ },
2152
2759
  openBinding(key, b) {
2153
2760
  bindings.set(key, b);
2154
2761
  },
@@ -2180,6 +2787,7 @@ function renderServerComponent(component, options = {}) {
2180
2787
  if (ctx) {
2181
2788
  ctx.commit = sink.commit;
2182
2789
  ctx.commitEpoch = () => sink.epoch;
2790
+ ctx.liveHoles = createLiveHoles(sink);
2183
2791
  }
2184
2792
  return serverComponentScope(() => component(props));
2185
2793
  };
@@ -2240,7 +2848,8 @@ function frameStream(makeCode, options) {
2240
2848
  }
2241
2849
  function slotRange(occurrence) {
2242
2850
  return {
2243
- t: `<!--slot:${occurrence}:start--><!--slot:${occurrence}:end-->`
2851
+ t: `<!--slot:${occurrence}:start--><!--slot:${occurrence}:end-->`,
2852
+ $slot: true
2244
2853
  };
2245
2854
  }
2246
2855
  const OCCURRENCE_UNSAFE = /[^A-Za-z0-9_.-]/g;
@@ -2288,14 +2897,28 @@ function tapFirstYield(iterable) {
2288
2897
  }
2289
2898
  };
2290
2899
  }
2900
+ function suppressedFill(render) {
2901
+ const live = solidJs.sharedConfig.context && solidJs.sharedConfig.context.liveHoles;
2902
+ if (!live) return render();
2903
+ live.suppressed++;
2904
+ try {
2905
+ return render();
2906
+ } finally {
2907
+ live.suppressed--;
2908
+ }
2909
+ }
2291
2910
  function createDocumentSlotProps(clientProps, frameId) {
2292
2911
  const counts = Object.create(null);
2293
2912
  const getters = new Map();
2294
- const range = (occurrence, content) => [{
2295
- t: `<!--slot:${occurrence}:start-->`
2296
- }, content, {
2297
- t: `<!--slot:${occurrence}:end-->`
2298
- }];
2913
+ const range = (occurrence, content) => {
2914
+ const r = [{
2915
+ t: `<!--slot:${occurrence}:start-->`
2916
+ }, content, {
2917
+ t: `<!--slot:${occurrence}:end-->`
2918
+ }];
2919
+ r.$slot = true;
2920
+ return r;
2921
+ };
2299
2922
  const zoneOwner = solidJs.getOwner ? solidJs.getOwner() : null;
2300
2923
  const scoped = (occurrence, render) => {
2301
2924
  const id = `sc-${frameId}-${occurrence}-`;
@@ -2318,27 +2941,68 @@ function createDocumentSlotProps(clientProps, frameId) {
2318
2941
  if (!fn) {
2319
2942
  fn = (...callArgs) => {
2320
2943
  if (callArgs.length === 0 || callArgs[0] === undefined) {
2321
- return scoped(prop, () => {
2944
+ return suppressedFill(() => scoped(prop, () => {
2322
2945
  const value = clientProps[prop];
2323
2946
  return range(prop, typeof value === "function" ? value() : value);
2324
- });
2947
+ }));
2325
2948
  }
2326
2949
  const raw = callArgs[0];
2327
2950
  const occurrence = occurrenceId(prop, raw, counts);
2328
2951
  const slot = clientProps[prop];
2329
2952
  if (typeof slot !== "function") return range(occurrence, undefined);
2330
2953
  const resolved = {};
2954
+ const liveArgs = solidJs.sharedConfig.context && solidJs.sharedConfig.context.live && solidJs.sharedConfig.context.live.args;
2331
2955
  const vals = {};
2956
+ const evals = {};
2957
+ const states = {};
2958
+ const minted = {};
2332
2959
  for (const key of Object.keys(raw)) {
2333
2960
  if (key === "$key") continue;
2334
- let value = raw[key];
2335
- for (let d = 0; typeof value === "function" && d < 16; d++) value = value();
2961
+ const desc = Object.getOwnPropertyDescriptor(raw, key);
2962
+ let evaluate = null;
2963
+ let value;
2964
+ if (desc.get) {
2965
+ const get = desc.get;
2966
+ evaluate = () => unwrapThunks(get.call(raw));
2967
+ } else {
2968
+ value = desc.value;
2969
+ if (typeof value === "function") {
2970
+ const fn = value;
2971
+ evaluate = () => unwrapThunks(fn);
2972
+ }
2973
+ }
2974
+ if (evaluate) {
2975
+ evals[key] = evaluate;
2976
+ const stampBefore = scopeStamp();
2977
+ try {
2978
+ value = evaluate();
2979
+ states[key] = {
2980
+ settled: true,
2981
+ last: value
2982
+ };
2983
+ } catch (err) {
2984
+ const blocked = solidJs.ssrHandleError && solidJs.ssrHandleError(err);
2985
+ if (!blocked) throw err;
2986
+ const state = states[key] = {
2987
+ settled: false,
2988
+ last: undefined
2989
+ };
2990
+ value = retryArgUntilSettled(evaluate, blocked, key, occurrence, v => {
2991
+ state.settled = true;
2992
+ state.last = v;
2993
+ if (liveArgs) liveArgs.commit();
2994
+ });
2995
+ }
2996
+ if (scopeStamp() !== stampBefore) minted[key] = true;
2997
+ }
2336
2998
  vals[key] = value;
2337
2999
  }
2338
3000
  const regions = [];
2339
3001
  for (const key of Object.keys(vals)) {
2340
3002
  const value = vals[key];
2341
- if (isServerContent(value)) {
3003
+ if (isContainerTraced(value)) {
3004
+ resolved[key] = value;
3005
+ } else if (isServerContent(value)) {
2342
3006
  const childId = `${frameId}.${occurrence}.${key}`;
2343
3007
  const region = {
2344
3008
  key,
@@ -2377,7 +3041,7 @@ function createDocumentSlotProps(clientProps, frameId) {
2377
3041
  resolved[key] = value;
2378
3042
  }
2379
3043
  }
2380
- const out = scoped(occurrence, () => range(occurrence, slot(resolved)));
3044
+ const out = suppressedFill(() => scoped(occurrence, () => range(occurrence, slot(resolved))));
2381
3045
  const unused = regions.filter(r => !r.used);
2382
3046
  if (solidJs.sharedConfig.context) {
2383
3047
  const args = {};
@@ -2390,17 +3054,33 @@ function createDocumentSlotProps(clientProps, frameId) {
2390
3054
  };
2391
3055
  continue;
2392
3056
  }
2393
- if (isServerContent(value)) continue;
2394
- args[key] = value;
3057
+ if (!isContainerTraced(value) && isServerContent(value)) continue;
3058
+ args[key] = envelopeContainerTraces(value);
2395
3059
  }
2396
- solidJs.sharedConfig.context.serialize(`sc:slot:${frameId}:${occurrence}`, args);
3060
+ solidJs.sharedConfig.context.serialize(`sc:slot:${frameId}:${occurrence}`, {
3061
+ ...args
3062
+ });
2397
3063
  for (const region of unused) {
2398
3064
  region.locked = true;
2399
3065
  solidJs.sharedConfig.context.serialize(`sc:region:${region.childId}`, resolveRegionHtml(solidJs.sharedConfig.context, region.value));
2400
3066
  }
3067
+ if (liveArgs) {
3068
+ for (const key of Object.keys(evals)) {
3069
+ if (regions.some(r => r.key === key)) continue;
3070
+ if (minted[key]) continue;
3071
+ const ledgerKey = `${frameId}:${occurrence}:${key}`;
3072
+ openArgBinding(liveArgs, ledgerKey, occurrence, key, evals[key], states[key], value => {
3073
+ args[key] = envelopeContainerTraces(value);
3074
+ liveArgs.slot(frameId, occurrence, {
3075
+ ...args
3076
+ });
3077
+ });
3078
+ }
3079
+ }
2401
3080
  }
2402
3081
  return out;
2403
3082
  };
3083
+ fn.$lhSkip = true;
2404
3084
  getters.set(prop, fn);
2405
3085
  }
2406
3086
  return fn;
@@ -2414,6 +3094,113 @@ function frameElementOpen(id) {
2414
3094
  return `<${FRAME_TAG} ${FRAME_ID_ATTR}="${escaped}" style="display:contents">`;
2415
3095
  }
2416
3096
  const FRAME_ELEMENT_CLOSE = `</${FRAME_TAG}>`;
3097
+ function armDocumentLiveHoles(ctx) {
3098
+ if (!ctx || ctx.liveHoles !== undefined) return;
3099
+ const live = ctx.live;
3100
+ if (live && live.holes !== undefined) {
3101
+ ctx.liveHoles = live.holes;
3102
+ if (live.holes) {
3103
+ ctx.commit = live.commit;
3104
+ ctx.commitEpoch = live.commitEpoch;
3105
+ }
3106
+ return;
3107
+ }
3108
+ if (!live || !ctx.async || ctx.noHydrate || !ctx.serialize || typeof ReadableStream !== "function") {
3109
+ ctx.liveHoles = null;
3110
+ if (live) live.holes = null;
3111
+ return;
3112
+ }
3113
+ const bindings = new Map();
3114
+ let epoch = 0;
3115
+ let sweepScheduled = false;
3116
+ let closed = false;
3117
+ const sweep = () => {
3118
+ epoch++;
3119
+ for (const b of [...bindings.values()]) {
3120
+ try {
3121
+ b.sweep();
3122
+ } catch (_) {
3123
+ }
3124
+ }
3125
+ };
3126
+ const scheduleSweep = () => {
3127
+ if (closed || sweepScheduled || !bindings.size) return;
3128
+ sweepScheduled = true;
3129
+ queueMicrotask(() => {
3130
+ sweepScheduled = false;
3131
+ if (!closed) sweep();
3132
+ });
3133
+ };
3134
+ let channel;
3135
+ ctx.serialize("sc:live", new ReadableStream({
3136
+ start(c) {
3137
+ channel = c;
3138
+ }
3139
+ }));
3140
+ const push = op => {
3141
+ if (!closed) channel.enqueue(op);
3142
+ };
3143
+ ctx.liveHoles = live.holes = createLiveHoles({
3144
+ openBinding(key, b) {
3145
+ bindings.set(key, b);
3146
+ },
3147
+ closeBinding(key) {
3148
+ bindings.delete(key);
3149
+ },
3150
+ hole(key, html) {
3151
+ push({
3152
+ type: "hole",
3153
+ key,
3154
+ html
3155
+ });
3156
+ },
3157
+ attr(key, attrs, removed) {
3158
+ const op = {
3159
+ type: "attr",
3160
+ key,
3161
+ attrs
3162
+ };
3163
+ if (removed && removed.length) op.removed = removed;
3164
+ push(op);
3165
+ },
3166
+ error(key, error) {
3167
+ push({
3168
+ type: "error",
3169
+ key,
3170
+ error
3171
+ });
3172
+ },
3173
+ commit: scheduleSweep,
3174
+ get epoch() {
3175
+ return epoch;
3176
+ }
3177
+ }, true);
3178
+ ctx.commit = live.commit = scheduleSweep;
3179
+ ctx.commitEpoch = live.commitEpoch = () => epoch;
3180
+ live.args = {
3181
+ openBinding(key, b) {
3182
+ bindings.set(key, b);
3183
+ },
3184
+ closeBinding(key) {
3185
+ bindings.delete(key);
3186
+ },
3187
+ slot(fid, occurrence, args) {
3188
+ push({
3189
+ type: "slot",
3190
+ fid,
3191
+ key: occurrence,
3192
+ args
3193
+ });
3194
+ },
3195
+ commit: scheduleSweep
3196
+ };
3197
+ live.end = () => {
3198
+ if (closed) return;
3199
+ if (bindings.size) sweep();
3200
+ closed = true;
3201
+ channel.close();
3202
+ };
3203
+ }
2417
3204
  function frameTransformDirectResult(value, {
2418
3205
  id,
2419
3206
  args
@@ -2424,6 +3211,7 @@ function frameTransformDirectResult(value, {
2424
3211
  t: frameElementOpen(id)
2425
3212
  },
2426
3213
  serverOwned(() => {
3214
+ armDocumentLiveHoles(solidJs.sharedConfig.context);
2427
3215
  const slotProps = createDocumentSlotProps(props, id);
2428
3216
  return serverComponentScope(() => component(slotProps));
2429
3217
  }), {
@@ -2487,60 +3275,48 @@ function retryArgUntilSettled(evaluate, blocked, key, occurrence, onSettle) {
2487
3275
  blocked.then(retry, retry);
2488
3276
  });
2489
3277
  }
2490
- function openArgBinding(sink, ctx, occurrence, key, evaluate, args, state) {
3278
+ function openArgBinding(sink, ledgerKey, occurrence, key, evaluate, state, emit) {
2491
3279
  const owner = solidJs.getOwner();
2492
- const ledgerKey = `${occurrence}:${key}`;
2493
- const reEmit = value => {
2494
- const ref = `arg:${occurrence}:${key}@${sink.nextArgRef(ledgerKey)}`;
2495
- sink.mintRef(ref);
2496
- ctx.serialize(ref, value);
2497
- args[key] = {
2498
- $ref: ref
2499
- };
2500
- sink.slot(occurrence, {
2501
- ...args
2502
- });
2503
- };
2504
- const binding = {
3280
+ sink.openBinding(ledgerKey, {
2505
3281
  sweep() {
2506
3282
  if (!state.settled) return;
2507
3283
  let value;
3284
+ const stampBefore = scopeStamp();
2508
3285
  try {
2509
3286
  value = owner ? solidJs.runWithOwner(owner, evaluate) : evaluate();
2510
3287
  } catch (err) {
2511
3288
  const blocked = solidJs.ssrHandleError && solidJs.ssrHandleError(err);
2512
3289
  if (!blocked) {
2513
3290
  sink.closeBinding(ledgerKey);
2514
- reEmit(Promise.reject(err instanceof Error ? err : new Error(String(err))));
3291
+ emit(Promise.reject(err instanceof Error ? err : new Error(String(err))));
3292
+ return;
3293
+ }
3294
+ if (scopeStamp() !== stampBefore) {
3295
+ sink.closeBinding(ledgerKey);
2515
3296
  return;
2516
3297
  }
2517
3298
  state.settled = false;
2518
- reEmit(retryArgUntilSettled(evaluate, blocked, key, occurrence, v => {
3299
+ emit(retryArgUntilSettled(evaluate, blocked, key, occurrence, v => {
2519
3300
  state.settled = true;
2520
3301
  state.last = v;
2521
3302
  sink.commit();
2522
3303
  }));
2523
3304
  return;
2524
3305
  }
3306
+ if (scopeStamp() !== stampBefore) {
3307
+ sink.closeBinding(ledgerKey);
3308
+ return;
3309
+ }
2525
3310
  if (value === state.last) return;
2526
3311
  state.last = value;
2527
3312
  if (isServerContent(value)) {
2528
3313
  sink.closeBinding(ledgerKey);
2529
- reEmit(Promise.reject(contentArgError(key, occurrence)));
3314
+ emit(Promise.reject(contentArgError(key, occurrence)));
2530
3315
  return;
2531
3316
  }
2532
- const t = typeof value;
2533
- if (value == null || t === "string" || t === "number" || t === "boolean") {
2534
- args[key] = value;
2535
- sink.slot(occurrence, {
2536
- ...args
2537
- });
2538
- } else {
2539
- reEmit(value);
2540
- }
3317
+ emit(value);
2541
3318
  }
2542
- };
2543
- sink.openBinding(ledgerKey, binding);
3319
+ });
2544
3320
  }
2545
3321
  function createSlotProps(sink, frame) {
2546
3322
  const counts = Object.create(null);
@@ -2558,6 +3334,17 @@ function createSlotProps(sink, frame) {
2558
3334
  if (callArgs.length === 0 || callArgs[0] === undefined) {
2559
3335
  return slotRange(prop);
2560
3336
  }
3337
+ const live = solidJs.sharedConfig.context && solidJs.sharedConfig.context.liveHoles;
3338
+ if (live) {
3339
+ if (live.sweeping) {
3340
+ live.gateHit = true;
3341
+ return {
3342
+ t: "",
3343
+ $slot: true
3344
+ };
3345
+ }
3346
+ live.recordStamp++;
3347
+ }
2561
3348
  const raw = callArgs[0];
2562
3349
  const occurrence = occurrenceId(prop, raw, counts);
2563
3350
  const args = {};
@@ -2576,6 +3363,7 @@ function createSlotProps(sink, frame) {
2576
3363
  let evaluate = null;
2577
3364
  let value;
2578
3365
  let state = null;
3366
+ const stampBefore = scopeStamp();
2579
3367
  try {
2580
3368
  if (desc.get) {
2581
3369
  const get = desc.get;
@@ -2603,6 +3391,7 @@ function createSlotProps(sink, frame) {
2603
3391
  sink.commit();
2604
3392
  });
2605
3393
  }
3394
+ const mintedEval = scopeStamp() !== stampBefore;
2606
3395
  const t = typeof value;
2607
3396
  if (value == null || t === "string" || t === "number" || t === "boolean") {
2608
3397
  args[key] = value;
@@ -2610,7 +3399,7 @@ function createSlotProps(sink, frame) {
2610
3399
  settled: true,
2611
3400
  last: value
2612
3401
  };
2613
- } else if (isServerContent(value)) {
3402
+ } else if (!isContainerTraced(value) && isServerContent(value)) {
2614
3403
  const resolved = ctx.resolve(value);
2615
3404
  if (resolved.h.length) {
2616
3405
  throw new Error("Async server content in a slot arg needs a boundary (arg '" + key + "' of " + occurrence + "). Wrap the async read in a <Suspense>, or move it above the slot.");
@@ -2621,7 +3410,7 @@ function createSlotProps(sink, frame) {
2621
3410
  };
2622
3411
  } else {
2623
3412
  const ref = `arg:${occurrence}:${key}`;
2624
- ctx.serialize(ref, value);
3413
+ ctx.serialize(ref, envelopeContainerTraces(value));
2625
3414
  args[key] = {
2626
3415
  $ref: ref
2627
3416
  };
@@ -2630,7 +3419,7 @@ function createSlotProps(sink, frame) {
2630
3419
  last: value
2631
3420
  };
2632
3421
  }
2633
- if (evaluate && state) opened.push({
3422
+ if (evaluate && state && !mintedEval) opened.push({
2634
3423
  key,
2635
3424
  evaluate,
2636
3425
  state
@@ -2644,10 +3433,28 @@ function createSlotProps(sink, frame) {
2644
3433
  });
2645
3434
  const ctx = solidJs.sharedConfig.context;
2646
3435
  for (const b of opened) {
2647
- openArgBinding(sink, ctx, occurrence, b.key, b.evaluate, args, b.state);
3436
+ const key = b.key;
3437
+ const ledgerKey = `${occurrence}:${key}`;
3438
+ openArgBinding(sink, ledgerKey, occurrence, key, b.evaluate, b.state, value => {
3439
+ const t = typeof value;
3440
+ if (value == null || t === "string" || t === "number" || t === "boolean") {
3441
+ args[key] = value;
3442
+ } else {
3443
+ const ref = `arg:${occurrence}:${key}@${sink.nextArgRef(ledgerKey)}`;
3444
+ sink.mintRef(ref);
3445
+ ctx.serialize(ref, envelopeContainerTraces(value));
3446
+ args[key] = {
3447
+ $ref: ref
3448
+ };
3449
+ }
3450
+ sink.slot(occurrence, {
3451
+ ...args
3452
+ });
3453
+ });
2648
3454
  }
2649
3455
  return slotRange(occurrence);
2650
3456
  };
3457
+ fn.$lhSkip = true;
2651
3458
  getters.set(prop, fn);
2652
3459
  }
2653
3460
  return fn;
@@ -2679,16 +3486,27 @@ function serverComponentResponse(component, options = {}, init = {}) {
2679
3486
  version
2680
3487
  }
2681
3488
  });
3489
+ let closed = false;
2682
3490
  const body = new ReadableStream({
2683
3491
  start(controller) {
2684
3492
  stream.pipe({
2685
3493
  write(chunk) {
2686
- controller.enqueue(createChunk(JSON.stringify(chunk)));
3494
+ if (closed) return;
3495
+ try {
3496
+ controller.enqueue(createChunk(JSON.stringify(chunk)));
3497
+ } catch (_) {
3498
+ closed = true;
3499
+ }
2687
3500
  },
2688
3501
  end() {
3502
+ if (closed) return;
3503
+ closed = true;
2689
3504
  controller.close();
2690
3505
  }
2691
3506
  });
3507
+ },
3508
+ cancel() {
3509
+ closed = true;
2692
3510
  }
2693
3511
  });
2694
3512
  return new Response(body, {
@@ -2772,9 +3590,17 @@ function frameFlightResponse({
2772
3590
  headers.set(FRAME_STREAM_HEADER, primary ? primary.id : "");
2773
3591
  headers.set("X-Content-Raw", "1");
2774
3592
  headers.set(SINGLE_FLIGHT_HEADER, "true");
3593
+ let closed = false;
2775
3594
  const body = new ReadableStream({
2776
3595
  async start(controller) {
2777
- const write = chunk => controller.enqueue(createChunk(JSON.stringify(chunk)));
3596
+ const write = chunk => {
3597
+ if (closed) return;
3598
+ try {
3599
+ controller.enqueue(createChunk(JSON.stringify(chunk)));
3600
+ } catch (_) {
3601
+ closed = true;
3602
+ }
3603
+ };
2778
3604
  try {
2779
3605
  for (const {
2780
3606
  id,
@@ -2801,10 +3627,19 @@ function frameFlightResponse({
2801
3627
  });
2802
3628
  }
2803
3629
  }
2804
- controller.close();
3630
+ if (!closed) {
3631
+ closed = true;
3632
+ controller.close();
3633
+ }
2805
3634
  } catch (err) {
2806
- controller.error(err);
3635
+ if (!closed) {
3636
+ closed = true;
3637
+ controller.error(err);
3638
+ }
2807
3639
  }
3640
+ },
3641
+ cancel() {
3642
+ closed = true;
2808
3643
  }
2809
3644
  });
2810
3645
  return new Response(body, {
@@ -2813,6 +3648,7 @@ function frameFlightResponse({
2813
3648
  });
2814
3649
  }
2815
3650
 
3651
+ setContainerTraceResolver(solidJs.getProjectionTrace);
2816
3652
  function asyncArg(value) {
2817
3653
  return value;
2818
3654
  }