sibujs 3.0.0 → 3.2.0

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 (78) hide show
  1. package/README.md +6 -0
  2. package/dist/browser.cjs +16 -8
  3. package/dist/browser.js +6 -5
  4. package/dist/build.cjs +276 -150
  5. package/dist/build.js +35 -24
  6. package/dist/cdn.global.js +7 -7
  7. package/dist/{chunk-RJIRT46U.js → chunk-2C4E3HBM.js} +5 -5
  8. package/dist/{chunk-XDKP4T7G.js → chunk-4JCAUOLN.js} +45 -23
  9. package/dist/{chunk-VSNLICTS.js → chunk-5N74TKLD.js} +1 -1
  10. package/dist/{chunk-XVYB3J6C.js → chunk-7XDYVJLE.js} +19 -9
  11. package/dist/{chunk-L52H775O.js → chunk-BGNLPNGV.js} +20 -12
  12. package/dist/{chunk-6QZO7MMG.js → chunk-C427DVQF.js} +1 -1
  13. package/dist/{chunk-5WD7BYTZ.js → chunk-FDY42FIU.js} +3 -2
  14. package/dist/{chunk-4YTVESDX.js → chunk-FOI23UJL.js} +11 -1
  15. package/dist/{chunk-2RA7SHDA.js → chunk-GOJMFRBL.js} +20 -4
  16. package/dist/{chunk-2KM2724A.js → chunk-GOUM4JCT.js} +6 -6
  17. package/dist/chunk-H3SRKIYX.js +17 -0
  18. package/dist/{chunk-NEWH4O5U.js → chunk-H6PCHJZQ.js} +2 -2
  19. package/dist/{chunk-UCS6AMJ7.js → chunk-HMJFCBRR.js} +26 -3
  20. package/dist/{chunk-JYD2PWXH.js → chunk-HXMS4SNP.js} +22 -15
  21. package/dist/{chunk-DF3GTP4Q.js → chunk-JYXOEYI4.js} +12 -18
  22. package/dist/{chunk-KZA7ANXP.js → chunk-NFYWLRUO.js} +11 -18
  23. package/dist/{chunk-KH4OE6WY.js → chunk-NPIEEKPT.js} +20 -11
  24. package/dist/{chunk-V65KTDZW.js → chunk-OYLPZO4N.js} +33 -15
  25. package/dist/{chunk-LYTCUZ7H.js → chunk-RDRSWYNP.js} +1 -1
  26. package/dist/{chunk-UKMXT5T6.js → chunk-RLUJL2MV.js} +7 -12
  27. package/dist/{chunk-INBOWHQ3.js → chunk-V2MTG5FT.js} +99 -36
  28. package/dist/{chunk-CNZ35WI2.js → chunk-VJE6DDYM.js} +2 -2
  29. package/dist/{chunk-2JQUV4Y3.js → chunk-VOCE4NNK.js} +157 -75
  30. package/dist/{chunk-STFTTMO2.js → chunk-X67UYC74.js} +31 -12
  31. package/dist/{chunk-YMOIAHWA.js → chunk-YFDGQWDA.js} +1 -1
  32. package/dist/{chunk-L4DAT4WU.js → chunk-Z2FWAE4B.js} +28 -1
  33. package/dist/data.cjs +211 -93
  34. package/dist/data.d.cts +7 -1
  35. package/dist/data.d.ts +7 -1
  36. package/dist/data.js +8 -8
  37. package/dist/devtools.cjs +38 -10
  38. package/dist/devtools.d.cts +1 -1
  39. package/dist/devtools.d.ts +1 -1
  40. package/dist/devtools.js +6 -6
  41. package/dist/ecosystem.cjs +163 -65
  42. package/dist/ecosystem.js +9 -9
  43. package/dist/extras.cjs +420 -198
  44. package/dist/extras.d.cts +2 -2
  45. package/dist/extras.d.ts +2 -2
  46. package/dist/extras.js +27 -24
  47. package/dist/index.cjs +255 -139
  48. package/dist/index.d.cts +15 -2
  49. package/dist/index.d.ts +15 -2
  50. package/dist/index.js +15 -13
  51. package/dist/{introspect-BZWKvQUZ.d.ts → introspect-DOZfmC-4.d.ts} +1 -1
  52. package/dist/{introspect-DsJlDD2T.d.cts → introspect-RjLfIFpL.d.cts} +1 -1
  53. package/dist/motion.cjs +10 -0
  54. package/dist/motion.js +3 -3
  55. package/dist/patterns.cjs +66 -39
  56. package/dist/patterns.js +8 -7
  57. package/dist/performance.cjs +101 -25
  58. package/dist/performance.d.cts +2 -2
  59. package/dist/performance.d.ts +2 -2
  60. package/dist/performance.js +8 -7
  61. package/dist/plugins.cjs +243 -138
  62. package/dist/plugins.d.cts +1 -1
  63. package/dist/plugins.d.ts +1 -1
  64. package/dist/plugins.js +96 -45
  65. package/dist/{ssr-FXD2PPMC.js → ssr-2QDQ27EV.js} +5 -3
  66. package/dist/{ssr-CrVNy6Pa.d.cts → ssr-D62yFwuw.d.cts} +8 -1
  67. package/dist/{ssr-CrVNy6Pa.d.ts → ssr-D62yFwuw.d.ts} +8 -1
  68. package/dist/ssr.cjs +185 -68
  69. package/dist/ssr.d.cts +1 -1
  70. package/dist/ssr.d.ts +1 -1
  71. package/dist/ssr.js +12 -10
  72. package/dist/testing.cjs +9 -4
  73. package/dist/testing.js +3 -3
  74. package/dist/ui.cjs +76 -39
  75. package/dist/ui.js +10 -9
  76. package/dist/widgets.cjs +61 -23
  77. package/dist/widgets.js +8 -8
  78. package/package.json +3 -1
