@solidjs/web 2.0.0-rc.0 → 2.0.0-rc.2

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 (40) hide show
  1. package/README.md +1 -1
  2. package/dist/dev.cjs +40 -11
  3. package/dist/dev.js +39 -12
  4. package/dist/server.cjs +419 -69
  5. package/dist/server.js +411 -73
  6. package/dist/web.cjs +37 -11
  7. package/dist/web.js +36 -12
  8. package/frames/dist/client.cjs +94 -8
  9. package/frames/dist/client.dev.cjs +97 -8
  10. package/frames/dist/client.dev.js +98 -9
  11. package/frames/dist/client.js +95 -9
  12. package/frames/dist/server.cjs +266 -56
  13. package/frames/dist/server.js +267 -57
  14. package/package.json +4 -3
  15. package/serialization/dist/decode.cjs +32 -3
  16. package/serialization/dist/decode.js +33 -4
  17. package/serialization/dist/serialization.cjs +32 -3
  18. package/serialization/dist/serialization.js +33 -4
  19. package/server-functions/dist/client.cjs +196 -8
  20. package/server-functions/dist/client.js +195 -9
  21. package/server-functions/dist/server.cjs +201 -36
  22. package/server-functions/dist/server.dev.cjs +201 -36
  23. package/server-functions/dist/server.dev.js +199 -37
  24. package/server-functions/dist/server.js +199 -37
  25. package/types/core.d.ts +3 -0
  26. package/types/frames/frame-client.d.ts +18 -0
  27. package/types/index.d.ts +16 -2
  28. package/types/jsx.d.ts +9 -0
  29. package/types/server-functions/client.d.ts +61 -0
  30. package/types/server-functions/server.d.ts +94 -1
  31. package/types/server-mock.d.ts +11 -2
  32. package/types/server.d.ts +23 -2
  33. package/types-cjs/core.d.cts +3 -0
  34. package/types-cjs/frames/frame-client.d.cts +18 -0
  35. package/types-cjs/index.d.cts +16 -2
  36. package/types-cjs/jsx.d.cts +9 -0
  37. package/types-cjs/server-functions/client.d.cts +61 -0
  38. package/types-cjs/server-functions/server.d.cts +94 -1
  39. package/types-cjs/server-mock.d.cts +11 -2
  40. package/types-cjs/server.d.cts +23 -2
