sibujs 2.0.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 (60) hide show
  1. package/dist/browser.cjs +144 -102
  2. package/dist/browser.js +4 -4
  3. package/dist/build.cjs +183 -102
  4. package/dist/build.js +10 -10
  5. package/dist/cdn.global.js +7 -7
  6. package/dist/{chunk-MIUAXB7K.js → chunk-3DZP6OIT.js} +2 -2
  7. package/dist/{chunk-ITX6OO3F.js → chunk-45YP72ZQ.js} +1 -1
  8. package/dist/{chunk-ND2664SF.js → chunk-AMK2TYNW.js} +13 -9
  9. package/dist/{chunk-R73P76YZ.js → chunk-CWBVQML6.js} +1 -1
  10. package/dist/{chunk-54EDRCEF.js → chunk-DRUZZAK4.js} +1 -1
  11. package/dist/{chunk-3NSGB5JN.js → chunk-GWWURC5M.js} +2 -2
  12. package/dist/{chunk-SAHNHTFC.js → chunk-KGYT6UO6.js} +3 -3
  13. package/dist/{chunk-52YJLLRO.js → chunk-NASX6ST2.js} +1 -1
  14. package/dist/{chunk-O2MNQFLP.js → chunk-O6EFQ3KT.js} +5 -5
  15. package/dist/{chunk-GTBNNBJ6.js → chunk-OJ3P4ECI.js} +1 -1
  16. package/dist/{chunk-7JDB7I65.js → chunk-ON5MMR2J.js} +4 -4
  17. package/dist/{chunk-KLRMB5ZS.js → chunk-P2HSJDDN.js} +2 -2
  18. package/dist/{chunk-VLPPXTYG.js → chunk-QO3WC6FS.js} +145 -93
  19. package/dist/{chunk-CC65Y57T.js → chunk-RDTDJCAB.js} +1 -1
  20. package/dist/{chunk-JXMMDLBY.js → chunk-TH2ILCYW.js} +8 -4
  21. package/dist/{chunk-3LR7GLWQ.js → chunk-V6C4FADE.js} +3 -3
  22. package/dist/{chunk-WOMYAHHI.js → chunk-WANSMF2L.js} +4 -4
  23. package/dist/{chunk-DFPFITST.js → chunk-WIPZPFBQ.js} +1 -1
  24. package/dist/{chunk-HB24TBAF.js → chunk-WZA53FXU.js} +38 -10
  25. package/dist/{chunk-JA6667UN.js → chunk-ZAQSMOED.js} +4 -4
  26. package/dist/data.cjs +176 -102
  27. package/dist/data.js +6 -6
  28. package/dist/devtools.cjs +148 -91
  29. package/dist/devtools.d.cts +1 -1
  30. package/dist/devtools.d.ts +1 -1
  31. package/dist/devtools.js +4 -4
  32. package/dist/ecosystem.cjs +176 -102
  33. package/dist/ecosystem.js +7 -7
  34. package/dist/extras.cjs +182 -104
  35. package/dist/extras.d.cts +1 -1
  36. package/dist/extras.d.ts +1 -1
  37. package/dist/extras.js +19 -19
  38. package/dist/index.cjs +185 -102
  39. package/dist/index.d.cts +15 -1
  40. package/dist/index.d.ts +15 -1
  41. package/dist/index.js +14 -10
  42. package/dist/{introspect-BWNjNw64.d.cts → introspect-2TOlQ7oa.d.cts} +3 -1
  43. package/dist/{introspect-cY2pg9pW.d.ts → introspect-DnIpHQQz.d.ts} +3 -1
  44. package/dist/motion.cjs +78 -62
  45. package/dist/motion.js +3 -3
  46. package/dist/patterns.cjs +176 -102
  47. package/dist/patterns.js +5 -5
  48. package/dist/performance.cjs +142 -89
  49. package/dist/performance.js +4 -4
  50. package/dist/plugins.cjs +142 -89
  51. package/dist/plugins.js +6 -6
  52. package/dist/ssr.cjs +144 -102
  53. package/dist/ssr.js +7 -7
  54. package/dist/testing.cjs +66 -28
  55. package/dist/testing.js +2 -2
  56. package/dist/ui.cjs +174 -89
  57. package/dist/ui.js +6 -6
  58. package/dist/widgets.cjs +176 -102
  59. package/dist/widgets.js +6 -6
  60. package/package.json +1 -1
