sibujs 3.3.2 → 3.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/dist/browser.cjs +21 -4
  2. package/dist/browser.js +4 -4
  3. package/dist/build.cjs +10 -3
  4. package/dist/build.js +11 -11
  5. package/dist/cdn.global.js +7 -7
  6. package/dist/{chunk-N5TQVEKE.js → chunk-23VT3KZB.js} +1 -1
  7. package/dist/{chunk-IQJ36UTJ.js → chunk-25LY5SRH.js} +31 -24
  8. package/dist/{chunk-6TCOWMGY.js → chunk-5K6RVA2S.js} +1 -1
  9. package/dist/{chunk-YUBEOWII.js → chunk-5Y34FWED.js} +16 -5
  10. package/dist/chunk-7ZHH77QA.js +9 -0
  11. package/dist/{chunk-G6N3LMO2.js → chunk-F3HO2MP7.js} +1 -1
  12. package/dist/{chunk-FJIRS3FM.js → chunk-F7HW2NI5.js} +1 -3
  13. package/dist/{chunk-AEOLHSSQ.js → chunk-IEYFHN5V.js} +72 -25
  14. package/dist/{chunk-FJO2ZL4Q.js → chunk-IQN5W7GE.js} +73 -16
  15. package/dist/{chunk-JCQG2I2G.js → chunk-IWFE4AHO.js} +1 -1
  16. package/dist/{chunk-2ARSB7NG.js → chunk-MYXEBADX.js} +27 -20
  17. package/dist/{chunk-A7CZH3GN.js → chunk-QCQQ2N5H.js} +41 -20
  18. package/dist/{chunk-Q46YIQYW.js → chunk-QTOOBABV.js} +22 -5
  19. package/dist/{chunk-ZEUP4TUD.js → chunk-RZKGMHH4.js} +6 -6
  20. package/dist/{chunk-QCFBIVIQ.js → chunk-SBPUXWCE.js} +1 -1
  21. package/dist/{chunk-RLTFJYDN.js → chunk-TBDTU7UO.js} +1 -1
  22. package/dist/{chunk-P7C7SEJV.js → chunk-TVCCXPU2.js} +5 -5
  23. package/dist/{chunk-4NJEAPLI.js → chunk-UOMYIAG6.js} +1 -1
  24. package/dist/{chunk-655B7MMR.js → chunk-WFUUT6TG.js} +15 -8
  25. package/dist/{chunk-YUR5SX7F.js → chunk-WTFMV2RU.js} +70 -59
  26. package/dist/{chunk-3JHCYHWN.js → chunk-WWV3SJ3L.js} +19 -13
  27. package/dist/{chunk-62V653X2.js → chunk-Y35NQNLG.js} +79 -44
  28. package/dist/{chunk-5VH3GIDX.js → chunk-ZXCZWMZT.js} +1 -1
  29. package/dist/data.cjs +16 -2
  30. package/dist/data.js +7 -6
  31. package/dist/devtools.cjs +71 -21
  32. package/dist/devtools.d.cts +12 -5
  33. package/dist/devtools.d.ts +12 -5
  34. package/dist/devtools.js +6 -5
  35. package/dist/ecosystem.cjs +11 -2
  36. package/dist/ecosystem.js +10 -9
  37. package/dist/extras.cjs +454 -250
  38. package/dist/extras.d.cts +1 -1
  39. package/dist/extras.d.ts +1 -1
  40. package/dist/extras.js +26 -22
  41. package/dist/index.cjs +10 -3
  42. package/dist/index.d.cts +4 -1
  43. package/dist/index.d.ts +4 -1
  44. package/dist/index.js +19 -19
  45. package/dist/motion.cjs +223 -204
  46. package/dist/motion.d.cts +8 -1
  47. package/dist/motion.d.ts +8 -1
  48. package/dist/motion.js +6 -3
  49. package/dist/patterns.cjs +13 -6
  50. package/dist/patterns.d.cts +4 -1
  51. package/dist/patterns.d.ts +4 -1
  52. package/dist/patterns.js +5 -5
  53. package/dist/performance.cjs +70 -56
  54. package/dist/performance.js +6 -5
  55. package/dist/plugins.cjs +98 -42
  56. package/dist/plugins.d.cts +2 -1
  57. package/dist/plugins.d.ts +2 -1
  58. package/dist/plugins.js +90 -37
  59. package/dist/ssr.cjs +112 -91
  60. package/dist/ssr.d.cts +8 -1
  61. package/dist/ssr.d.ts +8 -1
  62. package/dist/ssr.js +9 -8
  63. package/dist/testing.cjs +18 -4
  64. package/dist/testing.js +18 -7
  65. package/dist/ui.cjs +322 -281
  66. package/dist/ui.d.cts +0 -20
  67. package/dist/ui.d.ts +0 -20
  68. package/dist/ui.js +28 -22
  69. package/dist/widgets.cjs +75 -13
  70. package/dist/widgets.d.cts +6 -1
  71. package/dist/widgets.d.ts +6 -1
  72. package/dist/widgets.js +7 -6
  73. package/package.json +1 -1
