sibujs 2.0.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.cjs +369 -276
- package/dist/browser.js +4 -4
- package/dist/build.cjs +411 -300
- package/dist/build.js +10 -10
- package/dist/cdn.global.js +8 -8
- package/dist/{chunk-JA6667UN.js → chunk-2JQUV4Y3.js} +4 -4
- package/dist/{chunk-3NSGB5JN.js → chunk-2KM2724A.js} +2 -2
- package/dist/{chunk-52YJLLRO.js → chunk-4YTVESDX.js} +1 -1
- package/dist/chunk-5WD7BYTZ.js +152 -0
- package/dist/{chunk-CC65Y57T.js → chunk-6QZO7MMG.js} +48 -16
- package/dist/{chunk-54EDRCEF.js → chunk-DF3GTP4Q.js} +7 -2
- package/dist/{chunk-ND2664SF.js → chunk-J63GPPCJ.js} +13 -9
- package/dist/{chunk-O2MNQFLP.js → chunk-KH4OE6WY.js} +5 -5
- package/dist/{chunk-3LR7GLWQ.js → chunk-KZA7ANXP.js} +3 -3
- package/dist/chunk-L4DAT4WU.js +400 -0
- package/dist/{chunk-WOMYAHHI.js → chunk-L52H775O.js} +4 -4
- package/dist/{chunk-ITX6OO3F.js → chunk-NEWH4O5U.js} +1 -1
- package/dist/{chunk-7JDB7I65.js → chunk-RJIRT46U.js} +4 -4
- package/dist/{chunk-KLRMB5ZS.js → chunk-STFTTMO2.js} +2 -2
- package/dist/{chunk-DFPFITST.js → chunk-UKMXT5T6.js} +1 -1
- package/dist/{chunk-SAHNHTFC.js → chunk-V65KTDZW.js} +3 -3
- package/dist/{chunk-R73P76YZ.js → chunk-VSNLICTS.js} +1 -1
- package/dist/{chunk-MIUAXB7K.js → chunk-XDKP4T7G.js} +2 -2
- package/dist/{chunk-JXMMDLBY.js → chunk-XVYB3J6C.js} +27 -29
- package/dist/{chunk-GTBNNBJ6.js → chunk-YMOIAHWA.js} +1 -1
- package/dist/data.cjs +382 -274
- package/dist/data.js +6 -6
- package/dist/devtools.cjs +398 -284
- package/dist/devtools.d.cts +1 -1
- package/dist/devtools.d.ts +1 -1
- package/dist/devtools.js +4 -4
- package/dist/ecosystem.cjs +382 -274
- package/dist/ecosystem.js +7 -7
- package/dist/extras.cjs +421 -299
- package/dist/extras.d.cts +1 -1
- package/dist/extras.d.ts +1 -1
- package/dist/extras.js +19 -19
- package/dist/index.cjs +413 -300
- package/dist/index.d.cts +16 -11
- package/dist/index.d.ts +16 -11
- package/dist/index.js +14 -10
- package/dist/{introspect-cY2pg9pW.d.ts → introspect-BZWKvQUZ.d.ts} +2 -1
- package/dist/{introspect-BWNjNw64.d.cts → introspect-DsJlDD2T.d.cts} +2 -1
- package/dist/motion.cjs +189 -149
- package/dist/motion.js +3 -3
- package/dist/patterns.cjs +382 -274
- package/dist/patterns.js +5 -5
- package/dist/performance.cjs +360 -260
- package/dist/performance.js +4 -4
- package/dist/plugins.cjs +376 -257
- package/dist/plugins.js +6 -6
- package/dist/ssr.cjs +383 -271
- package/dist/ssr.js +7 -7
- package/dist/testing.cjs +168 -109
- package/dist/testing.js +2 -2
- package/dist/ui.cjs +373 -258
- package/dist/ui.js +6 -6
- package/dist/widgets.cjs +382 -274
- package/dist/widgets.js +6 -6
- package/package.json +1 -1
- package/dist/chunk-HB24TBAF.js +0 -121
- package/dist/chunk-VLPPXTYG.js +0 -332
package/dist/ui.cjs
CHANGED
|
@@ -103,11 +103,88 @@ function devWarn(message) {
|
|
|
103
103
|
|
|
104
104
|
// src/reactivity/track.ts
|
|
105
105
|
var _isDev2 = isDev();
|
|
106
|
-
var
|
|
107
|
-
var
|
|
108
|
-
|
|
106
|
+
var POOL_MAX = 4096;
|
|
107
|
+
var nodePool = [];
|
|
108
|
+
function createNode() {
|
|
109
|
+
return {
|
|
110
|
+
sig: null,
|
|
111
|
+
sub: null,
|
|
112
|
+
epoch: 0,
|
|
113
|
+
sigPrev: null,
|
|
114
|
+
sigNext: null,
|
|
115
|
+
subPrev: null,
|
|
116
|
+
subNext: null,
|
|
117
|
+
prevActive: null
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function allocNode(sig, sub, epoch) {
|
|
121
|
+
const n = nodePool.pop();
|
|
122
|
+
if (n) {
|
|
123
|
+
n.sig = sig;
|
|
124
|
+
n.sub = sub;
|
|
125
|
+
n.epoch = epoch;
|
|
126
|
+
return n;
|
|
127
|
+
}
|
|
128
|
+
const fresh = createNode();
|
|
129
|
+
fresh.sig = sig;
|
|
130
|
+
fresh.sub = sub;
|
|
131
|
+
fresh.epoch = epoch;
|
|
132
|
+
return fresh;
|
|
133
|
+
}
|
|
134
|
+
function freeNode(node) {
|
|
135
|
+
node.sig = null;
|
|
136
|
+
node.sub = null;
|
|
137
|
+
node.sigPrev = null;
|
|
138
|
+
node.sigNext = null;
|
|
139
|
+
node.subPrev = null;
|
|
140
|
+
node.subNext = null;
|
|
141
|
+
node.prevActive = null;
|
|
142
|
+
if (nodePool.length < POOL_MAX) nodePool.push(node);
|
|
143
|
+
}
|
|
144
|
+
function linkSignal(sig, node) {
|
|
145
|
+
const oldHead = sig.subsHead ?? null;
|
|
146
|
+
node.sigPrev = null;
|
|
147
|
+
node.sigNext = oldHead;
|
|
148
|
+
if (oldHead) oldHead.sigPrev = node;
|
|
149
|
+
else sig.subsTail = node;
|
|
150
|
+
sig.subsHead = node;
|
|
151
|
+
sig.__sc = (sig.__sc ?? 0) + 1;
|
|
152
|
+
}
|
|
153
|
+
function unlinkSignal(node) {
|
|
154
|
+
const sig = node.sig;
|
|
155
|
+
if (!sig) return;
|
|
156
|
+
const prev = node.sigPrev;
|
|
157
|
+
const next = node.sigNext;
|
|
158
|
+
if (prev) prev.sigNext = next;
|
|
159
|
+
else sig.subsHead = next;
|
|
160
|
+
if (next) next.sigPrev = prev;
|
|
161
|
+
else sig.subsTail = prev;
|
|
162
|
+
sig.__sc = (sig.__sc ?? 1) - 1;
|
|
163
|
+
if (sig.__activeNode === node) sig.__activeNode = node.prevActive;
|
|
164
|
+
if (sig.__sc === 0) {
|
|
165
|
+
sig.subsHead = null;
|
|
166
|
+
sig.subsTail = null;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
function linkSub(sub, node) {
|
|
170
|
+
const oldTail = sub.depsTail ?? null;
|
|
171
|
+
node.subPrev = oldTail;
|
|
172
|
+
node.subNext = null;
|
|
173
|
+
if (oldTail) oldTail.subNext = node;
|
|
174
|
+
else sub.depsHead = node;
|
|
175
|
+
sub.depsTail = node;
|
|
176
|
+
}
|
|
177
|
+
function unlinkSub(node) {
|
|
178
|
+
const sub = node.sub;
|
|
179
|
+
if (!sub) return;
|
|
180
|
+
const prev = node.subPrev;
|
|
181
|
+
const next = node.subNext;
|
|
182
|
+
if (prev) prev.subNext = next;
|
|
183
|
+
else sub.depsHead = next;
|
|
184
|
+
if (next) next.subPrev = prev;
|
|
185
|
+
else sub.depsTail = prev;
|
|
186
|
+
}
|
|
109
187
|
var currentSubscriber = null;
|
|
110
|
-
var SUBS = "__s";
|
|
111
188
|
var notifyDepth = 0;
|
|
112
189
|
var pendingQueue = [];
|
|
113
190
|
var pendingSet = /* @__PURE__ */ new Set();
|
|
@@ -120,63 +197,130 @@ function safeInvoke(sub) {
|
|
|
120
197
|
}
|
|
121
198
|
}
|
|
122
199
|
var trackingSuspended = false;
|
|
200
|
+
var subscriberEpochCounter = 0;
|
|
123
201
|
function retrack(effectFn, subscriber) {
|
|
124
202
|
const prev = currentSubscriber;
|
|
125
203
|
currentSubscriber = subscriber;
|
|
204
|
+
const sub = subscriber;
|
|
205
|
+
const epoch = ++subscriberEpochCounter;
|
|
206
|
+
sub._epoch = epoch;
|
|
207
|
+
sub._structDirty = false;
|
|
208
|
+
for (let n = sub.depsHead ?? null; n !== null; n = n.subNext) {
|
|
209
|
+
const sig = n.sig;
|
|
210
|
+
n.prevActive = sig.__activeNode ?? null;
|
|
211
|
+
sig.__activeNode = n;
|
|
212
|
+
}
|
|
126
213
|
try {
|
|
127
214
|
effectFn();
|
|
128
215
|
} finally {
|
|
129
216
|
currentSubscriber = prev;
|
|
217
|
+
let node = sub.depsHead ?? null;
|
|
218
|
+
while (node !== null) {
|
|
219
|
+
const next = node.subNext;
|
|
220
|
+
const sig = node.sig;
|
|
221
|
+
sig.__activeNode = node.prevActive;
|
|
222
|
+
node.prevActive = null;
|
|
223
|
+
if (node.epoch !== epoch) {
|
|
224
|
+
unlinkSub(node);
|
|
225
|
+
unlinkSignal(node);
|
|
226
|
+
freeNode(node);
|
|
227
|
+
}
|
|
228
|
+
node = next;
|
|
229
|
+
}
|
|
130
230
|
}
|
|
131
231
|
}
|
|
132
232
|
function track(effectFn, subscriber) {
|
|
133
233
|
if (!subscriber) subscriber = effectFn;
|
|
134
234
|
cleanup(subscriber);
|
|
135
|
-
|
|
136
|
-
if (stackTop >= stackCapacity) {
|
|
137
|
-
stackCapacity *= 2;
|
|
138
|
-
subscriberStack.length = stackCapacity;
|
|
139
|
-
}
|
|
140
|
-
subscriberStack[stackTop] = subscriber;
|
|
235
|
+
const prev = currentSubscriber;
|
|
141
236
|
currentSubscriber = subscriber;
|
|
142
237
|
try {
|
|
143
238
|
effectFn();
|
|
144
239
|
} finally {
|
|
145
|
-
|
|
146
|
-
|
|
240
|
+
currentSubscriber = prev;
|
|
241
|
+
const sub2 = subscriber;
|
|
242
|
+
for (let n = sub2.depsHead ?? null; n !== null; n = n.subNext) {
|
|
243
|
+
const sig = n.sig;
|
|
244
|
+
sig.__activeNode = n.prevActive;
|
|
245
|
+
n.prevActive = null;
|
|
246
|
+
}
|
|
147
247
|
}
|
|
148
|
-
|
|
248
|
+
const sub = subscriber;
|
|
249
|
+
return sub._dispose ?? (sub._dispose = () => cleanup(subscriber));
|
|
149
250
|
}
|
|
150
251
|
function recordDependency(signal2) {
|
|
151
252
|
if (!currentSubscriber) return;
|
|
152
253
|
const sub = currentSubscriber;
|
|
153
|
-
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const set = /* @__PURE__ */ new Set();
|
|
160
|
-
set.add(sub._dep);
|
|
161
|
-
set.add(signal2);
|
|
162
|
-
sub._deps = set;
|
|
163
|
-
sub._dep = void 0;
|
|
164
|
-
} else {
|
|
165
|
-
sub._dep = signal2;
|
|
254
|
+
const sig = signal2;
|
|
255
|
+
const epoch = sub._epoch ?? 0;
|
|
256
|
+
const active = sig.__activeNode ?? null;
|
|
257
|
+
if (active !== null && active.sub === sub) {
|
|
258
|
+
active.epoch = epoch;
|
|
259
|
+
return;
|
|
166
260
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
261
|
+
const node = allocNode(signal2, sub, epoch);
|
|
262
|
+
node.prevActive = active;
|
|
263
|
+
sig.__activeNode = node;
|
|
264
|
+
linkSub(sub, node);
|
|
265
|
+
linkSignal(sig, node);
|
|
266
|
+
sub._structDirty = true;
|
|
267
|
+
}
|
|
268
|
+
function cleanup(subscriber) {
|
|
269
|
+
const sub = subscriber;
|
|
270
|
+
let node = sub.depsHead ?? null;
|
|
271
|
+
sub.depsHead = null;
|
|
272
|
+
sub.depsTail = null;
|
|
273
|
+
while (node) {
|
|
274
|
+
const next = node.subNext;
|
|
275
|
+
unlinkSignal(node);
|
|
276
|
+
freeNode(node);
|
|
277
|
+
node = next;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
var maxSubscriberRepeats = 50;
|
|
281
|
+
var maxDrainIterations = 1e6;
|
|
282
|
+
var drainEpoch = 0;
|
|
283
|
+
function tickRepeat(sub) {
|
|
284
|
+
const s = sub;
|
|
285
|
+
if (s._runEpoch !== drainEpoch) {
|
|
286
|
+
s._runEpoch = drainEpoch;
|
|
287
|
+
s._runs = 1;
|
|
288
|
+
return false;
|
|
289
|
+
}
|
|
290
|
+
s._runs = (s._runs ?? 0) + 1;
|
|
291
|
+
return s._runs > maxSubscriberRepeats;
|
|
292
|
+
}
|
|
293
|
+
function cycleError(sub) {
|
|
294
|
+
if (typeof console !== "undefined") {
|
|
295
|
+
const name = sub.__name ?? "<unnamed>";
|
|
296
|
+
console.error(
|
|
297
|
+
`[SibuJS] subscriber "${name}" fired more than ${maxSubscriberRepeats} times \u2014 likely a write-reads-self cycle between effects/signals. Breaking to prevent infinite loop.`
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
function absoluteDrainError() {
|
|
302
|
+
if (typeof console !== "undefined") {
|
|
303
|
+
console.error(
|
|
304
|
+
`[SibuJS] Notification drain exceeded ${maxDrainIterations} iterations \u2014 absolute safety net tripped. Breaking to prevent infinite loop.`
|
|
305
|
+
);
|
|
171
306
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
307
|
+
}
|
|
308
|
+
function drainQueue() {
|
|
309
|
+
let i = 0;
|
|
310
|
+
while (i < pendingQueue.length) {
|
|
311
|
+
if (i >= maxDrainIterations) {
|
|
312
|
+
absoluteDrainError();
|
|
313
|
+
break;
|
|
314
|
+
}
|
|
315
|
+
const sub = pendingQueue[i++];
|
|
316
|
+
if (tickRepeat(sub)) {
|
|
317
|
+
cycleError(sub);
|
|
318
|
+
break;
|
|
319
|
+
}
|
|
320
|
+
pendingSet.delete(sub);
|
|
321
|
+
safeInvoke(sub);
|
|
177
322
|
}
|
|
178
323
|
}
|
|
179
|
-
var maxDrainIterations = 1e5;
|
|
180
324
|
function propagateDirty(sub) {
|
|
181
325
|
sub();
|
|
182
326
|
const rootSig = sub._sig;
|
|
@@ -186,131 +330,66 @@ function propagateDirty(sub) {
|
|
|
186
330
|
stack.push(rootSig);
|
|
187
331
|
while (stack.length > baseLen) {
|
|
188
332
|
const sig = stack.pop();
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
if (
|
|
194
|
-
nSig
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
if (s._c) {
|
|
207
|
-
const nSig = s._sig;
|
|
208
|
-
if (nSig && !nSig._d) {
|
|
209
|
-
nSig._d = true;
|
|
210
|
-
stack.push(nSig);
|
|
211
|
-
} else if (!nSig) {
|
|
212
|
-
s();
|
|
333
|
+
let node = sig.subsHead ?? null;
|
|
334
|
+
while (node) {
|
|
335
|
+
const s = node.sub;
|
|
336
|
+
if (s) {
|
|
337
|
+
if (s._c) {
|
|
338
|
+
const nSig = s._sig;
|
|
339
|
+
if (nSig) {
|
|
340
|
+
if (!nSig._d) {
|
|
341
|
+
nSig._d = true;
|
|
342
|
+
stack.push(nSig);
|
|
343
|
+
}
|
|
344
|
+
} else {
|
|
345
|
+
s();
|
|
346
|
+
}
|
|
347
|
+
} else if (!pendingSet.has(s)) {
|
|
348
|
+
pendingSet.add(s);
|
|
349
|
+
pendingQueue.push(s);
|
|
213
350
|
}
|
|
214
|
-
} else if (!pendingSet.has(s)) {
|
|
215
|
-
pendingSet.add(s);
|
|
216
|
-
pendingQueue.push(s);
|
|
217
351
|
}
|
|
352
|
+
node = node.sigNext;
|
|
218
353
|
}
|
|
219
354
|
}
|
|
220
355
|
}
|
|
221
356
|
function notifySubscribers(signal2) {
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
if (first._c) {
|
|
226
|
-
propagateDirty(first);
|
|
227
|
-
} else if (!pendingSet.has(first)) {
|
|
228
|
-
pendingSet.add(first);
|
|
229
|
-
pendingQueue.push(first);
|
|
230
|
-
}
|
|
231
|
-
return;
|
|
232
|
-
}
|
|
233
|
-
notifyDepth++;
|
|
234
|
-
try {
|
|
235
|
-
if (first._c) {
|
|
236
|
-
propagateDirty(first);
|
|
237
|
-
} else {
|
|
238
|
-
safeInvoke(first);
|
|
239
|
-
}
|
|
240
|
-
let i = 0;
|
|
241
|
-
while (i < pendingQueue.length) {
|
|
242
|
-
if (i >= maxDrainIterations) {
|
|
243
|
-
if (typeof console !== "undefined") {
|
|
244
|
-
console.error(
|
|
245
|
-
`[SibuJS] Notification queue exceeded ${maxDrainIterations} iterations \u2014 likely an effect that writes to a signal it reads. Breaking to prevent infinite loop.`
|
|
246
|
-
);
|
|
247
|
-
}
|
|
248
|
-
break;
|
|
249
|
-
}
|
|
250
|
-
safeInvoke(pendingQueue[i]);
|
|
251
|
-
i++;
|
|
252
|
-
}
|
|
253
|
-
} finally {
|
|
254
|
-
notifyDepth--;
|
|
255
|
-
if (notifyDepth === 0) {
|
|
256
|
-
pendingQueue.length = 0;
|
|
257
|
-
pendingSet.clear();
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
return;
|
|
261
|
-
}
|
|
262
|
-
const subs = signal2[SUBS];
|
|
263
|
-
if (!subs || subs.size === 0) return;
|
|
357
|
+
const sig = signal2;
|
|
358
|
+
const head = sig.subsHead;
|
|
359
|
+
if (!head) return;
|
|
264
360
|
if (notifyDepth > 0) {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
361
|
+
let node = head;
|
|
362
|
+
while (node) {
|
|
363
|
+
const s = node.sub;
|
|
364
|
+
if (s) {
|
|
365
|
+
if (s._c) {
|
|
366
|
+
propagateDirty(s);
|
|
367
|
+
} else if (!pendingSet.has(s)) {
|
|
368
|
+
pendingSet.add(s);
|
|
369
|
+
pendingQueue.push(s);
|
|
370
|
+
}
|
|
271
371
|
}
|
|
372
|
+
node = node.sigNext;
|
|
272
373
|
}
|
|
273
374
|
return;
|
|
274
375
|
}
|
|
275
376
|
notifyDepth++;
|
|
377
|
+
drainEpoch++;
|
|
276
378
|
try {
|
|
277
|
-
let
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
if (
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
}
|
|
287
|
-
} else {
|
|
288
|
-
for (let i2 = 0; i2 < directCount; i2++) {
|
|
289
|
-
if (pendingQueue[i2]._c) {
|
|
290
|
-
propagateDirty(pendingQueue[i2]);
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
for (let i2 = 0; i2 < directCount; i2++) {
|
|
294
|
-
const sub = pendingQueue[i2];
|
|
295
|
-
if (!sub._c && !pendingSet.has(sub)) {
|
|
296
|
-
pendingSet.add(sub);
|
|
297
|
-
safeInvoke(sub);
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
let i = directCount;
|
|
302
|
-
while (i < pendingQueue.length) {
|
|
303
|
-
if (i - directCount >= maxDrainIterations) {
|
|
304
|
-
if (typeof console !== "undefined") {
|
|
305
|
-
console.error(
|
|
306
|
-
`[SibuJS] Notification queue exceeded ${maxDrainIterations} iterations \u2014 likely an effect that writes to a signal it reads. Breaking to prevent infinite loop.`
|
|
307
|
-
);
|
|
379
|
+
let node = head;
|
|
380
|
+
while (node) {
|
|
381
|
+
const s = node.sub;
|
|
382
|
+
if (s) {
|
|
383
|
+
if (s._c) {
|
|
384
|
+
propagateDirty(s);
|
|
385
|
+
} else if (!pendingSet.has(s)) {
|
|
386
|
+
pendingSet.add(s);
|
|
387
|
+
pendingQueue.push(s);
|
|
308
388
|
}
|
|
309
|
-
break;
|
|
310
389
|
}
|
|
311
|
-
|
|
312
|
-
i++;
|
|
390
|
+
node = node.sigNext;
|
|
313
391
|
}
|
|
392
|
+
drainQueue();
|
|
314
393
|
} finally {
|
|
315
394
|
notifyDepth--;
|
|
316
395
|
if (notifyDepth === 0) {
|
|
@@ -319,37 +398,6 @@ function notifySubscribers(signal2) {
|
|
|
319
398
|
}
|
|
320
399
|
}
|
|
321
400
|
}
|
|
322
|
-
function cleanup(subscriber) {
|
|
323
|
-
const sub = subscriber;
|
|
324
|
-
const singleDep = sub._dep;
|
|
325
|
-
if (singleDep !== void 0) {
|
|
326
|
-
const subs = singleDep[SUBS];
|
|
327
|
-
if (subs) {
|
|
328
|
-
subs.delete(subscriber);
|
|
329
|
-
if (singleDep.__f === subscriber) {
|
|
330
|
-
singleDep.__f = subs.size === 1 ? subs.values().next().value : void 0;
|
|
331
|
-
} else if (subs.size === 1 && singleDep.__f === void 0) {
|
|
332
|
-
singleDep.__f = subs.values().next().value;
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
sub._dep = void 0;
|
|
336
|
-
return;
|
|
337
|
-
}
|
|
338
|
-
const deps = sub._deps;
|
|
339
|
-
if (!deps || deps.size === 0) return;
|
|
340
|
-
for (const signal2 of deps) {
|
|
341
|
-
const subs = signal2[SUBS];
|
|
342
|
-
if (subs) {
|
|
343
|
-
subs.delete(subscriber);
|
|
344
|
-
if (signal2.__f === subscriber) {
|
|
345
|
-
signal2.__f = subs.size === 1 ? subs.values().next().value : void 0;
|
|
346
|
-
} else if (subs.size === 1 && signal2.__f === void 0) {
|
|
347
|
-
signal2.__f = subs.values().next().value;
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
deps.clear();
|
|
352
|
-
}
|
|
353
401
|
|
|
354
402
|
// src/core/signals/derived.ts
|
|
355
403
|
function derived(getter, options) {
|
|
@@ -359,6 +407,7 @@ function derived(getter, options) {
|
|
|
359
407
|
const cs = {};
|
|
360
408
|
cs._d = false;
|
|
361
409
|
cs._g = getter;
|
|
410
|
+
cs.__v = 0;
|
|
362
411
|
const markDirty = () => {
|
|
363
412
|
if (cs._d) return;
|
|
364
413
|
cs._d = true;
|
|
@@ -388,11 +437,14 @@ function derived(getter, options) {
|
|
|
388
437
|
evaluating = true;
|
|
389
438
|
let threw = true;
|
|
390
439
|
try {
|
|
440
|
+
const prev = cs._v;
|
|
391
441
|
retrack(() => {
|
|
392
|
-
|
|
442
|
+
const next = getter();
|
|
443
|
+
cs._v = equals && cs._v !== void 0 ? equals(cs._v, next) ? cs._v : next : next;
|
|
393
444
|
cs._d = false;
|
|
394
445
|
threw = false;
|
|
395
446
|
}, markDirty);
|
|
447
|
+
if (!Object.is(prev, cs._v)) cs.__v++;
|
|
396
448
|
} finally {
|
|
397
449
|
evaluating = false;
|
|
398
450
|
if (threw) cs._d = true;
|
|
@@ -412,6 +464,7 @@ function derived(getter, options) {
|
|
|
412
464
|
cs._d = false;
|
|
413
465
|
threw = false;
|
|
414
466
|
}, markDirty);
|
|
467
|
+
if (!Object.is(oldValue, cs._v)) cs.__v++;
|
|
415
468
|
} finally {
|
|
416
469
|
evaluating = false;
|
|
417
470
|
if (threw) cs._d = true;
|
|
@@ -444,32 +497,64 @@ function enqueueBatchedSignal(signal2) {
|
|
|
444
497
|
var _g = globalThis;
|
|
445
498
|
var _isDev3 = isDev();
|
|
446
499
|
function signal(initial, options) {
|
|
447
|
-
const state = {
|
|
500
|
+
const state = {
|
|
501
|
+
value: initial,
|
|
502
|
+
__v: 0,
|
|
503
|
+
__sc: 0,
|
|
504
|
+
subsHead: null,
|
|
505
|
+
subsTail: null,
|
|
506
|
+
__activeNode: null,
|
|
507
|
+
__name: void 0
|
|
508
|
+
};
|
|
448
509
|
const debugName = _isDev3 ? options?.name : void 0;
|
|
449
510
|
const equalsFn = options?.equals;
|
|
450
|
-
if (debugName)
|
|
451
|
-
state.__name = debugName;
|
|
452
|
-
}
|
|
511
|
+
if (debugName) state.__name = debugName;
|
|
453
512
|
function get() {
|
|
454
513
|
recordDependency(state);
|
|
455
514
|
return state.value;
|
|
456
515
|
}
|
|
457
516
|
get.__signal = state;
|
|
458
517
|
if (debugName) get.__name = debugName;
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
const
|
|
518
|
+
let set;
|
|
519
|
+
if (equalsFn) {
|
|
520
|
+
set = (next) => {
|
|
521
|
+
const prev = state.value;
|
|
522
|
+
const newValue = typeof next === "function" ? next(prev) : next;
|
|
523
|
+
if (equalsFn(prev, newValue)) return;
|
|
524
|
+
state.value = newValue;
|
|
525
|
+
state.__v++;
|
|
526
|
+
if (_isDev3) {
|
|
527
|
+
const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
528
|
+
if (hook) hook.emit("signal:update", { signal: state, name: debugName, oldValue: prev, newValue });
|
|
529
|
+
}
|
|
530
|
+
if (!enqueueBatchedSignal(state)) {
|
|
531
|
+
notifySubscribers(state);
|
|
532
|
+
}
|
|
533
|
+
};
|
|
534
|
+
} else if (_isDev3) {
|
|
535
|
+
set = (next) => {
|
|
536
|
+
const prev = state.value;
|
|
537
|
+
const newValue = typeof next === "function" ? next(prev) : next;
|
|
538
|
+
if (Object.is(newValue, prev)) return;
|
|
464
539
|
state.value = newValue;
|
|
540
|
+
state.__v++;
|
|
465
541
|
const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
466
|
-
if (hook) hook.emit("signal:update", { signal: state, name: debugName, oldValue, newValue });
|
|
467
|
-
|
|
542
|
+
if (hook) hook.emit("signal:update", { signal: state, name: debugName, oldValue: prev, newValue });
|
|
543
|
+
if (!enqueueBatchedSignal(state)) {
|
|
544
|
+
notifySubscribers(state);
|
|
545
|
+
}
|
|
546
|
+
};
|
|
547
|
+
} else {
|
|
548
|
+
set = (next) => {
|
|
549
|
+
const prev = state.value;
|
|
550
|
+
const newValue = typeof next === "function" ? next(prev) : next;
|
|
551
|
+
if (Object.is(newValue, prev)) return;
|
|
468
552
|
state.value = newValue;
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
553
|
+
state.__v++;
|
|
554
|
+
if (!enqueueBatchedSignal(state)) {
|
|
555
|
+
notifySubscribers(state);
|
|
556
|
+
}
|
|
557
|
+
};
|
|
473
558
|
}
|
|
474
559
|
if (_isDev3) {
|
|
475
560
|
const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
@@ -799,92 +884,122 @@ function isSSR() {
|
|
|
799
884
|
|
|
800
885
|
// src/core/signals/effect.ts
|
|
801
886
|
var _g2 = globalThis;
|
|
887
|
+
var MAX_RERUNS = 100;
|
|
888
|
+
function flushUserCleanups(ctx) {
|
|
889
|
+
const list = ctx.userCleanups;
|
|
890
|
+
if (list.length === 0) return;
|
|
891
|
+
ctx.userCleanups = [];
|
|
892
|
+
for (let i = list.length - 1; i >= 0; i--) {
|
|
893
|
+
try {
|
|
894
|
+
list[i]();
|
|
895
|
+
} catch (err) {
|
|
896
|
+
if (typeof console !== "undefined") console.warn("[SibuJS effect] onCleanup threw:", err);
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
function drainReruns(ctx) {
|
|
901
|
+
let reruns = 1;
|
|
902
|
+
do {
|
|
903
|
+
ctx.rerunPending = false;
|
|
904
|
+
if (ctx.userCleanups.length > 0) flushUserCleanups(ctx);
|
|
905
|
+
retrack(ctx.bodyFn, ctx.subscriber);
|
|
906
|
+
} while (ctx.rerunPending && ++reruns <= MAX_RERUNS);
|
|
907
|
+
if (ctx.rerunPending) {
|
|
908
|
+
ctx.rerunPending = false;
|
|
909
|
+
if (_g2.__SIBU_DEV_WARN__ !== false && typeof console !== "undefined") {
|
|
910
|
+
console.error(
|
|
911
|
+
`[SibuJS] effect re-requested itself ${MAX_RERUNS}+ times \u2014 likely a write-reads-self cycle. Breaking to prevent infinite loop.`
|
|
912
|
+
);
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
function disposeEffect(ctx) {
|
|
917
|
+
if (ctx.disposed) return;
|
|
918
|
+
ctx.disposed = true;
|
|
919
|
+
const h = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
920
|
+
if (h) {
|
|
921
|
+
try {
|
|
922
|
+
h.emit("effect:destroy", { effectFn: ctx.fn });
|
|
923
|
+
} catch {
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
try {
|
|
927
|
+
if (ctx.userCleanups.length > 0) flushUserCleanups(ctx);
|
|
928
|
+
} catch (err) {
|
|
929
|
+
if (typeof console !== "undefined") {
|
|
930
|
+
console.warn("[SibuJS effect] onCleanup threw during dispose:", err);
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
try {
|
|
934
|
+
cleanup(ctx.subscriber);
|
|
935
|
+
} catch (err) {
|
|
936
|
+
if (typeof console !== "undefined") {
|
|
937
|
+
console.warn("[SibuJS effect] dispose threw:", err);
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
}
|
|
802
941
|
function effect(effectFn, options) {
|
|
803
942
|
devAssert(typeof effectFn === "function", "effect: argument must be a function.");
|
|
804
943
|
if (isSSR()) return () => {
|
|
805
944
|
};
|
|
806
|
-
const
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
userCleanups
|
|
945
|
+
const ctx = {
|
|
946
|
+
fn: effectFn,
|
|
947
|
+
onError: options?.onError,
|
|
948
|
+
userCleanups: [],
|
|
949
|
+
running: false,
|
|
950
|
+
rerunPending: false,
|
|
951
|
+
disposed: false,
|
|
952
|
+
onCleanup: null,
|
|
953
|
+
subscriber: null,
|
|
954
|
+
bodyFn: null
|
|
810
955
|
};
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
const list = userCleanups;
|
|
814
|
-
userCleanups = [];
|
|
815
|
-
for (let i = list.length - 1; i >= 0; i--) {
|
|
816
|
-
try {
|
|
817
|
-
list[i]();
|
|
818
|
-
} catch (err) {
|
|
819
|
-
if (typeof console !== "undefined") {
|
|
820
|
-
console.warn("[SibuJS effect] onCleanup threw:", err);
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
}
|
|
956
|
+
ctx.onCleanup = (fn) => {
|
|
957
|
+
ctx.userCleanups.push(fn);
|
|
824
958
|
};
|
|
825
|
-
const
|
|
826
|
-
|
|
959
|
+
const onErrorCaptured = ctx.onError;
|
|
960
|
+
ctx.bodyFn = onErrorCaptured ? () => {
|
|
827
961
|
try {
|
|
828
|
-
|
|
962
|
+
ctx.fn(ctx.onCleanup);
|
|
829
963
|
} catch (err) {
|
|
830
|
-
|
|
964
|
+
onErrorCaptured(err);
|
|
831
965
|
}
|
|
832
|
-
} :
|
|
833
|
-
|
|
966
|
+
} : () => {
|
|
967
|
+
ctx.fn(ctx.onCleanup);
|
|
834
968
|
};
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
if (_g2.__SIBU_DEV_WARN__ !== false && typeof console !== "undefined") {
|
|
839
|
-
console.warn(
|
|
840
|
-
"[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."
|
|
841
|
-
);
|
|
842
|
-
}
|
|
969
|
+
const sub = (() => {
|
|
970
|
+
if (ctx.running) {
|
|
971
|
+
ctx.rerunPending = true;
|
|
843
972
|
return;
|
|
844
973
|
}
|
|
845
|
-
running = true;
|
|
974
|
+
ctx.running = true;
|
|
846
975
|
try {
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
976
|
+
ctx.rerunPending = false;
|
|
977
|
+
if (ctx.userCleanups.length > 0) flushUserCleanups(ctx);
|
|
978
|
+
retrack(ctx.bodyFn, sub);
|
|
979
|
+
if (ctx.rerunPending) drainReruns(ctx);
|
|
850
980
|
} finally {
|
|
851
|
-
running = false;
|
|
981
|
+
ctx.running = false;
|
|
982
|
+
ctx.rerunPending = false;
|
|
852
983
|
}
|
|
853
|
-
};
|
|
854
|
-
|
|
984
|
+
});
|
|
985
|
+
sub.depsHead = null;
|
|
986
|
+
sub.depsTail = null;
|
|
987
|
+
sub._epoch = 0;
|
|
988
|
+
sub._structDirty = false;
|
|
989
|
+
sub._runEpoch = 0;
|
|
990
|
+
sub._runs = 0;
|
|
991
|
+
ctx.subscriber = sub;
|
|
992
|
+
ctx.running = true;
|
|
855
993
|
try {
|
|
856
|
-
|
|
994
|
+
retrack(ctx.bodyFn, ctx.subscriber);
|
|
995
|
+
if (ctx.rerunPending) drainReruns(ctx);
|
|
857
996
|
} finally {
|
|
858
|
-
running = false;
|
|
997
|
+
ctx.running = false;
|
|
998
|
+
ctx.rerunPending = false;
|
|
859
999
|
}
|
|
860
1000
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
861
1001
|
if (hook) hook.emit("effect:create", { effectFn });
|
|
862
|
-
|
|
863
|
-
return () => {
|
|
864
|
-
if (disposed) return;
|
|
865
|
-
disposed = true;
|
|
866
|
-
const h = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
867
|
-
if (h) {
|
|
868
|
-
try {
|
|
869
|
-
h.emit("effect:destroy", { effectFn });
|
|
870
|
-
} catch {
|
|
871
|
-
}
|
|
872
|
-
}
|
|
873
|
-
try {
|
|
874
|
-
runUserCleanups();
|
|
875
|
-
} catch (err) {
|
|
876
|
-
if (typeof console !== "undefined") {
|
|
877
|
-
console.warn("[SibuJS effect] onCleanup threw during dispose:", err);
|
|
878
|
-
}
|
|
879
|
-
}
|
|
880
|
-
try {
|
|
881
|
-
cleanupHandle();
|
|
882
|
-
} catch (err) {
|
|
883
|
-
if (typeof console !== "undefined") {
|
|
884
|
-
console.warn("[SibuJS effect] dispose threw:", err);
|
|
885
|
-
}
|
|
886
|
-
}
|
|
887
|
-
};
|
|
1002
|
+
return () => disposeEffect(ctx);
|
|
888
1003
|
}
|
|
889
1004
|
|
|
890
1005
|
// src/ui/virtualList.ts
|