package/dist/web.cjs CHANGED
@@ -87,13 +87,18 @@ function reconcileArrays(parentNode, a, b, marker) {
87
87
  map = null,
88
88
  anchor,
89
89
  anchorTag;
90
+ const isLive = n => {
91
+ if (!n) return false;
92
+ const tag = n[$$SLOT];
93
+ return n.parentNode === parentNode && (!tag || tag === marker);
94
+ };
90
95
  while (aStart < aEnd || bStart < bEnd) {
91
- if (a[aStart] === b[bStart]) {
96
+ if (a[aStart] === b[bStart] && isLive(a[aStart])) {
92
97
  aStart++;
93
98
  bStart++;
94
99
  continue;
95
100
  }
96
- while (a[aEnd - 1] === b[bEnd - 1]) {
101
+ while (a[aEnd - 1] === b[bEnd - 1] && isLive(a[aEnd - 1])) {
97
102
  aEnd--;
98
103
  bEnd--;
99
104
  }
@@ -586,6 +591,11 @@ function ref(fn, element) {
586
591
  const resolved = solidJs.untrack(fn);
587
592
  solidJs.runWithOwner(null, () => applyRef(resolved, element));
588
593
  }
594
+ const PURE_ROW = Symbol.for("solid.pure-row");
595
+ function rowProof(fn) {
596
+ fn[PURE_ROW] = true;
597
+ return fn;
598
+ }
589
599
  function scope(fn) {
590
600
  fn.$s = true;
591
601
  return fn;
@@ -649,6 +659,11 @@ function stripTextSeparators(nodes) {
649
659
  nodes.length = j;
650
660
  return nodes;
651
661
  }
662
+ function patchDriver(subject, body) {
663
+ {
664
+ effect(() => body(subject, subject, false), () => body(subject, undefined, true));
665
+ }
666
+ }
652
667
  function insert(parent, accessor, marker, initial, options) {
653
668
  const multi = marker !== undefined;
654
669
  const host = options && options.host;
@@ -889,7 +904,7 @@ function initHeadRegistry() {
889
904
  headOwned = new Map();
890
905
  headApplied = new Map();
891
906
  const t = document.querySelector("title");
892
- headFallbackTitle = t && !t.hasAttribute("data-dh") ? t.textContent : null;
907
+ headFallbackTitle = t ? t.hasAttribute("data-dh") ? t.getAttribute("data-dhf") : t.textContent : null;
893
908
  if (globalThis._$HY) globalThis._$HY.h = applyServerHeadOps;
894
909
  }
895
910
  function applyServerHeadOps(ops) {
@@ -944,7 +959,11 @@ function flushHeadRegistry() {
944
959
  headOwned.delete(identity);
945
960
  headApplied.delete(identity);
946
961
  if (identity === "title") {
947
- if (headFallbackTitle != null) setHeadTitle(headFallbackTitle).removeAttribute("data-dh");
962
+ if (headFallbackTitle != null) {
963
+ const el = setHeadTitle(headFallbackTitle);
964
+ el.removeAttribute("data-dh");
965
+ el.removeAttribute("data-dhf");
966
+ }
948
967
  } else {
949
968
  for (let i = 0; i < els.length; i++) els[i].remove();
950
969
  }
@@ -1108,7 +1127,7 @@ function loadModuleAssets(mapping) {
1108
1127
  const pending = [];
1109
1128
  for (const key in mapping) {
1110
1129
  if (hy.modules[key]) continue;
1111
- const entryUrl = mapping[key];
1130
+ const entryUrl = new URL(mapping[key], document.baseURI).href;
1112
1131
  if (!hy.loading[key]) {
1113
1132
  hy.loading[key] = import(entryUrl).then(mod => {
1114
1133
  hy.modules[key] = mod;
@@ -1361,6 +1380,7 @@ function eventHandler(e, container, state) {
1361
1380
  }
1362
1381
  const owner = state && (state.owners.size === 1 && state.owners.has(container) ? container : findOwner(e.target, state)?.owner);
1363
1382
  if (state && !owner) return;
1383
+ if (owner && owner === resumeNode) return;
1364
1384
  e[$$EVENT_OWNER] = owner || true;
1365
1385
  let node = resumeNode || e.target;
1366
1386
  const key = `$$${e.type}`;
@@ -1371,7 +1391,11 @@ function eventHandler(e, container, state) {
1371
1391
  value
1372
1392
  });
1373
1393
  const handleNode = () => {
1374
- const handler = node[key];
1394
+ let handler = node[key];
1395
+ if (handler === undefined && node.hasAttribute && node.hasAttribute("_bnd")) {
1396
+ const seam = globalThis[Symbol.for("dx.bnd")];
1397
+ if (seam) handler = seam.resolve(node, e.type);
1398
+ }
1375
1399
  if (handler && !node.disabled) {
1376
1400
  const data = node[`${key}Data`];
1377
1401
  data !== undefined ? handler.call(node, data, e) : handler.call(node, e);
@@ -1381,7 +1405,7 @@ function eventHandler(e, container, state) {
1381
1405
  return true;
1382
1406
  };
1383
1407
  const walkUpTree = () => {
1384
- while (handleNode()) {
1408
+ while (node && handleNode()) {
1385
1409
  if (node === boundary || node.parentNode === boundary) break;
1386
1410
  node = node._$host || node.parentNode || node.host;
1387
1411
  }
@@ -1828,21 +1852,21 @@ function createElement(tagName, is = undefined) {
1828
1852
  is
1829
1853
  });
1830
1854
  }
1831
- function loadClientOnly(fn, setComp) {
1832
- fn().then(m => setComp(() => m.default));
1855
+ function loadClientOnly(fn, setComp, exportName) {
1856
+ fn().then(m => setComp(() => exportName ? m[exportName] : m.default));
1833
1857
  }
1834
1858
  function clientOnly(fn, options = {},
1835
1859
  _moduleUrl) {
1836
1860
  const [comp, setComp] = solidJs.createSignal();
1837
1861
  let started = !options.lazy;
1838
- started && loadClientOnly(fn, setComp);
1862
+ started && loadClientOnly(fn, setComp, options.export);
1839
1863
  return props => {
1840
1864
  let Comp;
1841
1865
  let m;
1842
1866
  const rest = solidJs.omit(props, "fallback");
1843
1867
  if (!started) {
1844
1868
  started = true;
1845
- loadClientOnly(fn, setComp);
1869
+ loadClientOnly(fn, setComp, options.export);
1846
1870
  }
1847
1871
  if ((Comp = solidJs.untrack(comp)) && !solidJs.sharedConfig.hydrating) return Comp(rest);
1848
1872
  const [mounted, setMounted] = solidJs.createSignal(!solidJs.sharedConfig.hydrating);
@@ -1972,6 +1996,7 @@ exports.markSafeError = markSafeError;
1972
1996
  exports.memo = memo;
1973
1997
  exports.mergeProps = mergeProps;
1974
1998
  exports.parseCookieHeader = parseCookieHeader;
1999
+ exports.patchDriver = patchDriver;
1975
2000
  exports.redirect = redirect;
1976
2001
  exports.ref = ref;
1977
2002
  exports.registerDelegatedContainer = registerDelegatedContainer;
@@ -1983,6 +2008,7 @@ exports.renderToStream = renderToStream;
1983
2008
  exports.renderToString = renderToString;
1984
2009
  exports.resolveSSRNode = resolveSSRNode;
1985
2010
  exports.respond = respond;
2011
+ exports.rowProof = rowProof;
1986
2012
  exports.runHydrationEvents = runHydrationEvents;
1987
2013
  exports.scope = scope;
1988
2014
  exports.serializeCookie = serializeCookie;
package/dist/web.js CHANGED
@@ -86,13 +86,18 @@ function reconcileArrays(parentNode, a, b, marker) {
86
86
  map = null,
87
87
  anchor,
88
88
  anchorTag;
89
+ const isLive = n => {
90
+ if (!n) return false;
91
+ const tag = n[$$SLOT];
92
+ return n.parentNode === parentNode && (!tag || tag === marker);
93
+ };
89
94
  while (aStart < aEnd || bStart < bEnd) {
90
- if (a[aStart] === b[bStart]) {
95
+ if (a[aStart] === b[bStart] && isLive(a[aStart])) {
91
96
  aStart++;
92
97
  bStart++;
93
98
  continue;
94
99
  }
95
- while (a[aEnd - 1] === b[bEnd - 1]) {
100
+ while (a[aEnd - 1] === b[bEnd - 1] && isLive(a[aEnd - 1])) {
96
101
  aEnd--;
97
102
  bEnd--;
98
103
  }
@@ -585,6 +590,11 @@ function ref(fn, element) {
585
590
  const resolved = untrack(fn);
586
591
  runWithOwner(null, () => applyRef(resolved, element));
587
592
  }
593
+ const PURE_ROW = Symbol.for("solid.pure-row");
594
+ function rowProof(fn) {
595
+ fn[PURE_ROW] = true;
596
+ return fn;
597
+ }
588
598
  function scope(fn) {
589
599
  fn.$s = true;
590
600
  return fn;
@@ -648,6 +658,11 @@ function stripTextSeparators(nodes) {
648
658
  nodes.length = j;
649
659
  return nodes;
650
660
  }
661
+ function patchDriver(subject, body) {
662
+ {
663
+ effect(() => body(subject, subject, false), () => body(subject, undefined, true));
664
+ }
665
+ }
651
666
  function insert(parent, accessor, marker, initial, options) {
652
667
  const multi = marker !== undefined;
653
668
  const host = options && options.host;
@@ -888,7 +903,7 @@ function initHeadRegistry() {
888
903
  headOwned = new Map();
889
904
  headApplied = new Map();
890
905
  const t = document.querySelector("title");
891
- headFallbackTitle = t && !t.hasAttribute("data-dh") ? t.textContent : null;
906
+ headFallbackTitle = t ? t.hasAttribute("data-dh") ? t.getAttribute("data-dhf") : t.textContent : null;
892
907
  if (globalThis._$HY) globalThis._$HY.h = applyServerHeadOps;
893
908
  }
894
909
  function applyServerHeadOps(ops) {
@@ -943,7 +958,11 @@ function flushHeadRegistry() {
943
958
  headOwned.delete(identity);
944
959
  headApplied.delete(identity);
945
960
  if (identity === "title") {
946
- if (headFallbackTitle != null) setHeadTitle(headFallbackTitle).removeAttribute("data-dh");
961
+ if (headFallbackTitle != null) {
962
+ const el = setHeadTitle(headFallbackTitle);
963
+ el.removeAttribute("data-dh");
964
+ el.removeAttribute("data-dhf");
965
+ }
947
966
  } else {
948
967
  for (let i = 0; i < els.length; i++) els[i].remove();
949
968
  }
@@ -1107,7 +1126,7 @@ function loadModuleAssets(mapping) {
1107
1126
  const pending = [];
1108
1127
  for (const key in mapping) {
1109
1128
  if (hy.modules[key]) continue;
1110
- const entryUrl = mapping[key];
1129
+ const entryUrl = new URL(mapping[key], document.baseURI).href;
1111
1130
  if (!hy.loading[key]) {
1112
1131
  hy.loading[key] = import(entryUrl).then(mod => {
1113
1132
  hy.modules[key] = mod;
@@ -1360,6 +1379,7 @@ function eventHandler(e, container, state) {
1360
1379
  }
1361
1380
  const owner = state && (state.owners.size === 1 && state.owners.has(container) ? container : findOwner(e.target, state)?.owner);
1362
1381
  if (state && !owner) return;
1382
+ if (owner && owner === resumeNode) return;
1363
1383
  e[$$EVENT_OWNER] = owner || true;
1364
1384
  let node = resumeNode || e.target;
1365
1385
  const key = `$$${e.type}`;
@@ -1370,7 +1390,11 @@ function eventHandler(e, container, state) {
1370
1390
  value
1371
1391
  });
1372
1392
  const handleNode = () => {
1373
- const handler = node[key];
1393
+ let handler = node[key];
1394
+ if (handler === undefined && node.hasAttribute && node.hasAttribute("_bnd")) {
1395
+ const seam = globalThis[Symbol.for("dx.bnd")];
1396
+ if (seam) handler = seam.resolve(node, e.type);
1397
+ }
1374
1398
  if (handler && !node.disabled) {
1375
1399
  const data = node[`${key}Data`];
1376
1400
  data !== undefined ? handler.call(node, data, e) : handler.call(node, e);
@@ -1380,7 +1404,7 @@ function eventHandler(e, container, state) {
1380
1404
  return true;
1381
1405
  };
1382
1406
  const walkUpTree = () => {
1383
- while (handleNode()) {
1407
+ while (node && handleNode()) {
1384
1408
  if (node === boundary || node.parentNode === boundary) break;
1385
1409
  node = node._$host || node.parentNode || node.host;
1386
1410
  }
@@ -1827,21 +1851,21 @@ function createElement(tagName, is = undefined) {
1827
1851
  is
1828
1852
  });
1829
1853
  }
1830
- function loadClientOnly(fn, setComp) {
1831
- fn().then(m => setComp(() => m.default));
1854
+ function loadClientOnly(fn, setComp, exportName) {
1855
+ fn().then(m => setComp(() => exportName ? m[exportName] : m.default));
1832
1856
  }
1833
1857
  function clientOnly(fn, options = {},
1834
1858
  _moduleUrl) {
1835
1859
  const [comp, setComp] = createSignal();
1836
1860
  let started = !options.lazy;
1837
- started && loadClientOnly(fn, setComp);
1861
+ started && loadClientOnly(fn, setComp, options.export);
1838
1862
  return props => {
1839
1863
  let Comp;
1840
1864
  let m;
1841
1865
  const rest = omit(props, "fallback");
1842
1866
  if (!started) {
1843
1867
  started = true;
1844
- loadClientOnly(fn, setComp);
1868
+ loadClientOnly(fn, setComp, options.export);
1845
1869
  }
1846
1870
  if ((Comp = untrack(comp)) && !sharedConfig.hydrating) return Comp(rest);
1847
1871
  const [mounted, setMounted] = createSignal(!sharedConfig.hydrating);
@@ -1855,4 +1879,4 @@ _moduleUrl) {
1855
1879
  function httpStatus(_code, _text) {}
1856
1880
  function httpHeader(_name, _value, _options) {}
1857
1881
 
1858
- export { ChildProperties, DOMElements, DOMWithState, DelegatedEvents, Dynamic, HREF, voidFn as HydrationScript, MathMLElements, Namespaces, Portal, REVALIDATE_HEADER, RawTextElements, RequestContext, ResponseEnvelope, SAFE_ERROR, SVGElements, VoidElements, acquireAsset, addEvent, applyRef, assign, claimElement, claimElementTree, className, clearFlashCookie, clientOnly, commitEventResponse, composeMiddleware, createRequestEvent, createResponseStub, createSSRResponse, delegateEvents, dynamic, dynamicProperty, effect, escape, voidFn as generateHydrationScript, getDelegatedRoot, getExpectedRedirectStatus, getFirstChild, getHydrationKey, getNextElement, getNextMarker, getNextMatch, getNextSibling, voidFn as getRequestEvent, getServerFunctionMetadata, getServerFunctionRPC, hasFlashCookie, httpHeader, httpStatus, hydrate, insert, installHydrationRuntime, isDev, isHref, isResponseEnvelope, isSafeError, isServer, isServerFunction, markSafeError, memo, mergeProps, parseCookieHeader, redirect, ref, registerDelegatedContainer, registerDelegatedRoot, registerElementClaim, reload, render, renderToStream, renderToString, resolveSSRNode, respond, runHydrationEvents, scope, serializeCookie, setAttribute, setAttributeNS, setProperty, setStyleProperty, spread, ssr, ssrAttribute, ssrClassName, ssrElement, ssrGroup, ssrHydrationKey, ssrStyle, ssrStyleProperty, style, template, unregisterDelegatedContainer, unregisterDelegatedRoot, useHead, warmAsset };
1882
+ export { ChildProperties, DOMElements, DOMWithState, DelegatedEvents, Dynamic, HREF, voidFn as HydrationScript, MathMLElements, Namespaces, Portal, REVALIDATE_HEADER, RawTextElements, RequestContext, ResponseEnvelope, SAFE_ERROR, SVGElements, VoidElements, acquireAsset, addEvent, applyRef, assign, claimElement, claimElementTree, className, clearFlashCookie, clientOnly, commitEventResponse, composeMiddleware, createRequestEvent, createResponseStub, createSSRResponse, delegateEvents, dynamic, dynamicProperty, effect, escape, voidFn as generateHydrationScript, getDelegatedRoot, getExpectedRedirectStatus, getFirstChild, getHydrationKey, getNextElement, getNextMarker, getNextMatch, getNextSibling, voidFn as getRequestEvent, getServerFunctionMetadata, getServerFunctionRPC, hasFlashCookie, httpHeader, httpStatus, hydrate, insert, installHydrationRuntime, isDev, isHref, isResponseEnvelope, isSafeError, isServer, isServerFunction, markSafeError, memo, mergeProps, parseCookieHeader, patchDriver, redirect, ref, registerDelegatedContainer, registerDelegatedRoot, registerElementClaim, reload, render, renderToStream, renderToString, resolveSSRNode, respond, rowProof, runHydrationEvents, scope, serializeCookie, setAttribute, setAttributeNS, setProperty, setStyleProperty, spread, ssr, ssrAttribute, ssrClassName, ssrElement, ssrGroup, ssrHydrationKey, ssrStyle, ssrStyleProperty, style, template, unregisterDelegatedContainer, unregisterDelegatedRoot, useHead, warmAsset };
@@ -17,6 +17,71 @@ function claimNode(handlers, el) {
17
17
  for (let i = 0; i < handlers.length; i++) handlers[i](el);
18
18
  }
19
19
  const claimedAttr = name => name === "href" || name === "action";
20
+ const BOUND_SEAM = Symbol.for("dx.bnd");
21
+ const boundSeam = globalThis[BOUND_SEAM] || (globalThis[BOUND_SEAM] = {});
22
+ const BND_ATTR = "_bnd";
23
+ const BND_SELECTOR = "[_bnd]";
24
+ function bndMap(el) {
25
+ const s = el.getAttribute(BND_ATTR);
26
+ if (!s) return undefined;
27
+ const map = {};
28
+ for (const entry of s.split(",")) {
29
+ const eq = entry.indexOf("=");
30
+ if (eq < 1) continue;
31
+ const pos = entry.slice(0, eq);
32
+ const prop = decodeURIComponent(entry.slice(eq + 1));
33
+ const prev = map[pos];
34
+ if (prev === undefined) map[pos] = prop;else if (Array.isArray(prev)) prev.push(prop);else map[pos] = [prev, prop];
35
+ }
36
+ return map;
37
+ }
38
+ boundSeam.resolve = (el, type) => {
39
+ const frame = el._$bndFrame;
40
+ if (!frame) return undefined;
41
+ const map = bndMap(el);
42
+ const prop = map && map[type];
43
+ if (typeof prop !== "string") return undefined;
44
+ return claimFn(frame, type, prop);
45
+ };
46
+ function claimFn(frame, pos, prop) {
47
+ const fn = frame.clientProp(prop);
48
+ if (typeof fn === "function") return fn;
49
+ return undefined;
50
+ }
51
+ function sweepBound(root, frame, delegate, scope) {
52
+ const isElement = root.nodeType === ELEMENT_NODE;
53
+ if (!isElement && root.nodeType !== 11 ) return;
54
+ let els;
55
+ if (isElement && root.hasAttribute(BND_ATTR)) (els = []).push(root);
56
+ const found = root.querySelectorAll(BND_SELECTOR);
57
+ if (found.length) {
58
+ els || (els = []);
59
+ for (let i = 0; i < found.length; i++) els.push(found[i]);
60
+ }
61
+ if (!els) return;
62
+ const run = () => {
63
+ let types;
64
+ for (const el of els) {
65
+ el._$bndFrame = frame;
66
+ const map = bndMap(el);
67
+ if (!map) continue;
68
+ for (const pos in map) {
69
+ if (pos === "ref") fireRefs(frame, el, map.ref);else (types || (types = [])).push(pos);
70
+ }
71
+ }
72
+ if (types && delegate) delegate(types);
73
+ };
74
+ scope ? scope(run) : run();
75
+ }
76
+ function fireRefs(frame, el, prop) {
77
+ const fired = el._$bndFired || (el._$bndFired = new Set());
78
+ for (const p of Array.isArray(prop) ? prop : [prop]) {
79
+ if (fired.has(p)) continue;
80
+ fired.add(p);
81
+ const fn = claimFn(frame, "ref", p);
82
+ if (fn) fn(el);
83
+ }
84
+ }
20
85
  function claimTree(handlers, root) {
21
86
  const isElement = root.nodeType === ELEMENT_NODE;
22
87
  if (!isElement && root.nodeType !== 11 ) return;
@@ -116,6 +181,7 @@ function createFrameHost(options = {}) {
116
181
  return true;
117
182
  };
118
183
  return {
184
+ delegate: options.delegate,
119
185
  register(id, frame) {
120
186
  let set = frames.get(id);
121
187
  if (!set) frames.set(id, set = new Set());
@@ -210,10 +276,18 @@ class FrameImpl {
210
276
  if (!this.#disposed) this.#flush();
211
277
  };
212
278
  #claimTree = (node, direct) => {
279
+ if (!direct && node.nodeType !== TEXT_NODE && node.nodeType !== COMMENT_NODE) {
280
+ const o = this.#options;
281
+ sweepBound(node, this, o.delegate || o.host && o.host.delegate, o.ownerScope);
282
+ }
213
283
  const handlers = claimHandlers();
214
284
  if (!handlers) return;
215
285
  this.#scoped(() => direct ? claimNode(handlers, node) : claimTree(handlers, node));
216
286
  };
287
+ clientProp(name) {
288
+ const props = this.#options.props;
289
+ return props ? props[name] : undefined;
290
+ }
217
291
  #scoped(fn) {
218
292
  const scope = this.#options.ownerScope;
219
293
  return scope ? scope(fn) : fn();
@@ -662,7 +736,7 @@ class FrameImpl {
662
736
  parent.insertBefore(fragment, this.#end);
663
737
  this.#hasContent = true;
664
738
  } else {
665
- const claim = claimHandlers() ? this.#claimTree : null;
739
+ const claim = this.#claimTree;
666
740
  const ranges = new Map();
667
741
  this.#collectSlots(ranges);
668
742
  const grafts = [];
@@ -678,8 +752,7 @@ class FrameImpl {
678
752
  if (!close) {
679
753
  return false;
680
754
  }
681
- const claim = claimHandlers() ? this.#claimTree : null;
682
- reconcileChildren(open.parentNode, parseFragment(html), open, close, claim);
755
+ reconcileChildren(open.parentNode, parseFragment(html), open, close, this.#claimTree);
683
756
  return true;
684
757
  }
685
758
  #applyAttrs(addr, text, removed) {
@@ -703,7 +776,6 @@ class FrameImpl {
703
776
  removeUntil(this.#parent(), this.#firstContent(), this.#end);
704
777
  }
705
778
  #claimContent() {
706
- if (!claimHandlers()) return;
707
779
  let n = this.#firstContent();
708
780
  while (n && n !== this.#end) {
709
781
  this.#claimTree(n);
@@ -995,7 +1067,7 @@ function isSlotMarker(node) {
995
1067
  }
996
1068
  function compatible(a, b) {
997
1069
  if (a.nodeType !== b.nodeType) return false;
998
- if (a.nodeType === ELEMENT_NODE) return a.nodeName === b.nodeName;
1070
+ if (a.nodeType === ELEMENT_NODE) return a.nodeName === b.nodeName && a.getAttribute("_key") === b.getAttribute("_key");
999
1071
  return a.nodeType === TEXT_NODE || a.nodeType === COMMENT_NODE;
1000
1072
  }
1001
1073
  function preservesOpen(el) {
@@ -1406,7 +1478,9 @@ function isMaterializedContainer(value) {
1406
1478
  return value !== null && typeof value === "object" && state.materializedValues.has(value);
1407
1479
  }
1408
1480
  function isContainerTraceMarker(value) {
1409
- return value != null && typeof value === "object" && value.$tr != null && typeof value.$tr[Symbol.asyncIterator] === "function";
1481
+ if (value == null || typeof value !== "object" || value.$tr == null) return false;
1482
+ const tr = value.$tr;
1483
+ return tr.__SEROVAL_STREAM__ === true || typeof tr[Symbol.asyncIterator] === "function";
1410
1484
  }
1411
1485
  function reviveContainerTraces(value) {
1412
1486
  if (!state.materializeTrace || value == null || typeof value !== "object") return value;
@@ -1452,7 +1526,8 @@ function getFrameHost() {
1452
1526
  applyData: c => tableFor(c.id)?.apply(c),
1453
1527
  resolve: (ref, id) => tableFor(id)?.resolve(ref),
1454
1528
  revive: reviveContainerTraces,
1455
- isContainer: isMaterializedContainer
1529
+ isContainer: isMaterializedContainer,
1530
+ delegate: web.delegateEvents
1456
1531
  });
1457
1532
  }
1458
1533
  return sharedHost;
@@ -1528,7 +1603,16 @@ function slotArgsProxy(args) {
1528
1603
  if (!isAsyncValue(v)) return v;
1529
1604
  let read = asyncReads.get(key);
1530
1605
  if (!read) {
1531
- const make = () => solidJs.createMemo(() => args()[key]);
1606
+ const make = () => solidJs.createMemo(() => {
1607
+ const raw = args()[key];
1608
+ if (raw != null && typeof raw.then === "function") {
1609
+ if (raw.s === 1) return raw.v;
1610
+ if (raw.s === 2) throw raw.v;
1611
+ }
1612
+ return raw;
1613
+ }, {
1614
+ transparent: true
1615
+ });
1532
1616
  read = owner ? solidJs.runWithOwner(owner, make) : make();
1533
1617
  asyncReads.set(key, read);
1534
1618
  }
@@ -1647,6 +1731,7 @@ function boundaryComponent(host, fnId) {
1647
1731
  host,
1648
1732
  id,
1649
1733
  slots: slotsFor(props),
1734
+ props,
1650
1735
  ownerScope: boundaryScope(owner),
1651
1736
  reveal: revealSeam(owner),
1652
1737
  onApply: () => {
@@ -1831,6 +1916,7 @@ function adoptBoundary(host, id, el, props, binding) {
1831
1916
  host,
1832
1917
  id: address,
1833
1918
  slots: slotsFor(props),
1919
+ props,
1834
1920
  ownerScope: boundaryScope(owner),
1835
1921
  reveal: revealSeam(owner),
1836
1922
  onApply: () => {
@@ -17,6 +17,74 @@ function claimNode(handlers, el) {
17
17
  for (let i = 0; i < handlers.length; i++) handlers[i](el);
18
18
  }
19
19
  const claimedAttr = name => name === "href" || name === "action";
20
+ const BOUND_SEAM = Symbol.for("dx.bnd");
21
+ const boundSeam = globalThis[BOUND_SEAM] || (globalThis[BOUND_SEAM] = {});
22
+ const BND_ATTR = "_bnd";
23
+ const BND_SELECTOR = "[_bnd]";
24
+ function bndMap(el) {
25
+ const s = el.getAttribute(BND_ATTR);
26
+ if (!s) return undefined;
27
+ const map = {};
28
+ for (const entry of s.split(",")) {
29
+ const eq = entry.indexOf("=");
30
+ if (eq < 1) continue;
31
+ const pos = entry.slice(0, eq);
32
+ const prop = decodeURIComponent(entry.slice(eq + 1));
33
+ const prev = map[pos];
34
+ if (prev === undefined) map[pos] = prop;else if (Array.isArray(prev)) prev.push(prop);else map[pos] = [prev, prop];
35
+ }
36
+ return map;
37
+ }
38
+ boundSeam.resolve = (el, type) => {
39
+ const frame = el._$bndFrame;
40
+ if (!frame) return undefined;
41
+ const map = bndMap(el);
42
+ const prop = map && map[type];
43
+ if (typeof prop !== "string") return undefined;
44
+ return claimFn(frame, type, prop);
45
+ };
46
+ function claimFn(frame, pos, prop) {
47
+ const fn = frame.clientProp(prop);
48
+ if (typeof fn === "function") return fn;
49
+ if (fn !== undefined) {
50
+ console.warn(`A server element claims \`${pos}\` from client prop \`${prop}\`, but the mounted ` + `frame's prop is not a function.`);
51
+ }
52
+ return undefined;
53
+ }
54
+ function sweepBound(root, frame, delegate, scope) {
55
+ const isElement = root.nodeType === ELEMENT_NODE;
56
+ if (!isElement && root.nodeType !== 11 ) return;
57
+ let els;
58
+ if (isElement && root.hasAttribute(BND_ATTR)) (els = []).push(root);
59
+ const found = root.querySelectorAll(BND_SELECTOR);
60
+ if (found.length) {
61
+ els || (els = []);
62
+ for (let i = 0; i < found.length; i++) els.push(found[i]);
63
+ }
64
+ if (!els) return;
65
+ const run = () => {
66
+ let types;
67
+ for (const el of els) {
68
+ el._$bndFrame = frame;
69
+ const map = bndMap(el);
70
+ if (!map) continue;
71
+ for (const pos in map) {
72
+ if (pos === "ref") fireRefs(frame, el, map.ref);else (types || (types = [])).push(pos);
73
+ }
74
+ }
75
+ if (types && delegate) delegate(types);
76
+ };
77
+ scope ? scope(run) : run();
78
+ }
79
+ function fireRefs(frame, el, prop) {
80
+ const fired = el._$bndFired || (el._$bndFired = new Set());
81
+ for (const p of Array.isArray(prop) ? prop : [prop]) {
82
+ if (fired.has(p)) continue;
83
+ fired.add(p);
84
+ const fn = claimFn(frame, "ref", p);
85
+ if (fn) fn(el);
86
+ }
87
+ }
20
88
  function claimTree(handlers, root) {
21
89
  const isElement = root.nodeType === ELEMENT_NODE;
22
90
  if (!isElement && root.nodeType !== 11 ) return;
@@ -116,6 +184,7 @@ function createFrameHost(options = {}) {
116
184
  return true;
117
185
  };
118
186
  return {
187
+ delegate: options.delegate,
119
188
  register(id, frame) {
120
189
  let set = frames.get(id);
121
190
  if (!set) frames.set(id, set = new Set());
@@ -210,10 +279,18 @@ class FrameImpl {
210
279
  if (!this.#disposed) this.#flush();
211
280
  };
212
281
  #claimTree = (node, direct) => {
282
+ if (!direct && node.nodeType !== TEXT_NODE && node.nodeType !== COMMENT_NODE) {
283
+ const o = this.#options;
284
+ sweepBound(node, this, o.delegate || o.host && o.host.delegate, o.ownerScope);
285
+ }
213
286
  const handlers = claimHandlers();
214
287
  if (!handlers) return;
215
288
  this.#scoped(() => direct ? claimNode(handlers, node) : claimTree(handlers, node));
216
289
  };
290
+ clientProp(name) {
291
+ const props = this.#options.props;
292
+ return props ? props[name] : undefined;
293
+ }
217
294
  #scoped(fn) {
218
295
  const scope = this.#options.ownerScope;
219
296
  return scope ? scope(fn) : fn();
@@ -663,7 +740,7 @@ class FrameImpl {
663
740
  parent.insertBefore(fragment, this.#end);
664
741
  this.#hasContent = true;
665
742
  } else {
666
- const claim = claimHandlers() ? this.#claimTree : null;
743
+ const claim = this.#claimTree;
667
744
  const ranges = new Map();
668
745
  this.#collectSlots(ranges);
669
746
  const grafts = [];
@@ -682,8 +759,7 @@ class FrameImpl {
682
759
  }
683
760
  return false;
684
761
  }
685
- const claim = claimHandlers() ? this.#claimTree : null;
686
- reconcileChildren(open.parentNode, parseFragment(html), open, close, claim);
762
+ reconcileChildren(open.parentNode, parseFragment(html), open, close, this.#claimTree);
687
763
  return true;
688
764
  }
689
765
  #applyAttrs(addr, text, removed) {
@@ -707,7 +783,6 @@ class FrameImpl {
707
783
  removeUntil(this.#parent(), this.#firstContent(), this.#end);
708
784
  }
709
785
  #claimContent() {
710
- if (!claimHandlers()) return;
711
786
  let n = this.#firstContent();
712
787
  while (n && n !== this.#end) {
713
788
  this.#claimTree(n);
@@ -1003,7 +1078,7 @@ function isSlotMarker(node) {
1003
1078
  }
1004
1079
  function compatible(a, b) {
1005
1080
  if (a.nodeType !== b.nodeType) return false;
1006
- if (a.nodeType === ELEMENT_NODE) return a.nodeName === b.nodeName;
1081
+ if (a.nodeType === ELEMENT_NODE) return a.nodeName === b.nodeName && a.getAttribute("_key") === b.getAttribute("_key");
1007
1082
  return a.nodeType === TEXT_NODE || a.nodeType === COMMENT_NODE;
1008
1083
  }
1009
1084
  function preservesOpen(el) {
@@ -1423,7 +1498,9 @@ function isMaterializedContainer(value) {
1423
1498
  return value !== null && typeof value === "object" && state.materializedValues.has(value);
1424
1499
  }
1425
1500
  function isContainerTraceMarker(value) {
1426
- return value != null && typeof value === "object" && value.$tr != null && typeof value.$tr[Symbol.asyncIterator] === "function";
1501
+ if (value == null || typeof value !== "object" || value.$tr == null) return false;
1502
+ const tr = value.$tr;
1503
+ return tr.__SEROVAL_STREAM__ === true || typeof tr[Symbol.asyncIterator] === "function";
1427
1504
  }
1428
1505
  function reviveContainerTraces(value) {
1429
1506
  if (!state.materializeTrace || value == null || typeof value !== "object") return value;
@@ -1469,7 +1546,8 @@ function getFrameHost() {
1469
1546
  applyData: c => tableFor(c.id)?.apply(c),
1470
1547
  resolve: (ref, id) => tableFor(id)?.resolve(ref),
1471
1548
  revive: reviveContainerTraces,
1472
- isContainer: isMaterializedContainer
1549
+ isContainer: isMaterializedContainer,
1550
+ delegate: web.delegateEvents
1473
1551
  });
1474
1552
  }
1475
1553
  return sharedHost;
@@ -1545,7 +1623,16 @@ function slotArgsProxy(args) {
1545
1623
  if (!isAsyncValue(v)) return v;
1546
1624
  let read = asyncReads.get(key);
1547
1625
  if (!read) {
1548
- const make = () => solidJs.createMemo(() => args()[key]);
1626
+ const make = () => solidJs.createMemo(() => {
1627
+ const raw = args()[key];
1628
+ if (raw != null && typeof raw.then === "function") {
1629
+ if (raw.s === 1) return raw.v;
1630
+ if (raw.s === 2) throw raw.v;
1631
+ }
1632
+ return raw;
1633
+ }, {
1634
+ transparent: true
1635
+ });
1549
1636
  read = owner ? solidJs.runWithOwner(owner, make) : make();
1550
1637
  asyncReads.set(key, read);
1551
1638
  }
@@ -1664,6 +1751,7 @@ function boundaryComponent(host, fnId) {
1664
1751
  host,
1665
1752
  id,
1666
1753
  slots: slotsFor(props),
1754
+ props,
1667
1755
  ownerScope: boundaryScope(owner),
1668
1756
  reveal: revealSeam(owner),
1669
1757
  onApply: () => {
@@ -1848,6 +1936,7 @@ function adoptBoundary(host, id, el, props, binding) {
1848
1936
  host,
1849
1937
  id: address,
1850
1938
  slots: slotsFor(props),
1939
+ props,
1851
1940
  ownerScope: boundaryScope(owner),
1852
1941
  reveal: revealSeam(owner),
1853
1942
  onApply: () => {