package/dist/index.cjs CHANGED
@@ -99,6 +99,7 @@ __export(index_exports, {
99
99
  footer: () => footer,
100
100
  form: () => form,
101
101
  g: () => g,
102
+ getRequestScopedCache: () => getRequestScopedCache,
102
103
  getSSRStore: () => getSSRStore,
103
104
  getSlot: () => getSlot,
104
105
  h1: () => h1,
@@ -248,9 +249,17 @@ function devWarn(message) {
248
249
  }
249
250
 
250
251
  // src/utils/sanitize.ts
252
+ function stripControlChars(value) {
253
+ return value.replace(/[\x00-\x20\x7f-\x9f]+/g, "");
254
+ }
255
+ function isEventHandlerAttr(name) {
256
+ if (name.length < 3) return false;
257
+ const lower = name.toLowerCase();
258
+ return lower[0] === "o" && lower[1] === "n" && lower.charCodeAt(2) >= 97 && lower.charCodeAt(2) <= 122;
259
+ }
251
260
  var SAFE_URL_PROTOCOLS = ["http:", "https:", "mailto:", "tel:", "ftp:"];
252
261
  function sanitizeUrl(url) {
253
- const trimmed = url.replace(/[\x00-\x20\x7f-\x9f]+/g, "").trim();
262
+ const trimmed = stripControlChars(url).trim();
254
263
  if (!trimmed) return "";
255
264
  const lower = trimmed.toLowerCase();
256
265
  let schemeEnd = -1;
@@ -313,7 +322,7 @@ var URL_ATTRIBUTES = /* @__PURE__ */ new Set([
313
322
  "data"
314
323
  ]);
315
324
  function isUrlAttribute(attr) {
316
- return URL_ATTRIBUTES.has(attr);
325
+ return URL_ATTRIBUTES.has(attr.toLowerCase());
317
326
  }
318
327
 
319
328
  // src/reactivity/track.ts
@@ -471,7 +480,7 @@ function retrack(effectFn, subscriber) {
471
480
  }
472
481
  }
473
482
  function track(effectFn, subscriber) {
474
- if (!subscriber) subscriber = effectFn;
483
+ if (!subscriber) return reactiveBinding(effectFn);
475
484
  cleanup(subscriber);
476
485
  const prev = currentSubscriber;
477
486
  currentSubscriber = subscriber;
@@ -489,6 +498,32 @@ function track(effectFn, subscriber) {
489
498
  const sub2 = subscriber;
490
499
  return sub2._dispose ?? (sub2._dispose = () => cleanup(subscriber));
491
500
  }
501
+ function reactiveBinding(commit) {
502
+ const run = () => {
503
+ const s2 = subscriber;
504
+ if (s2._disposed || s2._reentrant) return;
505
+ s2._reentrant = true;
506
+ try {
507
+ retrack(commit, subscriber);
508
+ } finally {
509
+ s2._reentrant = false;
510
+ }
511
+ };
512
+ const subscriber = run;
513
+ subscriber.depsHead = null;
514
+ subscriber.depsTail = null;
515
+ subscriber._epoch = 0;
516
+ subscriber._structDirty = false;
517
+ subscriber._runEpoch = 0;
518
+ subscriber._runs = 0;
519
+ subscriber._reentrant = false;
520
+ subscriber._disposed = false;
521
+ run();
522
+ return subscriber._dispose ?? (subscriber._dispose = () => {
523
+ subscriber._disposed = true;
524
+ cleanup(subscriber);
525
+ });
526
+ }
492
527
  function recordDependency(signal2) {
493
528
  if (!currentSubscriber) return;
494
529
  const sub2 = currentSubscriber;
@@ -680,11 +715,6 @@ var _isDev3 = isDev();
680
715
  function setProp(el, key, val) {
681
716
  el[key] = val;
682
717
  }
683
- function isEventHandlerAttr(name) {
684
- if (name.length < 3) return false;
685
- const lower = name.toLowerCase();
686
- return lower[0] === "o" && lower[1] === "n" && lower.charCodeAt(2) >= 97 && lower.charCodeAt(2) <= 122;
687
- }
688
718
  function bindAttribute(el, attr, getter) {
689
719
  if (isEventHandlerAttr(attr)) {
690
720
  if (_isDev3)
@@ -720,8 +750,7 @@ function bindAttribute(el, attr, getter) {
720
750
  el.setAttribute(attr, isUrlAttribute(attr) ? sanitizeUrl(str) : str);
721
751
  }
722
752
  }
723
- const teardown = track(commit);
724
- return teardown;
753
+ return reactiveBinding(commit);
725
754
  }
726
755
  function bindDynamic(el, nameGetter, valueGetter) {
727
756
  let prevName = null;
@@ -740,7 +769,7 @@ function bindDynamic(el, nameGetter, valueGetter) {
740
769
  if (_isDev3) devWarn(`bindDynamic: value getter threw: ${err instanceof Error ? err.message : String(err)}`);
741
770
  return;
742
771
  }
743
- if ((name[0] === "o" || name[0] === "O") && (name[1] === "n" || name[1] === "N")) return;
772
+ if (isEventHandlerAttr(name)) return;
744
773
  if (prevName !== null && prevName !== name) {
745
774
  el.removeAttribute(prevName);
746
775
  }
@@ -752,7 +781,7 @@ function bindDynamic(el, nameGetter, valueGetter) {
752
781
  }
753
782
  prevName = name;
754
783
  }
755
- const teardown = track(commit);
784
+ const teardown = reactiveBinding(commit);
756
785
  return () => {
757
786
  teardown();
758
787
  if (prevName !== null) {
@@ -761,83 +790,9 @@ function bindDynamic(el, nameGetter, valueGetter) {
761
790
  };
762
791
  }
763
792
 
764
- // src/reactivity/bindChildNode.ts
765
- var _isDev4 = isDev();
766
- function bindChildNode(placeholder, getter) {
767
- let lastNodes = [];
768
- function commit() {
769
- let result;
770
- try {
771
- result = getter();
772
- } catch (err) {
773
- if (_isDev4) devWarn(`bindChildNode: getter threw: ${err instanceof Error ? err.message : String(err)}`);
774
- return;
775
- }
776
- if (result == null || typeof result === "boolean") {
777
- for (let i2 = 0; i2 < lastNodes.length; i2++) {
778
- const node = lastNodes[i2];
779
- if (node.parentNode) node.parentNode.removeChild(node);
780
- }
781
- lastNodes.length = 0;
782
- return;
783
- }
784
- const parent = placeholder.parentNode;
785
- if (!parent) {
786
- lastNodes.length = 0;
787
- return;
788
- }
789
- let newNodes;
790
- if (Array.isArray(result)) {
791
- newNodes = [];
792
- const seen = /* @__PURE__ */ new Set();
793
- for (let i2 = 0; i2 < result.length; i2++) {
794
- const item = result[i2];
795
- if (item == null || typeof item === "boolean") continue;
796
- const node = item instanceof Node ? item : document.createTextNode(String(item));
797
- if (seen.has(node)) {
798
- if (_isDev4)
799
- devWarn("bindChildNode: duplicate node reference in array \u2014 only the first occurrence is rendered.");
800
- continue;
801
- }
802
- seen.add(node);
803
- newNodes.push(node);
804
- }
805
- } else {
806
- const node = result instanceof Node ? result : document.createTextNode(String(result));
807
- newNodes = [node];
808
- }
809
- let reused;
810
- if (lastNodes.length > 0 && newNodes.length > 0) {
811
- const lastSet = new Set(lastNodes);
812
- reused = /* @__PURE__ */ new Set();
813
- for (let i2 = 0; i2 < newNodes.length; i2++) {
814
- if (lastSet.has(newNodes[i2])) reused.add(newNodes[i2]);
815
- }
816
- }
817
- for (let i2 = 0; i2 < lastNodes.length; i2++) {
818
- const node = lastNodes[i2];
819
- if (reused?.has(node)) continue;
820
- if (node.parentNode) node.parentNode.removeChild(node);
821
- }
822
- const anchor = placeholder.nextSibling;
823
- for (let i2 = 0; i2 < newNodes.length; i2++) {
824
- const node = newNodes[i2];
825
- if (reused?.has(node) && node.parentNode === parent) {
826
- if (node.nextSibling !== anchor) {
827
- parent.insertBefore(node, anchor);
828
- }
829
- } else {
830
- parent.insertBefore(node, anchor);
831
- }
832
- }
833
- lastNodes = newNodes;
834
- }
835
- return track(commit);
836
- }
837
-
838
793
  // src/core/rendering/dispose.ts
839
794
  var elementDisposers = /* @__PURE__ */ new WeakMap();
840
- var _isDev5 = isDev();
795
+ var _isDev4 = isDev();
841
796
  var activeBindingCount = 0;
842
797
  function registerDisposer(node, teardown) {
843
798
  let disposers = elementDisposers.get(node);
@@ -846,7 +801,7 @@ function registerDisposer(node, teardown) {
846
801
  elementDisposers.set(node, disposers);
847
802
  }
848
803
  disposers.push(teardown);
849
- if (_isDev5) activeBindingCount++;
804
+ if (_isDev4) activeBindingCount++;
850
805
  }
851
806
  function dispose(node) {
852
807
  const stack = [node];
@@ -865,12 +820,12 @@ function dispose(node) {
865
820
  if (disposers) {
866
821
  const snapshot = disposers.slice();
867
822
  elementDisposers.delete(current);
868
- if (_isDev5) activeBindingCount -= snapshot.length;
823
+ if (_isDev4) activeBindingCount -= snapshot.length;
869
824
  for (const d of snapshot) {
870
825
  try {
871
826
  d();
872
827
  } catch (err) {
873
- if (_isDev5 && typeof console !== "undefined") {
828
+ if (_isDev4 && typeof console !== "undefined") {
874
829
  console.warn("[SibuJS] Disposer threw during cleanup:", err);
875
830
  }
876
831
  }
@@ -881,12 +836,12 @@ function dispose(node) {
881
836
  if (!added || added.length === 0) break;
882
837
  const moreSnapshot = added.slice();
883
838
  elementDisposers.delete(current);
884
- if (_isDev5) activeBindingCount -= moreSnapshot.length;
839
+ if (_isDev4) activeBindingCount -= moreSnapshot.length;
885
840
  for (const d of moreSnapshot) {
886
841
  try {
887
842
  d();
888
843
  } catch (err) {
889
- if (_isDev5 && typeof console !== "undefined") {
844
+ if (_isDev4 && typeof console !== "undefined") {
890
845
  console.warn("[SibuJS] Disposer threw during cleanup:", err);
891
846
  }
892
847
  }
@@ -896,7 +851,7 @@ function dispose(node) {
896
851
  }
897
852
  }
898
853
  function checkLeaks(warnThreshold = 0) {
899
- if (!_isDev5) return 0;
854
+ if (!_isDev4) return 0;
900
855
  if (warnThreshold > 0 && activeBindingCount > warnThreshold) {
901
856
  devWarn(
902
857
  `checkLeaks: ${activeBindingCount} active DOM bindings detected. Expected \u2264${warnThreshold}. This may indicate a component was removed from the DOM without calling dispose().`
@@ -905,6 +860,79 @@ function checkLeaks(warnThreshold = 0) {
905
860
  return activeBindingCount;
906
861
  }
907
862
 
863
+ // src/reactivity/bindChildNode.ts
864
+ var _isDev5 = isDev();
865
+ function bindChildNode(placeholder, getter) {
866
+ let lastNodes = [];
867
+ function commit() {
868
+ let result;
869
+ try {
870
+ result = getter();
871
+ } catch (err) {
872
+ if (_isDev5) devWarn(`bindChildNode: getter threw: ${err instanceof Error ? err.message : String(err)}`);
873
+ return;
874
+ }
875
+ if (result == null || typeof result === "boolean") {
876
+ for (let i2 = 0; i2 < lastNodes.length; i2++) {
877
+ const node = lastNodes[i2];
878
+ dispose(node);
879
+ if (node.parentNode) node.parentNode.removeChild(node);
880
+ }
881
+ lastNodes.length = 0;
882
+ return;
883
+ }
884
+ const parent = placeholder.parentNode;
885
+ if (!parent) {
886
+ lastNodes.length = 0;
887
+ return;
888
+ }
889
+ let newNodes;
890
+ if (Array.isArray(result)) {
891
+ newNodes = [];
892
+ const seen = /* @__PURE__ */ new Set();
893
+ for (let i2 = 0; i2 < result.length; i2++) {
894
+ const item = result[i2];
895
+ if (item == null || typeof item === "boolean") continue;
896
+ const node = item instanceof Node ? item : document.createTextNode(String(item));
897
+ if (seen.has(node)) {
898
+ if (_isDev5)
899
+ devWarn("bindChildNode: duplicate node reference in array \u2014 only the first occurrence is rendered.");
900
+ continue;
901
+ }
902
+ seen.add(node);
903
+ newNodes.push(node);
904
+ }
905
+ } else {
906
+ const node = result instanceof Node ? result : document.createTextNode(String(result));
907
+ newNodes = [node];
908
+ }
909
+ let reused;
910
+ if (lastNodes.length > 0 && newNodes.length > 0) {
911
+ const lastSet = new Set(lastNodes);
912
+ reused = /* @__PURE__ */ new Set();
913
+ for (let i2 = 0; i2 < newNodes.length; i2++) {
914
+ if (lastSet.has(newNodes[i2])) reused.add(newNodes[i2]);
915
+ }
916
+ }
917
+ for (let i2 = 0; i2 < lastNodes.length; i2++) {
918
+ const node = lastNodes[i2];
919
+ if (reused?.has(node)) continue;
920
+ dispose(node);
921
+ if (node.parentNode) node.parentNode.removeChild(node);
922
+ }
923
+ let prev = placeholder;
924
+ for (let i2 = 0; i2 < newNodes.length; i2++) {
925
+ const node = newNodes[i2];
926
+ if (prev.nextSibling !== node) {
927
+ parent.insertBefore(node, prev.nextSibling);
928
+ }
929
+ prev = node;
930
+ }
931
+ lastNodes = newNodes;
932
+ }
933
+ return reactiveBinding(commit);
934
+ }
935
+
908
936
  // src/core/rendering/tagFactory.ts
909
937
  var SVG_NS = "http://www.w3.org/2000/svg";
910
938
  var _isDev6 = isDev();
@@ -931,6 +959,18 @@ var CLOBBER_RISKY_IDS = /* @__PURE__ */ new Set([
931
959
  function setProp2(el, key, val) {
932
960
  el[key] = val;
933
961
  }
962
+ function looksLikeClassList(s2) {
963
+ const t = s2.trim();
964
+ if (!t) return false;
965
+ const tokens = t.split(/\s+/);
966
+ let sawClassish = false;
967
+ for (let i2 = 0; i2 < tokens.length; i2++) {
968
+ const tok = tokens[i2];
969
+ if (!/^-?[A-Za-z_][A-Za-z0-9_:/.-]*$/.test(tok)) return false;
970
+ if (/[-:/0-9]/.test(tok)) sawClassish = true;
971
+ }
972
+ return sawClassish;
973
+ }
934
974
  var kebabCache = /* @__PURE__ */ new Map();
935
975
  function toKebab(prop) {
936
976
  let cached = kebabCache.get(prop);
@@ -1066,6 +1106,11 @@ var tagFactory = (tag, ns) => {
1066
1106
  appendChildren(el, second);
1067
1107
  return el;
1068
1108
  }
1109
+ if (_isDev6 && looksLikeClassList(first)) {
1110
+ devWarn(
1111
+ `tagFactory: lone string "${first}" looks like a class list but is being rendered as TEXT. For a class, use ${tag}({ class: "${first}" }) \u2014 or ${tag}("${first}", children) to set the class AND add children.`
1112
+ );
1113
+ }
1069
1114
  el.textContent = first;
1070
1115
  return el;
1071
1116
  }
@@ -1123,7 +1168,7 @@ var tagFactory = (tag, ns) => {
1123
1168
  const value = props[key];
1124
1169
  if (value == null) continue;
1125
1170
  const lkey = key.toLowerCase();
1126
- if (lkey[0] === "o" && lkey[1] === "n") continue;
1171
+ if (isEventHandlerAttr(key)) continue;
1127
1172
  if (typeof value === "function") {
1128
1173
  registerDisposer(el, bindAttribute(el, key, value));
1129
1174
  } else if (typeof value === "boolean") {
@@ -1404,14 +1449,28 @@ function parseTemplate(strings) {
1404
1449
  }
1405
1450
  return { kind: "mixed", statics, exprs };
1406
1451
  }
1407
- const valStart = pos;
1408
- while (pos < len) {
1409
- const c = template2.charCodeAt(pos);
1410
- if (c === 32 || c === 9 || c === 10 || c === 13 || c === 62 || c === 47) break;
1411
- pos++;
1452
+ {
1453
+ const statics = [];
1454
+ const exprs = [];
1455
+ let current = "";
1456
+ while (pos < len) {
1457
+ const c = template2.charCodeAt(pos);
1458
+ if (c === 32 || c === 9 || c === 10 || c === 13 || c === 62) break;
1459
+ const innerIdx = tryExprIdx();
1460
+ if (innerIdx >= 0) {
1461
+ statics.push(current);
1462
+ current = "";
1463
+ exprs.push(innerIdx);
1464
+ } else {
1465
+ current += template2[pos++];
1466
+ }
1467
+ }
1468
+ statics.push(current);
1469
+ if (exprs.length === 0) {
1470
+ return { kind: "static", value: statics[0] };
1471
+ }
1472
+ return { kind: "mixed", statics, exprs };
1412
1473
  }
1413
- const val = template2.slice(valStart, pos);
1414
- return { kind: "static", value: val };
1415
1474
  }
1416
1475
  function parseAttrs() {
1417
1476
  const attrs = [];
@@ -1468,6 +1527,30 @@ function parseTemplate(strings) {
1468
1527
  while (pos < len) {
1469
1528
  if (template2[pos] === "<" && pos + 1 < len && template2[pos + 1] === "/") break;
1470
1529
  if (template2[pos] === "<") {
1530
+ const next = template2[pos + 1];
1531
+ if (next === "!") {
1532
+ if (template2.startsWith("<!--", pos)) {
1533
+ const end = template2.indexOf("-->", pos + 4);
1534
+ pos = end === -1 ? len : end + 3;
1535
+ } else if (template2.startsWith("<![CDATA[", pos)) {
1536
+ const end = template2.indexOf("]]>", pos + 9);
1537
+ pos = end === -1 ? len : end + 3;
1538
+ } else {
1539
+ const end = template2.indexOf(">", pos);
1540
+ pos = end === -1 ? len : end + 1;
1541
+ }
1542
+ continue;
1543
+ }
1544
+ if (next === "?") {
1545
+ const end = template2.indexOf(">", pos);
1546
+ pos = end === -1 ? len : end + 1;
1547
+ continue;
1548
+ }
1549
+ if (!(next >= "a" && next <= "z") && !(next >= "A" && next <= "Z")) {
1550
+ children.push({ t: 1, value: "<" });
1551
+ pos++;
1552
+ continue;
1553
+ }
1471
1554
  pos++;
1472
1555
  const tag = readTagName();
1473
1556
  const attrs = parseAttrs();
@@ -1516,7 +1599,7 @@ function executeElement(tmpl, values) {
1516
1599
  case 1: {
1517
1600
  const name = attr.name;
1518
1601
  const lname = name.toLowerCase();
1519
- if (lname[0] === "o" && lname[1] === "n") break;
1602
+ if (isEventHandlerAttr(name)) break;
1520
1603
  const val = values[attr.idx];
1521
1604
  if (typeof val === "function") {
1522
1605
  registerDisposer(el, bindAttribute(el, name, val));
@@ -1765,6 +1848,11 @@ function each(getArray, render, options) {
1765
1848
  workMap.clear();
1766
1849
  keyIndexMap.clear();
1767
1850
  for (let i2 = 0; i2 < newLen; i2++) {
1851
+ if (_isDev8 && keyIndexMap.has(newKeys[i2])) {
1852
+ devWarn(
1853
+ `each: duplicate key "${String(newKeys[i2])}" at index ${i2} (first seen at ${keyIndexMap.get(newKeys[i2])}). Keys must be unique \u2014 duplicates cause rows to be dropped or mis-ordered.`
1854
+ );
1855
+ }
1768
1856
  keyIndexMap.set(newKeys[i2], i2);
1769
1857
  }
1770
1858
  for (let i2 = 0; i2 < newLen; i2++) {
@@ -1996,7 +2084,7 @@ function show(condition, element) {
1996
2084
  const update = () => {
1997
2085
  element.style.display = condition() ? "" : "none";
1998
2086
  };
1999
- track(update);
2087
+ registerDisposer(element, track(update));
2000
2088
  return element;
2001
2089
  }
2002
2090
  function when(condition, thenBranch, elseBranch) {
@@ -2023,7 +2111,7 @@ function when(condition, thenBranch, elseBranch) {
2023
2111
  }
2024
2112
  initialized = true;
2025
2113
  };
2026
- track(update);
2114
+ registerDisposer(anchor, track(update));
2027
2115
  if (!initialized) {
2028
2116
  queueMicrotask(() => {
2029
2117
  if (!initialized && anchor.parentNode) update();
@@ -2058,7 +2146,7 @@ function match(value, cases, fallback) {
2058
2146
  }
2059
2147
  initialized = true;
2060
2148
  };
2061
- track(update);
2149
+ registerDisposer(anchor, track(update));
2062
2150
  if (!initialized) {
2063
2151
  queueMicrotask(() => {
2064
2152
  if (!initialized && anchor.parentNode) update();
@@ -2099,6 +2187,12 @@ function KeepAlive(activeKey, cases, options) {
2099
2187
  return;
2100
2188
  }
2101
2189
  node = factory();
2190
+ if (node instanceof DocumentFragment) {
2191
+ const wrapper = document.createElement("div");
2192
+ wrapper.style.display = "contents";
2193
+ wrapper.appendChild(node);
2194
+ node = wrapper;
2195
+ }
2102
2196
  cache2.set(key, node);
2103
2197
  lruOrder.push(key);
2104
2198
  if (max > 0 && lruOrder.length > max) {
@@ -2383,11 +2477,15 @@ function signal(initial, options) {
2383
2477
  var als = null;
2384
2478
  try {
2385
2479
  if (typeof process !== "undefined" && process.versions && process.versions.node) {
2386
- const req = Function("return typeof require==='function'?require:null")();
2387
- if (req) {
2388
- const mod = req("node:async_hooks");
2389
- als = new mod.AsyncLocalStorage();
2480
+ let mod = null;
2481
+ const getBuiltin = process.getBuiltinModule;
2482
+ if (typeof getBuiltin === "function") {
2483
+ mod = getBuiltin("node:async_hooks");
2484
+ } else {
2485
+ const req = Function("return typeof require==='function'?require:null")();
2486
+ if (req) mod = req("node:async_hooks");
2390
2487
  }
2488
+ if (mod) als = new mod.AsyncLocalStorage();
2391
2489
  }
2392
2490
  } catch {
2393
2491
  als = null;
@@ -2403,6 +2501,17 @@ function getSSRStore() {
2403
2501
  function isSSR() {
2404
2502
  return getSSRStore().ssr;
2405
2503
  }
2504
+ function getRequestScopedCache(name) {
2505
+ if (!isSSR()) return null;
2506
+ const store2 = getSSRStore();
2507
+ const caches = store2.caches ?? (store2.caches = /* @__PURE__ */ new Map());
2508
+ let c = caches.get(name);
2509
+ if (!c) {
2510
+ c = /* @__PURE__ */ new Map();
2511
+ caches.set(name, c);
2512
+ }
2513
+ return c;
2514
+ }
2406
2515
  function enableSSR() {
2407
2516
  getSSRStore().ssr = true;
2408
2517
  }
@@ -2537,6 +2646,7 @@ function effect(effectFn, options) {
2537
2646
  ctx.fn(ctx.onCleanup);
2538
2647
  };
2539
2648
  const sub2 = (() => {
2649
+ if (ctx.disposed) return;
2540
2650
  if (ctx.running) {
2541
2651
  ctx.rerunPending = true;
2542
2652
  return;
@@ -2579,6 +2689,7 @@ function derived(getter, options) {
2579
2689
  const equals = options?.equals;
2580
2690
  const cs = {};
2581
2691
  cs._d = false;
2692
+ cs._init = false;
2582
2693
  cs._g = getter;
2583
2694
  cs.__v = 0;
2584
2695
  const markDirty = () => {
@@ -2587,11 +2698,18 @@ function derived(getter, options) {
2587
2698
  };
2588
2699
  markDirty._c = 1;
2589
2700
  markDirty._sig = cs;
2701
+ const recompute = () => {
2702
+ const next = getter();
2703
+ cs._v = equals && cs._init ? equals(cs._v, next) ? cs._v : next : next;
2704
+ cs._d = false;
2705
+ cs._init = true;
2706
+ };
2590
2707
  track(() => {
2591
2708
  let threw = true;
2592
2709
  try {
2593
2710
  cs._v = getter();
2594
2711
  cs._d = false;
2712
+ cs._init = true;
2595
2713
  threw = false;
2596
2714
  } finally {
2597
2715
  if (threw) cs._d = true;
@@ -2607,20 +2725,13 @@ function derived(getter, options) {
2607
2725
  }
2608
2726
  if (trackingSuspended) {
2609
2727
  if (cs._d) {
2728
+ const prev = cs._v;
2610
2729
  evaluating = true;
2611
- let threw = true;
2612
2730
  try {
2613
- const prev = cs._v;
2614
- retrack(() => {
2615
- const next = getter();
2616
- cs._v = equals && cs._v !== void 0 ? equals(cs._v, next) ? cs._v : next : next;
2617
- cs._d = false;
2618
- threw = false;
2619
- }, markDirty);
2731
+ retrack(recompute, markDirty);
2620
2732
  if (!Object.is(prev, cs._v)) cs.__v++;
2621
2733
  } finally {
2622
2734
  evaluating = false;
2623
- if (threw) cs._d = true;
2624
2735
  }
2625
2736
  }
2626
2737
  return cs._v;
@@ -2629,18 +2740,11 @@ function derived(getter, options) {
2629
2740
  if (cs._d) {
2630
2741
  const oldValue = cs._v;
2631
2742
  evaluating = true;
2632
- let threw = true;
2633
2743
  try {
2634
- retrack(() => {
2635
- const next = getter();
2636
- cs._v = equals && cs._v !== void 0 ? equals(cs._v, next) ? cs._v : next : next;
2637
- cs._d = false;
2638
- threw = false;
2639
- }, markDirty);
2744
+ retrack(recompute, markDirty);
2640
2745
  if (!Object.is(oldValue, cs._v)) cs.__v++;
2641
2746
  } finally {
2642
2747
  evaluating = false;
2643
- if (threw) cs._d = true;
2644
2748
  }
2645
2749
  if (hook && oldValue !== cs._v) {
2646
2750
  hook.emit("computed:update", { signal: cs, oldValue, newValue: cs._v });
@@ -2693,12 +2797,12 @@ function store(initialState) {
2693
2797
  signals[key] = [getter, setter];
2694
2798
  });
2695
2799
  const store2 = new Proxy({}, {
2696
- get(_, prop) {
2697
- if (prop in signals) {
2800
+ get(target, prop) {
2801
+ if (typeof prop === "string" && Object.hasOwn(signals, prop)) {
2698
2802
  const getter = signals[prop][0];
2699
2803
  return getter();
2700
2804
  }
2701
- return void 0;
2805
+ return Reflect.get(target, prop);
2702
2806
  },
2703
2807
  set() {
2704
2808
  throw new Error(
@@ -2718,7 +2822,7 @@ function store(initialState) {
2718
2822
  const nextState = typeof patch === "function" ? patch(current) : patch;
2719
2823
  batch(() => {
2720
2824
  Object.entries(nextState).forEach(([key, value]) => {
2721
- if (key in signals) {
2825
+ if (Object.hasOwn(signals, key)) {
2722
2826
  signals[key][1](value);
2723
2827
  }
2724
2828
  });
@@ -3016,6 +3120,14 @@ function deepEqual(a2, b2, seen) {
3016
3120
  }
3017
3121
  return true;
3018
3122
  }
3123
+ if (a2 instanceof DataView) {
3124
+ if (!(b2 instanceof DataView)) return false;
3125
+ if (a2.byteLength !== b2.byteLength) return false;
3126
+ for (let i2 = 0; i2 < a2.byteLength; i2++) {
3127
+ if (a2.getUint8(i2) !== b2.getUint8(i2)) return false;
3128
+ }
3129
+ return true;
3130
+ }
3019
3131
  if (ArrayBuffer.isView(a2) && ArrayBuffer.isView(b2)) {
3020
3132
  const ta = a2;
3021
3133
  const tb = b2;
@@ -3034,7 +3146,7 @@ function deepEqual(a2, b2, seen) {
3034
3146
  const keysB = Object.keys(objB);
3035
3147
  if (keysA.length !== keysB.length) return false;
3036
3148
  return keysA.every(
3037
- (key) => deepEqual(objA[key], objB[key], seen)
3149
+ (key) => Object.hasOwn(objB, key) && deepEqual(objA[key], objB[key], seen)
3038
3150
  );
3039
3151
  }
3040
3152
  function deepSignal(initial) {
@@ -3537,34 +3649,37 @@ function Suspense({ nodes, fallback }) {
3537
3649
  container.appendChild(fallbackEl);
3538
3650
  let suspenseDisposed = false;
3539
3651
  let observer = null;
3652
+ let childEl = null;
3540
3653
  registerDisposer(container, () => {
3541
3654
  suspenseDisposed = true;
3542
3655
  if (observer) {
3543
3656
  observer.disconnect();
3544
3657
  observer = null;
3545
3658
  }
3659
+ if (childEl && !container.contains(childEl)) dispose(childEl);
3546
3660
  });
3547
3661
  queueMicrotask(() => {
3548
3662
  if (suspenseDisposed) return;
3549
3663
  try {
3550
- const childEl = nodes();
3551
- if (childEl.classList.contains("sibu-lazy")) {
3552
- if (!childEl.querySelector(".sibu-lazy-loading")) {
3553
- container.replaceChildren(childEl);
3664
+ const el = nodes();
3665
+ childEl = el;
3666
+ if (el.classList.contains("sibu-lazy")) {
3667
+ if (!el.querySelector(".sibu-lazy-loading")) {
3668
+ container.replaceChildren(el);
3554
3669
  return;
3555
3670
  }
3556
3671
  observer = new MutationObserver(() => {
3557
3672
  if (suspenseDisposed) return;
3558
- const loading = childEl.querySelector(".sibu-lazy-loading");
3673
+ const loading = el.querySelector(".sibu-lazy-loading");
3559
3674
  if (!loading) {
3560
3675
  observer?.disconnect();
3561
3676
  observer = null;
3562
- container.replaceChildren(childEl);
3677
+ container.replaceChildren(el);
3563
3678
  }
3564
3679
  });
3565
- observer.observe(childEl, { childList: true, subtree: true });
3680
+ observer.observe(el, { childList: true, subtree: true });
3566
3681
  } else {
3567
- container.replaceChildren(childEl);
3682
+ container.replaceChildren(el);
3568
3683
  }
3569
3684
  } catch (err) {
3570
3685
  const errorObj = err instanceof Error ? err : new Error(String(err));
@@ -4478,6 +4593,7 @@ function Loading(props = {}) {
4478
4593
  footer,
4479
4594
  form,
4480
4595
  g,
4596
+ getRequestScopedCache,
4481
4597
  getSSRStore,
4482
4598
  getSlot,
4483
4599
  h1,