sibujs 1.5.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.cjs +332 -121
- package/dist/browser.d.cts +5 -0
- package/dist/browser.d.ts +5 -0
- package/dist/browser.js +6 -6
- package/dist/build.cjs +1049 -344
- package/dist/build.js +15 -13
- package/dist/cdn.global.js +17 -16
- package/dist/chunk-2RA7SHDA.js +65 -0
- package/dist/chunk-2UPRY23K.js +80 -0
- package/dist/{chunk-BMPL52BF.js → chunk-3DZP6OIT.js} +118 -66
- package/dist/chunk-3JHCYHWN.js +125 -0
- package/dist/{chunk-CZUGLNJS.js → chunk-45YP72ZQ.js} +3 -3
- package/dist/{chunk-JCDUJN2F.js → chunk-AMK2TYNW.js} +490 -153
- package/dist/{chunk-NHUC2QWH.js → chunk-CWBVQML6.js} +1 -1
- package/dist/{chunk-XHK6BDAJ.js → chunk-DRUZZAK4.js} +25 -8
- package/dist/{chunk-RJ46C3CS.js → chunk-GWWURC5M.js} +71 -20
- package/dist/{chunk-3X2YG6YM.js → chunk-JYD2PWXH.js} +59 -28
- package/dist/{chunk-2BYQDGN3.js → chunk-KGYT6UO6.js} +234 -63
- package/dist/{chunk-5X6PP2UK.js → chunk-LMLD24FC.js} +2 -2
- package/dist/{chunk-M4NLBH4I.js → chunk-LYTCUZ7H.js} +3 -2
- package/dist/{chunk-XUEEGU5O.js → chunk-NASX6ST2.js} +16 -4
- package/dist/{chunk-VQDZK23A.js → chunk-O6EFQ3KT.js} +181 -66
- package/dist/{chunk-BGN5ZMP4.js → chunk-OJ3P4ECI.js} +14 -2
- package/dist/chunk-ON5MMR2J.js +1327 -0
- package/dist/{chunk-SFKNRVCU.js → chunk-P2HSJDDN.js} +135 -79
- package/dist/chunk-QO3WC6FS.js +384 -0
- package/dist/{chunk-WZSPOOER.js → chunk-RDTDJCAB.js} +8 -5
- package/dist/{chunk-7GRNSCFT.js → chunk-TH2ILCYW.js} +312 -185
- package/dist/chunk-UCS6AMJ7.js +79 -0
- package/dist/{chunk-VAPYJN4X.js → chunk-V6C4FADE.js} +93 -23
- package/dist/{chunk-OUZZEE4S.js → chunk-WANSMF2L.js} +17 -11
- package/dist/{chunk-23VV7YD3.js → chunk-WIPZPFBQ.js} +25 -30
- package/dist/chunk-WZA53FXU.js +149 -0
- package/dist/{chunk-BGTHZHJ5.js → chunk-ZAQSMOED.js} +188 -44
- package/dist/{customElement-BL3Uo8dL.d.cts → customElement-CPfIrbvg.d.cts} +14 -10
- package/dist/{customElement-BL3Uo8dL.d.ts → customElement-CPfIrbvg.d.ts} +14 -10
- package/dist/data.cjs +536 -151
- package/dist/data.d.cts +20 -2
- package/dist/data.d.ts +20 -2
- package/dist/data.js +11 -9
- package/dist/devtools.cjs +613 -266
- package/dist/devtools.d.cts +1 -1
- package/dist/devtools.d.ts +1 -1
- package/dist/devtools.js +12 -6
- package/dist/ecosystem.cjs +602 -197
- package/dist/ecosystem.d.cts +9 -7
- package/dist/ecosystem.d.ts +9 -7
- package/dist/ecosystem.js +12 -11
- package/dist/extras.cjs +3500 -1608
- package/dist/extras.d.cts +9 -9
- package/dist/extras.d.ts +9 -9
- package/dist/extras.js +58 -45
- package/dist/index.cjs +1055 -344
- package/dist/index.d.cts +85 -8
- package/dist/index.d.ts +85 -8
- package/dist/index.js +32 -16
- package/dist/{introspect-BumjnBKr.d.cts → introspect-2TOlQ7oa.d.cts} +25 -3
- package/dist/{introspect-CZrlcaYy.d.ts → introspect-DnIpHQQz.d.ts} +25 -3
- package/dist/motion.cjs +122 -63
- package/dist/motion.js +4 -4
- package/dist/patterns.cjs +450 -110
- package/dist/patterns.d.cts +11 -12
- package/dist/patterns.d.ts +11 -12
- package/dist/patterns.js +7 -7
- package/dist/performance.cjs +373 -149
- package/dist/performance.d.cts +23 -16
- package/dist/performance.d.ts +23 -16
- package/dist/performance.js +13 -8
- package/dist/plugin-D30wlGW5.d.cts +71 -0
- package/dist/plugin-D30wlGW5.d.ts +71 -0
- package/dist/plugins.cjs +729 -301
- package/dist/plugins.d.cts +10 -3
- package/dist/plugins.d.ts +10 -3
- package/dist/plugins.js +106 -38
- package/dist/{ssr-Do_SiVoL.d.cts → ssr-CrVNy6Pa.d.cts} +9 -15
- package/dist/{ssr-Do_SiVoL.d.ts → ssr-CrVNy6Pa.d.ts} +9 -15
- package/dist/{ssr-4PBXAOO3.js → ssr-FXD2PPMC.js} +4 -3
- package/dist/ssr.cjs +736 -274
- package/dist/ssr.d.cts +26 -6
- package/dist/ssr.d.ts +26 -6
- package/dist/ssr.js +12 -11
- package/dist/{tagFactory-DaJ0YWX6.d.cts → tagFactory-S17H2qxu.d.cts} +9 -1
- package/dist/{tagFactory-DaJ0YWX6.d.ts → tagFactory-S17H2qxu.d.ts} +9 -1
- package/dist/testing.cjs +303 -76
- package/dist/testing.d.cts +17 -4
- package/dist/testing.d.ts +17 -4
- package/dist/testing.js +100 -44
- package/dist/ui.cjs +589 -178
- package/dist/ui.d.cts +1 -1
- package/dist/ui.d.ts +1 -1
- package/dist/ui.js +20 -17
- package/dist/widgets.cjs +1103 -146
- package/dist/widgets.d.cts +104 -2
- package/dist/widgets.d.ts +104 -2
- package/dist/widgets.js +9 -7
- package/package.json +8 -2
- package/dist/chunk-32DY64NT.js +0 -282
- package/dist/chunk-3AIRKM3B.js +0 -1263
- package/dist/chunk-3ARAQO7B.js +0 -398
- package/dist/chunk-3CRQALYP.js +0 -877
- package/dist/chunk-4EI4AG32.js +0 -482
- package/dist/chunk-4MYMUBRS.js +0 -21
- package/dist/chunk-5ZYQ6KDD.js +0 -154
- package/dist/chunk-6BMPXPUW.js +0 -26
- package/dist/chunk-6HLLIF3K.js +0 -398
- package/dist/chunk-6LSNVCS2.js +0 -937
- package/dist/chunk-6SA3QQES.js +0 -61
- package/dist/chunk-77L6NL3X.js +0 -1097
- package/dist/chunk-7BF6TK55.js +0 -1097
- package/dist/chunk-7TQKR4PP.js +0 -294
- package/dist/chunk-7V26P53V.js +0 -712
- package/dist/chunk-AZ3ISID5.js +0 -298
- package/dist/chunk-B7SWRFUT.js +0 -332
- package/dist/chunk-BTU3TJDS.js +0 -365
- package/dist/chunk-BW3WT46K.js +0 -937
- package/dist/chunk-C6KFWOFV.js +0 -616
- package/dist/chunk-CHF5OHIA.js +0 -61
- package/dist/chunk-CHJ27IGK.js +0 -26
- package/dist/chunk-CMBFNA7L.js +0 -27
- package/dist/chunk-DAHRH4ON.js +0 -331
- package/dist/chunk-DKOHBI74.js +0 -924
- package/dist/chunk-DTCOOBMX.js +0 -725
- package/dist/chunk-EBGIRKQY.js +0 -616
- package/dist/chunk-EUZND3CB.js +0 -27
- package/dist/chunk-EVCZO745.js +0 -365
- package/dist/chunk-EWFVA3TJ.js +0 -282
- package/dist/chunk-F3FA4F32.js +0 -292
- package/dist/chunk-FGOEVHY3.js +0 -60
- package/dist/chunk-G3BOQPVO.js +0 -365
- package/dist/chunk-GCOK2LC3.js +0 -282
- package/dist/chunk-GJPXRJ45.js +0 -37
- package/dist/chunk-HGMJFBC7.js +0 -654
- package/dist/chunk-JAKHTMQU.js +0 -1000
- package/dist/chunk-JCI5M6U6.js +0 -956
- package/dist/chunk-K4G4ZQNR.js +0 -286
- package/dist/chunk-K5ZUMYVS.js +0 -89
- package/dist/chunk-KQPDEVVS.js +0 -398
- package/dist/chunk-L6JRBDNS.js +0 -60
- package/dist/chunk-LA6KQEDU.js +0 -712
- package/dist/chunk-MB6QFH3I.js +0 -2776
- package/dist/chunk-MDVXJWFN.js +0 -304
- package/dist/chunk-MEZVEBPN.js +0 -2008
- package/dist/chunk-MK4ERFYL.js +0 -2249
- package/dist/chunk-MLKGABMK.js +0 -9
- package/dist/chunk-MQ5GOYPH.js +0 -2249
- package/dist/chunk-MYRV7VDM.js +0 -742
- package/dist/chunk-N6IZB6KJ.js +0 -567
- package/dist/chunk-NEKUBFPT.js +0 -60
- package/dist/chunk-NMRUZALC.js +0 -1097
- package/dist/chunk-NYVAC6P5.js +0 -37
- package/dist/chunk-NZIIMDWI.js +0 -84
- package/dist/chunk-OF7UZIVB.js +0 -725
- package/dist/chunk-P3XWXJZU.js +0 -282
- package/dist/chunk-P6W3STU4.js +0 -2249
- package/dist/chunk-PBHF5WKN.js +0 -616
- package/dist/chunk-PDZQY43A.js +0 -616
- package/dist/chunk-PTQJDMRT.js +0 -146
- package/dist/chunk-PZEGYCF5.js +0 -61
- package/dist/chunk-QBMDLBU2.js +0 -975
- package/dist/chunk-QWZG56ET.js +0 -2744
- package/dist/chunk-RQGQSLQK.js +0 -725
- package/dist/chunk-SDLZDHKP.js +0 -107
- package/dist/chunk-TDGZL5CU.js +0 -365
- package/dist/chunk-TNQWPPE6.js +0 -37
- package/dist/chunk-TSOKIX5Z.js +0 -654
- package/dist/chunk-UHNL42EF.js +0 -2730
- package/dist/chunk-UNXCEF6S.js +0 -21
- package/dist/chunk-V2XTI523.js +0 -347
- package/dist/chunk-VAU366PN.js +0 -2241
- package/dist/chunk-VMVDTCXB.js +0 -712
- package/dist/chunk-VQNQZCWJ.js +0 -61
- package/dist/chunk-VRW3FULF.js +0 -725
- package/dist/chunk-WADYRCO2.js +0 -304
- package/dist/chunk-WILQZRO4.js +0 -282
- package/dist/chunk-WR5D4EGH.js +0 -26
- package/dist/chunk-WUHJISPP.js +0 -298
- package/dist/chunk-XYU6TZOW.js +0 -182
- package/dist/chunk-Y6GP4QGG.js +0 -276
- package/dist/chunk-YECR7UIA.js +0 -347
- package/dist/chunk-YUTWTI4B.js +0 -654
- package/dist/chunk-Z65KYU7I.js +0 -26
- package/dist/chunk-Z6POF5YC.js +0 -975
- package/dist/chunk-ZBJP6WFL.js +0 -482
- package/dist/chunk-ZD6OAMTH.js +0 -277
- package/dist/chunk-ZWKZCBO6.js +0 -317
- package/dist/contracts-DDrwxvJ-.d.cts +0 -245
- package/dist/contracts-DDrwxvJ-.d.ts +0 -245
- package/dist/contracts-DOrhwbke.d.cts +0 -245
- package/dist/contracts-DOrhwbke.d.ts +0 -245
- package/dist/contracts-xo5ckdRP.d.cts +0 -240
- package/dist/contracts-xo5ckdRP.d.ts +0 -240
- package/dist/customElement-BKQfbSZQ.d.cts +0 -262
- package/dist/customElement-BKQfbSZQ.d.ts +0 -262
- package/dist/customElement-D2DJp_xn.d.cts +0 -313
- package/dist/customElement-D2DJp_xn.d.ts +0 -313
- package/dist/customElement-yz8uyk-0.d.cts +0 -308
- package/dist/customElement-yz8uyk-0.d.ts +0 -308
- package/dist/introspect-Cb0zgpi2.d.cts +0 -477
- package/dist/introspect-Y2xNXGSf.d.ts +0 -477
- package/dist/plugin-Bek4RhJY.d.cts +0 -43
- package/dist/plugin-Bek4RhJY.d.ts +0 -43
- package/dist/ssr-3RXHP5ES.js +0 -38
- package/dist/ssr-6GIMY5MX.js +0 -38
- package/dist/ssr-BA6sxxUd.d.cts +0 -135
- package/dist/ssr-BA6sxxUd.d.ts +0 -135
- package/dist/ssr-WKUPVSSK.js +0 -36
- package/dist/tagFactory-Dl8QCLga.d.cts +0 -23
- package/dist/tagFactory-Dl8QCLga.d.ts +0 -23
package/dist/data.cjs
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// data.ts
|
|
21
21
|
var data_exports = {};
|
|
22
22
|
__export(data_exports, {
|
|
23
|
+
__resetQueryCache: () => __resetQueryCache,
|
|
23
24
|
calculateDelay: () => calculateDelay,
|
|
24
25
|
clearQueryCache: () => clearQueryCache,
|
|
25
26
|
debounce: () => debounce,
|
|
@@ -50,26 +51,39 @@ function isDev() {
|
|
|
50
51
|
var _isDev = isDev();
|
|
51
52
|
function devAssert(condition, message) {
|
|
52
53
|
if (_isDev && !condition) {
|
|
53
|
-
throw new Error(`[
|
|
54
|
+
throw new Error(`[SibuJS] ${message}`);
|
|
54
55
|
}
|
|
55
56
|
}
|
|
56
57
|
function devWarn(message) {
|
|
57
58
|
if (_isDev) {
|
|
58
|
-
console.warn(`[
|
|
59
|
+
console.warn(`[SibuJS] ${message}`);
|
|
59
60
|
}
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
// src/reactivity/track.ts
|
|
63
64
|
var _isDev2 = isDev();
|
|
64
|
-
var
|
|
65
|
-
var
|
|
65
|
+
var STACK_INITIAL = 32;
|
|
66
|
+
var STACK_SHRINK_THRESHOLD = 128;
|
|
67
|
+
var subscriberStack = new Array(STACK_INITIAL);
|
|
68
|
+
var stackCapacity = STACK_INITIAL;
|
|
66
69
|
var stackTop = -1;
|
|
67
70
|
var currentSubscriber = null;
|
|
68
|
-
var signalSubscribers = /* @__PURE__ */ new WeakMap();
|
|
69
71
|
var SUBS = "__s";
|
|
72
|
+
function syncFastPath(signal2, subs) {
|
|
73
|
+
const size = subs.size;
|
|
74
|
+
if (size === 0) {
|
|
75
|
+
signal2.__f = void 0;
|
|
76
|
+
delete signal2[SUBS];
|
|
77
|
+
} else if (size === 1) {
|
|
78
|
+
signal2.__f = subs.values().next().value;
|
|
79
|
+
} else {
|
|
80
|
+
signal2.__f = void 0;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
70
83
|
var notifyDepth = 0;
|
|
71
84
|
var pendingQueue = [];
|
|
72
85
|
var pendingSet = /* @__PURE__ */ new Set();
|
|
86
|
+
var propagateStack = [];
|
|
73
87
|
function safeInvoke(sub) {
|
|
74
88
|
try {
|
|
75
89
|
sub();
|
|
@@ -78,6 +92,47 @@ function safeInvoke(sub) {
|
|
|
78
92
|
}
|
|
79
93
|
}
|
|
80
94
|
var trackingSuspended = false;
|
|
95
|
+
var subscriberEpochCounter = 0;
|
|
96
|
+
function retrack(effectFn, subscriber) {
|
|
97
|
+
const prev = currentSubscriber;
|
|
98
|
+
currentSubscriber = subscriber;
|
|
99
|
+
const sub = subscriber;
|
|
100
|
+
const epoch = ++subscriberEpochCounter;
|
|
101
|
+
sub._epoch = epoch;
|
|
102
|
+
try {
|
|
103
|
+
effectFn();
|
|
104
|
+
} finally {
|
|
105
|
+
currentSubscriber = prev;
|
|
106
|
+
pruneStaleDeps(sub, epoch);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function pruneStaleDeps(sub, currentEpoch) {
|
|
110
|
+
if (sub._dep !== void 0) {
|
|
111
|
+
if (sub._depEpoch !== currentEpoch) {
|
|
112
|
+
const sig = sub._dep;
|
|
113
|
+
const subs = sig[SUBS];
|
|
114
|
+
if (subs?.delete(sub)) syncFastPath(sig, subs);
|
|
115
|
+
sub._dep = void 0;
|
|
116
|
+
sub._depEpoch = void 0;
|
|
117
|
+
}
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
const deps = sub._deps;
|
|
121
|
+
if (!deps || deps.size === 0) return;
|
|
122
|
+
let stales;
|
|
123
|
+
for (const [signal2, epoch] of deps) {
|
|
124
|
+
if (epoch !== currentEpoch) {
|
|
125
|
+
(stales ?? (stales = [])).push(signal2);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (!stales) return;
|
|
129
|
+
for (const signal2 of stales) {
|
|
130
|
+
deps.delete(signal2);
|
|
131
|
+
const sig = signal2;
|
|
132
|
+
const subs = sig[SUBS];
|
|
133
|
+
if (subs?.delete(sub)) syncFastPath(sig, subs);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
81
136
|
function track(effectFn, subscriber) {
|
|
82
137
|
if (!subscriber) subscriber = effectFn;
|
|
83
138
|
cleanup(subscriber);
|
|
@@ -93,37 +148,49 @@ function track(effectFn, subscriber) {
|
|
|
93
148
|
} finally {
|
|
94
149
|
stackTop--;
|
|
95
150
|
currentSubscriber = stackTop >= 0 ? subscriberStack[stackTop] : null;
|
|
151
|
+
if (stackTop < 0 && stackCapacity > STACK_SHRINK_THRESHOLD) {
|
|
152
|
+
stackCapacity = Math.max(STACK_INITIAL, stackCapacity >>> 1);
|
|
153
|
+
subscriberStack.length = stackCapacity;
|
|
154
|
+
}
|
|
96
155
|
}
|
|
97
156
|
return () => cleanup(subscriber);
|
|
98
157
|
}
|
|
99
158
|
function recordDependency(signal2) {
|
|
100
159
|
if (!currentSubscriber) return;
|
|
101
160
|
const sub = currentSubscriber;
|
|
102
|
-
|
|
161
|
+
const epoch = sub._epoch;
|
|
162
|
+
if (sub._dep === signal2) {
|
|
163
|
+
sub._depEpoch = epoch;
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
103
166
|
const deps = sub._deps;
|
|
104
167
|
if (deps) {
|
|
105
|
-
|
|
106
|
-
deps.add(signal2);
|
|
168
|
+
deps.set(signal2, epoch);
|
|
107
169
|
} else if (sub._dep !== void 0) {
|
|
108
|
-
const
|
|
109
|
-
set
|
|
110
|
-
set
|
|
111
|
-
sub._deps =
|
|
170
|
+
const map = /* @__PURE__ */ new Map();
|
|
171
|
+
map.set(sub._dep, sub._depEpoch);
|
|
172
|
+
map.set(signal2, epoch);
|
|
173
|
+
sub._deps = map;
|
|
112
174
|
sub._dep = void 0;
|
|
175
|
+
sub._depEpoch = void 0;
|
|
113
176
|
} else {
|
|
114
177
|
sub._dep = signal2;
|
|
178
|
+
sub._depEpoch = epoch;
|
|
115
179
|
}
|
|
116
|
-
|
|
180
|
+
const sig = signal2;
|
|
181
|
+
let subs = sig[SUBS];
|
|
117
182
|
if (!subs) {
|
|
118
183
|
subs = /* @__PURE__ */ new Set();
|
|
119
|
-
|
|
120
|
-
signal2[SUBS] = subs;
|
|
184
|
+
sig[SUBS] = subs;
|
|
121
185
|
}
|
|
186
|
+
const prevSize = subs.size;
|
|
122
187
|
subs.add(currentSubscriber);
|
|
123
|
-
if (subs.size
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
188
|
+
if (subs.size !== prevSize) {
|
|
189
|
+
if (subs.size === 1) {
|
|
190
|
+
sig.__f = currentSubscriber;
|
|
191
|
+
} else if (sig.__f !== void 0) {
|
|
192
|
+
sig.__f = void 0;
|
|
193
|
+
}
|
|
127
194
|
}
|
|
128
195
|
}
|
|
129
196
|
function queueSignalNotification(signal2) {
|
|
@@ -138,66 +205,102 @@ function queueSignalNotification(signal2) {
|
|
|
138
205
|
}
|
|
139
206
|
}
|
|
140
207
|
}
|
|
141
|
-
var
|
|
208
|
+
var maxSubscriberRepeats = 50;
|
|
209
|
+
var maxDrainIterations = 1e6;
|
|
210
|
+
var drainEpoch = 0;
|
|
211
|
+
function tickRepeat(sub) {
|
|
212
|
+
const s = sub;
|
|
213
|
+
if (s._runEpoch !== drainEpoch) {
|
|
214
|
+
s._runEpoch = drainEpoch;
|
|
215
|
+
s._runs = 1;
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
return ++s._runs > maxSubscriberRepeats;
|
|
219
|
+
}
|
|
220
|
+
function cycleError(sub) {
|
|
221
|
+
if (typeof console !== "undefined") {
|
|
222
|
+
const name = sub.__name ?? "<unnamed>";
|
|
223
|
+
console.error(
|
|
224
|
+
`[SibuJS] subscriber "${name}" fired more than ${maxSubscriberRepeats} times \u2014 likely a write-reads-self cycle between effects/signals. Breaking to prevent infinite loop.`
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
function absoluteDrainError() {
|
|
229
|
+
if (typeof console !== "undefined") {
|
|
230
|
+
console.error(
|
|
231
|
+
`[SibuJS] Notification drain exceeded ${maxDrainIterations} iterations \u2014 absolute safety net tripped. Breaking to prevent infinite loop.`
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
function drainQueue() {
|
|
236
|
+
let i = 0;
|
|
237
|
+
while (i < pendingQueue.length) {
|
|
238
|
+
if (i >= maxDrainIterations) {
|
|
239
|
+
absoluteDrainError();
|
|
240
|
+
break;
|
|
241
|
+
}
|
|
242
|
+
const sub = pendingQueue[i++];
|
|
243
|
+
if (tickRepeat(sub)) {
|
|
244
|
+
cycleError(sub);
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
247
|
+
pendingSet.delete(sub);
|
|
248
|
+
safeInvoke(sub);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
142
251
|
function drainNotificationQueue() {
|
|
143
252
|
if (notifyDepth > 0) return;
|
|
144
253
|
notifyDepth++;
|
|
254
|
+
drainEpoch++;
|
|
145
255
|
try {
|
|
146
|
-
|
|
147
|
-
while (i < pendingQueue.length) {
|
|
148
|
-
if (i >= MAX_DRAIN_ITERATIONS) {
|
|
149
|
-
if (typeof console !== "undefined") {
|
|
150
|
-
console.error(
|
|
151
|
-
`[SibuJS] Notification queue exceeded ${MAX_DRAIN_ITERATIONS} iterations \u2014 likely an effect that writes to a signal it reads. Breaking to prevent infinite loop.`
|
|
152
|
-
);
|
|
153
|
-
}
|
|
154
|
-
break;
|
|
155
|
-
}
|
|
156
|
-
safeInvoke(pendingQueue[i]);
|
|
157
|
-
i++;
|
|
158
|
-
}
|
|
256
|
+
drainQueue();
|
|
159
257
|
} finally {
|
|
160
|
-
pendingQueue.length = 0;
|
|
161
|
-
pendingSet.clear();
|
|
162
258
|
notifyDepth--;
|
|
259
|
+
if (notifyDepth === 0) {
|
|
260
|
+
pendingQueue.length = 0;
|
|
261
|
+
pendingSet.clear();
|
|
262
|
+
}
|
|
163
263
|
}
|
|
164
264
|
}
|
|
165
265
|
function propagateDirty(sub) {
|
|
166
266
|
sub();
|
|
167
|
-
|
|
168
|
-
|
|
267
|
+
const rootSig = sub._sig;
|
|
268
|
+
if (!rootSig) return;
|
|
269
|
+
const stack = propagateStack;
|
|
270
|
+
const baseLen = stack.length;
|
|
271
|
+
stack.push(rootSig);
|
|
272
|
+
while (stack.length > baseLen) {
|
|
273
|
+
const sig = stack.pop();
|
|
169
274
|
const first = sig.__f;
|
|
170
275
|
if (first) {
|
|
171
276
|
if (first._c) {
|
|
172
277
|
const nSig = first._sig;
|
|
173
|
-
nSig._d
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
if (!pendingSet.has(first)) {
|
|
278
|
+
if (!nSig._d) {
|
|
279
|
+
nSig._d = true;
|
|
280
|
+
stack.push(nSig);
|
|
281
|
+
}
|
|
282
|
+
} else if (!pendingSet.has(first)) {
|
|
178
283
|
pendingSet.add(first);
|
|
179
284
|
pendingQueue.push(first);
|
|
180
285
|
}
|
|
181
|
-
|
|
286
|
+
continue;
|
|
182
287
|
}
|
|
183
288
|
const subs = sig[SUBS];
|
|
184
|
-
if (!subs)
|
|
185
|
-
let nextSig;
|
|
289
|
+
if (!subs) continue;
|
|
186
290
|
for (const s of subs) {
|
|
187
291
|
if (s._c) {
|
|
188
|
-
s();
|
|
189
292
|
const nSig = s._sig;
|
|
190
|
-
if (nSig && !
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
293
|
+
if (nSig && !nSig._d) {
|
|
294
|
+
nSig._d = true;
|
|
295
|
+
stack.push(nSig);
|
|
296
|
+
} else if (!nSig) {
|
|
297
|
+
s();
|
|
194
298
|
}
|
|
195
299
|
} else if (!pendingSet.has(s)) {
|
|
196
300
|
pendingSet.add(s);
|
|
197
301
|
pendingQueue.push(s);
|
|
198
302
|
}
|
|
199
303
|
}
|
|
200
|
-
sig = nextSig;
|
|
201
304
|
}
|
|
202
305
|
}
|
|
203
306
|
function notifySubscribers(signal2) {
|
|
@@ -213,21 +316,22 @@ function notifySubscribers(signal2) {
|
|
|
213
316
|
return;
|
|
214
317
|
}
|
|
215
318
|
notifyDepth++;
|
|
319
|
+
drainEpoch++;
|
|
216
320
|
try {
|
|
217
321
|
if (first._c) {
|
|
218
322
|
propagateDirty(first);
|
|
323
|
+
} else if (tickRepeat(first)) {
|
|
324
|
+
cycleError(first);
|
|
219
325
|
} else {
|
|
220
326
|
safeInvoke(first);
|
|
221
327
|
}
|
|
222
|
-
|
|
223
|
-
while (i < pendingQueue.length) {
|
|
224
|
-
safeInvoke(pendingQueue[i]);
|
|
225
|
-
i++;
|
|
226
|
-
}
|
|
328
|
+
drainQueue();
|
|
227
329
|
} finally {
|
|
228
|
-
pendingQueue.length = 0;
|
|
229
|
-
pendingSet.clear();
|
|
230
330
|
notifyDepth--;
|
|
331
|
+
if (notifyDepth === 0) {
|
|
332
|
+
pendingQueue.length = 0;
|
|
333
|
+
pendingSet.clear();
|
|
334
|
+
}
|
|
231
335
|
}
|
|
232
336
|
return;
|
|
233
337
|
}
|
|
@@ -245,57 +349,45 @@ function notifySubscribers(signal2) {
|
|
|
245
349
|
return;
|
|
246
350
|
}
|
|
247
351
|
notifyDepth++;
|
|
352
|
+
drainEpoch++;
|
|
248
353
|
try {
|
|
249
|
-
let directCount = 0;
|
|
250
354
|
for (const sub of subs) {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
for (let i2 = 0; i2 < directCount; i2++) {
|
|
259
|
-
if (!pendingQueue[i2]._c) {
|
|
260
|
-
if (!pendingSet.has(pendingQueue[i2])) {
|
|
261
|
-
safeInvoke(pendingQueue[i2]);
|
|
262
|
-
}
|
|
355
|
+
if (sub._c) {
|
|
356
|
+
propagateDirty(sub);
|
|
357
|
+
} else if (!pendingSet.has(sub)) {
|
|
358
|
+
pendingSet.add(sub);
|
|
359
|
+
pendingQueue.push(sub);
|
|
263
360
|
}
|
|
264
361
|
}
|
|
265
|
-
|
|
266
|
-
while (i < pendingQueue.length) {
|
|
267
|
-
safeInvoke(pendingQueue[i]);
|
|
268
|
-
i++;
|
|
269
|
-
}
|
|
362
|
+
drainQueue();
|
|
270
363
|
} finally {
|
|
271
|
-
pendingQueue.length = 0;
|
|
272
|
-
pendingSet.clear();
|
|
273
364
|
notifyDepth--;
|
|
365
|
+
if (notifyDepth === 0) {
|
|
366
|
+
pendingQueue.length = 0;
|
|
367
|
+
pendingSet.clear();
|
|
368
|
+
}
|
|
274
369
|
}
|
|
275
370
|
}
|
|
276
371
|
function cleanup(subscriber) {
|
|
277
372
|
const sub = subscriber;
|
|
278
373
|
const singleDep = sub._dep;
|
|
279
374
|
if (singleDep !== void 0) {
|
|
280
|
-
const
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
singleDep.__f = void 0;
|
|
285
|
-
}
|
|
375
|
+
const sig = singleDep;
|
|
376
|
+
const subs = sig[SUBS];
|
|
377
|
+
if (subs?.delete(subscriber)) {
|
|
378
|
+
syncFastPath(sig, subs);
|
|
286
379
|
}
|
|
287
380
|
sub._dep = void 0;
|
|
381
|
+
sub._depEpoch = void 0;
|
|
288
382
|
return;
|
|
289
383
|
}
|
|
290
384
|
const deps = sub._deps;
|
|
291
385
|
if (!deps || deps.size === 0) return;
|
|
292
|
-
for (const signal2 of deps) {
|
|
293
|
-
const
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
signal2.__f = void 0;
|
|
298
|
-
}
|
|
386
|
+
for (const signal2 of deps.keys()) {
|
|
387
|
+
const sig = signal2;
|
|
388
|
+
const subs = sig[SUBS];
|
|
389
|
+
if (subs?.delete(subscriber)) {
|
|
390
|
+
syncFastPath(sig, subs);
|
|
299
391
|
}
|
|
300
392
|
}
|
|
301
393
|
deps.clear();
|
|
@@ -305,6 +397,7 @@ function cleanup(subscriber) {
|
|
|
305
397
|
function derived(getter, options) {
|
|
306
398
|
devAssert(typeof getter === "function", "derived: argument must be a getter function.");
|
|
307
399
|
const debugName = options?.name;
|
|
400
|
+
const equals = options?.equals;
|
|
308
401
|
const cs = {};
|
|
309
402
|
cs._d = false;
|
|
310
403
|
cs._g = getter;
|
|
@@ -315,8 +408,14 @@ function derived(getter, options) {
|
|
|
315
408
|
markDirty._c = 1;
|
|
316
409
|
markDirty._sig = cs;
|
|
317
410
|
track(() => {
|
|
318
|
-
|
|
319
|
-
|
|
411
|
+
let threw = true;
|
|
412
|
+
try {
|
|
413
|
+
cs._v = getter();
|
|
414
|
+
cs._d = false;
|
|
415
|
+
threw = false;
|
|
416
|
+
} finally {
|
|
417
|
+
if (threw) cs._d = true;
|
|
418
|
+
}
|
|
320
419
|
}, markDirty);
|
|
321
420
|
const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
322
421
|
let evaluating = false;
|
|
@@ -329,11 +428,16 @@ function derived(getter, options) {
|
|
|
329
428
|
if (trackingSuspended) {
|
|
330
429
|
if (cs._d) {
|
|
331
430
|
evaluating = true;
|
|
431
|
+
let threw = true;
|
|
332
432
|
try {
|
|
333
|
-
|
|
334
|
-
|
|
433
|
+
retrack(() => {
|
|
434
|
+
cs._v = getter();
|
|
435
|
+
cs._d = false;
|
|
436
|
+
threw = false;
|
|
437
|
+
}, markDirty);
|
|
335
438
|
} finally {
|
|
336
439
|
evaluating = false;
|
|
440
|
+
if (threw) cs._d = true;
|
|
337
441
|
}
|
|
338
442
|
}
|
|
339
443
|
return cs._v;
|
|
@@ -342,13 +446,17 @@ function derived(getter, options) {
|
|
|
342
446
|
if (cs._d) {
|
|
343
447
|
const oldValue = cs._v;
|
|
344
448
|
evaluating = true;
|
|
449
|
+
let threw = true;
|
|
345
450
|
try {
|
|
346
|
-
|
|
451
|
+
retrack(() => {
|
|
452
|
+
const next = getter();
|
|
453
|
+
cs._v = equals && cs._v !== void 0 ? equals(cs._v, next) ? cs._v : next : next;
|
|
347
454
|
cs._d = false;
|
|
348
|
-
|
|
455
|
+
threw = false;
|
|
349
456
|
}, markDirty);
|
|
350
457
|
} finally {
|
|
351
458
|
evaluating = false;
|
|
459
|
+
if (threw) cs._d = true;
|
|
352
460
|
}
|
|
353
461
|
if (hook && oldValue !== cs._v) {
|
|
354
462
|
hook.emit("computed:update", { signal: cs, oldValue, newValue: cs._v });
|
|
@@ -366,9 +474,28 @@ function derived(getter, options) {
|
|
|
366
474
|
}
|
|
367
475
|
|
|
368
476
|
// src/core/ssr-context.ts
|
|
369
|
-
var
|
|
477
|
+
var als = null;
|
|
478
|
+
try {
|
|
479
|
+
if (typeof process !== "undefined" && process.versions && process.versions.node) {
|
|
480
|
+
const req = Function("return typeof require==='function'?require:null")();
|
|
481
|
+
if (req) {
|
|
482
|
+
const mod = req("node:async_hooks");
|
|
483
|
+
als = new mod.AsyncLocalStorage();
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
} catch {
|
|
487
|
+
als = null;
|
|
488
|
+
}
|
|
489
|
+
var fallbackStore = { ssr: false, suspenseIdCounter: 0 };
|
|
490
|
+
function getSSRStore() {
|
|
491
|
+
if (als) {
|
|
492
|
+
const s = als.getStore();
|
|
493
|
+
if (s) return s;
|
|
494
|
+
}
|
|
495
|
+
return fallbackStore;
|
|
496
|
+
}
|
|
370
497
|
function isSSR() {
|
|
371
|
-
return
|
|
498
|
+
return getSSRStore().ssr;
|
|
372
499
|
}
|
|
373
500
|
|
|
374
501
|
// src/core/signals/effect.ts
|
|
@@ -378,26 +505,114 @@ function effect(effectFn, options) {
|
|
|
378
505
|
if (isSSR()) return () => {
|
|
379
506
|
};
|
|
380
507
|
const onError = options?.onError;
|
|
508
|
+
let userCleanups = [];
|
|
509
|
+
const onCleanup = (fn) => {
|
|
510
|
+
userCleanups.push(fn);
|
|
511
|
+
};
|
|
512
|
+
const runUserCleanups = () => {
|
|
513
|
+
if (userCleanups.length === 0) return;
|
|
514
|
+
const list = userCleanups;
|
|
515
|
+
userCleanups = [];
|
|
516
|
+
for (let i = list.length - 1; i >= 0; i--) {
|
|
517
|
+
try {
|
|
518
|
+
list[i]();
|
|
519
|
+
} catch (err) {
|
|
520
|
+
if (typeof console !== "undefined") {
|
|
521
|
+
console.warn("[SibuJS effect] onCleanup threw:", err);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
const invokeBody = () => effectFn(onCleanup);
|
|
381
527
|
const wrappedFn = onError ? () => {
|
|
382
528
|
try {
|
|
383
|
-
|
|
529
|
+
invokeBody();
|
|
384
530
|
} catch (err) {
|
|
385
531
|
onError(err);
|
|
386
532
|
}
|
|
387
|
-
} :
|
|
533
|
+
} : invokeBody;
|
|
388
534
|
let cleanupHandle = () => {
|
|
389
535
|
};
|
|
536
|
+
let running = false;
|
|
537
|
+
let rerunPending = false;
|
|
538
|
+
const MAX_RERUNS = 100;
|
|
390
539
|
const subscriber = () => {
|
|
391
|
-
|
|
392
|
-
|
|
540
|
+
if (running) {
|
|
541
|
+
rerunPending = true;
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
running = true;
|
|
545
|
+
try {
|
|
546
|
+
let reruns = 0;
|
|
547
|
+
do {
|
|
548
|
+
rerunPending = false;
|
|
549
|
+
runUserCleanups();
|
|
550
|
+
cleanupHandle();
|
|
551
|
+
cleanupHandle = track(wrappedFn, subscriber);
|
|
552
|
+
if (++reruns > MAX_RERUNS) {
|
|
553
|
+
if (_g.__SIBU_DEV_WARN__ !== false && typeof console !== "undefined") {
|
|
554
|
+
console.error(
|
|
555
|
+
`[SibuJS] effect re-requested itself ${MAX_RERUNS}+ times \u2014 likely a write-reads-self cycle. Breaking to prevent infinite loop.`
|
|
556
|
+
);
|
|
557
|
+
}
|
|
558
|
+
rerunPending = false;
|
|
559
|
+
break;
|
|
560
|
+
}
|
|
561
|
+
} while (rerunPending);
|
|
562
|
+
} finally {
|
|
563
|
+
running = false;
|
|
564
|
+
rerunPending = false;
|
|
565
|
+
}
|
|
393
566
|
};
|
|
394
|
-
|
|
567
|
+
running = true;
|
|
568
|
+
try {
|
|
569
|
+
let reruns = 0;
|
|
570
|
+
do {
|
|
571
|
+
rerunPending = false;
|
|
572
|
+
runUserCleanups();
|
|
573
|
+
cleanupHandle();
|
|
574
|
+
cleanupHandle = track(wrappedFn, subscriber);
|
|
575
|
+
if (++reruns > MAX_RERUNS) {
|
|
576
|
+
if (_g.__SIBU_DEV_WARN__ !== false && typeof console !== "undefined") {
|
|
577
|
+
console.error(
|
|
578
|
+
`[SibuJS] effect re-requested itself ${MAX_RERUNS}+ times on initial run \u2014 likely a write-reads-self cycle. Breaking to prevent infinite loop.`
|
|
579
|
+
);
|
|
580
|
+
}
|
|
581
|
+
rerunPending = false;
|
|
582
|
+
break;
|
|
583
|
+
}
|
|
584
|
+
} while (rerunPending);
|
|
585
|
+
} finally {
|
|
586
|
+
running = false;
|
|
587
|
+
rerunPending = false;
|
|
588
|
+
}
|
|
395
589
|
const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
396
590
|
if (hook) hook.emit("effect:create", { effectFn });
|
|
591
|
+
let disposed = false;
|
|
397
592
|
return () => {
|
|
593
|
+
if (disposed) return;
|
|
594
|
+
disposed = true;
|
|
398
595
|
const h = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
399
|
-
if (h)
|
|
400
|
-
|
|
596
|
+
if (h) {
|
|
597
|
+
try {
|
|
598
|
+
h.emit("effect:destroy", { effectFn });
|
|
599
|
+
} catch {
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
try {
|
|
603
|
+
runUserCleanups();
|
|
604
|
+
} catch (err) {
|
|
605
|
+
if (typeof console !== "undefined") {
|
|
606
|
+
console.warn("[SibuJS effect] onCleanup threw during dispose:", err);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
try {
|
|
610
|
+
cleanupHandle();
|
|
611
|
+
} catch (err) {
|
|
612
|
+
if (typeof console !== "undefined") {
|
|
613
|
+
console.warn("[SibuJS effect] dispose threw:", err);
|
|
614
|
+
}
|
|
615
|
+
}
|
|
401
616
|
};
|
|
402
617
|
}
|
|
403
618
|
|
|
@@ -421,10 +636,13 @@ function enqueueBatchedSignal(signal2) {
|
|
|
421
636
|
return true;
|
|
422
637
|
}
|
|
423
638
|
function flushBatch() {
|
|
424
|
-
|
|
425
|
-
|
|
639
|
+
try {
|
|
640
|
+
for (const signal2 of pendingSignals) {
|
|
641
|
+
queueSignalNotification(signal2);
|
|
642
|
+
}
|
|
643
|
+
} finally {
|
|
644
|
+
pendingSignals.clear();
|
|
426
645
|
}
|
|
427
|
-
pendingSignals.clear();
|
|
428
646
|
drainNotificationQueue();
|
|
429
647
|
}
|
|
430
648
|
|
|
@@ -481,10 +699,12 @@ function calculateDelay(attempt, strategy, baseDelay, maxDelay, jitter) {
|
|
|
481
699
|
break;
|
|
482
700
|
}
|
|
483
701
|
delay = Math.min(delay, maxDelay);
|
|
702
|
+
if (!Number.isFinite(delay)) delay = Number.MAX_SAFE_INTEGER;
|
|
484
703
|
if (jitter > 0) {
|
|
485
704
|
const jitterRange = delay * jitter;
|
|
486
705
|
delay += (Math.random() * 2 - 1) * jitterRange;
|
|
487
706
|
}
|
|
707
|
+
if (!Number.isFinite(delay) || Number.isNaN(delay)) delay = 0;
|
|
488
708
|
return Math.max(0, delay);
|
|
489
709
|
}
|
|
490
710
|
async function withRetry(fn, options, onRetry, signal2) {
|
|
@@ -498,6 +718,7 @@ async function withRetry(fn, options, onRetry, signal2) {
|
|
|
498
718
|
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
499
719
|
if (signal2?.aborted) throw new DOMException("Aborted", "AbortError");
|
|
500
720
|
try {
|
|
721
|
+
if (signal2?.aborted) throw new DOMException("Aborted", "AbortError");
|
|
501
722
|
return await fn();
|
|
502
723
|
} catch (error) {
|
|
503
724
|
lastError = error;
|
|
@@ -579,24 +800,46 @@ function query(key, fetcher, options = {}) {
|
|
|
579
800
|
let entry = queryCache.get(key2);
|
|
580
801
|
if (!entry) {
|
|
581
802
|
entry = getOrCreateEntry(key2);
|
|
582
|
-
entry.subscribers++;
|
|
583
803
|
entry.listeners.add(onCacheUpdate);
|
|
584
804
|
entry.refetchers.add(doFetch);
|
|
585
805
|
}
|
|
586
806
|
if (entry.promise) {
|
|
587
807
|
setIsFetching(true);
|
|
808
|
+
const captured = entry.promise;
|
|
588
809
|
try {
|
|
589
|
-
await
|
|
810
|
+
await captured;
|
|
811
|
+
if (disposed || currentKey !== key2) return;
|
|
812
|
+
if (entry.promise === captured) {
|
|
813
|
+
onCacheUpdate();
|
|
814
|
+
if (entry.error) onError?.(entry.error);
|
|
815
|
+
else if (entry.data !== void 0) onSuccess?.(entry.data);
|
|
816
|
+
}
|
|
590
817
|
} catch {
|
|
818
|
+
if (disposed || currentKey !== key2) return;
|
|
819
|
+
if (entry.promise === captured) {
|
|
820
|
+
onCacheUpdate();
|
|
821
|
+
if (entry.error) onError?.(entry.error);
|
|
822
|
+
}
|
|
823
|
+
} finally {
|
|
824
|
+
if (!disposed && currentKey === key2) onSettled?.();
|
|
591
825
|
}
|
|
592
|
-
onCacheUpdate();
|
|
593
826
|
return;
|
|
594
827
|
}
|
|
595
828
|
abortController?.abort();
|
|
596
829
|
abortController = new AbortController();
|
|
597
830
|
const signal2 = abortController.signal;
|
|
598
831
|
setIsFetching(true);
|
|
599
|
-
|
|
832
|
+
let promise;
|
|
833
|
+
try {
|
|
834
|
+
promise = withRetry(() => fetcher({ signal: signal2, key: key2 }), retryOptions, void 0, signal2);
|
|
835
|
+
} catch (err) {
|
|
836
|
+
setIsFetching(false);
|
|
837
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
838
|
+
entry.error = errorObj;
|
|
839
|
+
onError?.(errorObj);
|
|
840
|
+
onSettled?.();
|
|
841
|
+
return;
|
|
842
|
+
}
|
|
600
843
|
entry.promise = promise;
|
|
601
844
|
try {
|
|
602
845
|
const result = await promise;
|
|
@@ -658,6 +901,7 @@ function query(key, fetcher, options = {}) {
|
|
|
658
901
|
oldEntry.subscribers--;
|
|
659
902
|
if (oldEntry.subscribers <= 0 && cacheTime >= 0) {
|
|
660
903
|
const oldKey = currentKey;
|
|
904
|
+
if (oldEntry.gcTimer !== null) clearTimeout(oldEntry.gcTimer);
|
|
661
905
|
oldEntry.gcTimer = setTimeout(() => queryCache.delete(oldKey), cacheTime);
|
|
662
906
|
}
|
|
663
907
|
}
|
|
@@ -665,7 +909,7 @@ function query(key, fetcher, options = {}) {
|
|
|
665
909
|
const keyChanged = currentKey !== key2;
|
|
666
910
|
currentKey = key2;
|
|
667
911
|
const entry = getOrCreateEntry(key2, initialData);
|
|
668
|
-
if (keyChanged
|
|
912
|
+
if (keyChanged) entry.subscribers++;
|
|
669
913
|
if (entry.gcTimer !== null) {
|
|
670
914
|
clearTimeout(entry.gcTimer);
|
|
671
915
|
entry.gcTimer = null;
|
|
@@ -680,6 +924,11 @@ function query(key, fetcher, options = {}) {
|
|
|
680
924
|
setError(entry.error);
|
|
681
925
|
});
|
|
682
926
|
}
|
|
927
|
+
if (!keyChanged && currentKey === key2 && entry.data !== void 0) {
|
|
928
|
+
const isDataStale2 = entry.dataUpdatedAt === 0 || Date.now() - entry.dataUpdatedAt >= staleTime;
|
|
929
|
+
if (enabled && isDataStale2 && !entry.promise) doFetch();
|
|
930
|
+
return;
|
|
931
|
+
}
|
|
683
932
|
const isDataStale = entry.dataUpdatedAt === 0 || Date.now() - entry.dataUpdatedAt >= staleTime;
|
|
684
933
|
if (enabled && (entry.data === void 0 || isDataStale)) {
|
|
685
934
|
doFetch();
|
|
@@ -707,6 +956,7 @@ function query(key, fetcher, options = {}) {
|
|
|
707
956
|
}
|
|
708
957
|
}
|
|
709
958
|
function dispose() {
|
|
959
|
+
if (disposed) return;
|
|
710
960
|
disposed = true;
|
|
711
961
|
abortController?.abort();
|
|
712
962
|
effectCleanup();
|
|
@@ -719,12 +969,17 @@ function query(key, fetcher, options = {}) {
|
|
|
719
969
|
entry.subscribers--;
|
|
720
970
|
if (entry.subscribers <= 0 && cacheTime >= 0) {
|
|
721
971
|
const key2 = currentKey;
|
|
972
|
+
if (entry.gcTimer !== null) clearTimeout(entry.gcTimer);
|
|
722
973
|
entry.gcTimer = setTimeout(() => queryCache.delete(key2), cacheTime);
|
|
723
974
|
}
|
|
724
975
|
}
|
|
725
976
|
}
|
|
726
|
-
if (focusHandler
|
|
727
|
-
|
|
977
|
+
if (focusHandler && typeof globalThis.removeEventListener === "function") {
|
|
978
|
+
globalThis.removeEventListener("focus", focusHandler);
|
|
979
|
+
}
|
|
980
|
+
if (onlineHandler && typeof globalThis.removeEventListener === "function") {
|
|
981
|
+
globalThis.removeEventListener("online", onlineHandler);
|
|
982
|
+
}
|
|
728
983
|
}
|
|
729
984
|
return {
|
|
730
985
|
data,
|
|
@@ -768,7 +1023,19 @@ function clearQueryCache() {
|
|
|
768
1023
|
}
|
|
769
1024
|
queryCache.clear();
|
|
770
1025
|
for (const listener of activeListeners) listener();
|
|
771
|
-
for (const refetcher of activeRefetchers)
|
|
1026
|
+
for (const refetcher of activeRefetchers) {
|
|
1027
|
+
refetcher().catch((err) => {
|
|
1028
|
+
if (typeof console !== "undefined") {
|
|
1029
|
+
console.warn("[SibuJS query] refetch after clearQueryCache failed:", err);
|
|
1030
|
+
}
|
|
1031
|
+
});
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
function __resetQueryCache() {
|
|
1035
|
+
for (const entry of queryCache.values()) {
|
|
1036
|
+
if (entry.gcTimer) clearTimeout(entry.gcTimer);
|
|
1037
|
+
}
|
|
1038
|
+
queryCache.clear();
|
|
772
1039
|
}
|
|
773
1040
|
|
|
774
1041
|
// src/data/mutation.ts
|
|
@@ -831,7 +1098,10 @@ function mutation(mutationFn, options = {}) {
|
|
|
831
1098
|
isSuccess,
|
|
832
1099
|
isIdle,
|
|
833
1100
|
mutate: (variables) => {
|
|
834
|
-
execute(variables).catch(() => {
|
|
1101
|
+
execute(variables).catch((err) => {
|
|
1102
|
+
if (typeof console !== "undefined") {
|
|
1103
|
+
console.warn("[SibuJS mutation] mutate() failed; check `.error()` signal or onError option.", err);
|
|
1104
|
+
}
|
|
835
1105
|
});
|
|
836
1106
|
},
|
|
837
1107
|
mutateAsync: execute,
|
|
@@ -867,11 +1137,13 @@ function infiniteQuery(key, fetcher, options) {
|
|
|
867
1137
|
const hasPreviousPage = derived(() => prevPageParam() !== void 0);
|
|
868
1138
|
let abortController = null;
|
|
869
1139
|
let disposed = false;
|
|
1140
|
+
let runId = 0;
|
|
870
1141
|
async function fetchPage(pageParam, direction) {
|
|
871
1142
|
if (disposed) return;
|
|
872
1143
|
abortController?.abort();
|
|
873
1144
|
abortController = new AbortController();
|
|
874
1145
|
const signal2 = abortController.signal;
|
|
1146
|
+
const myRun = ++runId;
|
|
875
1147
|
batch(() => {
|
|
876
1148
|
setIsFetching(true);
|
|
877
1149
|
if (direction === "next") setIsFetchingNext(true);
|
|
@@ -880,7 +1152,7 @@ function infiniteQuery(key, fetcher, options) {
|
|
|
880
1152
|
});
|
|
881
1153
|
try {
|
|
882
1154
|
const page = await withRetry(() => fetcher({ signal: signal2, pageParam }), retryOptions, void 0, signal2);
|
|
883
|
-
if (disposed) return;
|
|
1155
|
+
if (disposed || myRun !== runId) return;
|
|
884
1156
|
const currentPages = pages();
|
|
885
1157
|
let newPages;
|
|
886
1158
|
if (direction === "prev") {
|
|
@@ -900,7 +1172,7 @@ function infiniteQuery(key, fetcher, options) {
|
|
|
900
1172
|
});
|
|
901
1173
|
onSuccess?.(newPages);
|
|
902
1174
|
} catch (err) {
|
|
903
|
-
if (disposed) return;
|
|
1175
|
+
if (disposed || myRun !== runId) return;
|
|
904
1176
|
if (err instanceof DOMException && err.name === "AbortError") return;
|
|
905
1177
|
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
906
1178
|
batch(() => {
|
|
@@ -915,9 +1187,12 @@ function infiniteQuery(key, fetcher, options) {
|
|
|
915
1187
|
const effectCleanup = effect(() => {
|
|
916
1188
|
resolveKey();
|
|
917
1189
|
if (enabled) {
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
1190
|
+
abortController?.abort();
|
|
1191
|
+
batch(() => {
|
|
1192
|
+
setPages([]);
|
|
1193
|
+
setNextPageParam(initialPageParam);
|
|
1194
|
+
setPrevPageParam(void 0);
|
|
1195
|
+
});
|
|
921
1196
|
fetchPage(initialPageParam, "initial");
|
|
922
1197
|
}
|
|
923
1198
|
});
|
|
@@ -1154,18 +1429,57 @@ function idbPut(db, store, item) {
|
|
|
1154
1429
|
tx.onerror = () => reject(tx.error);
|
|
1155
1430
|
});
|
|
1156
1431
|
}
|
|
1157
|
-
function
|
|
1432
|
+
function idbPutWithChange(db, item, change) {
|
|
1433
|
+
return new Promise((resolve, reject) => {
|
|
1434
|
+
const tx = db.transaction(["items", "_changes"], "readwrite");
|
|
1435
|
+
tx.objectStore("items").put(item);
|
|
1436
|
+
tx.objectStore("_changes").put(change);
|
|
1437
|
+
tx.oncomplete = () => resolve();
|
|
1438
|
+
tx.onerror = () => reject(tx.error);
|
|
1439
|
+
});
|
|
1440
|
+
}
|
|
1441
|
+
function idbDeleteWithChange(db, key, change) {
|
|
1442
|
+
return new Promise((resolve, reject) => {
|
|
1443
|
+
const tx = db.transaction(["items", "_changes"], "readwrite");
|
|
1444
|
+
tx.objectStore("items").delete(key);
|
|
1445
|
+
tx.objectStore("_changes").put(change);
|
|
1446
|
+
tx.oncomplete = () => resolve();
|
|
1447
|
+
tx.onerror = () => reject(tx.error);
|
|
1448
|
+
});
|
|
1449
|
+
}
|
|
1450
|
+
function idbGetAllWithKeys(db, store) {
|
|
1451
|
+
return new Promise((resolve, reject) => {
|
|
1452
|
+
const tx = db.transaction(store, "readonly");
|
|
1453
|
+
const out = [];
|
|
1454
|
+
const req = tx.objectStore(store).openCursor();
|
|
1455
|
+
req.onsuccess = () => {
|
|
1456
|
+
const cursor = req.result;
|
|
1457
|
+
if (cursor) {
|
|
1458
|
+
out.push({ key: cursor.primaryKey, value: cursor.value });
|
|
1459
|
+
cursor.continue();
|
|
1460
|
+
} else {
|
|
1461
|
+
resolve(out);
|
|
1462
|
+
}
|
|
1463
|
+
};
|
|
1464
|
+
req.onerror = () => reject(req.error);
|
|
1465
|
+
});
|
|
1466
|
+
}
|
|
1467
|
+
function idbDeleteKeys(db, store, keys) {
|
|
1468
|
+
if (keys.length === 0) return Promise.resolve();
|
|
1158
1469
|
return new Promise((resolve, reject) => {
|
|
1159
1470
|
const tx = db.transaction(store, "readwrite");
|
|
1160
|
-
tx.objectStore(store)
|
|
1471
|
+
const objStore = tx.objectStore(store);
|
|
1472
|
+
for (const k of keys) objStore.delete(k);
|
|
1161
1473
|
tx.oncomplete = () => resolve();
|
|
1162
1474
|
tx.onerror = () => reject(tx.error);
|
|
1163
1475
|
});
|
|
1164
1476
|
}
|
|
1165
|
-
function
|
|
1477
|
+
function idbPutMany(db, store, items) {
|
|
1478
|
+
if (items.length === 0) return Promise.resolve();
|
|
1166
1479
|
return new Promise((resolve, reject) => {
|
|
1167
1480
|
const tx = db.transaction(store, "readwrite");
|
|
1168
|
-
tx.objectStore(store)
|
|
1481
|
+
const objStore = tx.objectStore(store);
|
|
1482
|
+
for (const item of items) objStore.put(item);
|
|
1169
1483
|
tx.oncomplete = () => resolve();
|
|
1170
1484
|
tx.onerror = () => reject(tx.error);
|
|
1171
1485
|
});
|
|
@@ -1188,15 +1502,13 @@ async function offlineStore(options) {
|
|
|
1188
1502
|
setPendingCount(changes.length);
|
|
1189
1503
|
}
|
|
1190
1504
|
async function put(item) {
|
|
1191
|
-
await
|
|
1192
|
-
await idbPut(db, "_changes", { type: "put", item, timestamp: Date.now() });
|
|
1505
|
+
await idbPutWithChange(db, item, { type: "put", item, timestamp: Date.now() });
|
|
1193
1506
|
await refreshData();
|
|
1194
1507
|
}
|
|
1195
1508
|
async function remove(key) {
|
|
1196
1509
|
const existing = await idbGet(db, "items", key);
|
|
1197
1510
|
if (existing) {
|
|
1198
|
-
await
|
|
1199
|
-
await idbPut(db, "_changes", { type: "delete", item: existing, timestamp: Date.now() });
|
|
1511
|
+
await idbDeleteWithChange(db, key, { type: "delete", item: existing, timestamp: Date.now() });
|
|
1200
1512
|
await refreshData();
|
|
1201
1513
|
}
|
|
1202
1514
|
}
|
|
@@ -1207,25 +1519,45 @@ async function offlineStore(options) {
|
|
|
1207
1519
|
return data().filter(filter);
|
|
1208
1520
|
}
|
|
1209
1521
|
async function sync() {
|
|
1210
|
-
if (!adapter || isSyncing()) return;
|
|
1522
|
+
if (!adapter || isSyncing() || closed) return;
|
|
1211
1523
|
setIsSyncing(true);
|
|
1212
1524
|
try {
|
|
1213
|
-
const
|
|
1214
|
-
if (
|
|
1215
|
-
|
|
1525
|
+
const snapshot = await idbGetAllWithKeys(db, "_changes");
|
|
1526
|
+
if (closed) return;
|
|
1527
|
+
if (snapshot.length > 0) {
|
|
1528
|
+
const result = await adapter.push(snapshot.map((e) => e.value));
|
|
1529
|
+
if (closed) return;
|
|
1216
1530
|
if (result.ok) {
|
|
1217
|
-
await
|
|
1531
|
+
await idbDeleteKeys(
|
|
1532
|
+
db,
|
|
1533
|
+
"_changes",
|
|
1534
|
+
snapshot.map((e) => e.key)
|
|
1535
|
+
);
|
|
1536
|
+
if (closed) return;
|
|
1218
1537
|
}
|
|
1219
1538
|
}
|
|
1220
1539
|
const remoteItems = await adapter.pull(lastSynced());
|
|
1221
|
-
|
|
1222
|
-
|
|
1540
|
+
if (closed) return;
|
|
1541
|
+
const pendingChanges = await idbGetAll(db, "_changes");
|
|
1542
|
+
if (closed) return;
|
|
1543
|
+
const pendingKeys = /* @__PURE__ */ new Set();
|
|
1544
|
+
for (const c of pendingChanges) {
|
|
1545
|
+
const k = c.item[keyPath];
|
|
1546
|
+
if (k != null) pendingKeys.add(k);
|
|
1223
1547
|
}
|
|
1548
|
+
const safeRemote = remoteItems.filter((item) => {
|
|
1549
|
+
const k = item[keyPath];
|
|
1550
|
+
return k == null || !pendingKeys.has(k);
|
|
1551
|
+
});
|
|
1552
|
+
await idbPutMany(db, "items", safeRemote);
|
|
1553
|
+
if (closed) return;
|
|
1224
1554
|
const now = Date.now();
|
|
1225
1555
|
await idbPut(db, "_meta", now);
|
|
1556
|
+
if (closed) return;
|
|
1226
1557
|
setLastSynced(now);
|
|
1227
1558
|
await refreshData();
|
|
1228
|
-
} catch {
|
|
1559
|
+
} catch (err) {
|
|
1560
|
+
if (typeof console !== "undefined") console.warn("[offlineStore] sync failed", err);
|
|
1229
1561
|
} finally {
|
|
1230
1562
|
setIsSyncing(false);
|
|
1231
1563
|
}
|
|
@@ -1233,13 +1565,21 @@ async function offlineStore(options) {
|
|
|
1233
1565
|
function attach(newAdapter) {
|
|
1234
1566
|
adapter = newAdapter;
|
|
1235
1567
|
}
|
|
1568
|
+
let onlineHandler = null;
|
|
1569
|
+
let closed = false;
|
|
1236
1570
|
function close() {
|
|
1571
|
+
closed = true;
|
|
1572
|
+
if (onlineHandler && typeof window !== "undefined") {
|
|
1573
|
+
window.removeEventListener("online", onlineHandler);
|
|
1574
|
+
onlineHandler = null;
|
|
1575
|
+
}
|
|
1237
1576
|
db.close();
|
|
1238
1577
|
}
|
|
1239
1578
|
if (autoSync && typeof window !== "undefined") {
|
|
1240
|
-
|
|
1579
|
+
onlineHandler = () => {
|
|
1241
1580
|
sync();
|
|
1242
|
-
}
|
|
1581
|
+
};
|
|
1582
|
+
window.addEventListener("online", onlineHandler);
|
|
1243
1583
|
}
|
|
1244
1584
|
return {
|
|
1245
1585
|
data,
|
|
@@ -1262,9 +1602,11 @@ function syncAdapter(config) {
|
|
|
1262
1602
|
// src/core/rendering/context.ts
|
|
1263
1603
|
function context(defaultValue) {
|
|
1264
1604
|
const [getValue, setValue] = signal(defaultValue);
|
|
1265
|
-
|
|
1605
|
+
const ctx = {
|
|
1266
1606
|
provide(value) {
|
|
1607
|
+
const previous2 = getValue();
|
|
1267
1608
|
setValue(value);
|
|
1609
|
+
return () => setValue(previous2);
|
|
1268
1610
|
},
|
|
1269
1611
|
use() {
|
|
1270
1612
|
return getValue;
|
|
@@ -1274,8 +1616,18 @@ function context(defaultValue) {
|
|
|
1274
1616
|
},
|
|
1275
1617
|
set(value) {
|
|
1276
1618
|
setValue(value);
|
|
1619
|
+
},
|
|
1620
|
+
withContext(value, fn) {
|
|
1621
|
+
const previous2 = getValue();
|
|
1622
|
+
setValue(value);
|
|
1623
|
+
try {
|
|
1624
|
+
return fn();
|
|
1625
|
+
} finally {
|
|
1626
|
+
setValue(previous2);
|
|
1627
|
+
}
|
|
1277
1628
|
}
|
|
1278
1629
|
};
|
|
1630
|
+
return ctx;
|
|
1279
1631
|
}
|
|
1280
1632
|
|
|
1281
1633
|
// src/data/routeLoader.ts
|
|
@@ -1296,9 +1648,16 @@ function loaderData() {
|
|
|
1296
1648
|
error: resource2.error
|
|
1297
1649
|
};
|
|
1298
1650
|
}
|
|
1299
|
-
async function preloadRoute(route, context2) {
|
|
1651
|
+
async function preloadRoute(route, context2, callerSignal) {
|
|
1300
1652
|
if (!route.loader) return void 0;
|
|
1301
1653
|
const controller = new AbortController();
|
|
1654
|
+
if (callerSignal) {
|
|
1655
|
+
if (callerSignal.aborted) {
|
|
1656
|
+
controller.abort();
|
|
1657
|
+
} else {
|
|
1658
|
+
callerSignal.addEventListener("abort", () => controller.abort(), { once: true });
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1302
1661
|
return route.loader(context2, { signal: controller.signal });
|
|
1303
1662
|
}
|
|
1304
1663
|
|
|
@@ -1313,7 +1672,7 @@ function validateWsUrl(raw) {
|
|
|
1313
1672
|
function socket(url, options) {
|
|
1314
1673
|
const autoReconnect = options?.autoReconnect ?? false;
|
|
1315
1674
|
const reconnectDelay = options?.reconnectDelay ?? 1e3;
|
|
1316
|
-
const maxReconnects = options?.maxReconnects ??
|
|
1675
|
+
const maxReconnects = options?.maxReconnects ?? 10;
|
|
1317
1676
|
const heartbeat = options?.heartbeat;
|
|
1318
1677
|
const protocols = options?.protocols;
|
|
1319
1678
|
const [data, setData] = signal(null);
|
|
@@ -1347,13 +1706,19 @@ function socket(url, options) {
|
|
|
1347
1706
|
ws.onclose = () => {
|
|
1348
1707
|
setStatus("closed");
|
|
1349
1708
|
stopHeartbeat();
|
|
1350
|
-
|
|
1709
|
+
const wasManual = manuallyClosed;
|
|
1710
|
+
manuallyClosed = false;
|
|
1711
|
+
if (autoReconnect && !disposed && !wasManual && reconnectCount < maxReconnects) {
|
|
1712
|
+
const cap = 3e4;
|
|
1713
|
+
const delay = Math.min(cap, reconnectDelay * 2 ** reconnectCount);
|
|
1714
|
+
const jittered = delay * (0.5 + Math.random() * 0.5);
|
|
1351
1715
|
reconnectCount++;
|
|
1352
1716
|
reconnectTimer = setTimeout(() => {
|
|
1717
|
+
reconnectTimer = null;
|
|
1718
|
+
if (disposed || manuallyClosed) return;
|
|
1353
1719
|
connect();
|
|
1354
|
-
},
|
|
1720
|
+
}, jittered);
|
|
1355
1721
|
}
|
|
1356
|
-
manuallyClosed = false;
|
|
1357
1722
|
};
|
|
1358
1723
|
ws.onerror = () => {
|
|
1359
1724
|
};
|
|
@@ -1399,13 +1764,24 @@ function socket(url, options) {
|
|
|
1399
1764
|
}
|
|
1400
1765
|
|
|
1401
1766
|
// src/utils/sanitize.ts
|
|
1767
|
+
var SAFE_URL_PROTOCOLS = ["http:", "https:", "mailto:", "tel:", "ftp:"];
|
|
1402
1768
|
function sanitizeUrl(url) {
|
|
1403
1769
|
const trimmed = url.replace(/[\x00-\x20\x7f-\x9f]+/g, "").trim();
|
|
1404
1770
|
if (!trimmed) return "";
|
|
1405
1771
|
const lower = trimmed.toLowerCase();
|
|
1406
|
-
|
|
1407
|
-
|
|
1772
|
+
let schemeEnd = -1;
|
|
1773
|
+
for (let i = 0; i < lower.length; i++) {
|
|
1774
|
+
const ch = lower.charCodeAt(i);
|
|
1775
|
+
if (ch === 58) {
|
|
1776
|
+
schemeEnd = i;
|
|
1777
|
+
break;
|
|
1778
|
+
}
|
|
1779
|
+
if (ch === 47 || ch === 63 || ch === 35) break;
|
|
1408
1780
|
}
|
|
1781
|
+
if (schemeEnd === -1) return trimmed;
|
|
1782
|
+
const scheme = lower.slice(0, schemeEnd + 1);
|
|
1783
|
+
if (!/^[a-z][a-z0-9+.-]*:$/.test(scheme)) return trimmed;
|
|
1784
|
+
if (SAFE_URL_PROTOCOLS.indexOf(scheme) === -1) return "";
|
|
1409
1785
|
return trimmed;
|
|
1410
1786
|
}
|
|
1411
1787
|
|
|
@@ -1417,12 +1793,16 @@ function validateSseUrl(raw) {
|
|
|
1417
1793
|
}
|
|
1418
1794
|
function stream(url, options) {
|
|
1419
1795
|
const autoReconnect = options?.autoReconnect ?? false;
|
|
1796
|
+
const maxReconnects = options?.maxReconnects ?? 10;
|
|
1797
|
+
const baseMs = options?.reconnectBaseMs ?? 1e3;
|
|
1798
|
+
const maxMs = options?.reconnectMaxMs ?? 3e4;
|
|
1420
1799
|
const [data, setData] = signal(null);
|
|
1421
1800
|
const [event, setEvent] = signal(null);
|
|
1422
1801
|
const [status, setStatus] = signal("connecting");
|
|
1423
1802
|
let source = null;
|
|
1424
1803
|
let disposed = false;
|
|
1425
1804
|
let reconnectTimer = null;
|
|
1805
|
+
let attempts = 0;
|
|
1426
1806
|
function connect() {
|
|
1427
1807
|
if (disposed) return;
|
|
1428
1808
|
const safeUrl = validateSseUrl(url);
|
|
@@ -1436,6 +1816,7 @@ function stream(url, options) {
|
|
|
1436
1816
|
});
|
|
1437
1817
|
source.onopen = () => {
|
|
1438
1818
|
setStatus("open");
|
|
1819
|
+
attempts = 0;
|
|
1439
1820
|
};
|
|
1440
1821
|
source.onmessage = (evt) => {
|
|
1441
1822
|
setData(evt.data);
|
|
@@ -1445,11 +1826,14 @@ function stream(url, options) {
|
|
|
1445
1826
|
if (source && source.readyState === EventSource.CLOSED) {
|
|
1446
1827
|
setStatus("closed");
|
|
1447
1828
|
source = null;
|
|
1448
|
-
if (autoReconnect && !disposed) {
|
|
1829
|
+
if (autoReconnect && !disposed && attempts < maxReconnects) {
|
|
1830
|
+
const delay = Math.min(maxMs, baseMs * 2 ** attempts);
|
|
1831
|
+
const jittered = delay * (0.5 + Math.random() * 0.5);
|
|
1832
|
+
attempts++;
|
|
1449
1833
|
reconnectTimer = setTimeout(() => {
|
|
1450
1834
|
reconnectTimer = null;
|
|
1451
1835
|
connect();
|
|
1452
|
-
},
|
|
1836
|
+
}, jittered);
|
|
1453
1837
|
}
|
|
1454
1838
|
}
|
|
1455
1839
|
};
|
|
@@ -1474,6 +1858,7 @@ function stream(url, options) {
|
|
|
1474
1858
|
}
|
|
1475
1859
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1476
1860
|
0 && (module.exports = {
|
|
1861
|
+
__resetQueryCache,
|
|
1477
1862
|
calculateDelay,
|
|
1478
1863
|
clearQueryCache,
|
|
1479
1864
|
debounce,
|