package/dist/plugins.js CHANGED
@@ -18,7 +18,7 @@ import {
18
18
  preloadCritical,
19
19
  prerenderRoutes,
20
20
  satisfies
21
- } from "./chunk-FJIRS3FM.js";
21
+ } from "./chunk-F7HW2NI5.js";
22
22
  import {
23
23
  isUnsafeKey
24
24
  } from "./chunk-H3SRKIYX.js";
@@ -32,21 +32,20 @@ import {
32
32
  triggerPluginError,
33
33
  triggerPluginMount,
34
34
  triggerPluginUnmount
35
- } from "./chunk-3JHCYHWN.js";
35
+ } from "./chunk-WWV3SJ3L.js";
36
+ import {
37
+ globalSingleton
38
+ } from "./chunk-7ZHH77QA.js";
36
39
  import {
37
40
  span
38
- } from "./chunk-6TCOWMGY.js";
41
+ } from "./chunk-5K6RVA2S.js";
39
42
  import {
40
43
  escapeScriptJson,
41
44
  isDangerousMetaRefresh,
42
45
  renderToString
43
46
  } from "./chunk-EX77FXTT.js";
44
- import "./chunk-ZEUP4TUD.js";
45
- import "./chunk-QCFBIVIQ.js";
46
- import {
47
- dispose,
48
- registerDisposer
49
- } from "./chunk-5VGSK6D2.js";
47
+ import "./chunk-RZKGMHH4.js";
48
+ import "./chunk-SBPUXWCE.js";
50
49
  import {
51
50
  isUrlAttribute,
52
51
  sanitizeCSSValue,
@@ -55,19 +54,27 @@ import {
55
54
  } from "./chunk-L3GAGWCC.js";
56
55
  import {
57
56
  effect
58
- } from "./chunk-N5TQVEKE.js";
57
+ } from "./chunk-23VT3KZB.js";
59
58
  import "./chunk-S3NFJO6L.js";
59
+ import {
60
+ dispose,
61
+ registerDisposer
62
+ } from "./chunk-5VGSK6D2.js";
60
63
  import {
61
64
  signal
62
- } from "./chunk-JCQG2I2G.js";
65
+ } from "./chunk-IWFE4AHO.js";
63
66
  import {
64
67
  track
65
- } from "./chunk-4NJEAPLI.js";
68
+ } from "./chunk-UOMYIAG6.js";
66
69
  import "./chunk-COY6PUD2.js";
67
70
 
68
71
  // src/plugins/i18n.ts
69
- var [currentLocale, setLocaleInternal] = signal("en");
70
- var locales = {};
72
+ var _i18n = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.i18n.v1"), () => ({
73
+ locale: signal("en"),
74
+ locales: {}
75
+ }));
76
+ var [currentLocale, setLocaleInternal] = _i18n.locale;
77
+ var locales = _i18n.locales;
71
78
  function setLocale(locale) {
72
79
  setLocaleInternal(locale);
73
80
  }
@@ -170,14 +177,39 @@ var NavigationController = class {
170
177
  return this.currentController !== null;
171
178
  }
172
179
  };
