sibujs 1.5.0 → 2.1.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 (208) hide show
  1. package/dist/browser.cjs +332 -121
  2. package/dist/browser.d.cts +5 -0
  3. package/dist/browser.d.ts +5 -0
  4. package/dist/browser.js +6 -6
  5. package/dist/build.cjs +1049 -344
  6. package/dist/build.js +15 -13
  7. package/dist/cdn.global.js +17 -16
  8. package/dist/chunk-2RA7SHDA.js +65 -0
  9. package/dist/chunk-2UPRY23K.js +80 -0
  10. package/dist/{chunk-BMPL52BF.js → chunk-3DZP6OIT.js} +118 -66
  11. package/dist/chunk-3JHCYHWN.js +125 -0
  12. package/dist/{chunk-CZUGLNJS.js → chunk-45YP72ZQ.js} +3 -3
  13. package/dist/{chunk-JCDUJN2F.js → chunk-AMK2TYNW.js} +490 -153
  14. package/dist/{chunk-NHUC2QWH.js → chunk-CWBVQML6.js} +1 -1
  15. package/dist/{chunk-XHK6BDAJ.js → chunk-DRUZZAK4.js} +25 -8
  16. package/dist/{chunk-RJ46C3CS.js → chunk-GWWURC5M.js} +71 -20
  17. package/dist/{chunk-3X2YG6YM.js → chunk-JYD2PWXH.js} +59 -28
  18. package/dist/{chunk-2BYQDGN3.js → chunk-KGYT6UO6.js} +234 -63
  19. package/dist/{chunk-5X6PP2UK.js → chunk-LMLD24FC.js} +2 -2
  20. package/dist/{chunk-M4NLBH4I.js → chunk-LYTCUZ7H.js} +3 -2
  21. package/dist/{chunk-XUEEGU5O.js → chunk-NASX6ST2.js} +16 -4
  22. package/dist/{chunk-VQDZK23A.js → chunk-O6EFQ3KT.js} +181 -66
  23. package/dist/{chunk-BGN5ZMP4.js → chunk-OJ3P4ECI.js} +14 -2
  24. package/dist/chunk-ON5MMR2J.js +1327 -0
  25. package/dist/{chunk-SFKNRVCU.js → chunk-P2HSJDDN.js} +135 -79
  26. package/dist/chunk-QO3WC6FS.js +384 -0
  27. package/dist/{chunk-WZSPOOER.js → chunk-RDTDJCAB.js} +8 -5
  28. package/dist/{chunk-7GRNSCFT.js → chunk-TH2ILCYW.js} +312 -185
  29. package/dist/chunk-UCS6AMJ7.js +79 -0
  30. package/dist/{chunk-VAPYJN4X.js → chunk-V6C4FADE.js} +93 -23
  31. package/dist/{chunk-OUZZEE4S.js → chunk-WANSMF2L.js} +17 -11
  32. package/dist/{chunk-23VV7YD3.js → chunk-WIPZPFBQ.js} +25 -30
  33. package/dist/chunk-WZA53FXU.js +149 -0
  34. package/dist/{chunk-BGTHZHJ5.js → chunk-ZAQSMOED.js} +188 -44
  35. package/dist/{customElement-BL3Uo8dL.d.cts → customElement-CPfIrbvg.d.cts} +14 -10
  36. package/dist/{customElement-BL3Uo8dL.d.ts → customElement-CPfIrbvg.d.ts} +14 -10
  37. package/dist/data.cjs +536 -151
  38. package/dist/data.d.cts +20 -2
  39. package/dist/data.d.ts +20 -2
  40. package/dist/data.js +11 -9
  41. package/dist/devtools.cjs +613 -266
  42. package/dist/devtools.d.cts +1 -1
  43. package/dist/devtools.d.ts +1 -1
  44. package/dist/devtools.js +12 -6
  45. package/dist/ecosystem.cjs +602 -197
  46. package/dist/ecosystem.d.cts +9 -7
  47. package/dist/ecosystem.d.ts +9 -7
  48. package/dist/ecosystem.js +12 -11
  49. package/dist/extras.cjs +3500 -1608
  50. package/dist/extras.d.cts +9 -9
  51. package/dist/extras.d.ts +9 -9
  52. package/dist/extras.js +58 -45
  53. package/dist/index.cjs +1055 -344
  54. package/dist/index.d.cts +85 -8
  55. package/dist/index.d.ts +85 -8
  56. package/dist/index.js +32 -16
  57. package/dist/{introspect-BumjnBKr.d.cts → introspect-2TOlQ7oa.d.cts} +25 -3
  58. package/dist/{introspect-CZrlcaYy.d.ts → introspect-DnIpHQQz.d.ts} +25 -3
  59. package/dist/motion.cjs +122 -63
  60. package/dist/motion.js +4 -4
  61. package/dist/patterns.cjs +450 -110
  62. package/dist/patterns.d.cts +11 -12
  63. package/dist/patterns.d.ts +11 -12
  64. package/dist/patterns.js +7 -7
  65. package/dist/performance.cjs +373 -149
  66. package/dist/performance.d.cts +23 -16
  67. package/dist/performance.d.ts +23 -16
  68. package/dist/performance.js +13 -8
  69. package/dist/plugin-D30wlGW5.d.cts +71 -0
  70. package/dist/plugin-D30wlGW5.d.ts +71 -0
  71. package/dist/plugins.cjs +729 -301
  72. package/dist/plugins.d.cts +10 -3
  73. package/dist/plugins.d.ts +10 -3
  74. package/dist/plugins.js +106 -38
  75. package/dist/{ssr-Do_SiVoL.d.cts → ssr-CrVNy6Pa.d.cts} +9 -15
  76. package/dist/{ssr-Do_SiVoL.d.ts → ssr-CrVNy6Pa.d.ts} +9 -15
  77. package/dist/{ssr-4PBXAOO3.js → ssr-FXD2PPMC.js} +4 -3
  78. package/dist/ssr.cjs +736 -274
  79. package/dist/ssr.d.cts +26 -6
  80. package/dist/ssr.d.ts +26 -6
  81. package/dist/ssr.js +12 -11
  82. package/dist/{tagFactory-DaJ0YWX6.d.cts → tagFactory-S17H2qxu.d.cts} +9 -1
  83. package/dist/{tagFactory-DaJ0YWX6.d.ts → tagFactory-S17H2qxu.d.ts} +9 -1
  84. package/dist/testing.cjs +303 -76
  85. package/dist/testing.d.cts +17 -4
  86. package/dist/testing.d.ts +17 -4
  87. package/dist/testing.js +100 -44
  88. package/dist/ui.cjs +589 -178
  89. package/dist/ui.d.cts +1 -1
  90. package/dist/ui.d.ts +1 -1
  91. package/dist/ui.js +20 -17
  92. package/dist/widgets.cjs +1103 -146
  93. package/dist/widgets.d.cts +104 -2
  94. package/dist/widgets.d.ts +104 -2
  95. package/dist/widgets.js +9 -7
  96. package/package.json +8 -2
  97. package/dist/chunk-32DY64NT.js +0 -282
  98. package/dist/chunk-3AIRKM3B.js +0 -1263
  99. package/dist/chunk-3ARAQO7B.js +0 -398
  100. package/dist/chunk-3CRQALYP.js +0 -877
  101. package/dist/chunk-4EI4AG32.js +0 -482
  102. package/dist/chunk-4MYMUBRS.js +0 -21
  103. package/dist/chunk-5ZYQ6KDD.js +0 -154
  104. package/dist/chunk-6BMPXPUW.js +0 -26
  105. package/dist/chunk-6HLLIF3K.js +0 -398
  106. package/dist/chunk-6LSNVCS2.js +0 -937
  107. package/dist/chunk-6SA3QQES.js +0 -61
  108. package/dist/chunk-77L6NL3X.js +0 -1097
  109. package/dist/chunk-7BF6TK55.js +0 -1097
  110. package/dist/chunk-7TQKR4PP.js +0 -294
  111. package/dist/chunk-7V26P53V.js +0 -712
  112. package/dist/chunk-AZ3ISID5.js +0 -298
  113. package/dist/chunk-B7SWRFUT.js +0 -332
  114. package/dist/chunk-BTU3TJDS.js +0 -365
  115. package/dist/chunk-BW3WT46K.js +0 -937
  116. package/dist/chunk-C6KFWOFV.js +0 -616
  117. package/dist/chunk-CHF5OHIA.js +0 -61
  118. package/dist/chunk-CHJ27IGK.js +0 -26
  119. package/dist/chunk-CMBFNA7L.js +0 -27
  120. package/dist/chunk-DAHRH4ON.js +0 -331
  121. package/dist/chunk-DKOHBI74.js +0 -924
  122. package/dist/chunk-DTCOOBMX.js +0 -725
  123. package/dist/chunk-EBGIRKQY.js +0 -616
  124. package/dist/chunk-EUZND3CB.js +0 -27
  125. package/dist/chunk-EVCZO745.js +0 -365
  126. package/dist/chunk-EWFVA3TJ.js +0 -282
  127. package/dist/chunk-F3FA4F32.js +0 -292
  128. package/dist/chunk-FGOEVHY3.js +0 -60
  129. package/dist/chunk-G3BOQPVO.js +0 -365
  130. package/dist/chunk-GCOK2LC3.js +0 -282
  131. package/dist/chunk-GJPXRJ45.js +0 -37
  132. package/dist/chunk-HGMJFBC7.js +0 -654
  133. package/dist/chunk-JAKHTMQU.js +0 -1000
  134. package/dist/chunk-JCI5M6U6.js +0 -956
  135. package/dist/chunk-K4G4ZQNR.js +0 -286
  136. package/dist/chunk-K5ZUMYVS.js +0 -89
  137. package/dist/chunk-KQPDEVVS.js +0 -398
  138. package/dist/chunk-L6JRBDNS.js +0 -60
  139. package/dist/chunk-LA6KQEDU.js +0 -712
  140. package/dist/chunk-MB6QFH3I.js +0 -2776
  141. package/dist/chunk-MDVXJWFN.js +0 -304
  142. package/dist/chunk-MEZVEBPN.js +0 -2008
  143. package/dist/chunk-MK4ERFYL.js +0 -2249
  144. package/dist/chunk-MLKGABMK.js +0 -9
  145. package/dist/chunk-MQ5GOYPH.js +0 -2249
  146. package/dist/chunk-MYRV7VDM.js +0 -742
  147. package/dist/chunk-N6IZB6KJ.js +0 -567
  148. package/dist/chunk-NEKUBFPT.js +0 -60
  149. package/dist/chunk-NMRUZALC.js +0 -1097
  150. package/dist/chunk-NYVAC6P5.js +0 -37
  151. package/dist/chunk-NZIIMDWI.js +0 -84
  152. package/dist/chunk-OF7UZIVB.js +0 -725
  153. package/dist/chunk-P3XWXJZU.js +0 -282
  154. package/dist/chunk-P6W3STU4.js +0 -2249
  155. package/dist/chunk-PBHF5WKN.js +0 -616
  156. package/dist/chunk-PDZQY43A.js +0 -616
  157. package/dist/chunk-PTQJDMRT.js +0 -146
  158. package/dist/chunk-PZEGYCF5.js +0 -61
  159. package/dist/chunk-QBMDLBU2.js +0 -975
  160. package/dist/chunk-QWZG56ET.js +0 -2744
  161. package/dist/chunk-RQGQSLQK.js +0 -725
  162. package/dist/chunk-SDLZDHKP.js +0 -107
  163. package/dist/chunk-TDGZL5CU.js +0 -365
  164. package/dist/chunk-TNQWPPE6.js +0 -37
  165. package/dist/chunk-TSOKIX5Z.js +0 -654
  166. package/dist/chunk-UHNL42EF.js +0 -2730
  167. package/dist/chunk-UNXCEF6S.js +0 -21
  168. package/dist/chunk-V2XTI523.js +0 -347
  169. package/dist/chunk-VAU366PN.js +0 -2241
  170. package/dist/chunk-VMVDTCXB.js +0 -712
  171. package/dist/chunk-VQNQZCWJ.js +0 -61
  172. package/dist/chunk-VRW3FULF.js +0 -725
  173. package/dist/chunk-WADYRCO2.js +0 -304
  174. package/dist/chunk-WILQZRO4.js +0 -282
  175. package/dist/chunk-WR5D4EGH.js +0 -26
  176. package/dist/chunk-WUHJISPP.js +0 -298
  177. package/dist/chunk-XYU6TZOW.js +0 -182
  178. package/dist/chunk-Y6GP4QGG.js +0 -276
  179. package/dist/chunk-YECR7UIA.js +0 -347
  180. package/dist/chunk-YUTWTI4B.js +0 -654
  181. package/dist/chunk-Z65KYU7I.js +0 -26
  182. package/dist/chunk-Z6POF5YC.js +0 -975
  183. package/dist/chunk-ZBJP6WFL.js +0 -482
  184. package/dist/chunk-ZD6OAMTH.js +0 -277
  185. package/dist/chunk-ZWKZCBO6.js +0 -317
  186. package/dist/contracts-DDrwxvJ-.d.cts +0 -245
  187. package/dist/contracts-DDrwxvJ-.d.ts +0 -245
  188. package/dist/contracts-DOrhwbke.d.cts +0 -245
  189. package/dist/contracts-DOrhwbke.d.ts +0 -245
  190. package/dist/contracts-xo5ckdRP.d.cts +0 -240
  191. package/dist/contracts-xo5ckdRP.d.ts +0 -240
  192. package/dist/customElement-BKQfbSZQ.d.cts +0 -262
  193. package/dist/customElement-BKQfbSZQ.d.ts +0 -262
  194. package/dist/customElement-D2DJp_xn.d.cts +0 -313
  195. package/dist/customElement-D2DJp_xn.d.ts +0 -313
  196. package/dist/customElement-yz8uyk-0.d.cts +0 -308
  197. package/dist/customElement-yz8uyk-0.d.ts +0 -308
  198. package/dist/introspect-Cb0zgpi2.d.cts +0 -477
  199. package/dist/introspect-Y2xNXGSf.d.ts +0 -477
  200. package/dist/plugin-Bek4RhJY.d.cts +0 -43
  201. package/dist/plugin-Bek4RhJY.d.ts +0 -43
  202. package/dist/ssr-3RXHP5ES.js +0 -38
  203. package/dist/ssr-6GIMY5MX.js +0 -38
  204. package/dist/ssr-BA6sxxUd.d.cts +0 -135
  205. package/dist/ssr-BA6sxxUd.d.ts +0 -135
  206. package/dist/ssr-WKUPVSSK.js +0 -36
  207. package/dist/tagFactory-Dl8QCLga.d.cts +0 -23
  208. package/dist/tagFactory-Dl8QCLga.d.ts +0 -23
