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/ecosystem.cjs
CHANGED
|
@@ -38,26 +38,39 @@ function isDev() {
|
|
|
38
38
|
var _isDev = isDev();
|
|
39
39
|
function devAssert(condition, message) {
|
|
40
40
|
if (_isDev && !condition) {
|
|
41
|
-
throw new Error(`[
|
|
41
|
+
throw new Error(`[SibuJS] ${message}`);
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
function devWarn(message) {
|
|
45
45
|
if (_isDev) {
|
|
46
|
-
console.warn(`[
|
|
46
|
+
console.warn(`[SibuJS] ${message}`);
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
// src/reactivity/track.ts
|
|
51
51
|
var _isDev2 = isDev();
|
|
52
|
-
var
|
|
53
|
-
var
|
|
52
|
+
var STACK_INITIAL = 32;
|
|
53
|
+
var STACK_SHRINK_THRESHOLD = 128;
|
|
54
|
+
var subscriberStack = new Array(STACK_INITIAL);
|
|
55
|
+
var stackCapacity = STACK_INITIAL;
|
|
54
56
|
var stackTop = -1;
|
|
55
57
|
var currentSubscriber = null;
|
|
56
|
-
var signalSubscribers = /* @__PURE__ */ new WeakMap();
|
|
57
58
|
var SUBS = "__s";
|
|
59
|
+
function syncFastPath(signal2, subs) {
|
|
60
|
+
const size = subs.size;
|
|
61
|
+
if (size === 0) {
|
|
62
|
+
signal2.__f = void 0;
|
|
63
|
+
delete signal2[SUBS];
|
|
64
|
+
} else if (size === 1) {
|
|
65
|
+
signal2.__f = subs.values().next().value;
|
|
66
|
+
} else {
|
|
67
|
+
signal2.__f = void 0;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
58
70
|
var notifyDepth = 0;
|
|
59
71
|
var pendingQueue = [];
|
|
60
72
|
var pendingSet = /* @__PURE__ */ new Set();
|
|
73
|
+
var propagateStack = [];
|
|
61
74
|
function safeInvoke(sub) {
|
|
62
75
|
try {
|
|
63
76
|
sub();
|
|
@@ -66,6 +79,47 @@ function safeInvoke(sub) {
|
|
|
66
79
|
}
|
|
67
80
|
}
|
|
68
81
|
var trackingSuspended = false;
|
|
82
|
+
var subscriberEpochCounter = 0;
|
|
83
|
+
function retrack(effectFn, subscriber) {
|
|
84
|
+
const prev = currentSubscriber;
|
|
85
|
+
currentSubscriber = subscriber;
|
|
86
|
+
const sub = subscriber;
|
|
87
|
+
const epoch = ++subscriberEpochCounter;
|
|
88
|
+
sub._epoch = epoch;
|
|
89
|
+
try {
|
|
90
|
+
effectFn();
|
|
91
|
+
} finally {
|
|
92
|
+
currentSubscriber = prev;
|
|
93
|
+
pruneStaleDeps(sub, epoch);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function pruneStaleDeps(sub, currentEpoch) {
|
|
97
|
+
if (sub._dep !== void 0) {
|
|
98
|
+
if (sub._depEpoch !== currentEpoch) {
|
|
99
|
+
const sig = sub._dep;
|
|
100
|
+
const subs = sig[SUBS];
|
|
101
|
+
if (subs?.delete(sub)) syncFastPath(sig, subs);
|
|
102
|
+
sub._dep = void 0;
|
|
103
|
+
sub._depEpoch = void 0;
|
|
104
|
+
}
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const deps = sub._deps;
|
|
108
|
+
if (!deps || deps.size === 0) return;
|
|
109
|
+
let stales;
|
|
110
|
+
for (const [signal2, epoch] of deps) {
|
|
111
|
+
if (epoch !== currentEpoch) {
|
|
112
|
+
(stales ?? (stales = [])).push(signal2);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (!stales) return;
|
|
116
|
+
for (const signal2 of stales) {
|
|
117
|
+
deps.delete(signal2);
|
|
118
|
+
const sig = signal2;
|
|
119
|
+
const subs = sig[SUBS];
|
|
120
|
+
if (subs?.delete(sub)) syncFastPath(sig, subs);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
69
123
|
function track(effectFn, subscriber) {
|
|
70
124
|
if (!subscriber) subscriber = effectFn;
|
|
71
125
|
cleanup(subscriber);
|
|
@@ -81,37 +135,49 @@ function track(effectFn, subscriber) {
|
|
|
81
135
|
} finally {
|
|
82
136
|
stackTop--;
|
|
83
137
|
currentSubscriber = stackTop >= 0 ? subscriberStack[stackTop] : null;
|
|
138
|
+
if (stackTop < 0 && stackCapacity > STACK_SHRINK_THRESHOLD) {
|
|
139
|
+
stackCapacity = Math.max(STACK_INITIAL, stackCapacity >>> 1);
|
|
140
|
+
subscriberStack.length = stackCapacity;
|
|
141
|
+
}
|
|
84
142
|
}
|
|
85
143
|
return () => cleanup(subscriber);
|
|
86
144
|
}
|
|
87
145
|
function recordDependency(signal2) {
|
|
88
146
|
if (!currentSubscriber) return;
|
|
89
147
|
const sub = currentSubscriber;
|
|
90
|
-
|
|
148
|
+
const epoch = sub._epoch;
|
|
149
|
+
if (sub._dep === signal2) {
|
|
150
|
+
sub._depEpoch = epoch;
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
91
153
|
const deps = sub._deps;
|
|
92
154
|
if (deps) {
|
|
93
|
-
|
|
94
|
-
deps.add(signal2);
|
|
155
|
+
deps.set(signal2, epoch);
|
|
95
156
|
} else if (sub._dep !== void 0) {
|
|
96
|
-
const
|
|
97
|
-
set
|
|
98
|
-
set
|
|
99
|
-
sub._deps =
|
|
157
|
+
const map = /* @__PURE__ */ new Map();
|
|
158
|
+
map.set(sub._dep, sub._depEpoch);
|
|
159
|
+
map.set(signal2, epoch);
|
|
160
|
+
sub._deps = map;
|
|
100
161
|
sub._dep = void 0;
|
|
162
|
+
sub._depEpoch = void 0;
|
|
101
163
|
} else {
|
|
102
164
|
sub._dep = signal2;
|
|
165
|
+
sub._depEpoch = epoch;
|
|
103
166
|
}
|
|
104
|
-
|
|
167
|
+
const sig = signal2;
|
|
168
|
+
let subs = sig[SUBS];
|
|
105
169
|
if (!subs) {
|
|
106
170
|
subs = /* @__PURE__ */ new Set();
|
|
107
|
-
|
|
108
|
-
signal2[SUBS] = subs;
|
|
171
|
+
sig[SUBS] = subs;
|
|
109
172
|
}
|
|
173
|
+
const prevSize = subs.size;
|
|
110
174
|
subs.add(currentSubscriber);
|
|
111
|
-
if (subs.size
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
175
|
+
if (subs.size !== prevSize) {
|
|
176
|
+
if (subs.size === 1) {
|
|
177
|
+
sig.__f = currentSubscriber;
|
|
178
|
+
} else if (sig.__f !== void 0) {
|
|
179
|
+
sig.__f = void 0;
|
|
180
|
+
}
|
|
115
181
|
}
|
|
116
182
|
}
|
|
117
183
|
function queueSignalNotification(signal2) {
|
|
@@ -126,66 +192,102 @@ function queueSignalNotification(signal2) {
|
|
|
126
192
|
}
|
|
127
193
|
}
|
|
128
194
|
}
|
|
129
|
-
var
|
|
195
|
+
var maxSubscriberRepeats = 50;
|
|
196
|
+
var maxDrainIterations = 1e6;
|
|
197
|
+
var drainEpoch = 0;
|
|
198
|
+
function tickRepeat(sub) {
|
|
199
|
+
const s = sub;
|
|
200
|
+
if (s._runEpoch !== drainEpoch) {
|
|
201
|
+
s._runEpoch = drainEpoch;
|
|
202
|
+
s._runs = 1;
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
return ++s._runs > maxSubscriberRepeats;
|
|
206
|
+
}
|
|
207
|
+
function cycleError(sub) {
|
|
208
|
+
if (typeof console !== "undefined") {
|
|
209
|
+
const name = sub.__name ?? "<unnamed>";
|
|
210
|
+
console.error(
|
|
211
|
+
`[SibuJS] subscriber "${name}" fired more than ${maxSubscriberRepeats} times \u2014 likely a write-reads-self cycle between effects/signals. Breaking to prevent infinite loop.`
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
function absoluteDrainError() {
|
|
216
|
+
if (typeof console !== "undefined") {
|
|
217
|
+
console.error(
|
|
218
|
+
`[SibuJS] Notification drain exceeded ${maxDrainIterations} iterations \u2014 absolute safety net tripped. Breaking to prevent infinite loop.`
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
function drainQueue() {
|
|
223
|
+
let i = 0;
|
|
224
|
+
while (i < pendingQueue.length) {
|
|
225
|
+
if (i >= maxDrainIterations) {
|
|
226
|
+
absoluteDrainError();
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
const sub = pendingQueue[i++];
|
|
230
|
+
if (tickRepeat(sub)) {
|
|
231
|
+
cycleError(sub);
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
234
|
+
pendingSet.delete(sub);
|
|
235
|
+
safeInvoke(sub);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
130
238
|
function drainNotificationQueue() {
|
|
131
239
|
if (notifyDepth > 0) return;
|
|
132
240
|
notifyDepth++;
|
|
241
|
+
drainEpoch++;
|
|
133
242
|
try {
|
|
134
|
-
|
|
135
|
-
while (i < pendingQueue.length) {
|
|
136
|
-
if (i >= MAX_DRAIN_ITERATIONS) {
|
|
137
|
-
if (typeof console !== "undefined") {
|
|
138
|
-
console.error(
|
|
139
|
-
`[SibuJS] Notification queue exceeded ${MAX_DRAIN_ITERATIONS} iterations \u2014 likely an effect that writes to a signal it reads. Breaking to prevent infinite loop.`
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
break;
|
|
143
|
-
}
|
|
144
|
-
safeInvoke(pendingQueue[i]);
|
|
145
|
-
i++;
|
|
146
|
-
}
|
|
243
|
+
drainQueue();
|
|
147
244
|
} finally {
|
|
148
|
-
pendingQueue.length = 0;
|
|
149
|
-
pendingSet.clear();
|
|
150
245
|
notifyDepth--;
|
|
246
|
+
if (notifyDepth === 0) {
|
|
247
|
+
pendingQueue.length = 0;
|
|
248
|
+
pendingSet.clear();
|
|
249
|
+
}
|
|
151
250
|
}
|
|
152
251
|
}
|
|
153
252
|
function propagateDirty(sub) {
|
|
154
253
|
sub();
|
|
155
|
-
|
|
156
|
-
|
|
254
|
+
const rootSig = sub._sig;
|
|
255
|
+
if (!rootSig) return;
|
|
256
|
+
const stack = propagateStack;
|
|
257
|
+
const baseLen = stack.length;
|
|
258
|
+
stack.push(rootSig);
|
|
259
|
+
while (stack.length > baseLen) {
|
|
260
|
+
const sig = stack.pop();
|
|
157
261
|
const first = sig.__f;
|
|
158
262
|
if (first) {
|
|
159
263
|
if (first._c) {
|
|
160
264
|
const nSig = first._sig;
|
|
161
|
-
nSig._d
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
if (!pendingSet.has(first)) {
|
|
265
|
+
if (!nSig._d) {
|
|
266
|
+
nSig._d = true;
|
|
267
|
+
stack.push(nSig);
|
|
268
|
+
}
|
|
269
|
+
} else if (!pendingSet.has(first)) {
|
|
166
270
|
pendingSet.add(first);
|
|
167
271
|
pendingQueue.push(first);
|
|
168
272
|
}
|
|
169
|
-
|
|
273
|
+
continue;
|
|
170
274
|
}
|
|
171
275
|
const subs = sig[SUBS];
|
|
172
|
-
if (!subs)
|
|
173
|
-
let nextSig;
|
|
276
|
+
if (!subs) continue;
|
|
174
277
|
for (const s of subs) {
|
|
175
278
|
if (s._c) {
|
|
176
|
-
s();
|
|
177
279
|
const nSig = s._sig;
|
|
178
|
-
if (nSig && !
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
280
|
+
if (nSig && !nSig._d) {
|
|
281
|
+
nSig._d = true;
|
|
282
|
+
stack.push(nSig);
|
|
283
|
+
} else if (!nSig) {
|
|
284
|
+
s();
|
|
182
285
|
}
|
|
183
286
|
} else if (!pendingSet.has(s)) {
|
|
184
287
|
pendingSet.add(s);
|
|
185
288
|
pendingQueue.push(s);
|
|
186
289
|
}
|
|
187
290
|
}
|
|
188
|
-
sig = nextSig;
|
|
189
291
|
}
|
|
190
292
|
}
|
|
191
293
|
function notifySubscribers(signal2) {
|
|
@@ -201,21 +303,22 @@ function notifySubscribers(signal2) {
|
|
|
201
303
|
return;
|
|
202
304
|
}
|
|
203
305
|
notifyDepth++;
|
|
306
|
+
drainEpoch++;
|
|
204
307
|
try {
|
|
205
308
|
if (first._c) {
|
|
206
309
|
propagateDirty(first);
|
|
310
|
+
} else if (tickRepeat(first)) {
|
|
311
|
+
cycleError(first);
|
|
207
312
|
} else {
|
|
208
313
|
safeInvoke(first);
|
|
209
314
|
}
|
|
210
|
-
|
|
211
|
-
while (i < pendingQueue.length) {
|
|
212
|
-
safeInvoke(pendingQueue[i]);
|
|
213
|
-
i++;
|
|
214
|
-
}
|
|
315
|
+
drainQueue();
|
|
215
316
|
} finally {
|
|
216
|
-
pendingQueue.length = 0;
|
|
217
|
-
pendingSet.clear();
|
|
218
317
|
notifyDepth--;
|
|
318
|
+
if (notifyDepth === 0) {
|
|
319
|
+
pendingQueue.length = 0;
|
|
320
|
+
pendingSet.clear();
|
|
321
|
+
}
|
|
219
322
|
}
|
|
220
323
|
return;
|
|
221
324
|
}
|
|
@@ -233,66 +336,73 @@ function notifySubscribers(signal2) {
|
|
|
233
336
|
return;
|
|
234
337
|
}
|
|
235
338
|
notifyDepth++;
|
|
339
|
+
drainEpoch++;
|
|
236
340
|
try {
|
|
237
|
-
let directCount = 0;
|
|
238
341
|
for (const sub of subs) {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
for (let i2 = 0; i2 < directCount; i2++) {
|
|
247
|
-
if (!pendingQueue[i2]._c) {
|
|
248
|
-
if (!pendingSet.has(pendingQueue[i2])) {
|
|
249
|
-
safeInvoke(pendingQueue[i2]);
|
|
250
|
-
}
|
|
342
|
+
if (sub._c) {
|
|
343
|
+
propagateDirty(sub);
|
|
344
|
+
} else if (!pendingSet.has(sub)) {
|
|
345
|
+
pendingSet.add(sub);
|
|
346
|
+
pendingQueue.push(sub);
|
|
251
347
|
}
|
|
252
348
|
}
|
|
253
|
-
|
|
254
|
-
while (i < pendingQueue.length) {
|
|
255
|
-
safeInvoke(pendingQueue[i]);
|
|
256
|
-
i++;
|
|
257
|
-
}
|
|
349
|
+
drainQueue();
|
|
258
350
|
} finally {
|
|
259
|
-
pendingQueue.length = 0;
|
|
260
|
-
pendingSet.clear();
|
|
261
351
|
notifyDepth--;
|
|
352
|
+
if (notifyDepth === 0) {
|
|
353
|
+
pendingQueue.length = 0;
|
|
354
|
+
pendingSet.clear();
|
|
355
|
+
}
|
|
262
356
|
}
|
|
263
357
|
}
|
|
264
358
|
function cleanup(subscriber) {
|
|
265
359
|
const sub = subscriber;
|
|
266
360
|
const singleDep = sub._dep;
|
|
267
361
|
if (singleDep !== void 0) {
|
|
268
|
-
const
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
singleDep.__f = void 0;
|
|
273
|
-
}
|
|
362
|
+
const sig = singleDep;
|
|
363
|
+
const subs = sig[SUBS];
|
|
364
|
+
if (subs?.delete(subscriber)) {
|
|
365
|
+
syncFastPath(sig, subs);
|
|
274
366
|
}
|
|
275
367
|
sub._dep = void 0;
|
|
368
|
+
sub._depEpoch = void 0;
|
|
276
369
|
return;
|
|
277
370
|
}
|
|
278
371
|
const deps = sub._deps;
|
|
279
372
|
if (!deps || deps.size === 0) return;
|
|
280
|
-
for (const signal2 of deps) {
|
|
281
|
-
const
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
signal2.__f = void 0;
|
|
286
|
-
}
|
|
373
|
+
for (const signal2 of deps.keys()) {
|
|
374
|
+
const sig = signal2;
|
|
375
|
+
const subs = sig[SUBS];
|
|
376
|
+
if (subs?.delete(subscriber)) {
|
|
377
|
+
syncFastPath(sig, subs);
|
|
287
378
|
}
|
|
288
379
|
}
|
|
289
380
|
deps.clear();
|
|
290
381
|
}
|
|
291
382
|
|
|
292
383
|
// src/core/ssr-context.ts
|
|
293
|
-
var
|
|
384
|
+
var als = null;
|
|
385
|
+
try {
|
|
386
|
+
if (typeof process !== "undefined" && process.versions && process.versions.node) {
|
|
387
|
+
const req = Function("return typeof require==='function'?require:null")();
|
|
388
|
+
if (req) {
|
|
389
|
+
const mod = req("node:async_hooks");
|
|
390
|
+
als = new mod.AsyncLocalStorage();
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
} catch {
|
|
394
|
+
als = null;
|
|
395
|
+
}
|
|
396
|
+
var fallbackStore = { ssr: false, suspenseIdCounter: 0 };
|
|
397
|
+
function getSSRStore() {
|
|
398
|
+
if (als) {
|
|
399
|
+
const s = als.getStore();
|
|
400
|
+
if (s) return s;
|
|
401
|
+
}
|
|
402
|
+
return fallbackStore;
|
|
403
|
+
}
|
|
294
404
|
function isSSR() {
|
|
295
|
-
return
|
|
405
|
+
return getSSRStore().ssr;
|
|
296
406
|
}
|
|
297
407
|
|
|
298
408
|
// src/core/signals/effect.ts
|
|
@@ -302,26 +412,114 @@ function effect(effectFn, options) {
|
|
|
302
412
|
if (isSSR()) return () => {
|
|
303
413
|
};
|
|
304
414
|
const onError = options?.onError;
|
|
415
|
+
let userCleanups = [];
|
|
416
|
+
const onCleanup = (fn) => {
|
|
417
|
+
userCleanups.push(fn);
|
|
418
|
+
};
|
|
419
|
+
const runUserCleanups = () => {
|
|
420
|
+
if (userCleanups.length === 0) return;
|
|
421
|
+
const list = userCleanups;
|
|
422
|
+
userCleanups = [];
|
|
423
|
+
for (let i = list.length - 1; i >= 0; i--) {
|
|
424
|
+
try {
|
|
425
|
+
list[i]();
|
|
426
|
+
} catch (err) {
|
|
427
|
+
if (typeof console !== "undefined") {
|
|
428
|
+
console.warn("[SibuJS effect] onCleanup threw:", err);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
};
|
|
433
|
+
const invokeBody = () => effectFn(onCleanup);
|
|
305
434
|
const wrappedFn = onError ? () => {
|
|
306
435
|
try {
|
|
307
|
-
|
|
436
|
+
invokeBody();
|
|
308
437
|
} catch (err) {
|
|
309
438
|
onError(err);
|
|
310
439
|
}
|
|
311
|
-
} :
|
|
440
|
+
} : invokeBody;
|
|
312
441
|
let cleanupHandle = () => {
|
|
313
442
|
};
|
|
443
|
+
let running = false;
|
|
444
|
+
let rerunPending = false;
|
|
445
|
+
const MAX_RERUNS = 100;
|
|
314
446
|
const subscriber = () => {
|
|
315
|
-
|
|
316
|
-
|
|
447
|
+
if (running) {
|
|
448
|
+
rerunPending = true;
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
running = true;
|
|
452
|
+
try {
|
|
453
|
+
let reruns = 0;
|
|
454
|
+
do {
|
|
455
|
+
rerunPending = false;
|
|
456
|
+
runUserCleanups();
|
|
457
|
+
cleanupHandle();
|
|
458
|
+
cleanupHandle = track(wrappedFn, subscriber);
|
|
459
|
+
if (++reruns > MAX_RERUNS) {
|
|
460
|
+
if (_g.__SIBU_DEV_WARN__ !== false && typeof console !== "undefined") {
|
|
461
|
+
console.error(
|
|
462
|
+
`[SibuJS] effect re-requested itself ${MAX_RERUNS}+ times \u2014 likely a write-reads-self cycle. Breaking to prevent infinite loop.`
|
|
463
|
+
);
|
|
464
|
+
}
|
|
465
|
+
rerunPending = false;
|
|
466
|
+
break;
|
|
467
|
+
}
|
|
468
|
+
} while (rerunPending);
|
|
469
|
+
} finally {
|
|
470
|
+
running = false;
|
|
471
|
+
rerunPending = false;
|
|
472
|
+
}
|
|
317
473
|
};
|
|
318
|
-
|
|
474
|
+
running = true;
|
|
475
|
+
try {
|
|
476
|
+
let reruns = 0;
|
|
477
|
+
do {
|
|
478
|
+
rerunPending = false;
|
|
479
|
+
runUserCleanups();
|
|
480
|
+
cleanupHandle();
|
|
481
|
+
cleanupHandle = track(wrappedFn, subscriber);
|
|
482
|
+
if (++reruns > MAX_RERUNS) {
|
|
483
|
+
if (_g.__SIBU_DEV_WARN__ !== false && typeof console !== "undefined") {
|
|
484
|
+
console.error(
|
|
485
|
+
`[SibuJS] effect re-requested itself ${MAX_RERUNS}+ times on initial run \u2014 likely a write-reads-self cycle. Breaking to prevent infinite loop.`
|
|
486
|
+
);
|
|
487
|
+
}
|
|
488
|
+
rerunPending = false;
|
|
489
|
+
break;
|
|
490
|
+
}
|
|
491
|
+
} while (rerunPending);
|
|
492
|
+
} finally {
|
|
493
|
+
running = false;
|
|
494
|
+
rerunPending = false;
|
|
495
|
+
}
|
|
319
496
|
const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
320
497
|
if (hook) hook.emit("effect:create", { effectFn });
|
|
498
|
+
let disposed = false;
|
|
321
499
|
return () => {
|
|
500
|
+
if (disposed) return;
|
|
501
|
+
disposed = true;
|
|
322
502
|
const h = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
323
|
-
if (h)
|
|
324
|
-
|
|
503
|
+
if (h) {
|
|
504
|
+
try {
|
|
505
|
+
h.emit("effect:destroy", { effectFn });
|
|
506
|
+
} catch {
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
try {
|
|
510
|
+
runUserCleanups();
|
|
511
|
+
} catch (err) {
|
|
512
|
+
if (typeof console !== "undefined") {
|
|
513
|
+
console.warn("[SibuJS effect] onCleanup threw during dispose:", err);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
try {
|
|
517
|
+
cleanupHandle();
|
|
518
|
+
} catch (err) {
|
|
519
|
+
if (typeof console !== "undefined") {
|
|
520
|
+
console.warn("[SibuJS effect] dispose threw:", err);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
325
523
|
};
|
|
326
524
|
}
|
|
327
525
|
|
|
@@ -345,10 +543,13 @@ function enqueueBatchedSignal(signal2) {
|
|
|
345
543
|
return true;
|
|
346
544
|
}
|
|
347
545
|
function flushBatch() {
|
|
348
|
-
|
|
349
|
-
|
|
546
|
+
try {
|
|
547
|
+
for (const signal2 of pendingSignals) {
|
|
548
|
+
queueSignalNotification(signal2);
|
|
549
|
+
}
|
|
550
|
+
} finally {
|
|
551
|
+
pendingSignals.clear();
|
|
350
552
|
}
|
|
351
|
-
pendingSignals.clear();
|
|
352
553
|
drainNotificationQueue();
|
|
353
554
|
}
|
|
354
555
|
|
|
@@ -391,6 +592,85 @@ function signal(initial, options) {
|
|
|
391
592
|
}
|
|
392
593
|
|
|
393
594
|
// src/plugins/plugin.ts
|
|
595
|
+
function createPluginRegistry() {
|
|
596
|
+
const installedPlugins = /* @__PURE__ */ new Set();
|
|
597
|
+
const hooks = { init: [], mount: [], unmount: [], error: [] };
|
|
598
|
+
const provided = /* @__PURE__ */ new Map();
|
|
599
|
+
const registry = {
|
|
600
|
+
installedPlugins,
|
|
601
|
+
hooks,
|
|
602
|
+
provided,
|
|
603
|
+
plugin(p, options) {
|
|
604
|
+
if (installedPlugins.has(p.name)) {
|
|
605
|
+
console.warn(`[Plugin] "${p.name}" is already installed.`);
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
608
|
+
const ctx = {
|
|
609
|
+
onInit: (cb) => hooks.init.push(cb),
|
|
610
|
+
onMount: (cb) => hooks.mount.push(cb),
|
|
611
|
+
onUnmount: (cb) => hooks.unmount.push(cb),
|
|
612
|
+
onError: (cb) => hooks.error.push(cb),
|
|
613
|
+
provide: (key, value) => provided.set(key, value)
|
|
614
|
+
};
|
|
615
|
+
const initHooksBefore = hooks.init.length;
|
|
616
|
+
p.install(ctx, options);
|
|
617
|
+
installedPlugins.add(p.name);
|
|
618
|
+
const justAdded = hooks.init.slice(initHooksBefore);
|
|
619
|
+
for (const cb of justAdded) {
|
|
620
|
+
try {
|
|
621
|
+
cb();
|
|
622
|
+
} catch (e) {
|
|
623
|
+
console.error(`[Plugin] "${p.name}" init error:`, e);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
},
|
|
627
|
+
inject(key, defaultValue) {
|
|
628
|
+
if (provided.has(key)) return provided.get(key);
|
|
629
|
+
if (defaultValue !== void 0) return defaultValue;
|
|
630
|
+
throw new Error(`[Plugin] No provider found for key "${key}"`);
|
|
631
|
+
},
|
|
632
|
+
triggerMount(element) {
|
|
633
|
+
const snapshot = hooks.mount.slice();
|
|
634
|
+
for (const hook of snapshot) {
|
|
635
|
+
try {
|
|
636
|
+
hook(element);
|
|
637
|
+
} catch (e) {
|
|
638
|
+
console.error("[Plugin] Mount hook error:", e);
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
},
|
|
642
|
+
triggerUnmount(element) {
|
|
643
|
+
const snapshot = hooks.unmount.slice();
|
|
644
|
+
for (const hook of snapshot) {
|
|
645
|
+
try {
|
|
646
|
+
hook(element);
|
|
647
|
+
} catch (e) {
|
|
648
|
+
console.error("[Plugin] Unmount hook error:", e);
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
},
|
|
652
|
+
triggerError(error) {
|
|
653
|
+
const snapshot = hooks.error.slice();
|
|
654
|
+
for (const hook of snapshot) {
|
|
655
|
+
try {
|
|
656
|
+
hook(error);
|
|
657
|
+
} catch (e) {
|
|
658
|
+
console.error("[Plugin] Error hook error:", e);
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
},
|
|
662
|
+
reset() {
|
|
663
|
+
installedPlugins.clear();
|
|
664
|
+
hooks.init.length = 0;
|
|
665
|
+
hooks.mount.length = 0;
|
|
666
|
+
hooks.unmount.length = 0;
|
|
667
|
+
hooks.error.length = 0;
|
|
668
|
+
provided.clear();
|
|
669
|
+
}
|
|
670
|
+
};
|
|
671
|
+
return registry;
|
|
672
|
+
}
|
|
673
|
+
var defaultRegistry = createPluginRegistry();
|
|
394
674
|
function createPlugin(name, install) {
|
|
395
675
|
return { name, install };
|
|
396
676
|
}
|
|
@@ -401,7 +681,7 @@ function mobXAdapter(options) {
|
|
|
401
681
|
const { autorun } = options;
|
|
402
682
|
const disposers = [];
|
|
403
683
|
function fromMobX(expression) {
|
|
404
|
-
const [getValue, setValue] = signal(
|
|
684
|
+
const [getValue, setValue] = signal(void 0);
|
|
405
685
|
const disposer = autorun(() => {
|
|
406
686
|
const newValue = expression();
|
|
407
687
|
batch(() => {
|
|
@@ -409,7 +689,13 @@ function mobXAdapter(options) {
|
|
|
409
689
|
});
|
|
410
690
|
});
|
|
411
691
|
disposers.push(disposer);
|
|
412
|
-
|
|
692
|
+
const getter = (() => getValue());
|
|
693
|
+
getter.dispose = () => {
|
|
694
|
+
const i = disposers.indexOf(disposer);
|
|
695
|
+
if (i >= 0) disposers.splice(i, 1);
|
|
696
|
+
disposer();
|
|
697
|
+
};
|
|
698
|
+
return getter;
|
|
413
699
|
}
|
|
414
700
|
function toMobX(sibuGetter, callback) {
|
|
415
701
|
return effect(() => {
|
|
@@ -431,6 +717,7 @@ function mobXAdapter(options) {
|
|
|
431
717
|
function derived(getter, options) {
|
|
432
718
|
devAssert(typeof getter === "function", "derived: argument must be a getter function.");
|
|
433
719
|
const debugName = options?.name;
|
|
720
|
+
const equals = options?.equals;
|
|
434
721
|
const cs = {};
|
|
435
722
|
cs._d = false;
|
|
436
723
|
cs._g = getter;
|
|
@@ -441,8 +728,14 @@ function derived(getter, options) {
|
|
|
441
728
|
markDirty._c = 1;
|
|
442
729
|
markDirty._sig = cs;
|
|
443
730
|
track(() => {
|
|
444
|
-
|
|
445
|
-
|
|
731
|
+
let threw = true;
|
|
732
|
+
try {
|
|
733
|
+
cs._v = getter();
|
|
734
|
+
cs._d = false;
|
|
735
|
+
threw = false;
|
|
736
|
+
} finally {
|
|
737
|
+
if (threw) cs._d = true;
|
|
738
|
+
}
|
|
446
739
|
}, markDirty);
|
|
447
740
|
const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
448
741
|
let evaluating = false;
|
|
@@ -455,11 +748,16 @@ function derived(getter, options) {
|
|
|
455
748
|
if (trackingSuspended) {
|
|
456
749
|
if (cs._d) {
|
|
457
750
|
evaluating = true;
|
|
751
|
+
let threw = true;
|
|
458
752
|
try {
|
|
459
|
-
|
|
460
|
-
|
|
753
|
+
retrack(() => {
|
|
754
|
+
cs._v = getter();
|
|
755
|
+
cs._d = false;
|
|
756
|
+
threw = false;
|
|
757
|
+
}, markDirty);
|
|
461
758
|
} finally {
|
|
462
759
|
evaluating = false;
|
|
760
|
+
if (threw) cs._d = true;
|
|
463
761
|
}
|
|
464
762
|
}
|
|
465
763
|
return cs._v;
|
|
@@ -468,13 +766,17 @@ function derived(getter, options) {
|
|
|
468
766
|
if (cs._d) {
|
|
469
767
|
const oldValue = cs._v;
|
|
470
768
|
evaluating = true;
|
|
769
|
+
let threw = true;
|
|
471
770
|
try {
|
|
472
|
-
|
|
771
|
+
retrack(() => {
|
|
772
|
+
const next = getter();
|
|
773
|
+
cs._v = equals && cs._v !== void 0 ? equals(cs._v, next) ? cs._v : next : next;
|
|
473
774
|
cs._d = false;
|
|
474
|
-
|
|
775
|
+
threw = false;
|
|
475
776
|
}, markDirty);
|
|
476
777
|
} finally {
|
|
477
778
|
evaluating = false;
|
|
779
|
+
if (threw) cs._d = true;
|
|
478
780
|
}
|
|
479
781
|
if (hook && oldValue !== cs._v) {
|
|
480
782
|
hook.emit("computed:update", { signal: cs, oldValue, newValue: cs._v });
|
|
@@ -501,12 +803,12 @@ function reduxAdapter(options) {
|
|
|
501
803
|
setState(store.getState());
|
|
502
804
|
});
|
|
503
805
|
});
|
|
504
|
-
function
|
|
806
|
+
function select(selector) {
|
|
505
807
|
return derived(() => selector(getState()));
|
|
506
808
|
}
|
|
507
809
|
const api = {
|
|
508
810
|
getState,
|
|
509
|
-
|
|
811
|
+
select,
|
|
510
812
|
dispatch: store.dispatch.bind(store),
|
|
511
813
|
destroy: unsubscribe
|
|
512
814
|
};
|
|
@@ -524,12 +826,12 @@ function zustandAdapter(options) {
|
|
|
524
826
|
setSibuState(state);
|
|
525
827
|
});
|
|
526
828
|
});
|
|
527
|
-
function
|
|
829
|
+
function select(selector) {
|
|
528
830
|
return derived(() => selector(getState()));
|
|
529
831
|
}
|
|
530
832
|
const api = {
|
|
531
833
|
getState,
|
|
532
|
-
|
|
834
|
+
select,
|
|
533
835
|
setState: store.setState.bind(store),
|
|
534
836
|
destroy() {
|
|
535
837
|
unsubscribe();
|
|
@@ -541,29 +843,79 @@ function zustandAdapter(options) {
|
|
|
541
843
|
}
|
|
542
844
|
|
|
543
845
|
// src/utils/sanitize.ts
|
|
846
|
+
var SAFE_URL_PROTOCOLS = ["http:", "https:", "mailto:", "tel:", "ftp:"];
|
|
544
847
|
function sanitizeUrl(url) {
|
|
545
848
|
const trimmed = url.replace(/[\x00-\x20\x7f-\x9f]+/g, "").trim();
|
|
546
849
|
if (!trimmed) return "";
|
|
547
850
|
const lower = trimmed.toLowerCase();
|
|
548
|
-
|
|
549
|
-
|
|
851
|
+
let schemeEnd = -1;
|
|
852
|
+
for (let i = 0; i < lower.length; i++) {
|
|
853
|
+
const ch = lower.charCodeAt(i);
|
|
854
|
+
if (ch === 58) {
|
|
855
|
+
schemeEnd = i;
|
|
856
|
+
break;
|
|
857
|
+
}
|
|
858
|
+
if (ch === 47 || ch === 63 || ch === 35) break;
|
|
550
859
|
}
|
|
860
|
+
if (schemeEnd === -1) return trimmed;
|
|
861
|
+
const scheme = lower.slice(0, schemeEnd + 1);
|
|
862
|
+
if (!/^[a-z][a-z0-9+.-]*:$/.test(scheme)) return trimmed;
|
|
863
|
+
if (SAFE_URL_PROTOCOLS.indexOf(scheme) === -1) return "";
|
|
551
864
|
return trimmed;
|
|
552
865
|
}
|
|
866
|
+
function sanitizeSrcset(value) {
|
|
867
|
+
const parts = value.split(",");
|
|
868
|
+
const out = [];
|
|
869
|
+
for (let i = 0; i < parts.length; i++) {
|
|
870
|
+
const part = parts[i].trim();
|
|
871
|
+
if (!part) continue;
|
|
872
|
+
const m = part.match(/^(\S+)(\s+.+)?$/);
|
|
873
|
+
if (!m) continue;
|
|
874
|
+
const safe = sanitizeUrl(m[1]);
|
|
875
|
+
if (!safe) continue;
|
|
876
|
+
out.push(m[2] ? `${safe}${m[2]}` : safe);
|
|
877
|
+
}
|
|
878
|
+
return out.join(", ");
|
|
879
|
+
}
|
|
553
880
|
function sanitizeCSSValue(value) {
|
|
554
|
-
const
|
|
555
|
-
|
|
881
|
+
const decoded = value.replace(/\\([0-9a-fA-F]{1,6})\s?/g, (_m, hex) => {
|
|
882
|
+
const code = Number.parseInt(hex, 16);
|
|
883
|
+
if (!Number.isFinite(code) || code < 0 || code > 1114111) return "";
|
|
884
|
+
try {
|
|
885
|
+
return String.fromCodePoint(code);
|
|
886
|
+
} catch {
|
|
887
|
+
return "";
|
|
888
|
+
}
|
|
889
|
+
});
|
|
890
|
+
const lower = decoded.toLowerCase().replace(/\s+/g, "");
|
|
891
|
+
if (lower.includes("url(") || lower.includes("expression(") || lower.includes("javascript:") || lower.includes("vbscript:") || lower.includes("-moz-binding") || lower.includes("behavior:") || lower.includes("@import") || lower.includes("image-set(") || lower.includes("filter:progid")) {
|
|
556
892
|
return "";
|
|
557
893
|
}
|
|
558
894
|
return value;
|
|
559
895
|
}
|
|
560
|
-
var URL_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
896
|
+
var URL_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
897
|
+
"href",
|
|
898
|
+
"xlink:href",
|
|
899
|
+
"src",
|
|
900
|
+
"action",
|
|
901
|
+
"formaction",
|
|
902
|
+
"formtarget",
|
|
903
|
+
"cite",
|
|
904
|
+
"poster",
|
|
905
|
+
"background",
|
|
906
|
+
"srcset",
|
|
907
|
+
"ping",
|
|
908
|
+
"data"
|
|
909
|
+
]);
|
|
561
910
|
function isUrlAttribute(attr) {
|
|
562
911
|
return URL_ATTRIBUTES.has(attr);
|
|
563
912
|
}
|
|
564
913
|
|
|
565
914
|
// src/reactivity/bindAttribute.ts
|
|
566
915
|
var _isDev4 = isDev();
|
|
916
|
+
function setProp(el, key, val) {
|
|
917
|
+
el[key] = val;
|
|
918
|
+
}
|
|
567
919
|
function isEventHandlerAttr(name) {
|
|
568
920
|
if (name.length < 3) return false;
|
|
569
921
|
const lower = name.toLowerCase();
|
|
@@ -589,7 +941,7 @@ function bindAttribute(el, attr, getter) {
|
|
|
589
941
|
}
|
|
590
942
|
if (typeof value === "boolean") {
|
|
591
943
|
if (attr in el && (attr === "checked" || attr === "disabled" || attr === "selected")) {
|
|
592
|
-
el
|
|
944
|
+
setProp(el, attr, value);
|
|
593
945
|
} else if (value) {
|
|
594
946
|
el.setAttribute(attr, "");
|
|
595
947
|
} else {
|
|
@@ -599,7 +951,7 @@ function bindAttribute(el, attr, getter) {
|
|
|
599
951
|
}
|
|
600
952
|
const str = String(value);
|
|
601
953
|
if ((attr === "value" || attr === "checked") && attr in el) {
|
|
602
|
-
el
|
|
954
|
+
setProp(el, attr, attr === "checked" ? Boolean(value) : str);
|
|
603
955
|
} else {
|
|
604
956
|
el.setAttribute(attr, isUrlAttribute(attr) ? sanitizeUrl(str) : str);
|
|
605
957
|
}
|
|
@@ -636,24 +988,29 @@ function bindChildNode(placeholder, getter) {
|
|
|
636
988
|
let newNodes;
|
|
637
989
|
if (Array.isArray(result)) {
|
|
638
990
|
newNodes = [];
|
|
991
|
+
const seen = /* @__PURE__ */ new Set();
|
|
639
992
|
for (let i = 0; i < result.length; i++) {
|
|
640
993
|
const item = result[i];
|
|
641
994
|
if (item == null || typeof item === "boolean") continue;
|
|
642
|
-
|
|
995
|
+
const node = item instanceof Node ? item : document.createTextNode(String(item));
|
|
996
|
+
if (seen.has(node)) {
|
|
997
|
+
if (_isDev5)
|
|
998
|
+
devWarn("bindChildNode: duplicate node reference in array \u2014 only the first occurrence is rendered.");
|
|
999
|
+
continue;
|
|
1000
|
+
}
|
|
1001
|
+
seen.add(node);
|
|
1002
|
+
newNodes.push(node);
|
|
643
1003
|
}
|
|
644
1004
|
} else {
|
|
645
1005
|
const node = result instanceof Node ? result : document.createTextNode(String(result));
|
|
646
1006
|
newNodes = [node];
|
|
647
1007
|
}
|
|
648
|
-
|
|
649
|
-
if (
|
|
1008
|
+
let reused;
|
|
1009
|
+
if (lastNodes.length > 0 && newNodes.length > 0) {
|
|
1010
|
+
const lastSet = new Set(lastNodes);
|
|
1011
|
+
reused = /* @__PURE__ */ new Set();
|
|
650
1012
|
for (let i = 0; i < newNodes.length; i++) {
|
|
651
|
-
|
|
652
|
-
if (newNodes[i] === lastNodes[j]) {
|
|
653
|
-
reused.add(newNodes[i]);
|
|
654
|
-
break;
|
|
655
|
-
}
|
|
656
|
-
}
|
|
1013
|
+
if (lastSet.has(newNodes[i])) reused.add(newNodes[i]);
|
|
657
1014
|
}
|
|
658
1015
|
}
|
|
659
1016
|
for (let i = 0; i < lastNodes.length; i++) {
|
|
@@ -692,6 +1049,30 @@ function registerDisposer(node, teardown) {
|
|
|
692
1049
|
}
|
|
693
1050
|
|
|
694
1051
|
// src/core/rendering/tagFactory.ts
|
|
1052
|
+
var _isDev7 = isDev();
|
|
1053
|
+
var BLOCKED_TAGS = /* @__PURE__ */ new Set(["script", "iframe", "object", "embed", "frame", "frameset"]);
|
|
1054
|
+
function validateTagName(tag) {
|
|
1055
|
+
const lower = tag.toLowerCase();
|
|
1056
|
+
if (BLOCKED_TAGS.has(lower)) {
|
|
1057
|
+
throw new Error(`tagFactory: refusing to create <${tag}> \u2014 tag is blocked for security reasons.`);
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
var CLOBBER_RISKY_IDS = /* @__PURE__ */ new Set([
|
|
1061
|
+
"config",
|
|
1062
|
+
"location",
|
|
1063
|
+
"history",
|
|
1064
|
+
"document",
|
|
1065
|
+
"window",
|
|
1066
|
+
"navigator",
|
|
1067
|
+
"name",
|
|
1068
|
+
"top",
|
|
1069
|
+
"parent",
|
|
1070
|
+
"self",
|
|
1071
|
+
"frames"
|
|
1072
|
+
]);
|
|
1073
|
+
function setProp2(el, key, val) {
|
|
1074
|
+
el[key] = val;
|
|
1075
|
+
}
|
|
695
1076
|
var kebabCache = /* @__PURE__ */ new Map();
|
|
696
1077
|
function toKebab(prop) {
|
|
697
1078
|
let cached = kebabCache.get(prop);
|
|
@@ -816,79 +1197,103 @@ function appendChildren(el, nodes) {
|
|
|
816
1197
|
}
|
|
817
1198
|
}
|
|
818
1199
|
}
|
|
819
|
-
var tagFactory = (tag, ns) =>
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
if (
|
|
824
|
-
|
|
825
|
-
|
|
1200
|
+
var tagFactory = (tag, ns) => {
|
|
1201
|
+
return (first, second) => {
|
|
1202
|
+
validateTagName(tag);
|
|
1203
|
+
const el = ns ? document.createElementNS(ns, tag) : document.createElement(tag);
|
|
1204
|
+
if (first === void 0) return el;
|
|
1205
|
+
if (typeof first === "string") {
|
|
1206
|
+
if (second !== void 0) {
|
|
1207
|
+
el.setAttribute("class", first);
|
|
1208
|
+
appendChildren(el, second);
|
|
1209
|
+
return el;
|
|
1210
|
+
}
|
|
1211
|
+
el.textContent = first;
|
|
826
1212
|
return el;
|
|
827
1213
|
}
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
1214
|
+
if (typeof first === "number") {
|
|
1215
|
+
el.textContent = String(first);
|
|
1216
|
+
return el;
|
|
1217
|
+
}
|
|
1218
|
+
if (Array.isArray(first) || first instanceof Node || typeof first === "function") {
|
|
1219
|
+
appendChildren(el, first);
|
|
1220
|
+
return el;
|
|
1221
|
+
}
|
|
1222
|
+
const props = first;
|
|
1223
|
+
const pClass = props.class;
|
|
1224
|
+
if (pClass != null) applyClass(el, pClass);
|
|
1225
|
+
const pId = props.id;
|
|
1226
|
+
if (pId != null) {
|
|
1227
|
+
if (_isDev7 && typeof pId === "string" && CLOBBER_RISKY_IDS.has(pId.toLowerCase())) {
|
|
1228
|
+
devWarn(
|
|
1229
|
+
`tagFactory: element id="${pId}" matches a common global and may cause DOM clobbering. Avoid setting ids from untrusted input.`
|
|
1230
|
+
);
|
|
1231
|
+
}
|
|
1232
|
+
el.id = pId;
|
|
1233
|
+
}
|
|
1234
|
+
const pNodes = second !== void 0 ? second : props.nodes;
|
|
1235
|
+
if (pNodes != null) appendChildren(el, pNodes);
|
|
1236
|
+
const pOn = props.on;
|
|
1237
|
+
if (pOn) {
|
|
1238
|
+
for (const ev in pOn) {
|
|
1239
|
+
const handler = pOn[ev];
|
|
1240
|
+
if (typeof handler === "function") {
|
|
1241
|
+
el.addEventListener(ev, handler);
|
|
1242
|
+
} else if (_isDev7) {
|
|
1243
|
+
devWarn(
|
|
1244
|
+
`tagFactory: on.${ev} handler is not a function (got ${typeof handler}). Event listener was not attached.`
|
|
1245
|
+
);
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
const pStyle = props.style;
|
|
1250
|
+
if (pStyle != null) applyStyle(el, pStyle);
|
|
1251
|
+
const pRef = props.ref;
|
|
1252
|
+
if (pRef) pRef.current = el;
|
|
1253
|
+
for (const key in props) {
|
|
1254
|
+
switch (key) {
|
|
1255
|
+
case "class":
|
|
1256
|
+
case "id":
|
|
1257
|
+
case "nodes":
|
|
1258
|
+
case "on":
|
|
1259
|
+
case "style":
|
|
1260
|
+
case "ref":
|
|
1261
|
+
case "onElement":
|
|
1262
|
+
continue;
|
|
1263
|
+
// already handled above / below
|
|
1264
|
+
default: {
|
|
1265
|
+
const value = props[key];
|
|
1266
|
+
if (value == null) continue;
|
|
1267
|
+
const lkey = key.toLowerCase();
|
|
1268
|
+
if (lkey[0] === "o" && lkey[1] === "n") continue;
|
|
1269
|
+
if (typeof value === "function") {
|
|
1270
|
+
registerDisposer(el, bindAttribute(el, key, value));
|
|
1271
|
+
} else if (typeof value === "boolean") {
|
|
1272
|
+
if (key in el && (key === "checked" || key === "disabled" || key === "selected")) {
|
|
1273
|
+
setProp2(el, key, value);
|
|
1274
|
+
} else if (value) {
|
|
1275
|
+
el.setAttribute(key, "");
|
|
1276
|
+
} else {
|
|
1277
|
+
el.removeAttribute(key);
|
|
1278
|
+
}
|
|
878
1279
|
} else {
|
|
879
|
-
|
|
1280
|
+
const str = String(value);
|
|
1281
|
+
if (lkey === "srcset") {
|
|
1282
|
+
el.setAttribute(key, sanitizeSrcset(str));
|
|
1283
|
+
} else if (isUrlAttribute(lkey)) {
|
|
1284
|
+
el.setAttribute(key, sanitizeUrl(str));
|
|
1285
|
+
} else {
|
|
1286
|
+
el.setAttribute(key, str);
|
|
1287
|
+
}
|
|
880
1288
|
}
|
|
881
|
-
} else {
|
|
882
|
-
const str = String(value);
|
|
883
|
-
el.setAttribute(key, isUrlAttribute(key) ? sanitizeUrl(str) : str);
|
|
884
1289
|
}
|
|
885
1290
|
}
|
|
886
1291
|
}
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
1292
|
+
if (props.onElement && typeof props.onElement === "function") {
|
|
1293
|
+
props.onElement(el);
|
|
1294
|
+
}
|
|
1295
|
+
return el;
|
|
1296
|
+
};
|
|
892
1297
|
};
|
|
893
1298
|
|
|
894
1299
|
// src/ecosystem/ui/componentAdapter.ts
|