173
- var RouteMatcher = class {
180
+ var RouteMatcher = class _RouteMatcher {
174
181
  constructor(routes) {
175
182
  this.routeTrie = /* @__PURE__ */ new Map();
176
183
  this.parentChain = /* @__PURE__ */ new Map();
177
184
  this.namedRoutes = /* @__PURE__ */ new Map();
178
185
  this.compiledPatterns = new LRUCache(50);
186
+ // Pattern routes (those with params/wildcards) ordered most-specific-first,
187
+ // rebuilt lazily after any mutation. Static full paths are served by the
188
+ // exact-match map and excluded here.
189
+ this.patternOrder = null;
179
190
  this.buildIndex(routes);
180
191
  }
192
+ // Specificity per segment: static (2) > param `:x` (1) > wildcard `*` (0).
193
+ static specificity(path) {
194
+ return path.split("/").filter(Boolean).map((seg) => seg.startsWith(":") ? 1 : seg.includes("*") ? 0 : 2);
195
+ }
196
+ getPatternOrder() {
197
+ if (this.patternOrder) return this.patternOrder;
198
+ const patterns = [...this.routeTrie].filter(([p]) => p.includes(":") || p.includes("*"));
199
+ patterns.sort(([a], [b]) => {
200
+ const ka = _RouteMatcher.specificity(a);
201
+ const kb = _RouteMatcher.specificity(b);
202
+ const len = Math.max(ka.length, kb.length);
203
+ for (let i = 0; i < len; i++) {
204
+ const va = ka[i] ?? -1;
205
+ const vb = kb[i] ?? -1;
206
+ if (va !== vb) return vb - va;
207
+ }
208
+ return 0;
209
+ });
210
+ this.patternOrder = patterns;
211
+ return patterns;
212
+ }
181
213
  buildIndex(routes, parentPath = "", ancestors = []) {
182
214
  for (const route2 of routes) {
183
215
  const fullPath = parentPath + route2.path;
@@ -204,7 +236,7 @@ var RouteMatcher = class {
204
236
  if (exactMatch) {
205
237
  return { route: exactMatch, params: {}, matched: this.parentChain.get(path) || [exactMatch] };
206
238
  }
207
- for (const [routePath, route2] of this.routeTrie) {
239
+ for (const [routePath, route2] of this.getPatternOrder()) {
208
240
  const match = this.matchPattern(path, routePath);
209
241
  if (match) {
210
242
  return { route: route2, params: match.params, matched: this.parentChain.get(routePath) || [route2] };
@@ -276,9 +308,11 @@ var RouteMatcher = class {
276
308
  this.parentChain.clear();
277
309
  this.namedRoutes.clear();
278
310
  this.compiledPatterns.clear();
311
+ this.patternOrder = null;
279
312
  this.buildIndex(routes);
280
313
  }
281
314
  addRoute(route2, parentPath = "") {
315
+ this.patternOrder = null;
282
316
  const fullPath = parentPath + route2.path;
283
317
  const parentAncestors = this.parentChain.get(parentPath) || [];
284
318
  const chain = [...parentAncestors, route2];
@@ -293,6 +327,7 @@ var RouteMatcher = class {
293
327
  }
294
328
  removeRoute(path) {
295
329
  this.compiledPatterns.clear();
330
+ this.patternOrder = null;
296
331
  const root = this.routeTrie.get(path);
297
332
  if (!root) return;
298
333
  const removed = /* @__PURE__ */ new Set();
@@ -559,14 +594,16 @@ var _SibuRouter = class _SibuRouter {
559
594
  this.initialize();
560
595
  }
561
596
  initialize() {
562
- if (this.options.mode === "history") {
563
- const popstateHandler = () => this.handleLocationChange(true);
564
- window.addEventListener("popstate", popstateHandler);
565
- this.cleanup.push(() => window.removeEventListener("popstate", popstateHandler));
566
- } else {
567
- const hashHandler = () => this.handleLocationChange(true);
568
- window.addEventListener("hashchange", hashHandler);
569
- this.cleanup.push(() => window.removeEventListener("hashchange", hashHandler));
597
+ if (typeof window !== "undefined") {
598
+ if (this.options.mode === "history") {
599
+ const popstateHandler = () => this.handleLocationChange(true);
600
+ window.addEventListener("popstate", popstateHandler);
601
+ this.cleanup.push(() => window.removeEventListener("popstate", popstateHandler));
602
+ } else {
603
+ const hashHandler = () => this.handleLocationChange(true);
604
+ window.addEventListener("hashchange", hashHandler);
605
+ this.cleanup.push(() => window.removeEventListener("hashchange", hashHandler));
606
+ }
570
607
  }
571
608
  queueMicrotask(() => {
572
609
  this.handleLocationChange(true);
@@ -1107,10 +1144,15 @@ function Route() {
1107
1144
  if (!routeInitialized && anchor.parentNode) wrappedUpdate();
1108
1145
  });
1109
1146
  }
1110
- routeCleanups.push(() => {
1147
+ let routeTorn = false;
1148
+ const routeCleanup = () => {
1149
+ if (routeTorn) return;
1150
+ routeTorn = true;
1111
1151
  routeTeardown();
1112
1152
  cleanupNodes();
1113
- });
1153
+ };
1154
+ registerDisposer(anchor, routeCleanup);
1155
+ routeCleanups.push(routeCleanup);
1114
1156
  return anchor;
1115
1157
  }
1116
1158
  function KeepAliveRoute(options) {
@@ -1220,7 +1262,10 @@ function KeepAliveRoute(options) {
1220
1262
  if (!initialized && anchor.parentNode) wrappedUpdate();
1221
1263
  });
1222
1264
  }
1223
- routeCleanups.push(() => {
1265
+ let kaTorn = false;
1266
+ const kaCleanup = () => {
1267
+ if (kaTorn) return;
1268
+ kaTorn = true;
1224
1269
  kaTeardown();
1225
1270
  for (const node of cache.values()) {
1226
1271
  dispose(node);
@@ -1230,12 +1275,15 @@ function KeepAliveRoute(options) {
1230
1275
  lruOrder.length = 0;
1231
1276
  if (currentNode?.parentNode) currentNode.parentNode.removeChild(currentNode);
1232
1277
  currentNode = null;
1233
- });
1278
+ };
1279
+ registerDisposer(anchor, kaCleanup);
1280
+ routeCleanups.push(kaCleanup);
1234
1281
  return anchor;
1235
1282
  }
1236
- function RouterLink(props) {
1283
+ function RouterLink(props, children) {
1237
1284
  if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
1238
1285
  const { to, replace: replace2 = false, activeClass, exactActiveClass, nodes, target, rel, class: classAttr, ...attrs } = props;
1286
+ const content = children !== void 0 ? children : nodes;
1239
1287
  const baseClass = typeof classAttr === "string" ? classAttr : "";
1240
1288
  const routeGetter = _routerRef.current.routeGetter;
1241
1289
  const rawHref = _routerRef.current["resolvePath"](to);
@@ -1285,12 +1333,12 @@ function RouterLink(props) {
1285
1333
  }
1286
1334
  }
1287
1335
  });
1288
- if (typeof nodes === "string") {
1289
- link.textContent = nodes;
1290
- } else if (nodes instanceof Node) {
1291
- link.appendChild(nodes);
1292
- } else if (Array.isArray(nodes)) {
1293
- nodes.forEach((child) => {
1336
+ if (typeof content === "string") {
1337
+ link.textContent = content;
1338
+ } else if (content instanceof Node) {
1339
+ link.appendChild(content);
1340
+ } else if (Array.isArray(content)) {
1341
+ content.forEach((child) => {
1294
1342
  if (typeof child === "string") {
1295
1343
  link.appendChild(document.createTextNode(child));
1296
1344
  } else if (child instanceof Node) {
@@ -1485,14 +1533,19 @@ function Outlet() {
1485
1533
  if (anchor.parentNode) update();
1486
1534
  });
1487
1535
  }
1488
- routeCleanups.push(() => {
1536
+ let outletTorn = false;
1537
+ const outletCleanup = () => {
1538
+ if (outletTorn) return;
1539
+ outletTorn = true;
1489
1540
  outletTeardown();
1490
1541
  if (currentNode) {
1491
1542
  dispose(currentNode);
1492
1543
  if (currentNode.parentNode) currentNode.parentNode.removeChild(currentNode);
1493
1544
  currentNode = null;
1494
1545
  }
1495
- });
1546
+ };
1547
+ registerDisposer(anchor, outletCleanup);
1548
+ routeCleanups.push(outletCleanup);
1496
1549
  return anchor;
1497
1550
  }
1498
1551
  function addRoute(route2, parentPath) {
package/dist/ssr.cjs CHANGED
@@ -713,8 +713,69 @@ function escapeAttr(str) {
713
713
  return str.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/'/g, "&#39;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
714
714
  }
715
715
 
716
- // src/reactivity/track-core.ts
716
+ // src/core/rendering/dispose.ts
717
+ var elementDisposers = /* @__PURE__ */ new WeakMap();
717
718
  var _isDev3 = isDev();
719
+ var activeBindingCount = 0;
720
+ function registerDisposer(node, teardown) {
721
+ let disposers = elementDisposers.get(node);
722
+ if (!disposers) {
723
+ disposers = [];
724
+ elementDisposers.set(node, disposers);
725
+ }
726
+ disposers.push(teardown);
727
+ if (_isDev3) activeBindingCount++;
728
+ }
729
+ function dispose(node) {
730
+ const stack = [node];
731
+ const order = [];
732
+ while (stack.length > 0) {
733
+ const current = stack.pop();
734
+ order.push(current);
735
+ const children = Array.from(current.childNodes);
736
+ for (let i2 = 0; i2 < children.length; i2++) {
737
+ stack.push(children[i2]);
738
+ }
739
+ }
740
+ for (let i2 = order.length - 1; i2 >= 0; i2--) {
741
+ const current = order[i2];
742
+ const disposers = elementDisposers.get(current);
743
+ if (disposers) {
744
+ const snapshot = disposers.slice();
745
+ elementDisposers.delete(current);
746
+ if (_isDev3) activeBindingCount -= snapshot.length;
747
+ for (const d of snapshot) {
748
+ try {
749
+ d();
750
+ } catch (err) {
751
+ if (_isDev3 && typeof console !== "undefined") {
752
+ console.warn("[SibuJS] Disposer threw during cleanup:", err);
753
+ }
754
+ }
755
+ }
756
+ let extraPasses = 0;
757
+ while (extraPasses++ < 8) {
758
+ const added = elementDisposers.get(current);
759
+ if (!added || added.length === 0) break;
760
+ const moreSnapshot = added.slice();
761
+ elementDisposers.delete(current);
762
+ if (_isDev3) activeBindingCount -= moreSnapshot.length;
763
+ for (const d of moreSnapshot) {
764
+ try {
765
+ d();
766
+ } catch (err) {
767
+ if (_isDev3 && typeof console !== "undefined") {
768
+ console.warn("[SibuJS] Disposer threw during cleanup:", err);
769
+ }
770
+ }
771
+ }
772
+ }
773
+ }
774
+ }
775
+ }
776
+
777
+ // src/reactivity/track-core.ts
778
+ var _isDev4 = isDev();
718
779
  var POOL_MAX = 4096;
719
780
  var nodePool = [];
720
781
  function createNode() {
@@ -806,7 +867,7 @@ function safeInvoke(sub2) {
806
867
  try {
807
868
  sub2();
808
869
  } catch (err) {
809
- if (_isDev3) devWarn(`Subscriber threw during notification: ${err instanceof Error ? err.message : String(err)}`);
870
+ if (_isDev4) devWarn(`Subscriber threw during notification: ${err instanceof Error ? err.message : String(err)}`);
810
871
  }
811
872
  }
812
873
  var suspendDepth = 0;
@@ -1128,14 +1189,14 @@ function forEachSubscriber(signal2, visit) {
1128
1189
  }
1129
1190
 
1130
1191
  // src/reactivity/track.ts
1131
- var _isDev4 = isDev();
1132
- var _runtimeVersion = true ? "3.3.2" : "dev";
1192
+ var _isDev5 = isDev();
1193
+ var _runtimeVersion = true ? "3.3.3" : "dev";
1133
1194
  var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
1134
1195
  function resolveReactiveApi() {
1135
1196
  const g2 = globalThis;
1136
1197
  const existing = g2[REGISTRY_KEY];
1137
1198
  if (existing) {
1138
- if (_isDev4 && !existing.__dupWarned) {
1199
+ if (_isDev5 && !existing.__dupWarned) {
1139
1200
  existing.__dupWarned = true;
1140
1201
  devWarn(
1141
1202
  `Multiple instances of the reactive runtime detected on this page (active: ${existing.version}, duplicate: ${_runtimeVersion}). Reactivity still works \u2014 all copies share the first one \u2014 but de-duplicate sibujs in your bundler (e.g. Vite optimizeDeps.exclude: ['sibujs'] or resolve.dedupe: ['sibujs']).`
@@ -1430,6 +1491,7 @@ function Head(props) {
1430
1491
  }
1431
1492
  };
1432
1493
  apply();
1494
+ registerDisposer(anchor, cleanup3);
1433
1495
  return anchor;
1434
1496
  }
1435
1497
  function setStructuredData(data2) {
@@ -1522,7 +1584,7 @@ var isBatching = API2.isBatching;
1522
1584
 
1523
1585
  // src/core/signals/signal.ts
1524
1586
  var _g2 = globalThis;
1525
- var _isDev5 = isDev();
1587
+ var _isDev6 = isDev();
1526
1588
  function signal(initial, options) {
1527
1589
  const state = {
1528
1590
  value: initial,
@@ -1533,7 +1595,7 @@ function signal(initial, options) {
1533
1595
  __activeNode: null,
1534
1596
  __name: void 0
1535
1597
  };
1536
- const debugName = _isDev5 ? options?.name : void 0;
1598
+ const debugName = _isDev6 ? options?.name : void 0;
1537
1599
  const equalsFn = options?.equals;
1538
1600
  if (debugName) state.__name = debugName;
1539
1601
  function get() {
@@ -1550,7 +1612,7 @@ function signal(initial, options) {
1550
1612
  if (equalsFn(prev, newValue)) return;
1551
1613
  state.value = newValue;
1552
1614
  state.__v++;
1553
- if (_isDev5) {
1615
+ if (_isDev6) {
1554
1616
  const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
1555
1617
  if (hook) hook.emit("signal:update", { signal: state, name: debugName, oldValue: prev, newValue });
1556
1618
  }
@@ -1558,7 +1620,7 @@ function signal(initial, options) {
1558
1620
  notifySubscribers2(state);
1559
1621
  }
1560
1622
  };
1561
- } else if (_isDev5) {
1623
+ } else if (_isDev6) {
1562
1624
  set = (next) => {
1563
1625
  const prev = state.value;
1564
1626
  const newValue = typeof next === "function" ? next(prev) : next;
@@ -1583,7 +1645,7 @@ function signal(initial, options) {
1583
1645
  }
1584
1646
  };
1585
1647
  }
1586
- if (_isDev5) {
1648
+ if (_isDev6) {
1587
1649
  const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
1588
1650
  if (hook) hook.emit("signal:create", { signal: state, name: debugName, getter: get, initial });
1589
1651
  }
@@ -1640,24 +1702,30 @@ function createAction(actionFn) {
1640
1702
  const [data2, setData] = signal(void 0);
1641
1703
  const [error, setError] = signal(void 0);
1642
1704
  const [loading, setLoading] = signal(false);
1705
+ let activeRun = 0;
1643
1706
  const submit = async (input2) => {
1707
+ const runId = ++activeRun;
1644
1708
  batch(() => {
1645
1709
  setLoading(true);
1646
1710
  setError(void 0);
1647
1711
  });
1648
1712
  try {
1649
1713
  const result = await actionFn(input2);
1650
- batch(() => {
1651
- setData(result);
1652
- setLoading(false);
1653
- });
1714
+ if (runId === activeRun) {
1715
+ batch(() => {
1716
+ setData(result);
1717
+ setLoading(false);
1718
+ });
1719
+ }
1654
1720
  return result;
1655
1721
  } catch (err) {
1656
1722
  const actionError = err instanceof Error ? err : new Error(String(err));
1657
- batch(() => {
1658
- setError(actionError);
1659
- setLoading(false);
1660
- });
1723
+ if (runId === activeRun) {
1724
+ batch(() => {
1725
+ setError(actionError);
1726
+ setLoading(false);
1727
+ });
1728
+ }
1661
1729
  throw actionError;
1662
1730
  }
1663
1731
  };
@@ -1671,15 +1739,14 @@ function scrollRestoration(options) {
1671
1739
  let popstateHandler = null;
1672
1740
  let currentKey = null;
1673
1741
  const save = (key) => {
1674
- positions.set(key, {
1675
- x: window.scrollX,
1676
- y: window.scrollY
1677
- });
1742
+ if (typeof window !== "undefined") {
1743
+ positions.set(key, { x: window.scrollX, y: window.scrollY });
1744
+ }
1678
1745
  currentKey = key;
1679
1746
  };
1680
1747
  const restore = (key) => {
1681
1748
  const pos = positions.get(key);
1682
- if (pos) {
1749
+ if (pos && typeof window !== "undefined") {
1683
1750
  window.scrollTo(pos.x, pos.y);
1684
1751
  }
1685
1752
  currentKey = key;
@@ -1687,7 +1754,7 @@ function scrollRestoration(options) {
1687
1754
  const getPosition = (key) => {
1688
1755
  return positions.get(key);
1689
1756
  };
1690
- if (mode === "auto") {
1757
+ if (mode === "auto" && typeof window !== "undefined") {
1691
1758
  popstateHandler = () => {
1692
1759
  if (currentKey) {
1693
1760
  save(currentKey);
@@ -1737,13 +1804,13 @@ function createMiddlewareChain() {
1737
1804
  }
1738
1805
 
1739
1806
  // src/reactivity/bindAttribute.ts
1740
- var _isDev6 = isDev();
1807
+ var _isDev7 = isDev();
1741
1808
  function setProp(el, key, val) {
1742
1809
  el[key] = val;
1743
1810
  }
1744
1811
  function bindAttribute(el, attr, getter) {
1745
1812
  if (isEventHandlerAttr(attr)) {
1746
- if (_isDev6)
1813
+ if (_isDev7)
1747
1814
  devWarn(
1748
1815
  `bindAttribute: refusing to bind event-handler attribute "${attr}". Use on:{ ${attr.slice(2)}: fn } instead.`
1749
1816
  );
@@ -1755,7 +1822,7 @@ function bindAttribute(el, attr, getter) {
1755
1822
  try {
1756
1823
  value = getter();
1757
1824
  } catch (err) {
1758
- if (_isDev6)
1825
+ if (_isDev7)
1759
1826
  devWarn(`bindAttribute: getter for "${attr}" threw: ${err instanceof Error ? err.message : String(err)}`);
1760
1827
  return;
1761
1828
  }
@@ -1779,67 +1846,6 @@ function bindAttribute(el, attr, getter) {
1779
1846
  return reactiveBinding2(commit);
1780
1847
  }
1781
1848
 
1782
- // src/core/rendering/dispose.ts
1783
- var elementDisposers = /* @__PURE__ */ new WeakMap();
1784
- var _isDev7 = isDev();
1785
- var activeBindingCount = 0;
1786
- function registerDisposer(node, teardown) {
1787
- let disposers = elementDisposers.get(node);
1788
- if (!disposers) {
1789
- disposers = [];
1790
- elementDisposers.set(node, disposers);
1791
- }
1792
- disposers.push(teardown);
1793
- if (_isDev7) activeBindingCount++;
1794
- }
1795
- function dispose(node) {
1796
- const stack = [node];
1797
- const order = [];
1798
- while (stack.length > 0) {
1799
- const current = stack.pop();
1800
- order.push(current);
1801
- const children = Array.from(current.childNodes);
1802
- for (let i2 = 0; i2 < children.length; i2++) {
1803
- stack.push(children[i2]);
1804
- }
1805
- }
1806
- for (let i2 = order.length - 1; i2 >= 0; i2--) {
1807
- const current = order[i2];
1808
- const disposers = elementDisposers.get(current);
1809
- if (disposers) {
1810
- const snapshot = disposers.slice();
1811
- elementDisposers.delete(current);
1812
- if (_isDev7) activeBindingCount -= snapshot.length;
1813
- for (const d of snapshot) {
1814
- try {
1815
- d();
1816
- } catch (err) {
1817
- if (_isDev7 && typeof console !== "undefined") {
1818
- console.warn("[SibuJS] Disposer threw during cleanup:", err);
1819
- }
1820
- }
1821
- }
1822
- let extraPasses = 0;
1823
- while (extraPasses++ < 8) {
1824
- const added = elementDisposers.get(current);
1825
- if (!added || added.length === 0) break;
1826
- const moreSnapshot = added.slice();
1827
- elementDisposers.delete(current);
1828
- if (_isDev7) activeBindingCount -= moreSnapshot.length;
1829
- for (const d of moreSnapshot) {
1830
- try {
1831
- d();
1832
- } catch (err) {
1833
- if (_isDev7 && typeof console !== "undefined") {
1834
- console.warn("[SibuJS] Disposer threw during cleanup:", err);
1835
- }
1836
- }
1837
- }
1838
- }
1839
- }
1840
- }
1841
- }
1842
-
1843
1849
  // src/reactivity/bindChildNode.ts
1844
1850
  var _isDev8 = isDev();
1845
1851
  function bindChildNode(placeholder, getter) {
@@ -2309,8 +2315,17 @@ var center = tagFactory("center");
2309
2315
  var font = tagFactory("font");
2310
2316
  var marquee = tagFactory("marquee");
2311
2317
 
2318
+ // src/utils/globalSingleton.ts
2319
+ function globalSingleton(key, create) {
2320
+ const g2 = globalThis;
2321
+ return g2[key] ?? (g2[key] = create());
2322
+ }
2323
+
2312
2324
  // src/platform/microfrontend.ts
2313
- var moduleCache = /* @__PURE__ */ new Map();
2325
+ var moduleCache = globalSingleton(
2326
+ /* @__PURE__ */ Symbol.for("sibujs.microfrontend.moduleCache.v1"),
2327
+ () => /* @__PURE__ */ new Map()
2328
+ );
2314
2329
  function createMicroApp(config) {
2315
2330
  const host = config.container ?? document.createElement("div");
2316
2331
  host.setAttribute("data-micro-app", config.name);
@@ -2727,8 +2742,14 @@ function createWorkerPool(workerFn2, poolSize) {
2727
2742
  }
2728
2743
 
2729
2744
  // src/platform/wasm.ts
2730
- var moduleCache2 = /* @__PURE__ */ new Map();
2731
- var instanceCache = /* @__PURE__ */ new Map();
2745
+ var moduleCache2 = globalSingleton(
2746
+ /* @__PURE__ */ Symbol.for("sibujs.wasm.moduleCache.v1"),
2747
+ () => /* @__PURE__ */ new Map()
2748
+ );
2749
+ var instanceCache = globalSingleton(
2750
+ /* @__PURE__ */ Symbol.for("sibujs.wasm.instanceCache.v1"),
2751
+ () => /* @__PURE__ */ new Map()
2752
+ );
2732
2753
  function wasm(source2, config = {}) {
2733
2754
  const [instance, setInstance] = signal(null);
2734
2755
  const [loading, setLoading] = signal(true);
package/dist/ssr.d.cts CHANGED
@@ -138,7 +138,14 @@ declare function wasm<T extends Record<string, unknown> = Record<string, unknown
138
138
  /**
139
139
  * Load and instantiate a WebAssembly module.
140
140
  * Supports loading from URL, ArrayBuffer, or Uint8Array.
141
- * Caches compiled modules for reuse.
141
+ *
142
+ * Caching: keyed by `cacheKey` (or, for a URL source, the URL itself). A keyed
143
+ * load is memoized as a **singleton instance** — every caller with the same key
144
+ * receives the *same* `WebAssembly.Instance`, which shares one linear memory and
145
+ * mutable globals. This is intentional (load-once / reuse), but it means callers
146
+ * that need isolated state must use distinct cache keys, or pass a non-URL source
147
+ * with no `cacheKey` (which instantiates fresh every call). Compiled modules are
148
+ * immutable and always safe to share.
142
149
  */
143
150
  interface LoadWasmOptions {
144
151
  imports?: WebAssembly.Imports;
package/dist/ssr.d.ts CHANGED
@@ -138,7 +138,14 @@ declare function wasm<T extends Record<string, unknown> = Record<string, unknown
138
138
  /**
139
139
  * Load and instantiate a WebAssembly module.
140
140
  * Supports loading from URL, ArrayBuffer, or Uint8Array.
141
- * Caches compiled modules for reuse.
141
+ *
142
+ * Caching: keyed by `cacheKey` (or, for a URL source, the URL itself). A keyed
143
+ * load is memoized as a **singleton instance** — every caller with the same key
144
+ * receives the *same* `WebAssembly.Instance`, which shares one linear memory and
145
+ * mutable globals. This is intentional (load-once / reuse), but it means callers
146
+ * that need isolated state must use distinct cache keys, or pass a non-URL source
147
+ * with no `cacheKey` (which instantiates fresh every call). Compiled modules are
148
+ * immutable and always safe to share.
142
149
  */
143
150
  interface LoadWasmOptions {
144
151
  imports?: WebAssembly.Imports;
package/dist/ssr.js CHANGED
@@ -22,8 +22,9 @@ import {
22
22
  wasm,
23
23
  worker,
24
24
  workerFn
25
- } from "./chunk-A7CZH3GN.js";
26
- import "./chunk-6TCOWMGY.js";
25
+ } from "./chunk-QCQQ2N5H.js";
26
+ import "./chunk-7ZHH77QA.js";
27
+ import "./chunk-5K6RVA2S.js";
27
28
  import {
28
29
  collectStream,
29
30
  deserializeState,
@@ -44,14 +45,14 @@ import {
44
45
  suspenseSwapScript,
45
46
  trustHTML
46
47
  } from "./chunk-EX77FXTT.js";
47
- import "./chunk-ZEUP4TUD.js";
48
- import "./chunk-QCFBIVIQ.js";
49
- import "./chunk-5VGSK6D2.js";
48
+ import "./chunk-RZKGMHH4.js";
49
+ import "./chunk-SBPUXWCE.js";
50
50
  import "./chunk-L3GAGWCC.js";
51
- import "./chunk-N5TQVEKE.js";
51
+ import "./chunk-23VT3KZB.js";
52
52
  import "./chunk-S3NFJO6L.js";
53
- import "./chunk-JCQG2I2G.js";
54
- import "./chunk-4NJEAPLI.js";
53
+ import "./chunk-5VGSK6D2.js";
54
+ import "./chunk-IWFE4AHO.js";
55
+ import "./chunk-UOMYIAG6.js";
55
56
  import "./chunk-COY6PUD2.js";
56
57
  export {
57
58
  Head,