@solidjs/web 2.0.0-beta.22 → 2.0.0-beta.24

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 (46) hide show
  1. package/dist/dev.cjs +25 -1
  2. package/dist/dev.js +25 -2
  3. package/dist/server.cjs +109 -45
  4. package/dist/server.js +109 -46
  5. package/dist/web.cjs +25 -1
  6. package/dist/web.js +25 -2
  7. package/frames/dist/client.cjs +1467 -0
  8. package/frames/dist/client.js +1455 -0
  9. package/frames/dist/server.cjs +1723 -0
  10. package/frames/dist/server.js +1712 -0
  11. package/frames/package.json +30 -0
  12. package/package.json +78 -5
  13. package/serialization/dist/serialization.cjs +83 -0
  14. package/serialization/dist/serialization.js +82 -1
  15. package/serialization/types/index.d.ts +12 -0
  16. package/serialization/types-cjs/index.d.cts +12 -0
  17. package/server-functions/dist/client.cjs +82 -55
  18. package/server-functions/dist/client.js +83 -56
  19. package/server-functions/dist/server.cjs +28 -7
  20. package/server-functions/dist/server.js +28 -7
  21. package/types/client.d.ts +8 -0
  22. package/types/core.d.ts +2 -1
  23. package/types/frames/client.d.ts +53 -0
  24. package/types/frames/frame-client.d.ts +222 -0
  25. package/types/frames/frame-sink.d.ts +145 -0
  26. package/types/frames/frame-transport.d.ts +106 -0
  27. package/types/frames/serializer.d.ts +151 -0
  28. package/types/frames/server.d.ts +21 -0
  29. package/types/serializer.d.ts +12 -0
  30. package/types/server-functions/client.d.ts +24 -0
  31. package/types/server-functions/server.d.ts +17 -0
  32. package/types/server-functions/shared.d.ts +17 -0
  33. package/types/server.d.ts +2 -0
  34. package/types-cjs/client.d.cts +8 -0
  35. package/types-cjs/core.d.cts +2 -1
  36. package/types-cjs/frames/client.d.cts +53 -0
  37. package/types-cjs/frames/frame-client.d.cts +222 -0
  38. package/types-cjs/frames/frame-sink.d.cts +145 -0
  39. package/types-cjs/frames/frame-transport.d.cts +106 -0
  40. package/types-cjs/frames/serializer.d.cts +151 -0
  41. package/types-cjs/frames/server.d.cts +21 -0
  42. package/types-cjs/serializer.d.cts +12 -0
  43. package/types-cjs/server-functions/client.d.cts +24 -0
  44. package/types-cjs/server-functions/server.d.cts +17 -0
  45. package/types-cjs/server-functions/shared.d.cts +17 -0
  46. package/types-cjs/server.d.cts +2 -0
package/dist/server.js CHANGED
@@ -312,7 +312,8 @@ function renderToStream(code, options = {}) {
312
312
  }
313
313
  tasks += task + ";";
314
314
  if (!timer && firstFlushed) {
315
- timer = setTimeout(writeTasks);
315
+ timer = true;
316
+ queue(() => queue(writeTasks));
316
317
  }
317
318
  };
