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/browser.cjs CHANGED
@@ -66,26 +66,39 @@ function isDev() {
66
66
  var _isDev = isDev();
67
67
  function devAssert(condition, message) {
68
68
  if (_isDev && !condition) {
69
- throw new Error(`[Sibu] ${message}`);
69
+ throw new Error(`[SibuJS] ${message}`);
70
70
  }
71
71
  }
72
72
  function devWarn(message) {
73
73
  if (_isDev) {
74
- console.warn(`[Sibu] ${message}`);
74
+ console.warn(`[SibuJS] ${message}`);
75
75
  }
76
76
  }
77
77
 
78
78
  // src/reactivity/track.ts
79
79
  var _isDev2 = isDev();
80
- var subscriberStack = new Array(32);
81
- var stackCapacity = 32;
80
+ var STACK_INITIAL = 32;
81
+ var STACK_SHRINK_THRESHOLD = 128;
82
+ var subscriberStack = new Array(STACK_INITIAL);
83
+ var stackCapacity = STACK_INITIAL;
82
84
  var stackTop = -1;
83
85
  var currentSubscriber = null;
84
- var signalSubscribers = /* @__PURE__ */ new WeakMap();
85
86
  var SUBS = "__s";
87
+ function syncFastPath(signal2, subs) {
88
+ const size = subs.size;
89
+ if (size === 0) {
90
+ signal2.__f = void 0;
91
+ delete signal2[SUBS];
92
+ } else if (size === 1) {
93
+ signal2.__f = subs.values().next().value;
94
+ } else {
95
+ signal2.__f = void 0;
96
+ }
97
+ }
86
98
  var notifyDepth = 0;
87
99
  var pendingQueue = [];
88
100
  var pendingSet = /* @__PURE__ */ new Set();
101
+ var propagateStack = [];
89
102
  function safeInvoke(sub) {
90
103
  try {
91
104
  sub();
@@ -108,37 +121,49 @@ function track(effectFn, subscriber) {
108
121
  } finally {
109
122
  stackTop--;
110
123
  currentSubscriber = stackTop >= 0 ? subscriberStack[stackTop] : null;
124
+ if (stackTop < 0 && stackCapacity > STACK_SHRINK_THRESHOLD) {
125
+ stackCapacity = Math.max(STACK_INITIAL, stackCapacity >>> 1);
126
+ subscriberStack.length = stackCapacity;
127
+ }
111
128
  }
112
129
  return () => cleanup(subscriber);
113
130
  }
114
131
  function recordDependency(signal2) {
115
132
  if (!currentSubscriber) return;
116
133
  const sub = currentSubscriber;
117
- if (sub._dep === signal2) return;
134
+ const epoch = sub._epoch;
135
+ if (sub._dep === signal2) {
136
+ sub._depEpoch = epoch;
137
+ return;
138
+ }
118
139
  const deps = sub._deps;
119
140
  if (deps) {
120
- if (deps.has(signal2)) return;
121
- deps.add(signal2);
141
+ deps.set(signal2, epoch);
122
142
  } else if (sub._dep !== void 0) {
123
- const set = /* @__PURE__ */ new Set();
124
- set.add(sub._dep);
125
- set.add(signal2);
126
- sub._deps = set;
143
+ const map = /* @__PURE__ */ new Map();
144
+ map.set(sub._dep, sub._depEpoch);
145
+ map.set(signal2, epoch);
146
+ sub._deps = map;
127
147
  sub._dep = void 0;
148
+ sub._depEpoch = void 0;
128
149
  } else {
129
150
  sub._dep = signal2;
151
+ sub._depEpoch = epoch;
130
152
  }
131
- let subs = signal2[SUBS];
153
+ const sig = signal2;
154
+ let subs = sig[SUBS];
132
155
  if (!subs) {
133
156
  subs = /* @__PURE__ */ new Set();
134
- signalSubscribers.set(signal2, subs);
135
- signal2[SUBS] = subs;
157
+ sig[SUBS] = subs;
136
158
  }
159
+ const prevSize = subs.size;
137
160
  subs.add(currentSubscriber);
138
- if (subs.size === 1) {
139
- signal2.__f = currentSubscriber;
140
- } else if (signal2.__f !== void 0) {
141
- signal2.__f = void 0;
161
+ if (subs.size !== prevSize) {
162
+ if (subs.size === 1) {
163
+ sig.__f = currentSubscriber;
164
+ } else if (sig.__f !== void 0) {
165
+ sig.__f = void 0;
166
+ }
142
167
  }
143
168
  }
144
169
  function queueSignalNotification(signal2) {
@@ -153,66 +178,102 @@ function queueSignalNotification(signal2) {
153
178
  }
154
179
  }
155
180
  }
156
- var MAX_DRAIN_ITERATIONS = 1e3;
181
+ var maxSubscriberRepeats = 50;
182
+ var maxDrainIterations = 1e6;
183
+ var drainEpoch = 0;
184
+ function tickRepeat(sub) {
185
+ const s = sub;
186
+ if (s._runEpoch !== drainEpoch) {
187
+ s._runEpoch = drainEpoch;
188
+ s._runs = 1;
189
+ return false;
190
+ }
191
+ return ++s._runs > maxSubscriberRepeats;
192
+ }
193
+ function cycleError(sub) {
194
+ if (typeof console !== "undefined") {
195
+ const name = sub.__name ?? "<unnamed>";
196
+ console.error(
197
+ `[SibuJS] subscriber "${name}" fired more than ${maxSubscriberRepeats} times \u2014 likely a write-reads-self cycle between effects/signals. Breaking to prevent infinite loop.`
198
+ );
199
+ }
200
+ }
201
+ function absoluteDrainError() {
202
+ if (typeof console !== "undefined") {
203
+ console.error(
204
+ `[SibuJS] Notification drain exceeded ${maxDrainIterations} iterations \u2014 absolute safety net tripped. Breaking to prevent infinite loop.`
205
+ );
206
+ }
207
+ }
208
+ function drainQueue() {
209
+ let i = 0;
210
+ while (i < pendingQueue.length) {
211
+ if (i >= maxDrainIterations) {
212
+ absoluteDrainError();
213
+ break;
214
+ }
215
+ const sub = pendingQueue[i++];
216
+ if (tickRepeat(sub)) {
217
+ cycleError(sub);
218
+ break;
219
+ }
220
+ pendingSet.delete(sub);
221
+ safeInvoke(sub);
222
+ }
223
+ }
157
224
  function drainNotificationQueue() {
158
225
  if (notifyDepth > 0) return;
159
226
  notifyDepth++;
227
+ drainEpoch++;
160
228
  try {
161
- let i = 0;
162
- while (i < pendingQueue.length) {
163
- if (i >= MAX_DRAIN_ITERATIONS) {
164
- if (typeof console !== "undefined") {
165
- console.error(
166
- `[SibuJS] Notification queue exceeded ${MAX_DRAIN_ITERATIONS} iterations \u2014 likely an effect that writes to a signal it reads. Breaking to prevent infinite loop.`
167
- );
168
- }
169
- break;
170
- }
171
- safeInvoke(pendingQueue[i]);
172
- i++;
173
- }
229
+ drainQueue();
174
230
  } finally {
175
- pendingQueue.length = 0;
176
- pendingSet.clear();
177
231
  notifyDepth--;
232
+ if (notifyDepth === 0) {
233
+ pendingQueue.length = 0;
234
+ pendingSet.clear();
235
+ }
178
236
  }
179
237
  }
180
238
  function propagateDirty(sub) {
181
239
  sub();
182
- let sig = sub._sig;
183
- while (sig) {
240
+ const rootSig = sub._sig;
241
+ if (!rootSig) return;
242
+ const stack = propagateStack;
243
+ const baseLen = stack.length;
244
+ stack.push(rootSig);
245
+ while (stack.length > baseLen) {
246
+ const sig = stack.pop();
184
247
  const first = sig.__f;
185
248
  if (first) {
186
249
  if (first._c) {
187
250
  const nSig = first._sig;
188
- nSig._d = true;
189
- sig = nSig;
190
- continue;
191
- }
192
- if (!pendingSet.has(first)) {
251
+ if (!nSig._d) {
252
+ nSig._d = true;
253
+ stack.push(nSig);
254
+ }
255
+ } else if (!pendingSet.has(first)) {
193
256
  pendingSet.add(first);
194
257
  pendingQueue.push(first);
195
258
  }
196
- break;
259
+ continue;
197
260
  }
198
261
  const subs = sig[SUBS];
199
- if (!subs) break;
200
- let nextSig;
262
+ if (!subs) continue;
201
263
  for (const s of subs) {
202
264
  if (s._c) {
203
- s();
204
265
  const nSig = s._sig;
205
- if (nSig && !nextSig) {
206
- nextSig = nSig;
207
- } else if (nSig) {
208
- propagateDirty(s);
266
+ if (nSig && !nSig._d) {
267
+ nSig._d = true;
268
+ stack.push(nSig);
269
+ } else if (!nSig) {
270
+ s();
209
271
  }
210
272
  } else if (!pendingSet.has(s)) {
211
273
  pendingSet.add(s);
212
274
  pendingQueue.push(s);
213
275
  }
214
276
  }
215
- sig = nextSig;
216
277
  }
217
278
  }
218
279
  function notifySubscribers(signal2) {
@@ -228,21 +289,22 @@ function notifySubscribers(signal2) {
228
289
  return;
229
290
  }
230
291
  notifyDepth++;
292
+ drainEpoch++;
231
293
  try {
232
294
  if (first._c) {
233
295
  propagateDirty(first);
296
+ } else if (tickRepeat(first)) {
297
+ cycleError(first);
234
298
  } else {
235
299
  safeInvoke(first);
236
300
  }
237
- let i = 0;
238
- while (i < pendingQueue.length) {
239
- safeInvoke(pendingQueue[i]);
240
- i++;
241
- }
301
+ drainQueue();
242
302
  } finally {
243
- pendingQueue.length = 0;
244
- pendingSet.clear();
245
303
  notifyDepth--;
304
+ if (notifyDepth === 0) {
305
+ pendingQueue.length = 0;
306
+ pendingSet.clear();
307
+ }
246
308
  }
247
309
  return;
248
310
  }
@@ -260,57 +322,45 @@ function notifySubscribers(signal2) {
260
322
  return;
261
323
  }
262
324
  notifyDepth++;
325
+ drainEpoch++;
263
326
  try {
264
- let directCount = 0;
265
327
  for (const sub of subs) {
266
- pendingQueue[directCount++] = sub;
267
- }
268
- for (let i2 = 0; i2 < directCount; i2++) {
269
- if (pendingQueue[i2]._c) {
270
- propagateDirty(pendingQueue[i2]);
271
- }
272
- }
273
- for (let i2 = 0; i2 < directCount; i2++) {
274
- if (!pendingQueue[i2]._c) {
275
- if (!pendingSet.has(pendingQueue[i2])) {
276
- safeInvoke(pendingQueue[i2]);
277
- }
328
+ if (sub._c) {
329
+ propagateDirty(sub);
330
+ } else if (!pendingSet.has(sub)) {
331
+ pendingSet.add(sub);
332
+ pendingQueue.push(sub);
278
333
  }
279
334
  }
280
- let i = directCount;
281
- while (i < pendingQueue.length) {
282
- safeInvoke(pendingQueue[i]);
283
- i++;
284
- }
335
+ drainQueue();
285
336
  } finally {
286
- pendingQueue.length = 0;
287
- pendingSet.clear();
288
337
  notifyDepth--;
338
+ if (notifyDepth === 0) {
339
+ pendingQueue.length = 0;
340
+ pendingSet.clear();
341
+ }
289
342
  }
290
343
  }
291
344
  function cleanup(subscriber) {
292
345
  const sub = subscriber;
293
346
  const singleDep = sub._dep;
294
347
  if (singleDep !== void 0) {
295
- const subs = singleDep[SUBS];
296
- if (subs) {
297
- subs.delete(subscriber);
298
- if (singleDep.__f === subscriber) {
299
- singleDep.__f = void 0;
300
- }
348
+ const sig = singleDep;
349
+ const subs = sig[SUBS];
350
+ if (subs?.delete(subscriber)) {
351
+ syncFastPath(sig, subs);
301
352
  }
302
353
  sub._dep = void 0;
354
+ sub._depEpoch = void 0;
303
355
  return;
304
356
  }
305
357
  const deps = sub._deps;
306
358
  if (!deps || deps.size === 0) return;
307
- for (const signal2 of deps) {
308
- const subs = signal2[SUBS];
309
- if (subs) {
310
- subs.delete(subscriber);
311
- if (signal2.__f === subscriber) {
312
- signal2.__f = void 0;
313
- }
359
+ for (const signal2 of deps.keys()) {
360
+ const sig = signal2;
361
+ const subs = sig[SUBS];
362
+ if (subs?.delete(subscriber)) {
363
+ syncFastPath(sig, subs);
314
364
  }
315
365
  }
316
366
  deps.clear();
@@ -336,10 +386,13 @@ function enqueueBatchedSignal(signal2) {
336
386
  return true;
337
387
  }
338
388
  function flushBatch() {
339
- for (const signal2 of pendingSignals) {
340
- queueSignalNotification(signal2);
389
+ try {
390
+ for (const signal2 of pendingSignals) {
391
+ queueSignalNotification(signal2);
392
+ }
393
+ } finally {
394
+ pendingSignals.clear();
341
395
  }
342
- pendingSignals.clear();
343
396
  drainNotificationQueue();
344
397
  }
345
398
 
@@ -401,9 +454,28 @@ function media(query) {
401
454
  }
402
455
 
403
456
  // src/core/ssr-context.ts
404
- var ssrMode = false;
457
+ var als = null;
458
+ try {
459
+ if (typeof process !== "undefined" && process.versions && process.versions.node) {
460
+ const req = Function("return typeof require==='function'?require:null")();
461
+ if (req) {
462
+ const mod = req("node:async_hooks");
463
+ als = new mod.AsyncLocalStorage();
464
+ }
465
+ }
466
+ } catch {
467
+ als = null;
468
+ }
469
+ var fallbackStore = { ssr: false, suspenseIdCounter: 0 };
470
+ function getSSRStore() {
471
+ if (als) {
472
+ const s = als.getStore();
473
+ if (s) return s;
474
+ }
475
+ return fallbackStore;
476
+ }
405
477
  function isSSR() {
406
- return ssrMode;
478
+ return getSSRStore().ssr;
407
479
  }
408
480
 
409
481
  // src/core/signals/effect.ts
@@ -413,26 +485,114 @@ function effect(effectFn, options) {
413
485
  if (isSSR()) return () => {
414
486
  };
415
487
  const onError = options?.onError;
488
+ let userCleanups = [];
489
+ const onCleanup = (fn) => {
490
+ userCleanups.push(fn);
491
+ };
492
+ const runUserCleanups = () => {
493
+ if (userCleanups.length === 0) return;
494
+ const list = userCleanups;
495
+ userCleanups = [];
496
+ for (let i = list.length - 1; i >= 0; i--) {
497
+ try {
498
+ list[i]();
499
+ } catch (err) {
500
+ if (typeof console !== "undefined") {
501
+ console.warn("[SibuJS effect] onCleanup threw:", err);
502
+ }
503
+ }
504
+ }
505
+ };
506
+ const invokeBody = () => effectFn(onCleanup);
416
507
  const wrappedFn = onError ? () => {
417
508
  try {
418
- effectFn();
509
+ invokeBody();
419
510
  } catch (err) {
420
511
  onError(err);
421
512
  }
422
- } : effectFn;
513
+ } : invokeBody;
423
514
  let cleanupHandle = () => {
424
515
  };
516
+ let running = false;
517
+ let rerunPending = false;
518
+ const MAX_RERUNS = 100;
425
519
  const subscriber = () => {
426
- cleanupHandle();
427
- cleanupHandle = track(wrappedFn, subscriber);
520
+ if (running) {
521
+ rerunPending = true;
522
+ return;
523
+ }
524
+ running = true;
525
+ try {
526
+ let reruns = 0;
527
+ do {
528
+ rerunPending = false;
529
+ runUserCleanups();
530
+ cleanupHandle();
531
+ cleanupHandle = track(wrappedFn, subscriber);
532
+ if (++reruns > MAX_RERUNS) {
533
+ if (_g2.__SIBU_DEV_WARN__ !== false && typeof console !== "undefined") {
534
+ console.error(
535
+ `[SibuJS] effect re-requested itself ${MAX_RERUNS}+ times \u2014 likely a write-reads-self cycle. Breaking to prevent infinite loop.`
536
+ );
537
+ }
538
+ rerunPending = false;
539
+ break;
540
+ }
541
+ } while (rerunPending);
542
+ } finally {
543
+ running = false;
544
+ rerunPending = false;
545
+ }
428
546
  };
429
- cleanupHandle = track(wrappedFn, subscriber);
547
+ running = true;
548
+ try {
549
+ let reruns = 0;
550
+ do {
551
+ rerunPending = false;
552
+ runUserCleanups();
553
+ cleanupHandle();
554
+ cleanupHandle = track(wrappedFn, subscriber);
555
+ if (++reruns > MAX_RERUNS) {
556
+ if (_g2.__SIBU_DEV_WARN__ !== false && typeof console !== "undefined") {
557
+ console.error(
558
+ `[SibuJS] effect re-requested itself ${MAX_RERUNS}+ times on initial run \u2014 likely a write-reads-self cycle. Breaking to prevent infinite loop.`
559
+ );
560
+ }
561
+ rerunPending = false;
562
+ break;
563
+ }
564
+ } while (rerunPending);
565
+ } finally {
566
+ running = false;
567
+ rerunPending = false;
568
+ }
430
569
  const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
431
570
  if (hook) hook.emit("effect:create", { effectFn });
571
+ let disposed = false;
432
572
  return () => {
573
+ if (disposed) return;
574
+ disposed = true;
433
575
  const h = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
434
- if (h) h.emit("effect:destroy", { effectFn });
435
- cleanupHandle();
576
+ if (h) {
577
+ try {
578
+ h.emit("effect:destroy", { effectFn });
579
+ } catch {
580
+ }
581
+ }
582
+ try {
583
+ runUserCleanups();
584
+ } catch (err) {
585
+ if (typeof console !== "undefined") {
586
+ console.warn("[SibuJS effect] onCleanup threw during dispose:", err);
587
+ }
588
+ }
589
+ try {
590
+ cleanupHandle();
591
+ } catch (err) {
592
+ if (typeof console !== "undefined") {
593
+ console.warn("[SibuJS effect] dispose threw:", err);
594
+ }
595
+ }
436
596
  };
437
597
  }
438
598
 
@@ -810,7 +970,10 @@ function dropZone(element, options) {
810
970
  const raw = e.dataTransfer.getData("application/json");
811
971
  if (raw) {
812
972
  try {
813
- transferData = JSON.parse(raw);
973
+ transferData = JSON.parse(
974
+ raw,
975
+ (k, v) => k === "__proto__" || k === "constructor" || k === "prototype" ? void 0 : v
976
+ );
814
977
  } catch {
815
978
  transferData = raw;
816
979
  }
@@ -1190,13 +1353,21 @@ function wakeLock() {
1190
1353
  }
1191
1354
  const onVisibility = () => {
1192
1355
  if (sentinel?.released && !document.hidden) {
1193
- void request();
1356
+ request().catch((err) => {
1357
+ if (typeof console !== "undefined") {
1358
+ console.warn("[SibuJS wakeLock] re-acquire failed:", err);
1359
+ }
1360
+ });
1194
1361
  }
1195
1362
  };
1196
1363
  document.addEventListener("visibilitychange", onVisibility);
1197
1364
  function dispose() {
1198
1365
  document.removeEventListener("visibilitychange", onVisibility);
1199
- void release();
1366
+ release().catch((err) => {
1367
+ if (typeof console !== "undefined") {
1368
+ console.warn("[SibuJS wakeLock] release failed:", err);
1369
+ }
1370
+ });
1200
1371
  }
1201
1372
  return { active, request, release, dispose };
1202
1373
  }
@@ -1392,11 +1563,21 @@ function speech() {
1392
1563
  };
1393
1564
  }
1394
1565
  const synth = window.speechSynthesis;
1395
- const interval = setInterval(() => {
1396
- setSpeaking(synth.speaking);
1397
- setPaused(synth.paused);
1398
- }, 200);
1566
+ let interval = null;
1567
+ function startPolling() {
1568
+ if (interval !== null) return;
1569
+ interval = setInterval(() => {
1570
+ setSpeaking(synth.speaking);
1571
+ setPaused(synth.paused);
1572
+ if (!synth.speaking && !synth.paused) {
1573
+ clearInterval(interval);
1574
+ interval = null;
1575
+ }
1576
+ }, 200);
1577
+ }
1578
+ let disposed = false;
1399
1579
  function speak(text, options = {}) {
1580
+ if (disposed) return;
1400
1581
  const u = new SpeechSynthesisUtterance(text);
1401
1582
  if (options.lang) u.lang = options.lang;
1402
1583
  if (options.rate != null) u.rate = options.rate;
@@ -1407,19 +1588,41 @@ function speech() {
1407
1588
  const match = voices.find((v) => v.name === options.voice);
1408
1589
  if (match) u.voice = match;
1409
1590
  }
1410
- u.addEventListener("start", () => setSpeaking(true));
1411
- u.addEventListener("end", () => {
1412
- setSpeaking(false);
1413
- setPaused(false);
1414
- });
1415
- u.addEventListener("error", () => {
1416
- setSpeaking(false);
1417
- setPaused(false);
1418
- });
1591
+ u.addEventListener(
1592
+ "start",
1593
+ () => {
1594
+ if (!disposed) setSpeaking(true);
1595
+ },
1596
+ { once: true }
1597
+ );
1598
+ u.addEventListener(
1599
+ "end",
1600
+ () => {
1601
+ if (disposed) return;
1602
+ setSpeaking(false);
1603
+ setPaused(false);
1604
+ },
1605
+ { once: true }
1606
+ );
1607
+ u.addEventListener(
1608
+ "error",
1609
+ () => {
1610
+ if (disposed) return;
1611
+ setSpeaking(false);
1612
+ setPaused(false);
1613
+ },
1614
+ { once: true }
1615
+ );
1419
1616
  synth.speak(u);
1617
+ setSpeaking(true);
1618
+ startPolling();
1420
1619
  }
1421
1620
  function dispose() {
1422
- clearInterval(interval);
1621
+ disposed = true;
1622
+ if (interval !== null) {
1623
+ clearInterval(interval);
1624
+ interval = null;
1625
+ }
1423
1626
  synth.cancel();
1424
1627
  }
1425
1628
  return {
@@ -1648,13 +1851,21 @@ function imageLoader(src) {
1648
1851
  };
1649
1852
  img.src = url;
1650
1853
  }
1854
+ let srcEffectTeardown = null;
1651
1855
  if (typeof src === "function") {
1652
- start(src());
1856
+ srcEffectTeardown = effect(() => {
1857
+ const url = src();
1858
+ start(url);
1859
+ });
1653
1860
  } else {
1654
1861
  start(src);
1655
1862
  }
1656
1863
  function dispose() {
1657
1864
  disposed = true;
1865
+ if (srcEffectTeardown) {
1866
+ srcEffectTeardown();
1867
+ srcEffectTeardown = null;
1868
+ }
1658
1869
  if (current) {
1659
1870
  current.onload = null;
1660
1871
  current.onerror = null;
@@ -370,6 +370,11 @@ declare function urlState(): {
370
370
  };
371
371
 
372
372
  /**
373
+ * Note on trust model: `BroadcastChannel` only delivers messages between
374
+ * same-origin browsing contexts (tabs, iframes, workers). We therefore treat
375
+ * incoming payloads as same-origin-trusted and pass them through unmodified.
376
+ * Do not use this transport for cross-origin messaging.
377
+ *
373
378
  * broadcast wraps the BroadcastChannel API as a reactive signal.
374
379
  * Unlike the `storage` event (which only fires for localStorage writes and
375
380
  * sends only the serialized value), a `BroadcastChannel` can send arbitrary
package/dist/browser.d.ts CHANGED
@@ -370,6 +370,11 @@ declare function urlState(): {
370
370
  };
371
371
 
372
372
  /**
373
+ * Note on trust model: `BroadcastChannel` only delivers messages between
374
+ * same-origin browsing contexts (tabs, iframes, workers). We therefore treat
375
+ * incoming payloads as same-origin-trusted and pass them through unmodified.
376
+ * Do not use this transport for cross-origin messaging.
377
+ *
373
378
  * broadcast wraps the BroadcastChannel API as a reactive signal.
374
379
  * Unlike the `storage` event (which only fires for localStorage writes and
375
380
  * sends only the serialized value), a `BroadcastChannel` can send arbitrary
package/dist/browser.js CHANGED
@@ -35,12 +35,12 @@ import {
35
35
  visibility,
36
36
  wakeLock,
37
37
  windowSize
38
- } from "./chunk-RJ46C3CS.js";
39
- import "./chunk-VQNQZCWJ.js";
40
- import "./chunk-EUZND3CB.js";
41
- import "./chunk-NZIIMDWI.js";
42
- import "./chunk-K4G4ZQNR.js";
43
- import "./chunk-5X6PP2UK.js";
38
+ } from "./chunk-GWWURC5M.js";
39
+ import "./chunk-WZA53FXU.js";
40
+ import "./chunk-2RA7SHDA.js";
41
+ import "./chunk-RDTDJCAB.js";
42
+ import "./chunk-QO3WC6FS.js";
43
+ import "./chunk-LMLD24FC.js";
44
44
  export {
45
45
  animationFrame,
46
46
  battery,