package/dist/patterns.cjs CHANGED
@@ -50,26 +50,39 @@ function isDev() {
50
50
  var _isDev = isDev();
51
51
  function devAssert(condition, message) {
52
52
  if (_isDev && !condition) {
53
- throw new Error(`[Sibu] ${message}`);
53
+ throw new Error(`[SibuJS] ${message}`);
54
54
  }
55
55
  }
56
56
  function devWarn(message) {
57
57
  if (_isDev) {
58
- console.warn(`[Sibu] ${message}`);
58
+ console.warn(`[SibuJS] ${message}`);
59
59
  }
60
60
  }
61
61
 
62
62
  // src/reactivity/track.ts
63
63
  var _isDev2 = isDev();
64
- var subscriberStack = new Array(32);
65
- var stackCapacity = 32;
64
+ var STACK_INITIAL = 32;
65
+ var STACK_SHRINK_THRESHOLD = 128;
66
+ var subscriberStack = new Array(STACK_INITIAL);
67
+ var stackCapacity = STACK_INITIAL;
66
68
  var stackTop = -1;
67
69
  var currentSubscriber = null;
68
- var signalSubscribers = /* @__PURE__ */ new WeakMap();
69
70
  var SUBS = "__s";
71
+ function syncFastPath(signal2, subs) {
72
+ const size = subs.size;
73
+ if (size === 0) {
74
+ signal2.__f = void 0;
75
+ delete signal2[SUBS];
76
+ } else if (size === 1) {
77
+ signal2.__f = subs.values().next().value;
78
+ } else {
79
+ signal2.__f = void 0;
80
+ }
81
+ }
70
82
  var notifyDepth = 0;
71
83
  var pendingQueue = [];
72
84
  var pendingSet = /* @__PURE__ */ new Set();
85
+ var propagateStack = [];
73
86
  function safeInvoke(sub) {
74
87
  try {
75
88
  sub();
@@ -78,6 +91,47 @@ function safeInvoke(sub) {
78
91
  }
79
92
  }
80
93
  var trackingSuspended = false;
94
+ var subscriberEpochCounter = 0;
95
+ function retrack(effectFn, subscriber) {
96
+ const prev = currentSubscriber;
97
+ currentSubscriber = subscriber;
98
+ const sub = subscriber;
99
+ const epoch = ++subscriberEpochCounter;
100
+ sub._epoch = epoch;
101
+ try {
102
+ effectFn();
103
+ } finally {
104
+ currentSubscriber = prev;
105
+ pruneStaleDeps(sub, epoch);
106
+ }
107
+ }
108
+ function pruneStaleDeps(sub, currentEpoch) {
109
+ if (sub._dep !== void 0) {
110
+ if (sub._depEpoch !== currentEpoch) {
111
+ const sig = sub._dep;
112
+ const subs = sig[SUBS];
113
+ if (subs?.delete(sub)) syncFastPath(sig, subs);
114
+ sub._dep = void 0;
115
+ sub._depEpoch = void 0;
116
+ }
117
+ return;
118
+ }
119
+ const deps = sub._deps;
120
+ if (!deps || deps.size === 0) return;
121
+ let stales;
122
+ for (const [signal2, epoch] of deps) {
123
+ if (epoch !== currentEpoch) {
124
+ (stales ?? (stales = [])).push(signal2);
125
+ }
126
+ }
127
+ if (!stales) return;
128
+ for (const signal2 of stales) {
129
+ deps.delete(signal2);
130
+ const sig = signal2;
131
+ const subs = sig[SUBS];
132
+ if (subs?.delete(sub)) syncFastPath(sig, subs);
133
+ }
134
+ }
81
135
  function track(effectFn, subscriber) {
82
136
  if (!subscriber) subscriber = effectFn;
83
137
  cleanup(subscriber);
@@ -93,75 +147,159 @@ function track(effectFn, subscriber) {
93
147
  } finally {
94
148
  stackTop--;
95
149
  currentSubscriber = stackTop >= 0 ? subscriberStack[stackTop] : null;
150
+ if (stackTop < 0 && stackCapacity > STACK_SHRINK_THRESHOLD) {
151
+ stackCapacity = Math.max(STACK_INITIAL, stackCapacity >>> 1);
152
+ subscriberStack.length = stackCapacity;
153
+ }
96
154
  }
97
155
  return () => cleanup(subscriber);
98
156
  }
99
157
  function recordDependency(signal2) {
100
158
  if (!currentSubscriber) return;
101
159
  const sub = currentSubscriber;
102
- if (sub._dep === signal2) return;
160
+ const epoch = sub._epoch;
161
+ if (sub._dep === signal2) {
162
+ sub._depEpoch = epoch;
163
+ return;
164
+ }
103
165
  const deps = sub._deps;
104
166
  if (deps) {
105
- if (deps.has(signal2)) return;
106
- deps.add(signal2);
167
+ deps.set(signal2, epoch);
107
168
  } else if (sub._dep !== void 0) {
108
- const set = /* @__PURE__ */ new Set();
109
- set.add(sub._dep);
110
- set.add(signal2);
111
- sub._deps = set;
169
+ const map = /* @__PURE__ */ new Map();
170
+ map.set(sub._dep, sub._depEpoch);
171
+ map.set(signal2, epoch);
172
+ sub._deps = map;
112
173
  sub._dep = void 0;
174
+ sub._depEpoch = void 0;
113
175
  } else {
114
176
  sub._dep = signal2;
177
+ sub._depEpoch = epoch;
115
178
  }
116
- let subs = signal2[SUBS];
179
+ const sig = signal2;
180
+ let subs = sig[SUBS];
117
181
  if (!subs) {
118
182
  subs = /* @__PURE__ */ new Set();
119
- signalSubscribers.set(signal2, subs);
120
- signal2[SUBS] = subs;
183
+ sig[SUBS] = subs;
121
184
  }
185
+ const prevSize = subs.size;
122
186
  subs.add(currentSubscriber);
123
- if (subs.size === 1) {
124
- signal2.__f = currentSubscriber;
125
- } else if (signal2.__f !== void 0) {
126
- signal2.__f = void 0;
187
+ if (subs.size !== prevSize) {
188
+ if (subs.size === 1) {
189
+ sig.__f = currentSubscriber;
190
+ } else if (sig.__f !== void 0) {
191
+ sig.__f = void 0;
192
+ }
193
+ }
194
+ }
195
+ function queueSignalNotification(signal2) {
196
+ const subs = signal2[SUBS];
197
+ if (!subs) return;
198
+ for (const sub of subs) {
199
+ if (sub._c) {
200
+ propagateDirty(sub);
201
+ } else if (!pendingSet.has(sub)) {
202
+ pendingSet.add(sub);
203
+ pendingQueue.push(sub);
204
+ }
205
+ }
206
+ }
207
+ var maxSubscriberRepeats = 50;
208
+ var maxDrainIterations = 1e6;
209
+ var drainEpoch = 0;
210
+ function tickRepeat(sub) {
211
+ const s = sub;
212
+ if (s._runEpoch !== drainEpoch) {
213
+ s._runEpoch = drainEpoch;
214
+ s._runs = 1;
215
+ return false;
216
+ }
217
+ return ++s._runs > maxSubscriberRepeats;
218
+ }
219
+ function cycleError(sub) {
220
+ if (typeof console !== "undefined") {
221
+ const name = sub.__name ?? "<unnamed>";
222
+ console.error(
223
+ `[SibuJS] subscriber "${name}" fired more than ${maxSubscriberRepeats} times \u2014 likely a write-reads-self cycle between effects/signals. Breaking to prevent infinite loop.`
224
+ );
225
+ }
226
+ }
227
+ function absoluteDrainError() {
228
+ if (typeof console !== "undefined") {
229
+ console.error(
230
+ `[SibuJS] Notification drain exceeded ${maxDrainIterations} iterations \u2014 absolute safety net tripped. Breaking to prevent infinite loop.`
231
+ );
232
+ }
233
+ }
234
+ function drainQueue() {
235
+ let i = 0;
236
+ while (i < pendingQueue.length) {
237
+ if (i >= maxDrainIterations) {
238
+ absoluteDrainError();
239
+ break;
240
+ }
241
+ const sub = pendingQueue[i++];
242
+ if (tickRepeat(sub)) {
243
+ cycleError(sub);
244
+ break;
245
+ }
246
+ pendingSet.delete(sub);
247
+ safeInvoke(sub);
248
+ }
249
+ }
250
+ function drainNotificationQueue() {
251
+ if (notifyDepth > 0) return;
252
+ notifyDepth++;
253
+ drainEpoch++;
254
+ try {
255
+ drainQueue();
256
+ } finally {
257
+ notifyDepth--;
258
+ if (notifyDepth === 0) {
259
+ pendingQueue.length = 0;
260
+ pendingSet.clear();
261
+ }
127
262
  }
128
263
  }
129
264
  function propagateDirty(sub) {
130
265
  sub();
131
- let sig = sub._sig;
132
- while (sig) {
266
+ const rootSig = sub._sig;
267
+ if (!rootSig) return;
268
+ const stack = propagateStack;
269
+ const baseLen = stack.length;
270
+ stack.push(rootSig);
271
+ while (stack.length > baseLen) {
272
+ const sig = stack.pop();
133
273
  const first = sig.__f;
134
274
  if (first) {
135
275
  if (first._c) {
136
276
  const nSig = first._sig;
137
- nSig._d = true;
138
- sig = nSig;
139
- continue;
140
- }
141
- if (!pendingSet.has(first)) {
277
+ if (!nSig._d) {
278
+ nSig._d = true;
279
+ stack.push(nSig);
280
+ }
281
+ } else if (!pendingSet.has(first)) {
142
282
  pendingSet.add(first);
143
283
  pendingQueue.push(first);
144
284
  }
145
- break;
285
+ continue;
146
286
  }
147
287
  const subs = sig[SUBS];
148
- if (!subs) break;
149
- let nextSig;
288
+ if (!subs) continue;
150
289
  for (const s of subs) {
151
290
  if (s._c) {
152
- s();
153
291
  const nSig = s._sig;
154
- if (nSig && !nextSig) {
155
- nextSig = nSig;
156
- } else if (nSig) {
157
- propagateDirty(s);
292
+ if (nSig && !nSig._d) {
293
+ nSig._d = true;
294
+ stack.push(nSig);
295
+ } else if (!nSig) {
296
+ s();
158
297
  }
159
298
  } else if (!pendingSet.has(s)) {
160
299
  pendingSet.add(s);
161
300
  pendingQueue.push(s);
162
301
  }
163
302
  }
164
- sig = nextSig;
165
303
  }
166
304
  }
167
305
  function notifySubscribers(signal2) {
@@ -177,21 +315,22 @@ function notifySubscribers(signal2) {
177
315
  return;
178
316
  }
179
317
  notifyDepth++;
318
+ drainEpoch++;
180
319
  try {
181
320
  if (first._c) {
182
321
  propagateDirty(first);
322
+ } else if (tickRepeat(first)) {
323
+ cycleError(first);
183
324
  } else {
184
325
  safeInvoke(first);
185
326
  }
186
- let i = 0;
187
- while (i < pendingQueue.length) {
188
- safeInvoke(pendingQueue[i]);
189
- i++;
190
- }
327
+ drainQueue();
191
328
  } finally {
192
- pendingQueue.length = 0;
193
- pendingSet.clear();
194
329
  notifyDepth--;
330
+ if (notifyDepth === 0) {
331
+ pendingQueue.length = 0;
332
+ pendingSet.clear();
333
+ }
195
334
  }
196
335
  return;
197
336
  }
@@ -209,57 +348,45 @@ function notifySubscribers(signal2) {
209
348
  return;
210
349
  }
211
350
  notifyDepth++;
351
+ drainEpoch++;
212
352
  try {
213
- let directCount = 0;
214
353
  for (const sub of subs) {
215
- pendingQueue[directCount++] = sub;
216
- }
217
- for (let i2 = 0; i2 < directCount; i2++) {
218
- if (pendingQueue[i2]._c) {
219
- propagateDirty(pendingQueue[i2]);
220
- }
221
- }
222
- for (let i2 = 0; i2 < directCount; i2++) {
223
- if (!pendingQueue[i2]._c) {
224
- if (!pendingSet.has(pendingQueue[i2])) {
225
- safeInvoke(pendingQueue[i2]);
226
- }
354
+ if (sub._c) {
355
+ propagateDirty(sub);
356
+ } else if (!pendingSet.has(sub)) {
357
+ pendingSet.add(sub);
358
+ pendingQueue.push(sub);
227
359
  }
228
360
  }
229
- let i = directCount;
230
- while (i < pendingQueue.length) {
231
- safeInvoke(pendingQueue[i]);
232
- i++;
233
- }
361
+ drainQueue();
234
362
  } finally {
235
- pendingQueue.length = 0;
236
- pendingSet.clear();
237
363
  notifyDepth--;
364
+ if (notifyDepth === 0) {
365
+ pendingQueue.length = 0;
366
+ pendingSet.clear();
367
+ }
238
368
  }
239
369
  }
240
370
  function cleanup(subscriber) {
241
371
  const sub = subscriber;
242
372
  const singleDep = sub._dep;
243
373
  if (singleDep !== void 0) {
244
- const subs = singleDep[SUBS];
245
- if (subs) {
246
- subs.delete(subscriber);
247
- if (singleDep.__f === subscriber) {
248
- singleDep.__f = void 0;
249
- }
374
+ const sig = singleDep;
375
+ const subs = sig[SUBS];
376
+ if (subs?.delete(subscriber)) {
377
+ syncFastPath(sig, subs);
250
378
  }
251
379
  sub._dep = void 0;
380
+ sub._depEpoch = void 0;
252
381
  return;
253
382
  }
254
383
  const deps = sub._deps;
255
384
  if (!deps || deps.size === 0) return;
256
- for (const signal2 of deps) {
257
- const subs = signal2[SUBS];
258
- if (subs) {
259
- subs.delete(subscriber);
260
- if (signal2.__f === subscriber) {
261
- signal2.__f = void 0;
262
- }
385
+ for (const signal2 of deps.keys()) {
386
+ const sig = signal2;
387
+ const subs = sig[SUBS];
388
+ if (subs?.delete(subscriber)) {
389
+ syncFastPath(sig, subs);
263
390
  }
264
391
  }
265
392
  deps.clear();
@@ -268,11 +395,32 @@ function cleanup(subscriber) {
268
395
  // src/reactivity/batch.ts
269
396
  var batchDepth = 0;
270
397
  var pendingSignals = /* @__PURE__ */ new Set();
398
+ function batch(fn) {
399
+ batchDepth++;
400
+ try {
401
+ return fn();
402
+ } finally {
403
+ batchDepth--;
404
+ if (batchDepth === 0) {
405
+ flushBatch();
406
+ }
407
+ }
408
+ }
271
409
  function enqueueBatchedSignal(signal2) {
272
410
  if (batchDepth === 0) return false;
273
411
  pendingSignals.add(signal2);
274
412
  return true;
275
413
  }
414
+ function flushBatch() {
415
+ try {
416
+ for (const signal2 of pendingSignals) {
417
+ queueSignalNotification(signal2);
418
+ }
419
+ } finally {
420
+ pendingSignals.clear();
421
+ }
422
+ drainNotificationQueue();
423
+ }
276
424
 
277
425
  // src/core/signals/signal.ts
278
426
  var _g = globalThis;
@@ -375,9 +523,28 @@ function machine(config) {
375
523
  }
376
524
 
377
525
  // src/core/ssr-context.ts
378
- var ssrMode = false;
526
+ var als = null;
527
+ try {
528
+ if (typeof process !== "undefined" && process.versions && process.versions.node) {
529
+ const req = Function("return typeof require==='function'?require:null")();
530
+ if (req) {
531
+ const mod = req("node:async_hooks");
532
+ als = new mod.AsyncLocalStorage();
533
+ }
534
+ }
535
+ } catch {
536
+ als = null;
537
+ }
538
+ var fallbackStore = { ssr: false, suspenseIdCounter: 0 };
539
+ function getSSRStore() {
540
+ if (als) {
541
+ const s = als.getStore();
542
+ if (s) return s;
543
+ }
544
+ return fallbackStore;
545
+ }
379
546
  function isSSR() {
380
- return ssrMode;
547
+ return getSSRStore().ssr;
381
548
  }
382
549
 
383
550
  // src/core/signals/effect.ts
@@ -387,26 +554,114 @@ function effect(effectFn, options) {
387
554
  if (isSSR()) return () => {
388
555
  };
389
556
  const onError = options?.onError;
557
+ let userCleanups = [];
558
+ const onCleanup = (fn) => {
559
+ userCleanups.push(fn);
560
+ };
561
+ const runUserCleanups = () => {
562
+ if (userCleanups.length === 0) return;
563
+ const list = userCleanups;
564
+ userCleanups = [];
565
+ for (let i = list.length - 1; i >= 0; i--) {
566
+ try {
567
+ list[i]();
568
+ } catch (err) {
569
+ if (typeof console !== "undefined") {
570
+ console.warn("[SibuJS effect] onCleanup threw:", err);
571
+ }
572
+ }
573
+ }
574
+ };
575
+ const invokeBody = () => effectFn(onCleanup);
390
576
  const wrappedFn = onError ? () => {
391
577
  try {
392
- effectFn();
578
+ invokeBody();
393
579
  } catch (err) {
394
580
  onError(err);
395
581
  }
396
- } : effectFn;
582
+ } : invokeBody;
397
583
  let cleanupHandle = () => {
398
584
  };
585
+ let running = false;
586
+ let rerunPending = false;
587
+ const MAX_RERUNS = 100;
399
588
  const subscriber = () => {
400
- cleanupHandle();
401
- cleanupHandle = track(wrappedFn, subscriber);
589
+ if (running) {
590
+ rerunPending = true;
591
+ return;
592
+ }
593
+ running = true;
594
+ try {
595
+ let reruns = 0;
596
+ do {
597
+ rerunPending = false;
598
+ runUserCleanups();
599
+ cleanupHandle();
600
+ cleanupHandle = track(wrappedFn, subscriber);
601
+ if (++reruns > MAX_RERUNS) {
602
+ if (_g2.__SIBU_DEV_WARN__ !== false && typeof console !== "undefined") {
603
+ console.error(
604
+ `[SibuJS] effect re-requested itself ${MAX_RERUNS}+ times \u2014 likely a write-reads-self cycle. Breaking to prevent infinite loop.`
605
+ );
606
+ }
607
+ rerunPending = false;
608
+ break;
609
+ }
610
+ } while (rerunPending);
611
+ } finally {
612
+ running = false;
613
+ rerunPending = false;
614
+ }
402
615
  };
403
- cleanupHandle = track(wrappedFn, subscriber);
616
+ running = true;
617
+ try {
618
+ let reruns = 0;
619
+ do {
620
+ rerunPending = false;
621
+ runUserCleanups();
622
+ cleanupHandle();
623
+ cleanupHandle = track(wrappedFn, subscriber);
624
+ if (++reruns > MAX_RERUNS) {
625
+ if (_g2.__SIBU_DEV_WARN__ !== false && typeof console !== "undefined") {
626
+ console.error(
627
+ `[SibuJS] effect re-requested itself ${MAX_RERUNS}+ times on initial run \u2014 likely a write-reads-self cycle. Breaking to prevent infinite loop.`
628
+ );
629
+ }
630
+ rerunPending = false;
631
+ break;
632
+ }
633
+ } while (rerunPending);
634
+ } finally {
635
+ running = false;
636
+ rerunPending = false;
637
+ }
404
638
  const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
405
639
  if (hook) hook.emit("effect:create", { effectFn });
640
+ let disposed = false;
406
641
  return () => {
642
+ if (disposed) return;
643
+ disposed = true;
407
644
  const h = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
408
- if (h) h.emit("effect:destroy", { effectFn });
409
- cleanupHandle();
645
+ if (h) {
646
+ try {
647
+ h.emit("effect:destroy", { effectFn });
648
+ } catch {
649
+ }
650
+ }
651
+ try {
652
+ runUserCleanups();
653
+ } catch (err) {
654
+ if (typeof console !== "undefined") {
655
+ console.warn("[SibuJS effect] onCleanup threw during dispose:", err);
656
+ }
657
+ }
658
+ try {
659
+ cleanupHandle();
660
+ } catch (err) {
661
+ if (typeof console !== "undefined") {
662
+ console.warn("[SibuJS effect] dispose threw:", err);
663
+ }
664
+ }
410
665
  };
411
666
  }
412
667
 
@@ -414,7 +669,11 @@ function effect(effectFn, options) {
414
669
  function persisted(key, initial, options = {}) {
415
670
  const storage = options.session ? sessionStorage : localStorage;
416
671
  const serialize = options.serialize || JSON.stringify;
417
- const deserialize = options.deserialize || JSON.parse;
672
+ const safeReviver = (k, v) => {
673
+ if (k === "__proto__" || k === "constructor" || k === "prototype") return void 0;
674
+ return v;
675
+ };
676
+ const deserialize = options.deserialize || ((raw) => JSON.parse(raw, safeReviver));
418
677
  const encrypt = options.encrypt;
419
678
  const decrypt = options.decrypt;
420
679
  const syncTabs = options.session ? false : options.syncTabs ?? true;
@@ -518,6 +777,27 @@ function optimisticList(initialValue) {
518
777
  const [pending, setPending] = signal(false);
519
778
  let inflightCount = 0;
520
779
  let version = 0;
780
+ let tempIdCounter = 0;
781
+ const itemIds = /* @__PURE__ */ new WeakMap();
782
+ const idToItem = /* @__PURE__ */ new Map();
783
+ function tagItem(item) {
784
+ const id = ++tempIdCounter;
785
+ if (item !== null && typeof item === "object") {
786
+ itemIds.set(item, id);
787
+ }
788
+ idToItem.set(id, item);
789
+ return id;
790
+ }
791
+ function findIndexById(list, id) {
792
+ for (let i = 0; i < list.length; i++) {
793
+ const it = list[i];
794
+ if (it !== null && typeof it === "object" && itemIds.get(it) === id) {
795
+ return i;
796
+ }
797
+ if (Object.is(it, idToItem.get(id))) return i;
798
+ }
799
+ return -1;
800
+ }
521
801
  function begin() {
522
802
  const v = ++version;
523
803
  inflightCount++;
@@ -533,12 +813,13 @@ function optimisticList(initialValue) {
533
813
  }
534
814
  async function add(item, asyncAction) {
535
815
  const prev = items();
816
+ const id = tagItem(item);
536
817
  setItems([...prev, item]);
537
818
  const myVersion = begin();
538
819
  try {
539
820
  const result = await asyncAction();
540
821
  setItems((current) => {
541
- const idx = current.lastIndexOf(item);
822
+ const idx = findIndexById(current, id);
542
823
  if (idx >= 0) {
543
824
  const next = [...current];
544
825
  next[idx] = result;
@@ -546,8 +827,10 @@ function optimisticList(initialValue) {
546
827
  }
547
828
  return [...current, result];
548
829
  });
830
+ idToItem.delete(id);
549
831
  end(myVersion);
550
832
  } catch {
833
+ idToItem.delete(id);
551
834
  end(myVersion, () => setItems(prev));
552
835
  }
553
836
  }
@@ -564,12 +847,13 @@ function optimisticList(initialValue) {
564
847
  }
565
848
  async function updateItem(predicate, patch, asyncAction) {
566
849
  const prev = items();
567
- const patchedRefs = [];
850
+ const patchedIds = [];
568
851
  setItems(
569
852
  prev.map((item) => {
570
853
  if (predicate(item)) {
571
854
  const patched = { ...item, ...patch };
572
- patchedRefs.push(patched);
855
+ const id = tagItem(patched);
856
+ patchedIds.push(id);
573
857
  return patched;
574
858
  }
575
859
  return item;
@@ -578,9 +862,19 @@ function optimisticList(initialValue) {
578
862
  const myVersion = begin();
579
863
  try {
580
864
  const result = await asyncAction();
581
- setItems((current) => current.map((item) => patchedRefs.includes(item) ? result : item));
865
+ setItems(
866
+ (current) => current.map((item) => {
867
+ if (item !== null && typeof item === "object") {
868
+ const existingId = itemIds.get(item);
869
+ if (existingId !== void 0 && patchedIds.includes(existingId)) return result;
870
+ }
871
+ return item;
872
+ })
873
+ );
874
+ for (const id of patchedIds) idToItem.delete(id);
582
875
  end(myVersion);
583
876
  } catch {
877
+ for (const id of patchedIds) idToItem.delete(id);
584
878
  end(myVersion, () => setItems(prev));
585
879
  }
586
880
  }
@@ -589,10 +883,7 @@ function optimisticList(initialValue) {
589
883
  pending,
590
884
  add,
591
885
  remove,
592
- update: updateItem,
593
- addOptimistic: add,
594
- removeOptimistic: remove,
595
- updateOptimistic: updateItem
886
+ update: updateItem
596
887
  };
597
888
  }
598
889
 
@@ -600,6 +891,7 @@ function optimisticList(initialValue) {
600
891
  function derived(getter, options) {
601
892
  devAssert(typeof getter === "function", "derived: argument must be a getter function.");
602
893
  const debugName = options?.name;
894
+ const equals = options?.equals;
603
895
  const cs = {};
604
896
  cs._d = false;
605
897
  cs._g = getter;
@@ -610,8 +902,14 @@ function derived(getter, options) {
610
902
  markDirty._c = 1;
611
903
  markDirty._sig = cs;
612
904
  track(() => {
613
- cs._d = false;
614
- cs._v = getter();
905
+ let threw = true;
906
+ try {
907
+ cs._v = getter();
908
+ cs._d = false;
909
+ threw = false;
910
+ } finally {
911
+ if (threw) cs._d = true;
912
+ }
615
913
  }, markDirty);
616
914
  const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
617
915
  let evaluating = false;
@@ -624,11 +922,16 @@ function derived(getter, options) {
624
922
  if (trackingSuspended) {
625
923
  if (cs._d) {
626
924
  evaluating = true;
925
+ let threw = true;
627
926
  try {
628
- cs._d = false;
629
- cs._v = getter();
927
+ retrack(() => {
928
+ cs._v = getter();
929
+ cs._d = false;
930
+ threw = false;
931
+ }, markDirty);
630
932
  } finally {
631
933
  evaluating = false;
934
+ if (threw) cs._d = true;
632
935
  }
633
936
  }
634
937
  return cs._v;
@@ -637,13 +940,17 @@ function derived(getter, options) {
637
940
  if (cs._d) {
638
941
  const oldValue = cs._v;
639
942
  evaluating = true;
943
+ let threw = true;
640
944
  try {
641
- track(() => {
945
+ retrack(() => {
946
+ const next = getter();
947
+ cs._v = equals && cs._v !== void 0 ? equals(cs._v, next) ? cs._v : next : next;
642
948
  cs._d = false;
643
- cs._v = getter();
949
+ threw = false;
644
950
  }, markDirty);
645
951
  } finally {
646
952
  evaluating = false;
953
+ if (threw) cs._d = true;
647
954
  }
648
955
  if (hook && oldValue !== cs._v) {
649
956
  hook.emit("computed:update", { signal: cs, oldValue, newValue: cs._v });
@@ -675,14 +982,16 @@ function timeline(initial, maxHistory = 100) {
675
982
  const idx = index();
676
983
  const newHistory = hist.slice(0, idx + 1);
677
984
  newHistory.push(newValue);
678
- if (newHistory.length > maxHistory) {
679
- newHistory.shift();
680
- setHistory(newHistory);
681
- setIndex(newHistory.length - 1);
682
- } else {
683
- setHistory(newHistory);
684
- setIndex(idx + 1);
685
- }
985
+ batch(() => {
986
+ if (newHistory.length > maxHistory) {
987
+ newHistory.shift();
988
+ setHistory(newHistory);
989
+ setIndex(newHistory.length - 1);
990
+ } else {
991
+ setHistory(newHistory);
992
+ setIndex(idx + 1);
993
+ }
994
+ });
686
995
  }
687
996
  function undo() {
688
997
  if (canUndo()) {
@@ -695,8 +1004,10 @@ function timeline(initial, maxHistory = 100) {
695
1004
  }
696
1005
  }
697
1006
  function reset() {
698
- setHistory([initial]);
699
- setIndex(0);
1007
+ batch(() => {
1008
+ setHistory([initial]);
1009
+ setIndex(0);
1010
+ });
700
1011
  }
701
1012
  function jumpTo(targetIndex) {
702
1013
  const hist = history();
@@ -708,8 +1019,37 @@ function timeline(initial, maxHistory = 100) {
708
1019
  }
709
1020
 
710
1021
  // src/patterns/globalStore.ts
1022
+ function deepClone(value) {
1023
+ if (typeof structuredClone === "function") {
1024
+ return structuredClone(value);
1025
+ }
1026
+ const seen = /* @__PURE__ */ new WeakSet();
1027
+ const clone = (v) => {
1028
+ if (v === null || typeof v !== "object") return v;
1029
+ if (seen.has(v)) throw new Error("deepClone: circular reference");
1030
+ seen.add(v);
1031
+ if (v instanceof Date) return new Date(v.getTime());
1032
+ if (v instanceof Map) {
1033
+ const out2 = /* @__PURE__ */ new Map();
1034
+ for (const [k, val] of v) out2.set(clone(k), clone(val));
1035
+ return out2;
1036
+ }
1037
+ if (v instanceof Set) {
1038
+ const out2 = /* @__PURE__ */ new Set();
1039
+ for (const val of v) out2.add(clone(val));
1040
+ return out2;
1041
+ }
1042
+ if (Array.isArray(v)) return v.map(clone);
1043
+ const out = {};
1044
+ for (const k of Object.keys(v)) {
1045
+ out[k] = clone(v[k]);
1046
+ }
1047
+ return out;
1048
+ };
1049
+ return clone(value);
1050
+ }
711
1051
  function globalStore(config) {
712
- const initialState = JSON.parse(JSON.stringify(config.state));
1052
+ const initialState = deepClone(config.state);
713
1053
  const [getState, setState] = signal({ ...initialState });
714
1054
  const listeners = /* @__PURE__ */ new Set();
715
1055
  const middlewares = config.middleware || [];