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/widgets.cjs
CHANGED
|
@@ -50,11 +50,88 @@ function devWarn(message) {
|
|
|
50
50
|
|
|
51
51
|
// src/reactivity/track.ts
|
|
52
52
|
var _isDev2 = isDev();
|
|
53
|
-
var
|
|
54
|
-
var
|
|
55
|
-
|
|
53
|
+
var POOL_MAX = 4096;
|
|
54
|
+
var nodePool = [];
|
|
55
|
+
function createNode() {
|
|
56
|
+
return {
|
|
57
|
+
sig: null,
|
|
58
|
+
sub: null,
|
|
59
|
+
epoch: 0,
|
|
60
|
+
sigPrev: null,
|
|
61
|
+
sigNext: null,
|
|
62
|
+
subPrev: null,
|
|
63
|
+
subNext: null,
|
|
64
|
+
prevActive: null
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function allocNode(sig, sub, epoch) {
|
|
68
|
+
const n = nodePool.pop();
|
|
69
|
+
if (n) {
|
|
70
|
+
n.sig = sig;
|
|
71
|
+
n.sub = sub;
|
|
72
|
+
n.epoch = epoch;
|
|
73
|
+
return n;
|
|
74
|
+
}
|
|
75
|
+
const fresh = createNode();
|
|
76
|
+
fresh.sig = sig;
|
|
77
|
+
fresh.sub = sub;
|
|
78
|
+
fresh.epoch = epoch;
|
|
79
|
+
return fresh;
|
|
80
|
+
}
|
|
81
|
+
function freeNode(node) {
|
|
82
|
+
node.sig = null;
|
|
83
|
+
node.sub = null;
|
|
84
|
+
node.sigPrev = null;
|
|
85
|
+
node.sigNext = null;
|
|
86
|
+
node.subPrev = null;
|
|
87
|
+
node.subNext = null;
|
|
88
|
+
node.prevActive = null;
|
|
89
|
+
if (nodePool.length < POOL_MAX) nodePool.push(node);
|
|
90
|
+
}
|
|
91
|
+
function linkSignal(sig, node) {
|
|
92
|
+
const oldHead = sig.subsHead ?? null;
|
|
93
|
+
node.sigPrev = null;
|
|
94
|
+
node.sigNext = oldHead;
|
|
95
|
+
if (oldHead) oldHead.sigPrev = node;
|
|
96
|
+
else sig.subsTail = node;
|
|
97
|
+
sig.subsHead = node;
|
|
98
|
+
sig.__sc = (sig.__sc ?? 0) + 1;
|
|
99
|
+
}
|
|
100
|
+
function unlinkSignal(node) {
|
|
101
|
+
const sig = node.sig;
|
|
102
|
+
if (!sig) return;
|
|
103
|
+
const prev = node.sigPrev;
|
|
104
|
+
const next = node.sigNext;
|
|
105
|
+
if (prev) prev.sigNext = next;
|
|
106
|
+
else sig.subsHead = next;
|
|
107
|
+
if (next) next.sigPrev = prev;
|
|
108
|
+
else sig.subsTail = prev;
|
|
109
|
+
sig.__sc = (sig.__sc ?? 1) - 1;
|
|
110
|
+
if (sig.__activeNode === node) sig.__activeNode = node.prevActive;
|
|
111
|
+
if (sig.__sc === 0) {
|
|
112
|
+
sig.subsHead = null;
|
|
113
|
+
sig.subsTail = null;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function linkSub(sub, node) {
|
|
117
|
+
const oldTail = sub.depsTail ?? null;
|
|
118
|
+
node.subPrev = oldTail;
|
|
119
|
+
node.subNext = null;
|
|
120
|
+
if (oldTail) oldTail.subNext = node;
|
|
121
|
+
else sub.depsHead = node;
|
|
122
|
+
sub.depsTail = node;
|
|
123
|
+
}
|
|
124
|
+
function unlinkSub(node) {
|
|
125
|
+
const sub = node.sub;
|
|
126
|
+
if (!sub) return;
|
|
127
|
+
const prev = node.subPrev;
|
|
128
|
+
const next = node.subNext;
|
|
129
|
+
if (prev) prev.subNext = next;
|
|
130
|
+
else sub.depsHead = next;
|
|
131
|
+
if (next) next.subPrev = prev;
|
|
132
|
+
else sub.depsTail = prev;
|
|
133
|
+
}
|
|
56
134
|
var currentSubscriber = null;
|
|
57
|
-
var SUBS = "__s";
|
|
58
135
|
var notifyDepth = 0;
|
|
59
136
|
var pendingQueue = [];
|
|
60
137
|
var pendingSet = /* @__PURE__ */ new Set();
|
|
@@ -67,92 +144,136 @@ function safeInvoke(sub) {
|
|
|
67
144
|
}
|
|
68
145
|
}
|
|
69
146
|
var trackingSuspended = false;
|
|
147
|
+
var subscriberEpochCounter = 0;
|
|
70
148
|
function retrack(effectFn, subscriber) {
|
|
71
149
|
const prev = currentSubscriber;
|
|
72
150
|
currentSubscriber = subscriber;
|
|
151
|
+
const sub = subscriber;
|
|
152
|
+
const epoch = ++subscriberEpochCounter;
|
|
153
|
+
sub._epoch = epoch;
|
|
154
|
+
sub._structDirty = false;
|
|
155
|
+
for (let n = sub.depsHead ?? null; n !== null; n = n.subNext) {
|
|
156
|
+
const sig = n.sig;
|
|
157
|
+
n.prevActive = sig.__activeNode ?? null;
|
|
158
|
+
sig.__activeNode = n;
|
|
159
|
+
}
|
|
73
160
|
try {
|
|
74
161
|
effectFn();
|
|
75
162
|
} finally {
|
|
76
163
|
currentSubscriber = prev;
|
|
164
|
+
let node = sub.depsHead ?? null;
|
|
165
|
+
while (node !== null) {
|
|
166
|
+
const next = node.subNext;
|
|
167
|
+
const sig = node.sig;
|
|
168
|
+
sig.__activeNode = node.prevActive;
|
|
169
|
+
node.prevActive = null;
|
|
170
|
+
if (node.epoch !== epoch) {
|
|
171
|
+
unlinkSub(node);
|
|
172
|
+
unlinkSignal(node);
|
|
173
|
+
freeNode(node);
|
|
174
|
+
}
|
|
175
|
+
node = next;
|
|
176
|
+
}
|
|
77
177
|
}
|
|
78
178
|
}
|
|
79
179
|
function track(effectFn, subscriber) {
|
|
80
180
|
if (!subscriber) subscriber = effectFn;
|
|
81
181
|
cleanup(subscriber);
|
|
82
|
-
|
|
83
|
-
if (stackTop >= stackCapacity) {
|
|
84
|
-
stackCapacity *= 2;
|
|
85
|
-
subscriberStack.length = stackCapacity;
|
|
86
|
-
}
|
|
87
|
-
subscriberStack[stackTop] = subscriber;
|
|
182
|
+
const prev = currentSubscriber;
|
|
88
183
|
currentSubscriber = subscriber;
|
|
89
184
|
try {
|
|
90
185
|
effectFn();
|
|
91
186
|
} finally {
|
|
92
|
-
|
|
93
|
-
|
|
187
|
+
currentSubscriber = prev;
|
|
188
|
+
const sub2 = subscriber;
|
|
189
|
+
for (let n = sub2.depsHead ?? null; n !== null; n = n.subNext) {
|
|
190
|
+
const sig = n.sig;
|
|
191
|
+
sig.__activeNode = n.prevActive;
|
|
192
|
+
n.prevActive = null;
|
|
193
|
+
}
|
|
94
194
|
}
|
|
95
|
-
|
|
195
|
+
const sub = subscriber;
|
|
196
|
+
return sub._dispose ?? (sub._dispose = () => cleanup(subscriber));
|
|
96
197
|
}
|
|
97
198
|
function recordDependency(signal2) {
|
|
98
199
|
if (!currentSubscriber) return;
|
|
99
200
|
const sub = currentSubscriber;
|
|
100
|
-
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
201
|
+
const sig = signal2;
|
|
202
|
+
const epoch = sub._epoch ?? 0;
|
|
203
|
+
const active = sig.__activeNode ?? null;
|
|
204
|
+
if (active !== null && active.sub === sub) {
|
|
205
|
+
active.epoch = epoch;
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
const node = allocNode(signal2, sub, epoch);
|
|
209
|
+
node.prevActive = active;
|
|
210
|
+
sig.__activeNode = node;
|
|
211
|
+
linkSub(sub, node);
|
|
212
|
+
linkSignal(sig, node);
|
|
213
|
+
sub._structDirty = true;
|
|
214
|
+
}
|
|
215
|
+
function cleanup(subscriber) {
|
|
216
|
+
const sub = subscriber;
|
|
217
|
+
let node = sub.depsHead ?? null;
|
|
218
|
+
sub.depsHead = null;
|
|
219
|
+
sub.depsTail = null;
|
|
220
|
+
while (node) {
|
|
221
|
+
const next = node.subNext;
|
|
222
|
+
unlinkSignal(node);
|
|
223
|
+
freeNode(node);
|
|
224
|
+
node = next;
|
|
113
225
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
226
|
+
}
|
|
227
|
+
var maxSubscriberRepeats = 50;
|
|
228
|
+
var maxDrainIterations = 1e6;
|
|
229
|
+
var drainEpoch = 0;
|
|
230
|
+
function tickRepeat(sub) {
|
|
231
|
+
const s = sub;
|
|
232
|
+
if (s._runEpoch !== drainEpoch) {
|
|
233
|
+
s._runEpoch = drainEpoch;
|
|
234
|
+
s._runs = 1;
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
s._runs = (s._runs ?? 0) + 1;
|
|
238
|
+
return s._runs > maxSubscriberRepeats;
|
|
239
|
+
}
|
|
240
|
+
function cycleError(sub) {
|
|
241
|
+
if (typeof console !== "undefined") {
|
|
242
|
+
const name = sub.__name ?? "<unnamed>";
|
|
243
|
+
console.error(
|
|
244
|
+
`[SibuJS] subscriber "${name}" fired more than ${maxSubscriberRepeats} times \u2014 likely a write-reads-self cycle between effects/signals. Breaking to prevent infinite loop.`
|
|
245
|
+
);
|
|
118
246
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
247
|
+
}
|
|
248
|
+
function absoluteDrainError() {
|
|
249
|
+
if (typeof console !== "undefined") {
|
|
250
|
+
console.error(
|
|
251
|
+
`[SibuJS] Notification drain exceeded ${maxDrainIterations} iterations \u2014 absolute safety net tripped. Breaking to prevent infinite loop.`
|
|
252
|
+
);
|
|
124
253
|
}
|
|
125
254
|
}
|
|
126
|
-
function
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
} else if (!pendingSet.has(sub)) {
|
|
133
|
-
pendingSet.add(sub);
|
|
134
|
-
pendingQueue.push(sub);
|
|
255
|
+
function drainQueue() {
|
|
256
|
+
let i = 0;
|
|
257
|
+
while (i < pendingQueue.length) {
|
|
258
|
+
if (i >= maxDrainIterations) {
|
|
259
|
+
absoluteDrainError();
|
|
260
|
+
break;
|
|
135
261
|
}
|
|
262
|
+
const sub = pendingQueue[i++];
|
|
263
|
+
if (tickRepeat(sub)) {
|
|
264
|
+
cycleError(sub);
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
267
|
+
pendingSet.delete(sub);
|
|
268
|
+
safeInvoke(sub);
|
|
136
269
|
}
|
|
137
270
|
}
|
|
138
|
-
var maxDrainIterations = 1e5;
|
|
139
271
|
function drainNotificationQueue() {
|
|
140
272
|
if (notifyDepth > 0) return;
|
|
141
273
|
notifyDepth++;
|
|
274
|
+
drainEpoch++;
|
|
142
275
|
try {
|
|
143
|
-
|
|
144
|
-
while (i < pendingQueue.length) {
|
|
145
|
-
if (i >= maxDrainIterations) {
|
|
146
|
-
if (typeof console !== "undefined") {
|
|
147
|
-
console.error(
|
|
148
|
-
`[SibuJS] Notification queue exceeded ${maxDrainIterations} iterations \u2014 likely an effect that writes to a signal it reads. Breaking to prevent infinite loop.`
|
|
149
|
-
);
|
|
150
|
-
}
|
|
151
|
-
break;
|
|
152
|
-
}
|
|
153
|
-
safeInvoke(pendingQueue[i]);
|
|
154
|
-
i++;
|
|
155
|
-
}
|
|
276
|
+
drainQueue();
|
|
156
277
|
} finally {
|
|
157
278
|
notifyDepth--;
|
|
158
279
|
if (notifyDepth === 0) {
|
|
@@ -170,131 +291,82 @@ function propagateDirty(sub) {
|
|
|
170
291
|
stack.push(rootSig);
|
|
171
292
|
while (stack.length > baseLen) {
|
|
172
293
|
const sig = stack.pop();
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
if (
|
|
178
|
-
nSig
|
|
179
|
-
|
|
294
|
+
let node = sig.subsHead ?? null;
|
|
295
|
+
while (node) {
|
|
296
|
+
const s = node.sub;
|
|
297
|
+
if (s) {
|
|
298
|
+
if (s._c) {
|
|
299
|
+
const nSig = s._sig;
|
|
300
|
+
if (nSig) {
|
|
301
|
+
if (!nSig._d) {
|
|
302
|
+
nSig._d = true;
|
|
303
|
+
stack.push(nSig);
|
|
304
|
+
}
|
|
305
|
+
} else {
|
|
306
|
+
s();
|
|
307
|
+
}
|
|
308
|
+
} else if (!pendingSet.has(s)) {
|
|
309
|
+
pendingSet.add(s);
|
|
310
|
+
pendingQueue.push(s);
|
|
180
311
|
}
|
|
181
|
-
} else if (!pendingSet.has(first)) {
|
|
182
|
-
pendingSet.add(first);
|
|
183
|
-
pendingQueue.push(first);
|
|
184
312
|
}
|
|
185
|
-
|
|
313
|
+
node = node.sigNext;
|
|
186
314
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
function queueSignalNotification(signal2) {
|
|
318
|
+
const sig = signal2;
|
|
319
|
+
let node = sig.subsHead ?? null;
|
|
320
|
+
while (node) {
|
|
321
|
+
const s = node.sub;
|
|
322
|
+
if (s) {
|
|
190
323
|
if (s._c) {
|
|
191
|
-
|
|
192
|
-
if (nSig && !nSig._d) {
|
|
193
|
-
nSig._d = true;
|
|
194
|
-
stack.push(nSig);
|
|
195
|
-
} else if (!nSig) {
|
|
196
|
-
s();
|
|
197
|
-
}
|
|
324
|
+
propagateDirty(s);
|
|
198
325
|
} else if (!pendingSet.has(s)) {
|
|
199
326
|
pendingSet.add(s);
|
|
200
327
|
pendingQueue.push(s);
|
|
201
328
|
}
|
|
202
329
|
}
|
|
330
|
+
node = node.sigNext;
|
|
203
331
|
}
|
|
204
332
|
}
|
|
205
333
|
function notifySubscribers(signal2) {
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
if (first._c) {
|
|
210
|
-
propagateDirty(first);
|
|
211
|
-
} else if (!pendingSet.has(first)) {
|
|
212
|
-
pendingSet.add(first);
|
|
213
|
-
pendingQueue.push(first);
|
|
214
|
-
}
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
notifyDepth++;
|
|
218
|
-
try {
|
|
219
|
-
if (first._c) {
|
|
220
|
-
propagateDirty(first);
|
|
221
|
-
} else {
|
|
222
|
-
safeInvoke(first);
|
|
223
|
-
}
|
|
224
|
-
let i = 0;
|
|
225
|
-
while (i < pendingQueue.length) {
|
|
226
|
-
if (i >= maxDrainIterations) {
|
|
227
|
-
if (typeof console !== "undefined") {
|
|
228
|
-
console.error(
|
|
229
|
-
`[SibuJS] Notification queue exceeded ${maxDrainIterations} iterations \u2014 likely an effect that writes to a signal it reads. Breaking to prevent infinite loop.`
|
|
230
|
-
);
|
|
231
|
-
}
|
|
232
|
-
break;
|
|
233
|
-
}
|
|
234
|
-
safeInvoke(pendingQueue[i]);
|
|
235
|
-
i++;
|
|
236
|
-
}
|
|
237
|
-
} finally {
|
|
238
|
-
notifyDepth--;
|
|
239
|
-
if (notifyDepth === 0) {
|
|
240
|
-
pendingQueue.length = 0;
|
|
241
|
-
pendingSet.clear();
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
|
-
const subs = signal2[SUBS];
|
|
247
|
-
if (!subs || subs.size === 0) return;
|
|
334
|
+
const sig = signal2;
|
|
335
|
+
const head = sig.subsHead;
|
|
336
|
+
if (!head) return;
|
|
248
337
|
if (notifyDepth > 0) {
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
338
|
+
let node = head;
|
|
339
|
+
while (node) {
|
|
340
|
+
const s = node.sub;
|
|
341
|
+
if (s) {
|
|
342
|
+
if (s._c) {
|
|
343
|
+
propagateDirty(s);
|
|
344
|
+
} else if (!pendingSet.has(s)) {
|
|
345
|
+
pendingSet.add(s);
|
|
346
|
+
pendingQueue.push(s);
|
|
347
|
+
}
|
|
255
348
|
}
|
|
349
|
+
node = node.sigNext;
|
|
256
350
|
}
|
|
257
351
|
return;
|
|
258
352
|
}
|
|
259
353
|
notifyDepth++;
|
|
354
|
+
drainEpoch++;
|
|
260
355
|
try {
|
|
261
|
-
let
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
if (
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
}
|
|
271
|
-
} else {
|
|
272
|
-
for (let i2 = 0; i2 < directCount; i2++) {
|
|
273
|
-
if (pendingQueue[i2]._c) {
|
|
274
|
-
propagateDirty(pendingQueue[i2]);
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
for (let i2 = 0; i2 < directCount; i2++) {
|
|
278
|
-
const sub = pendingQueue[i2];
|
|
279
|
-
if (!sub._c && !pendingSet.has(sub)) {
|
|
280
|
-
pendingSet.add(sub);
|
|
281
|
-
safeInvoke(sub);
|
|
356
|
+
let node = head;
|
|
357
|
+
while (node) {
|
|
358
|
+
const s = node.sub;
|
|
359
|
+
if (s) {
|
|
360
|
+
if (s._c) {
|
|
361
|
+
propagateDirty(s);
|
|
362
|
+
} else if (!pendingSet.has(s)) {
|
|
363
|
+
pendingSet.add(s);
|
|
364
|
+
pendingQueue.push(s);
|
|
282
365
|
}
|
|
283
366
|
}
|
|
367
|
+
node = node.sigNext;
|
|
284
368
|
}
|
|
285
|
-
|
|
286
|
-
while (i < pendingQueue.length) {
|
|
287
|
-
if (i - directCount >= maxDrainIterations) {
|
|
288
|
-
if (typeof console !== "undefined") {
|
|
289
|
-
console.error(
|
|
290
|
-
`[SibuJS] Notification queue exceeded ${maxDrainIterations} iterations \u2014 likely an effect that writes to a signal it reads. Breaking to prevent infinite loop.`
|
|
291
|
-
);
|
|
292
|
-
}
|
|
293
|
-
break;
|
|
294
|
-
}
|
|
295
|
-
safeInvoke(pendingQueue[i]);
|
|
296
|
-
i++;
|
|
297
|
-
}
|
|
369
|
+
drainQueue();
|
|
298
370
|
} finally {
|
|
299
371
|
notifyDepth--;
|
|
300
372
|
if (notifyDepth === 0) {
|
|
@@ -303,37 +375,6 @@ function notifySubscribers(signal2) {
|
|
|
303
375
|
}
|
|
304
376
|
}
|
|
305
377
|
}
|
|
306
|
-
function cleanup(subscriber) {
|
|
307
|
-
const sub = subscriber;
|
|
308
|
-
const singleDep = sub._dep;
|
|
309
|
-
if (singleDep !== void 0) {
|
|
310
|
-
const subs = singleDep[SUBS];
|
|
311
|
-
if (subs) {
|
|
312
|
-
subs.delete(subscriber);
|
|
313
|
-
if (singleDep.__f === subscriber) {
|
|
314
|
-
singleDep.__f = subs.size === 1 ? subs.values().next().value : void 0;
|
|
315
|
-
} else if (subs.size === 1 && singleDep.__f === void 0) {
|
|
316
|
-
singleDep.__f = subs.values().next().value;
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
sub._dep = void 0;
|
|
320
|
-
return;
|
|
321
|
-
}
|
|
322
|
-
const deps = sub._deps;
|
|
323
|
-
if (!deps || deps.size === 0) return;
|
|
324
|
-
for (const signal2 of deps) {
|
|
325
|
-
const subs = signal2[SUBS];
|
|
326
|
-
if (subs) {
|
|
327
|
-
subs.delete(subscriber);
|
|
328
|
-
if (signal2.__f === subscriber) {
|
|
329
|
-
signal2.__f = subs.size === 1 ? subs.values().next().value : void 0;
|
|
330
|
-
} else if (subs.size === 1 && signal2.__f === void 0) {
|
|
331
|
-
signal2.__f = subs.values().next().value;
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
deps.clear();
|
|
336
|
-
}
|
|
337
378
|
|
|
338
379
|
// src/core/signals/derived.ts
|
|
339
380
|
function derived(getter, options) {
|
|
@@ -343,6 +384,7 @@ function derived(getter, options) {
|
|
|
343
384
|
const cs = {};
|
|
344
385
|
cs._d = false;
|
|
345
386
|
cs._g = getter;
|
|
387
|
+
cs.__v = 0;
|
|
346
388
|
const markDirty = () => {
|
|
347
389
|
if (cs._d) return;
|
|
348
390
|
cs._d = true;
|
|
@@ -372,11 +414,14 @@ function derived(getter, options) {
|
|
|
372
414
|
evaluating = true;
|
|
373
415
|
let threw = true;
|
|
374
416
|
try {
|
|
417
|
+
const prev = cs._v;
|
|
375
418
|
retrack(() => {
|
|
376
|
-
|
|
419
|
+
const next = getter();
|
|
420
|
+
cs._v = equals && cs._v !== void 0 ? equals(cs._v, next) ? cs._v : next : next;
|
|
377
421
|
cs._d = false;
|
|
378
422
|
threw = false;
|
|
379
423
|
}, markDirty);
|
|
424
|
+
if (!Object.is(prev, cs._v)) cs.__v++;
|
|
380
425
|
} finally {
|
|
381
426
|
evaluating = false;
|
|
382
427
|
if (threw) cs._d = true;
|
|
@@ -396,6 +441,7 @@ function derived(getter, options) {
|
|
|
396
441
|
cs._d = false;
|
|
397
442
|
threw = false;
|
|
398
443
|
}, markDirty);
|
|
444
|
+
if (!Object.is(oldValue, cs._v)) cs.__v++;
|
|
399
445
|
} finally {
|
|
400
446
|
evaluating = false;
|
|
401
447
|
if (threw) cs._d = true;
|
|
@@ -442,92 +488,122 @@ function isSSR() {
|
|
|
442
488
|
|
|
443
489
|
// src/core/signals/effect.ts
|
|
444
490
|
var _g = globalThis;
|
|
491
|
+
var MAX_RERUNS = 100;
|
|
492
|
+
function flushUserCleanups(ctx) {
|
|
493
|
+
const list = ctx.userCleanups;
|
|
494
|
+
if (list.length === 0) return;
|
|
495
|
+
ctx.userCleanups = [];
|
|
496
|
+
for (let i = list.length - 1; i >= 0; i--) {
|
|
497
|
+
try {
|
|
498
|
+
list[i]();
|
|
499
|
+
} catch (err) {
|
|
500
|
+
if (typeof console !== "undefined") console.warn("[SibuJS effect] onCleanup threw:", err);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
function drainReruns(ctx) {
|
|
505
|
+
let reruns = 1;
|
|
506
|
+
do {
|
|
507
|
+
ctx.rerunPending = false;
|
|
508
|
+
if (ctx.userCleanups.length > 0) flushUserCleanups(ctx);
|
|
509
|
+
retrack(ctx.bodyFn, ctx.subscriber);
|
|
510
|
+
} while (ctx.rerunPending && ++reruns <= MAX_RERUNS);
|
|
511
|
+
if (ctx.rerunPending) {
|
|
512
|
+
ctx.rerunPending = false;
|
|
513
|
+
if (_g.__SIBU_DEV_WARN__ !== false && typeof console !== "undefined") {
|
|
514
|
+
console.error(
|
|
515
|
+
`[SibuJS] effect re-requested itself ${MAX_RERUNS}+ times \u2014 likely a write-reads-self cycle. Breaking to prevent infinite loop.`
|
|
516
|
+
);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
function disposeEffect(ctx) {
|
|
521
|
+
if (ctx.disposed) return;
|
|
522
|
+
ctx.disposed = true;
|
|
523
|
+
const h = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
524
|
+
if (h) {
|
|
525
|
+
try {
|
|
526
|
+
h.emit("effect:destroy", { effectFn: ctx.fn });
|
|
527
|
+
} catch {
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
try {
|
|
531
|
+
if (ctx.userCleanups.length > 0) flushUserCleanups(ctx);
|
|
532
|
+
} catch (err) {
|
|
533
|
+
if (typeof console !== "undefined") {
|
|
534
|
+
console.warn("[SibuJS effect] onCleanup threw during dispose:", err);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
try {
|
|
538
|
+
cleanup(ctx.subscriber);
|
|
539
|
+
} catch (err) {
|
|
540
|
+
if (typeof console !== "undefined") {
|
|
541
|
+
console.warn("[SibuJS effect] dispose threw:", err);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
}
|
|
445
545
|
function effect(effectFn, options) {
|
|
446
546
|
devAssert(typeof effectFn === "function", "effect: argument must be a function.");
|
|
447
547
|
if (isSSR()) return () => {
|
|
448
548
|
};
|
|
449
|
-
const
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
userCleanups
|
|
549
|
+
const ctx = {
|
|
550
|
+
fn: effectFn,
|
|
551
|
+
onError: options?.onError,
|
|
552
|
+
userCleanups: [],
|
|
553
|
+
running: false,
|
|
554
|
+
rerunPending: false,
|
|
555
|
+
disposed: false,
|
|
556
|
+
onCleanup: null,
|
|
557
|
+
subscriber: null,
|
|
558
|
+
bodyFn: null
|
|
453
559
|
};
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
const list = userCleanups;
|
|
457
|
-
userCleanups = [];
|
|
458
|
-
for (let i = list.length - 1; i >= 0; i--) {
|
|
459
|
-
try {
|
|
460
|
-
list[i]();
|
|
461
|
-
} catch (err) {
|
|
462
|
-
if (typeof console !== "undefined") {
|
|
463
|
-
console.warn("[SibuJS effect] onCleanup threw:", err);
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
}
|
|
560
|
+
ctx.onCleanup = (fn) => {
|
|
561
|
+
ctx.userCleanups.push(fn);
|
|
467
562
|
};
|
|
468
|
-
const
|
|
469
|
-
|
|
563
|
+
const onErrorCaptured = ctx.onError;
|
|
564
|
+
ctx.bodyFn = onErrorCaptured ? () => {
|
|
470
565
|
try {
|
|
471
|
-
|
|
566
|
+
ctx.fn(ctx.onCleanup);
|
|
472
567
|
} catch (err) {
|
|
473
|
-
|
|
568
|
+
onErrorCaptured(err);
|
|
474
569
|
}
|
|
475
|
-
} :
|
|
476
|
-
|
|
570
|
+
} : () => {
|
|
571
|
+
ctx.fn(ctx.onCleanup);
|
|
477
572
|
};
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
if (_g.__SIBU_DEV_WARN__ !== false && typeof console !== "undefined") {
|
|
482
|
-
console.warn(
|
|
483
|
-
"[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."
|
|
484
|
-
);
|
|
485
|
-
}
|
|
573
|
+
const sub = (() => {
|
|
574
|
+
if (ctx.running) {
|
|
575
|
+
ctx.rerunPending = true;
|
|
486
576
|
return;
|
|
487
577
|
}
|
|
488
|
-
running = true;
|
|
578
|
+
ctx.running = true;
|
|
489
579
|
try {
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
580
|
+
ctx.rerunPending = false;
|
|
581
|
+
if (ctx.userCleanups.length > 0) flushUserCleanups(ctx);
|
|
582
|
+
retrack(ctx.bodyFn, sub);
|
|
583
|
+
if (ctx.rerunPending) drainReruns(ctx);
|
|
493
584
|
} finally {
|
|
494
|
-
running = false;
|
|
585
|
+
ctx.running = false;
|
|
586
|
+
ctx.rerunPending = false;
|
|
495
587
|
}
|
|
496
|
-
};
|
|
497
|
-
|
|
588
|
+
});
|
|
589
|
+
sub.depsHead = null;
|
|
590
|
+
sub.depsTail = null;
|
|
591
|
+
sub._epoch = 0;
|
|
592
|
+
sub._structDirty = false;
|
|
593
|
+
sub._runEpoch = 0;
|
|
594
|
+
sub._runs = 0;
|
|
595
|
+
ctx.subscriber = sub;
|
|
596
|
+
ctx.running = true;
|
|
498
597
|
try {
|
|
499
|
-
|
|
598
|
+
retrack(ctx.bodyFn, ctx.subscriber);
|
|
599
|
+
if (ctx.rerunPending) drainReruns(ctx);
|
|
500
600
|
} finally {
|
|
501
|
-
running = false;
|
|
601
|
+
ctx.running = false;
|
|
602
|
+
ctx.rerunPending = false;
|
|
502
603
|
}
|
|
503
604
|
const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
504
605
|
if (hook) hook.emit("effect:create", { effectFn });
|
|
505
|
-
|
|
506
|
-
return () => {
|
|
507
|
-
if (disposed) return;
|
|
508
|
-
disposed = true;
|
|
509
|
-
const h = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
510
|
-
if (h) {
|
|
511
|
-
try {
|
|
512
|
-
h.emit("effect:destroy", { effectFn });
|
|
513
|
-
} catch {
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
try {
|
|
517
|
-
runUserCleanups();
|
|
518
|
-
} catch (err) {
|
|
519
|
-
if (typeof console !== "undefined") {
|
|
520
|
-
console.warn("[SibuJS effect] onCleanup threw during dispose:", err);
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
try {
|
|
524
|
-
cleanupHandle();
|
|
525
|
-
} catch (err) {
|
|
526
|
-
if (typeof console !== "undefined") {
|
|
527
|
-
console.warn("[SibuJS effect] dispose threw:", err);
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
};
|
|
606
|
+
return () => disposeEffect(ctx);
|
|
531
607
|
}
|
|
532
608
|
|
|
533
609
|
// src/reactivity/batch.ts
|
|
@@ -564,32 +640,64 @@ function flushBatch() {
|
|
|
564
640
|
var _g2 = globalThis;
|
|
565
641
|
var _isDev3 = isDev();
|
|
566
642
|
function signal(initial, options) {
|
|
567
|
-
const state = {
|
|
643
|
+
const state = {
|
|
644
|
+
value: initial,
|
|
645
|
+
__v: 0,
|
|
646
|
+
__sc: 0,
|
|
647
|
+
subsHead: null,
|
|
648
|
+
subsTail: null,
|
|
649
|
+
__activeNode: null,
|
|
650
|
+
__name: void 0
|
|
651
|
+
};
|
|
568
652
|
const debugName = _isDev3 ? options?.name : void 0;
|
|
569
653
|
const equalsFn = options?.equals;
|
|
570
|
-
if (debugName)
|
|
571
|
-
state.__name = debugName;
|
|
572
|
-
}
|
|
654
|
+
if (debugName) state.__name = debugName;
|
|
573
655
|
function get() {
|
|
574
656
|
recordDependency(state);
|
|
575
657
|
return state.value;
|
|
576
658
|
}
|
|
577
659
|
get.__signal = state;
|
|
578
660
|
if (debugName) get.__name = debugName;
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
const
|
|
661
|
+
let set;
|
|
662
|
+
if (equalsFn) {
|
|
663
|
+
set = (next) => {
|
|
664
|
+
const prev = state.value;
|
|
665
|
+
const newValue = typeof next === "function" ? next(prev) : next;
|
|
666
|
+
if (equalsFn(prev, newValue)) return;
|
|
667
|
+
state.value = newValue;
|
|
668
|
+
state.__v++;
|
|
669
|
+
if (_isDev3) {
|
|
670
|
+
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
671
|
+
if (hook) hook.emit("signal:update", { signal: state, name: debugName, oldValue: prev, newValue });
|
|
672
|
+
}
|
|
673
|
+
if (!enqueueBatchedSignal(state)) {
|
|
674
|
+
notifySubscribers(state);
|
|
675
|
+
}
|
|
676
|
+
};
|
|
677
|
+
} else if (_isDev3) {
|
|
678
|
+
set = (next) => {
|
|
679
|
+
const prev = state.value;
|
|
680
|
+
const newValue = typeof next === "function" ? next(prev) : next;
|
|
681
|
+
if (Object.is(newValue, prev)) return;
|
|
584
682
|
state.value = newValue;
|
|
683
|
+
state.__v++;
|
|
585
684
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
586
|
-
if (hook) hook.emit("signal:update", { signal: state, name: debugName, oldValue, newValue });
|
|
587
|
-
|
|
685
|
+
if (hook) hook.emit("signal:update", { signal: state, name: debugName, oldValue: prev, newValue });
|
|
686
|
+
if (!enqueueBatchedSignal(state)) {
|
|
687
|
+
notifySubscribers(state);
|
|
688
|
+
}
|
|
689
|
+
};
|
|
690
|
+
} else {
|
|
691
|
+
set = (next) => {
|
|
692
|
+
const prev = state.value;
|
|
693
|
+
const newValue = typeof next === "function" ? next(prev) : next;
|
|
694
|
+
if (Object.is(newValue, prev)) return;
|
|
588
695
|
state.value = newValue;
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
696
|
+
state.__v++;
|
|
697
|
+
if (!enqueueBatchedSignal(state)) {
|
|
698
|
+
notifySubscribers(state);
|
|
699
|
+
}
|
|
700
|
+
};
|
|
593
701
|
}
|
|
594
702
|
if (_isDev3) {
|
|
595
703
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|