318
319
  const onDone = () => {
@@ -327,10 +328,53 @@ function renderToStream(code, options = {}) {
327
328
  completed = true;
328
329
  if (firstFlushed) dispose();
329
330
  };
330
- const serializer = createHydrationSerializer({
331
+ const sink = {
332
+ data(payload) {
333
+ pushTask(payload);
334
+ },
335
+ fragment(key, value, meta) {
336
+ const deferActivation = !!meta.revealGroup;
337
+ const styles = meta.styles;
338
+ for (let i = 0; i < styles.inline.length; i++) {
339
+ buffer.write(renderInlineStyle(styles.inline[i], nonce));
340
+ }
341
+ if (styles.links.length) {
342
+ emitTask(`$dfs("${key}",${styles.links.length},${deferActivation ? 1 : 0})`);
343
+ writeTasks();
344
+ for (const url of styles.links) {
345
+ buffer.write(`<link rel="stylesheet" href="${url}" onload="$dfc('${key}')" onerror="$dfc('${key}')">`);
346
+ }
347
+ buffer.write(`<template id="${key}">${value}</template>`);
348
+ } else {
349
+ buffer.write(`<template id="${key}">${value}</template>`);
350
+ if (!deferActivation) {
351
+ emitTask(`$df("${key}")`);
352
+ }
353
+ }
354
+ },
355
+ reveal(keys, meta) {
356
+ emitTask(`${meta.fallback ? "$dflj" : "$dfj"}(${JSON.stringify(keys)})`);
357
+ },
358
+ asset(type, value) {
359
+ if (type === "module") {
360
+ buffer.write(`<link rel="modulepreload" href="${value}">`);
361
+ } else if (type === "inline-style") {
362
+ buffer.write(renderInlineStyle(value, nonce));
363
+ }
364
+ },
365
+ shell(shellHtml, meta) {
366
+ shellHtml = injectBeforeHead(shellHtml, meta.assets);
367
+ shellHtml = injectPreloadLinks(meta.preloads, shellHtml);
368
+ shellHtml = injectInlineStyles(meta.inlineStyles, shellHtml, nonce);
369
+ if (meta.tasks.length) shellHtml = injectScripts(shellHtml, meta.tasks, nonce);
370
+ buffer.write(shellHtml);
371
+ },
372
+ ...options.sink
373
+ };
374
+ const serializer = (options.serializer || createHydrationSerializer)({
331
375
  scopeId: options.renderId,
332
376
  plugins: options.plugins,
333
- onData: pushTask,
377
+ onData: payload => sink.data(payload),
334
378
  onDone,
335
379
  onError: options.onError
336
380
  });
@@ -352,7 +396,6 @@ function renderToStream(code, options = {}) {
352
396
  buffer.write(`<script${nonce ? ` nonce="${nonce}"` : ""}>${tasks}</script>`);
353
397
  tasks = "";
354
398
  }
355
- timer && clearTimeout(timer);
356
399
  timer = null;
357
400
  };
358
401
  let context;
@@ -404,7 +447,7 @@ function renderToStream(code, options = {}) {
404
447
  const entry = tracking.registerInlineStyle(value);
405
448
  if (firstFlushed && !tracking.currentBoundaryId && !entry.emitted) {
406
449
  entry.emitted = true;
407
- buffer.write(renderInlineStyle(entry, nonce));
450
+ sink.asset("inline-style", entry);
408
451
  }
409
452
  return;
410
453
  }
@@ -418,9 +461,7 @@ function renderToStream(code, options = {}) {
418
461
  }
419
462
  if (!tracking.emittedAssets.has(value)) {
420
463
  tracking.emittedAssets.add(value);
421
- if (firstFlushed && type === "module") {
422
- buffer.write(`<link rel="modulepreload" href="${value}">`);
423
- }
464
+ if (firstFlushed) sink.asset(type, value);
424
465
  }
425
466
  },
426
467
  block(p) {
@@ -502,23 +543,11 @@ function renderToStream(code, options = {}) {
502
543
  } else {
503
544
  serializeFragmentAssets(key, tracking.boundaryModules, context);
504
545
  const styles = collectStreamStyles(key, tracking, headStyles);
505
- const deferActivation = !!revealGroup;
506
- for (let i = 0; i < styles.inline.length; i++) {
507
- buffer.write(renderInlineStyle(styles.inline[i], nonce));
508
- }
509
- if (styles.links.length) {
510
- emitTask(`$dfs("${key}",${styles.links.length},${deferActivation ? 1 : 0})`);
511
- writeTasks();
512
- for (const url of styles.links) {
513
- buffer.write(`<link rel="stylesheet" href="${url}" onload="$dfc('${key}')" onerror="$dfc('${key}')">`);
514
- }
515
- buffer.write(`<template id="${key}">${value !== undefined ? value : " "}</template>`);
516
- } else {
517
- buffer.write(`<template id="${key}">${value !== undefined ? value : " "}</template>`);
518
- if (!deferActivation) {
519
- emitTask(`$df("${key}")`);
520
- }
521
- }
546
+ sink.fragment(key, value !== undefined ? value : " ", {
547
+ styles,
548
+ revealGroup,
549
+ error
550
+ });
522
551
  item.resolve(error);
523
552
  }
524
553
  }
@@ -529,12 +558,16 @@ function renderToStream(code, options = {}) {
529
558
  revealFragments(groupOrKeys) {
530
559
  const keys = resolveRevealKeys(groupOrKeys, true, true);
531
560
  if (!keys) return;
532
- emitTask(`$dfj(${JSON.stringify(keys)})`);
561
+ sink.reveal(keys, {
562
+ fallback: false
563
+ });
533
564
  },
534
565
  revealFallbacks(groupOrKeys) {
535
566
  const keys = resolveRevealKeys(groupOrKeys, false, false);
536
567
  if (!keys) return;
537
- emitTask(`$dflj(${JSON.stringify(keys)})`);
568
+ sink.reveal(keys, {
569
+ fallback: true
570
+ });
538
571
  }
539
572
  };
540
573
  applyAssetTracking(context, tracking, manifest);
@@ -594,16 +627,18 @@ function renderToStream(code, options = {}) {
594
627
  if (shellCompleted) return;
595
628
  if (!resolveRootHoles()) return;
596
629
  sharedConfig.context = context;
597
- html = injectAssets(context.assets, html);
630
+ const assetsHtml = resolveAssetsHtml(context.assets);
598
631
  headStyles = new Set();
599
632
  for (const url of tracking.emittedAssets) {
600
633
  if (url.endsWith(".css")) headStyles.add(url);
601
634
  }
602
- html = injectPreloadLinks(tracking.emittedAssets, html);
603
- html = injectInlineStyles(tracking.inlineStyles, html, nonce);
604
635
  serializeRootAssets();
605
- if (tasks.length) html = injectScripts(html, tasks, nonce);
606
- buffer.write(html);
636
+ sink.shell(html, {
637
+ assets: assetsHtml,
638
+ preloads: tracking.emittedAssets,
639
+ inlineStyles: tracking.inlineStyles,
640
+ tasks
641
+ });
607
642
  tasks = "";
608
643
  onCompleteShell && onCompleteShell({
609
644
  write(v) {
@@ -612,6 +647,26 @@ function renderToStream(code, options = {}) {
612
647
  });
613
648
  shellCompleted = true;
614
649
  }
650
+ const MIN_DRAIN_TURNS = 8;
651
+ let lastBlockingSize = -1;
652
+ let lastRegistrySize = -1;
653
+ let drainTurn = 0;
654
+ const scheduleFlush = fn => {
655
+ const attempt = () => {
656
+ if (registry.size !== lastRegistrySize || drainTurn++ < MIN_DRAIN_TURNS) {
657
+ if (registry.size !== lastRegistrySize) drainTurn = 0;
658
+ lastRegistrySize = registry.size;
659
+ queue(attempt);
660
+ return;
661
+ }
662
+ fn();
663
+ };
664
+ const progressed = blockingPromises.size !== lastBlockingSize;
665
+ lastBlockingSize = blockingPromises.size;
666
+ lastRegistrySize = -1;
667
+ drainTurn = 0;
668
+ progressed ? queue(attempt) : setTimeout(attempt);
669
+ };
615
670
  return {
616
671
  then(fn) {
617
672
  function complete() {
@@ -627,7 +682,7 @@ function renderToStream(code, options = {}) {
627
682
  } else onCompleteAll = complete;
628
683
  function flush() {
629
684
  allSettled(blockingPromises).then(() => {
630
- setTimeout(() => {
685
+ scheduleFlush(() => {
631
686
  if (!resolveRootHoles()) return flush();
632
687
  queue(flushEnd);
633
688
  });
@@ -638,7 +693,7 @@ function renderToStream(code, options = {}) {
638
693
  pipe(w) {
639
694
  function flush() {
640
695
  allSettled(blockingPromises).then(() => {
641
- setTimeout(() => {
696
+ scheduleFlush(() => {
642
697
  doShell();
643
698
  if (!shellCompleted) return flush();
644
699
  buffer = writable = w;
@@ -658,7 +713,7 @@ function renderToStream(code, options = {}) {
658
713
  const p = new Promise(r => resolve = r);
659
714
  function flush() {
660
715
  allSettled(blockingPromises).then(() => {
661
- setTimeout(() => {
716
+ scheduleFlush(() => {
662
717
  doShell();
663
718
  if (!shellCompleted) return flush();
664
719
  const encoder = new TextEncoder();
@@ -961,14 +1016,12 @@ function escape(s, attr) {
961
1016
  }
962
1017
  return s;
963
1018
  }
964
- const delimCode = attr ? 34 : 60;
965
- const len = s.length;
966
- for (let i = 0; i < len; i++) {
967
- const c = s.charCodeAt(i);
968
- if (c === 38 || c === delimCode) return escapeSlow(s, attr, i);
969
- }
970
- return s;
1019
+ const i = s.search(attr ? ESCAPE_ATTR : ESCAPE_CONTENT);
1020
+ if (i < 0) return s;
1021
+ return escapeSlow(s, attr, i);
971
1022
  }
1023
+ const ESCAPE_CONTENT = /[&<]/;
1024
+ const ESCAPE_ATTR = /[&"]/;
972
1025
  function escapeSlow(s, attr, start) {
973
1026
  const delim = attr ? '"' : "<";
974
1027
  const delimCode = attr ? 34 : 60;
@@ -1053,13 +1106,20 @@ function allSettled(promises) {
1053
1106
  return;
1054
1107
  });
1055
1108
  }
1056
- function injectAssets(assets, html) {
1057
- if (!assets || !assets.length) return html;
1109
+ function resolveAssetsHtml(assets) {
1110
+ if (!assets || !assets.length) return "";
1058
1111
  let out = "";
1059
1112
  for (let i = 0, len = assets.length; i < len; i++) out += assets[i]();
1113
+ return out;
1114
+ }
1115
+ function injectBeforeHead(html, content) {
1116
+ if (!content) return html;
1060
1117
  const index = html.indexOf("</head>");
1061
1118
  if (index === -1) return html;
1062
- return html.slice(0, index) + out + html.slice(index);
1119
+ return html.slice(0, index) + content + html.slice(index);
1120
+ }
1121
+ function injectAssets(assets, html) {
1122
+ return injectBeforeHead(html, resolveAssetsHtml(assets));
1063
1123
  }
1064
1124
  function injectPreloadLinks(emittedAssets, html, nonce) {
1065
1125
  if (!emittedAssets.size) return html;
@@ -1278,6 +1338,9 @@ function noopCleanup() {}
1278
1338
  function claimElement(node) {
1279
1339
  return node;
1280
1340
  }
1341
+ function claimElementTree(root) {
1342
+ return root;
1343
+ }
1281
1344
  function notSup() {
1282
1345
  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>.");
1283
1346
  }
@@ -1401,4 +1464,4 @@ function Portal(props) {
1401
1464
  return undefined;
1402
1465
  }
1403
1466
 
1404
- export { Assets, ChildProperties, DOMElements, DOMWithState, DelegatedEvents, Dynamic, HREF, HydrationScript, MathMLElements, Namespaces, Portal, RawTextElements, RequestContext, ResponseEnvelope, SVGElements, VoidElements, notSup as acquireAsset, notSup as addEvent, applyRef, notSup as assign, claimElement, notSup as className, notSup as delegateEvents, dynamic, notSup as dynamicProperty, effect, escape, generateHydrationScript, getAssets, notSup as getDelegatedRoot, getHydrationKey, notSup as getNextElement, notSup as getNextMarker, notSup as getNextMatch, getRequestEvent, notSup as hydrate, notSup as insert, isDev, isHref, isResponseEnvelope, isServer, memo, redirect, notSup as ref, notSup as registerDelegatedContainer, notSup as registerDelegatedRoot, registerElementClaim, reload, notSup as render, renderToStream, renderToString, renderToStringAsync, respond, notSup as runHydrationEvents, notSup as setAttribute, notSup as setAttributeNS, notSup as setProperty, notSup as setStyleProperty, notSup as spread, ssr, ssrAttribute, ssrClassName, ssrElement, ssrGroup, ssrHydrationKey, ssrStyle, ssrStyleProperty, notSup as style, notSup as template, notSup as unregisterDelegatedContainer, notSup as unregisterDelegatedRoot, useAssets };
1467
+ export { Assets, ChildProperties, DOMElements, DOMWithState, DelegatedEvents, Dynamic, HREF, HydrationScript, MathMLElements, Namespaces, Portal, RawTextElements, RequestContext, ResponseEnvelope, SVGElements, VoidElements, notSup as acquireAsset, notSup as addEvent, applyRef, notSup as assign, claimElement, claimElementTree, notSup as className, notSup as delegateEvents, dynamic, notSup as dynamicProperty, effect, escape, generateHydrationScript, getAssets, notSup as getDelegatedRoot, getHydrationKey, notSup as getNextElement, notSup as getNextMarker, notSup as getNextMatch, getRequestEvent, notSup as hydrate, notSup as insert, isDev, isHref, isResponseEnvelope, isServer, memo, redirect, notSup as ref, notSup as registerDelegatedContainer, notSup as registerDelegatedRoot, registerElementClaim, reload, notSup as render, renderToStream, renderToString, renderToStringAsync, respond, notSup as runHydrationEvents, notSup as setAttribute, notSup as setAttributeNS, notSup as setProperty, notSup as setStyleProperty, notSup as spread, ssr, ssrAttribute, ssrClassName, ssrElement, ssrGroup, ssrHydrationKey, ssrStyle, ssrStyleProperty, notSup as style, notSup as template, notSup as unregisterDelegatedContainer, notSup as unregisterDelegatedRoot, useAssets };
package/dist/web.cjs CHANGED
@@ -33,6 +33,7 @@ const DOMWithState = {
33
33
  const ChildProperties = /*#__PURE__*/new Set(["innerHTML", "textContent", "innerText", "children"]);
34
34
  const $$SLOT = /*#__PURE__*/Symbol("slot");
35
35
  const $$HOST = /*#__PURE__*/Symbol("host");
36
+ const $$FRAME = /*#__PURE__*/Symbol.for("dom-expressions.frame");
36
37
  const DelegatedEvents = /*#__PURE__*/new Set(["beforeinput", "click", "dblclick", "contextmenu", "focusin", "focusout", "input", "keydown", "keyup", "mousedown", "mousemove", "mouseout", "mouseover", "mouseup", "pointerdown", "pointermove", "pointerout", "pointerover", "pointerup", "touchend", "touchmove", "touchstart"]);
37
38
  const SVGElements = /*#__PURE__*/new Set([
38
39
  "altGlyph", "altGlyphDef", "altGlyphItem", "animate", "animateColor", "animateMotion", "animateTransform", "circle", "clipPath", "color-profile", "cursor", "defs", "desc", "ellipse", "feBlend", "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", "feDiffuseLighting", "feDisplacementMap", "feDistantLight", "feDropShadow", "feFlood", "feFuncA", "feFuncB", "feFuncG", "feFuncR", "feGaussianBlur", "feImage", "feMerge", "feMergeNode", "feMorphology", "feOffset", "fePointLight", "feSpecularLighting", "feSpotLight", "feTile", "feTurbulence", "filter", "font", "font-face", "font-face-format", "font-face-name", "font-face-src", "font-face-uri", "foreignObject", "g", "glyph", "glyphRef", "hkern", "image", "line", "linearGradient", "marker", "mask", "metadata", "missing-glyph", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect",
@@ -278,13 +279,29 @@ function setProperty(node, name, value) {
278
279
  node[name] = value;
279
280
  }
280
281
  let claimHandlers = null;
282
+ const CLAIM_SEAM = Symbol.for("dom-expressions.element-claims");
281
283
  function registerElementClaim(handler) {
282
- (claimHandlers || (claimHandlers = [])).push(handler);
284
+ (claimHandlers || (claimHandlers = globalThis[CLAIM_SEAM] = [])).push(handler);
283
285
  return () => {
284
286
  const index = claimHandlers.indexOf(handler);
285
287
  index > -1 && claimHandlers.splice(index, 1);
286
288
  };
287
289
  }
290
+ const CLAIMED_ELEMENTS = "a[href], form[action]";
291
+ function claimElementTree(root) {
292
+ const handlers = globalThis[CLAIM_SEAM];
293
+ if (handlers === undefined || handlers.length === 0) return root;
294
+ const isElement = root.nodeType === 1;
295
+ if (!isElement && root.nodeType !== 11) return root;
296
+ if (isElement && root.matches(CLAIMED_ELEMENTS)) {
297
+ for (let i = 0; i < handlers.length; i++) handlers[i](root);
298
+ }
299
+ const found = root.querySelectorAll(CLAIMED_ELEMENTS);
300
+ for (let i = 0; i < found.length; i++) {
301
+ for (let j = 0; j < handlers.length; j++) handlers[j](found[i]);
302
+ }
303
+ return root;
304
+ }
288
305
  function claimElement(node) {
289
306
  if (claimHandlers !== null) {
290
307
  for (let i = 0; i < claimHandlers.length; i++) claimHandlers[i](node);
@@ -951,6 +968,11 @@ function insertExpression(parent, value, current, marker) {
951
968
  parent.appendChild(value);
952
969
  }
953
970
  if (marker) value[$$SLOT] = marker;
971
+ } else if (value[$$FRAME]) {
972
+ if (current) {
973
+ cleanChildren(parent, Array.isArray(current) ? current : [current], multi ? marker : null);
974
+ }
975
+ value[$$FRAME](parent, multi ? marker : null);
954
976
  } else if (Array.isArray(value)) {
955
977
  const currentArray = current && Array.isArray(current);
956
978
  if (value.length === 0) {
@@ -971,6 +993,7 @@ function normalize(value, current, multi, doNotUnwrap) {
971
993
  doNotUnwrap
972
994
  });
973
995
  if (doNotUnwrap && typeof value === "function") return value;
996
+ if (value != null && value[$$FRAME]) return value;
974
997
  if (multi && !Array.isArray(value)) value = [value != null ? value : ""];
975
998
  if (Array.isArray(value)) {
976
999
  for (let i = 0, len = value.length; i < len; i++) {
@@ -1316,6 +1339,7 @@ exports.addEvent = addEvent;
1316
1339
  exports.applyRef = applyRef;
1317
1340
  exports.assign = assign;
1318
1341
  exports.claimElement = claimElement;
1342
+ exports.claimElementTree = claimElementTree;
1319
1343
  exports.className = className;
1320
1344
  exports.delegateEvents = delegateEvents;
1321
1345
  exports.dynamic = dynamic;
package/dist/web.js CHANGED
@@ -32,6 +32,7 @@ const DOMWithState = {
32
32
  const ChildProperties = /*#__PURE__*/new Set(["innerHTML", "textContent", "innerText", "children"]);
33
33
  const $$SLOT = /*#__PURE__*/Symbol("slot");
34
34
  const $$HOST = /*#__PURE__*/Symbol("host");
35
+ const $$FRAME = /*#__PURE__*/Symbol.for("dom-expressions.frame");
35
36
  const DelegatedEvents = /*#__PURE__*/new Set(["beforeinput", "click", "dblclick", "contextmenu", "focusin", "focusout", "input", "keydown", "keyup", "mousedown", "mousemove", "mouseout", "mouseover", "mouseup", "pointerdown", "pointermove", "pointerout", "pointerover", "pointerup", "touchend", "touchmove", "touchstart"]);
36
37
  const SVGElements = /*#__PURE__*/new Set([
37
38
  "altGlyph", "altGlyphDef", "altGlyphItem", "animate", "animateColor", "animateMotion", "animateTransform", "circle", "clipPath", "color-profile", "cursor", "defs", "desc", "ellipse", "feBlend", "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", "feDiffuseLighting", "feDisplacementMap", "feDistantLight", "feDropShadow", "feFlood", "feFuncA", "feFuncB", "feFuncG", "feFuncR", "feGaussianBlur", "feImage", "feMerge", "feMergeNode", "feMorphology", "feOffset", "fePointLight", "feSpecularLighting", "feSpotLight", "feTile", "feTurbulence", "filter", "font", "font-face", "font-face-format", "font-face-name", "font-face-src", "font-face-uri", "foreignObject", "g", "glyph", "glyphRef", "hkern", "image", "line", "linearGradient", "marker", "mask", "metadata", "missing-glyph", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect",
@@ -277,13 +278,29 @@ function setProperty(node, name, value) {
277
278
  node[name] = value;
278
279
  }
279
280
  let claimHandlers = null;
281
+ const CLAIM_SEAM = Symbol.for("dom-expressions.element-claims");
280
282
  function registerElementClaim(handler) {
281
- (claimHandlers || (claimHandlers = [])).push(handler);
283
+ (claimHandlers || (claimHandlers = globalThis[CLAIM_SEAM] = [])).push(handler);
282
284
  return () => {
283
285
  const index = claimHandlers.indexOf(handler);
284
286
  index > -1 && claimHandlers.splice(index, 1);
285
287
  };
286
288
  }
289
+ const CLAIMED_ELEMENTS = "a[href], form[action]";
290
+ function claimElementTree(root) {
291
+ const handlers = globalThis[CLAIM_SEAM];
292
+ if (handlers === undefined || handlers.length === 0) return root;
293
+ const isElement = root.nodeType === 1;
294
+ if (!isElement && root.nodeType !== 11) return root;
295
+ if (isElement && root.matches(CLAIMED_ELEMENTS)) {
296
+ for (let i = 0; i < handlers.length; i++) handlers[i](root);
297
+ }
298
+ const found = root.querySelectorAll(CLAIMED_ELEMENTS);
299
+ for (let i = 0; i < found.length; i++) {
300
+ for (let j = 0; j < handlers.length; j++) handlers[j](found[i]);
301
+ }
302
+ return root;
303
+ }
287
304
  function claimElement(node) {
288
305
  if (claimHandlers !== null) {
289
306
  for (let i = 0; i < claimHandlers.length; i++) claimHandlers[i](node);
@@ -950,6 +967,11 @@ function insertExpression(parent, value, current, marker) {
950
967
  parent.appendChild(value);
951
968
  }
952
969
  if (marker) value[$$SLOT] = marker;
970
+ } else if (value[$$FRAME]) {
971
+ if (current) {
972
+ cleanChildren(parent, Array.isArray(current) ? current : [current], multi ? marker : null);
973
+ }
974
+ value[$$FRAME](parent, multi ? marker : null);
953
975
  } else if (Array.isArray(value)) {
954
976
  const currentArray = current && Array.isArray(current);
955
977
  if (value.length === 0) {
@@ -970,6 +992,7 @@ function normalize(value, current, multi, doNotUnwrap) {
970
992
  doNotUnwrap
971
993
  });
972
994
  if (doNotUnwrap && typeof value === "function") return value;
995
+ if (value != null && value[$$FRAME]) return value;
973
996
  if (multi && !Array.isArray(value)) value = [value != null ? value : ""];
974
997
  if (Array.isArray(value)) {
975
998
  for (let i = 0, len = value.length; i < len; i++) {
@@ -1242,4 +1265,4 @@ function createElement(tagName, is = undefined) {
1242
1265
  });
1243
1266
  }
1244
1267
 
1245
- export { voidFn as Assets, ChildProperties, DOMElements, DOMWithState, DelegatedEvents, Dynamic, HREF, voidFn as HydrationScript, MathMLElements, Namespaces, Portal, RawTextElements, RequestContext, ResponseEnvelope, SVGElements, VoidElements, acquireAsset, addEvent, applyRef, assign, claimElement, className, delegateEvents, dynamic, dynamicProperty, effect, escape, voidFn as generateHydrationScript, voidFn as getAssets, getDelegatedRoot, getFirstChild, getHydrationKey, getNextElement, getNextMarker, getNextMatch, getNextSibling, voidFn as getRequestEvent, hydrate, insert, installHydrationRuntime, isDev, isHref, isResponseEnvelope, isServer, memo, mergeProps, redirect, ref, registerDelegatedContainer, registerDelegatedRoot, registerElementClaim, reload, render, renderToStream, renderToString, renderToStringAsync, resolveSSRNode, respond, runHydrationEvents, scope, setAttribute, setAttributeNS, setProperty, setStyleProperty, spread, ssr, ssrAttribute, ssrClassList, ssrElement, ssrHydrationKey, ssrStyle, style, template, unregisterDelegatedContainer, unregisterDelegatedRoot, voidFn as useAssets };
1268
+ export { voidFn as Assets, ChildProperties, DOMElements, DOMWithState, DelegatedEvents, Dynamic, HREF, voidFn as HydrationScript, MathMLElements, Namespaces, Portal, RawTextElements, RequestContext, ResponseEnvelope, SVGElements, VoidElements, acquireAsset, addEvent, applyRef, assign, claimElement, claimElementTree, className, delegateEvents, dynamic, dynamicProperty, effect, escape, voidFn as generateHydrationScript, voidFn as getAssets, getDelegatedRoot, getFirstChild, getHydrationKey, getNextElement, getNextMarker, getNextMatch, getNextSibling, voidFn as getRequestEvent, hydrate, insert, installHydrationRuntime, isDev, isHref, isResponseEnvelope, isServer, memo, mergeProps, redirect, ref, registerDelegatedContainer, registerDelegatedRoot, registerElementClaim, reload, render, renderToStream, renderToString, renderToStringAsync, resolveSSRNode, respond, runHydrationEvents, scope, setAttribute, setAttributeNS, setProperty, setStyleProperty, spread, ssr, ssrAttribute, ssrClassList, ssrElement, ssrHydrationKey, ssrStyle, style, template, unregisterDelegatedContainer, unregisterDelegatedRoot, voidFn as useAssets };