package/dist/browser.cjs CHANGED
@@ -77,11 +77,24 @@ function devWarn(message) {
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
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
+ }
85
98
  var notifyDepth = 0;
86
99
  var pendingQueue = [];
87
100
  var pendingSet = /* @__PURE__ */ new Set();
@@ -108,36 +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
- signal2[SUBS] = subs;
157
+ sig[SUBS] = subs;
135
158
  }
159
+ const prevSize = subs.size;
136
160
  subs.add(currentSubscriber);
137
- if (subs.size === 1) {
138
- signal2.__f = currentSubscriber;
139
- } else if (signal2.__f !== void 0) {
140
- 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
+ }
141
167
  }
142
168
  }
143
169
  function queueSignalNotification(signal2) {
@@ -152,24 +178,55 @@ function queueSignalNotification(signal2) {
152
178
  }
153
179
  }
154
180
  }
155
- var maxDrainIterations = 1e5;
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
+ }
156
224
  function drainNotificationQueue() {
157
225
  if (notifyDepth > 0) return;
158
226
  notifyDepth++;
227
+ drainEpoch++;
159
228
  try {
160
- let i = 0;
161
- while (i < pendingQueue.length) {
162
- if (i >= maxDrainIterations) {
163
- if (typeof console !== "undefined") {
164
- console.error(
165
- `[SibuJS] Notification queue exceeded ${maxDrainIterations} iterations \u2014 likely an effect that writes to a signal it reads. Breaking to prevent infinite loop.`
166
- );
167
- }
168
- break;
169
- }
170
- safeInvoke(pendingQueue[i]);
171
- i++;
172
- }
229
+ drainQueue();
173
230
  } finally {
174
231
  notifyDepth--;
175
232
  if (notifyDepth === 0) {
@@ -232,25 +289,16 @@ function notifySubscribers(signal2) {
232
289
  return;
233
290
  }
234
291
  notifyDepth++;
292
+ drainEpoch++;
235
293
  try {
236
294
  if (first._c) {
237
295
  propagateDirty(first);
296
+ } else if (tickRepeat(first)) {
297
+ cycleError(first);
238
298
  } else {
239
299
  safeInvoke(first);
240
300
  }
241
- let i = 0;
242
- while (i < pendingQueue.length) {
243
- if (i >= maxDrainIterations) {
244
- if (typeof console !== "undefined") {
245
- console.error(
246
- `[SibuJS] Notification queue exceeded ${maxDrainIterations} iterations \u2014 likely an effect that writes to a signal it reads. Breaking to prevent infinite loop.`
247
- );
248
- }
249
- break;
250
- }
251
- safeInvoke(pendingQueue[i]);
252
- i++;
253
- }
301
+ drainQueue();
254
302
  } finally {
255
303
  notifyDepth--;
256
304
  if (notifyDepth === 0) {
@@ -274,44 +322,17 @@ function notifySubscribers(signal2) {
274
322
  return;
275
323
  }
276
324
  notifyDepth++;
325
+ drainEpoch++;
277
326
  try {
278
- let directCount = 0;
279
- let hasComputedSub = false;
280
327
  for (const sub of subs) {
281
- if (sub._c) hasComputedSub = true;
282
- pendingQueue[directCount++] = sub;
283
- }
284
- if (!hasComputedSub) {
285
- for (let i2 = 0; i2 < directCount; i2++) {
286
- safeInvoke(pendingQueue[i2]);
287
- }
288
- } else {
289
- for (let i2 = 0; i2 < directCount; i2++) {
290
- if (pendingQueue[i2]._c) {
291
- propagateDirty(pendingQueue[i2]);
292
- }
293
- }
294
- for (let i2 = 0; i2 < directCount; i2++) {
295
- const sub = pendingQueue[i2];
296
- if (!sub._c && !pendingSet.has(sub)) {
297
- pendingSet.add(sub);
298
- safeInvoke(sub);
299
- }
300
- }
301
- }
302
- let i = directCount;
303
- while (i < pendingQueue.length) {
304
- if (i - directCount >= maxDrainIterations) {
305
- if (typeof console !== "undefined") {
306
- console.error(
307
- `[SibuJS] Notification queue exceeded ${maxDrainIterations} iterations \u2014 likely an effect that writes to a signal it reads. Breaking to prevent infinite loop.`
308
- );
309
- }
310
- break;
328
+ if (sub._c) {
329
+ propagateDirty(sub);
330
+ } else if (!pendingSet.has(sub)) {
331
+ pendingSet.add(sub);
332
+ pendingQueue.push(sub);
311
333
  }
312
- safeInvoke(pendingQueue[i]);
313
- i++;
314
334
  }
335
+ drainQueue();
315
336
  } finally {
316
337
  notifyDepth--;
317
338
  if (notifyDepth === 0) {
@@ -324,29 +345,22 @@ function cleanup(subscriber) {
324
345
  const sub = subscriber;
325
346
  const singleDep = sub._dep;
326
347
  if (singleDep !== void 0) {
327
- const subs = singleDep[SUBS];
328
- if (subs) {
329
- subs.delete(subscriber);
330
- if (singleDep.__f === subscriber) {
331
- singleDep.__f = subs.size === 1 ? subs.values().next().value : void 0;
332
- } else if (subs.size === 1 && singleDep.__f === void 0) {
333
- singleDep.__f = subs.values().next().value;
334
- }
348
+ const sig = singleDep;
349
+ const subs = sig[SUBS];
350
+ if (subs?.delete(subscriber)) {
351
+ syncFastPath(sig, subs);
335
352
  }
336
353
  sub._dep = void 0;
354
+ sub._depEpoch = void 0;
337
355
  return;
338
356
  }
339
357
  const deps = sub._deps;
340
358
  if (!deps || deps.size === 0) return;
341
- for (const signal2 of deps) {
342
- const subs = signal2[SUBS];
343
- if (subs) {
344
- subs.delete(subscriber);
345
- if (signal2.__f === subscriber) {
346
- signal2.__f = subs.size === 1 ? subs.values().next().value : void 0;
347
- } else if (subs.size === 1 && signal2.__f === void 0) {
348
- signal2.__f = subs.values().next().value;
349
- }
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);
350
364
  }
351
365
  }
352
366
  deps.clear();
@@ -500,29 +514,57 @@ function effect(effectFn, options) {
500
514
  let cleanupHandle = () => {
501
515
  };
502
516
  let running = false;
517
+ let rerunPending = false;
518
+ const MAX_RERUNS = 100;
503
519
  const subscriber = () => {
504
520
  if (running) {
505
- if (_g2.__SIBU_DEV_WARN__ !== false && typeof console !== "undefined") {
506
- console.warn(
507
- "[SibuJS] effect re-entered itself while running \u2014 the triggering update will be ignored. Wrap mutual writes in `batch()` or split the effect to avoid this."
508
- );
509
- }
521
+ rerunPending = true;
510
522
  return;
511
523
  }
512
524
  running = true;
513
525
  try {
514
- runUserCleanups();
515
- cleanupHandle();
516
- cleanupHandle = track(wrappedFn, subscriber);
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);
517
542
  } finally {
518
543
  running = false;
544
+ rerunPending = false;
519
545
  }
520
546
  };
521
547
  running = true;
522
548
  try {
523
- cleanupHandle = track(wrappedFn, subscriber);
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);
524
565
  } finally {
525
566
  running = false;
567
+ rerunPending = false;
526
568
  }
527
569
  const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
528
570
  if (hook) hook.emit("effect:create", { effectFn });
package/dist/browser.js CHANGED
@@ -35,11 +35,11 @@ import {
35
35
  visibility,
36
36
  wakeLock,
37
37
  windowSize
38
- } from "./chunk-3NSGB5JN.js";
39
- import "./chunk-HB24TBAF.js";
38
+ } from "./chunk-GWWURC5M.js";
39
+ import "./chunk-WZA53FXU.js";
40
40
  import "./chunk-2RA7SHDA.js";
41
- import "./chunk-CC65Y57T.js";
42
- import "./chunk-VLPPXTYG.js";
41
+ import "./chunk-RDTDJCAB.js";
42
+ import "./chunk-QO3WC6FS.js";
43
43
  import "./chunk-LMLD24FC.js";
44
44
  export {
45
45
  animationFrame,