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