sibujs 1.5.0 → 2.0.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 +238 -69
- package/dist/browser.d.cts +5 -0
- package/dist/browser.d.ts +5 -0
- package/dist/browser.js +6 -6
- package/dist/build.cjs +916 -292
- 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-3JHCYHWN.js +125 -0
- package/dist/{chunk-VAPYJN4X.js → chunk-3LR7GLWQ.js} +93 -23
- package/dist/{chunk-RJ46C3CS.js → chunk-3NSGB5JN.js} +71 -20
- package/dist/{chunk-XUEEGU5O.js → chunk-52YJLLRO.js} +16 -4
- package/dist/{chunk-XHK6BDAJ.js → chunk-54EDRCEF.js} +25 -8
- package/dist/chunk-7JDB7I65.js +1327 -0
- package/dist/{chunk-WZSPOOER.js → chunk-CC65Y57T.js} +8 -5
- package/dist/{chunk-23VV7YD3.js → chunk-DFPFITST.js} +25 -30
- package/dist/{chunk-BGN5ZMP4.js → chunk-GTBNNBJ6.js} +14 -2
- package/dist/chunk-HB24TBAF.js +121 -0
- package/dist/{chunk-CZUGLNJS.js → chunk-ITX6OO3F.js} +3 -3
- package/dist/{chunk-BGTHZHJ5.js → chunk-JA6667UN.js} +188 -44
- package/dist/{chunk-7GRNSCFT.js → chunk-JXMMDLBY.js} +306 -183
- package/dist/{chunk-3X2YG6YM.js → chunk-JYD2PWXH.js} +59 -28
- package/dist/{chunk-SFKNRVCU.js → chunk-KLRMB5ZS.js} +135 -79
- package/dist/{chunk-5X6PP2UK.js → chunk-LMLD24FC.js} +2 -2
- package/dist/{chunk-M4NLBH4I.js → chunk-LYTCUZ7H.js} +3 -2
- package/dist/{chunk-BMPL52BF.js → chunk-MIUAXB7K.js} +118 -66
- package/dist/{chunk-JCDUJN2F.js → chunk-ND2664SF.js} +486 -153
- package/dist/{chunk-VQDZK23A.js → chunk-O2MNQFLP.js} +181 -66
- package/dist/{chunk-NHUC2QWH.js → chunk-R73P76YZ.js} +1 -1
- package/dist/{chunk-2BYQDGN3.js → chunk-SAHNHTFC.js} +234 -63
- package/dist/chunk-UCS6AMJ7.js +79 -0
- package/dist/{chunk-K4G4ZQNR.js → chunk-VLPPXTYG.js} +84 -38
- package/dist/{chunk-OUZZEE4S.js → chunk-WOMYAHHI.js} +17 -11
- 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 +410 -99
- package/dist/data.d.cts +20 -2
- package/dist/data.d.ts +20 -2
- package/dist/data.js +11 -9
- package/dist/devtools.cjs +513 -223
- package/dist/devtools.d.cts +1 -1
- package/dist/devtools.d.ts +1 -1
- package/dist/devtools.js +12 -6
- package/dist/ecosystem.cjs +475 -144
- package/dist/ecosystem.d.cts +9 -7
- package/dist/ecosystem.d.ts +9 -7
- package/dist/ecosystem.js +12 -11
- package/dist/extras.cjs +3355 -1541
- package/dist/extras.d.cts +9 -9
- package/dist/extras.d.ts +9 -9
- package/dist/extras.js +58 -45
- package/dist/index.cjs +920 -292
- package/dist/index.d.cts +71 -8
- package/dist/index.d.ts +71 -8
- package/dist/index.js +28 -16
- package/dist/{introspect-BumjnBKr.d.cts → introspect-BWNjNw64.d.cts} +22 -2
- package/dist/{introspect-CZrlcaYy.d.ts → introspect-cY2pg9pW.d.ts} +22 -2
- package/dist/motion.cjs +77 -34
- package/dist/motion.js +4 -4
- package/dist/patterns.cjs +335 -69
- package/dist/patterns.d.cts +11 -12
- package/dist/patterns.d.ts +11 -12
- package/dist/patterns.js +7 -7
- package/dist/performance.cjs +279 -108
- 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 +635 -260
- 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 +642 -222
- 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 +252 -63
- package/dist/testing.d.cts +17 -4
- package/dist/testing.d.ts +17 -4
- package/dist/testing.js +100 -44
- package/dist/ui.cjs +463 -137
- package/dist/ui.d.cts +1 -1
- package/dist/ui.d.ts +1 -1
- package/dist/ui.js +20 -17
- package/dist/widgets.cjs +977 -94
- 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-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/patterns.cjs
CHANGED
|
@@ -50,12 +50,12 @@ function isDev() {
|
|
|
50
50
|
var _isDev = isDev();
|
|
51
51
|
function devAssert(condition, message) {
|
|
52
52
|
if (_isDev && !condition) {
|
|
53
|
-
throw new Error(`[
|
|
53
|
+
throw new Error(`[SibuJS] ${message}`);
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
function devWarn(message) {
|
|
57
57
|
if (_isDev) {
|
|
58
|
-
console.warn(`[
|
|
58
|
+
console.warn(`[SibuJS] ${message}`);
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
|
|
@@ -65,11 +65,11 @@ var subscriberStack = new Array(32);
|
|
|
65
65
|
var stackCapacity = 32;
|
|
66
66
|
var stackTop = -1;
|
|
67
67
|
var currentSubscriber = null;
|
|
68
|
-
var signalSubscribers = /* @__PURE__ */ new WeakMap();
|
|
69
68
|
var SUBS = "__s";
|
|
70
69
|
var notifyDepth = 0;
|
|
71
70
|
var pendingQueue = [];
|
|
72
71
|
var pendingSet = /* @__PURE__ */ new Set();
|
|
72
|
+
var propagateStack = [];
|
|
73
73
|
function safeInvoke(sub) {
|
|
74
74
|
try {
|
|
75
75
|
sub();
|
|
@@ -78,6 +78,15 @@ function safeInvoke(sub) {
|
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
var trackingSuspended = false;
|
|
81
|
+
function retrack(effectFn, subscriber) {
|
|
82
|
+
const prev = currentSubscriber;
|
|
83
|
+
currentSubscriber = subscriber;
|
|
84
|
+
try {
|
|
85
|
+
effectFn();
|
|
86
|
+
} finally {
|
|
87
|
+
currentSubscriber = prev;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
81
90
|
function track(effectFn, subscriber) {
|
|
82
91
|
if (!subscriber) subscriber = effectFn;
|
|
83
92
|
cleanup(subscriber);
|
|
@@ -116,7 +125,6 @@ function recordDependency(signal2) {
|
|
|
116
125
|
let subs = signal2[SUBS];
|
|
117
126
|
if (!subs) {
|
|
118
127
|
subs = /* @__PURE__ */ new Set();
|
|
119
|
-
signalSubscribers.set(signal2, subs);
|
|
120
128
|
signal2[SUBS] = subs;
|
|
121
129
|
}
|
|
122
130
|
subs.add(currentSubscriber);
|
|
@@ -126,42 +134,83 @@ function recordDependency(signal2) {
|
|
|
126
134
|
signal2.__f = void 0;
|
|
127
135
|
}
|
|
128
136
|
}
|
|
137
|
+
function queueSignalNotification(signal2) {
|
|
138
|
+
const subs = signal2[SUBS];
|
|
139
|
+
if (!subs) return;
|
|
140
|
+
for (const sub of subs) {
|
|
141
|
+
if (sub._c) {
|
|
142
|
+
propagateDirty(sub);
|
|
143
|
+
} else if (!pendingSet.has(sub)) {
|
|
144
|
+
pendingSet.add(sub);
|
|
145
|
+
pendingQueue.push(sub);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
var maxDrainIterations = 1e5;
|
|
150
|
+
function drainNotificationQueue() {
|
|
151
|
+
if (notifyDepth > 0) return;
|
|
152
|
+
notifyDepth++;
|
|
153
|
+
try {
|
|
154
|
+
let i = 0;
|
|
155
|
+
while (i < pendingQueue.length) {
|
|
156
|
+
if (i >= maxDrainIterations) {
|
|
157
|
+
if (typeof console !== "undefined") {
|
|
158
|
+
console.error(
|
|
159
|
+
`[SibuJS] Notification queue exceeded ${maxDrainIterations} iterations \u2014 likely an effect that writes to a signal it reads. Breaking to prevent infinite loop.`
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
safeInvoke(pendingQueue[i]);
|
|
165
|
+
i++;
|
|
166
|
+
}
|
|
167
|
+
} finally {
|
|
168
|
+
notifyDepth--;
|
|
169
|
+
if (notifyDepth === 0) {
|
|
170
|
+
pendingQueue.length = 0;
|
|
171
|
+
pendingSet.clear();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
129
175
|
function propagateDirty(sub) {
|
|
130
176
|
sub();
|
|
131
|
-
|
|
132
|
-
|
|
177
|
+
const rootSig = sub._sig;
|
|
178
|
+
if (!rootSig) return;
|
|
179
|
+
const stack = propagateStack;
|
|
180
|
+
const baseLen = stack.length;
|
|
181
|
+
stack.push(rootSig);
|
|
182
|
+
while (stack.length > baseLen) {
|
|
183
|
+
const sig = stack.pop();
|
|
133
184
|
const first = sig.__f;
|
|
134
185
|
if (first) {
|
|
135
186
|
if (first._c) {
|
|
136
187
|
const nSig = first._sig;
|
|
137
|
-
nSig._d
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
if (!pendingSet.has(first)) {
|
|
188
|
+
if (!nSig._d) {
|
|
189
|
+
nSig._d = true;
|
|
190
|
+
stack.push(nSig);
|
|
191
|
+
}
|
|
192
|
+
} else if (!pendingSet.has(first)) {
|
|
142
193
|
pendingSet.add(first);
|
|
143
194
|
pendingQueue.push(first);
|
|
144
195
|
}
|
|
145
|
-
|
|
196
|
+
continue;
|
|
146
197
|
}
|
|
147
198
|
const subs = sig[SUBS];
|
|
148
|
-
if (!subs)
|
|
149
|
-
let nextSig;
|
|
199
|
+
if (!subs) continue;
|
|
150
200
|
for (const s of subs) {
|
|
151
201
|
if (s._c) {
|
|
152
|
-
s();
|
|
153
202
|
const nSig = s._sig;
|
|
154
|
-
if (nSig && !
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
203
|
+
if (nSig && !nSig._d) {
|
|
204
|
+
nSig._d = true;
|
|
205
|
+
stack.push(nSig);
|
|
206
|
+
} else if (!nSig) {
|
|
207
|
+
s();
|
|
158
208
|
}
|
|
159
209
|
} else if (!pendingSet.has(s)) {
|
|
160
210
|
pendingSet.add(s);
|
|
161
211
|
pendingQueue.push(s);
|
|
162
212
|
}
|
|
163
213
|
}
|
|
164
|
-
sig = nextSig;
|
|
165
214
|
}
|
|
166
215
|
}
|
|
167
216
|
function notifySubscribers(signal2) {
|
|
@@ -185,13 +234,23 @@ function notifySubscribers(signal2) {
|
|
|
185
234
|
}
|
|
186
235
|
let i = 0;
|
|
187
236
|
while (i < pendingQueue.length) {
|
|
237
|
+
if (i >= maxDrainIterations) {
|
|
238
|
+
if (typeof console !== "undefined") {
|
|
239
|
+
console.error(
|
|
240
|
+
`[SibuJS] Notification queue exceeded ${maxDrainIterations} iterations \u2014 likely an effect that writes to a signal it reads. Breaking to prevent infinite loop.`
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
188
245
|
safeInvoke(pendingQueue[i]);
|
|
189
246
|
i++;
|
|
190
247
|
}
|
|
191
248
|
} finally {
|
|
192
|
-
pendingQueue.length = 0;
|
|
193
|
-
pendingSet.clear();
|
|
194
249
|
notifyDepth--;
|
|
250
|
+
if (notifyDepth === 0) {
|
|
251
|
+
pendingQueue.length = 0;
|
|
252
|
+
pendingSet.clear();
|
|
253
|
+
}
|
|
195
254
|
}
|
|
196
255
|
return;
|
|
197
256
|
}
|
|
@@ -211,30 +270,48 @@ function notifySubscribers(signal2) {
|
|
|
211
270
|
notifyDepth++;
|
|
212
271
|
try {
|
|
213
272
|
let directCount = 0;
|
|
273
|
+
let hasComputedSub = false;
|
|
214
274
|
for (const sub of subs) {
|
|
275
|
+
if (sub._c) hasComputedSub = true;
|
|
215
276
|
pendingQueue[directCount++] = sub;
|
|
216
277
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
278
|
+
if (!hasComputedSub) {
|
|
279
|
+
for (let i2 = 0; i2 < directCount; i2++) {
|
|
280
|
+
safeInvoke(pendingQueue[i2]);
|
|
220
281
|
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
282
|
+
} else {
|
|
283
|
+
for (let i2 = 0; i2 < directCount; i2++) {
|
|
284
|
+
if (pendingQueue[i2]._c) {
|
|
285
|
+
propagateDirty(pendingQueue[i2]);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
for (let i2 = 0; i2 < directCount; i2++) {
|
|
289
|
+
const sub = pendingQueue[i2];
|
|
290
|
+
if (!sub._c && !pendingSet.has(sub)) {
|
|
291
|
+
pendingSet.add(sub);
|
|
292
|
+
safeInvoke(sub);
|
|
226
293
|
}
|
|
227
294
|
}
|
|
228
295
|
}
|
|
229
296
|
let i = directCount;
|
|
230
297
|
while (i < pendingQueue.length) {
|
|
298
|
+
if (i - directCount >= maxDrainIterations) {
|
|
299
|
+
if (typeof console !== "undefined") {
|
|
300
|
+
console.error(
|
|
301
|
+
`[SibuJS] Notification queue exceeded ${maxDrainIterations} iterations \u2014 likely an effect that writes to a signal it reads. Breaking to prevent infinite loop.`
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
break;
|
|
305
|
+
}
|
|
231
306
|
safeInvoke(pendingQueue[i]);
|
|
232
307
|
i++;
|
|
233
308
|
}
|
|
234
309
|
} finally {
|
|
235
|
-
pendingQueue.length = 0;
|
|
236
|
-
pendingSet.clear();
|
|
237
310
|
notifyDepth--;
|
|
311
|
+
if (notifyDepth === 0) {
|
|
312
|
+
pendingQueue.length = 0;
|
|
313
|
+
pendingSet.clear();
|
|
314
|
+
}
|
|
238
315
|
}
|
|
239
316
|
}
|
|
240
317
|
function cleanup(subscriber) {
|
|
@@ -245,7 +322,9 @@ function cleanup(subscriber) {
|
|
|
245
322
|
if (subs) {
|
|
246
323
|
subs.delete(subscriber);
|
|
247
324
|
if (singleDep.__f === subscriber) {
|
|
248
|
-
singleDep.__f = void 0;
|
|
325
|
+
singleDep.__f = subs.size === 1 ? subs.values().next().value : void 0;
|
|
326
|
+
} else if (subs.size === 1 && singleDep.__f === void 0) {
|
|
327
|
+
singleDep.__f = subs.values().next().value;
|
|
249
328
|
}
|
|
250
329
|
}
|
|
251
330
|
sub._dep = void 0;
|
|
@@ -258,7 +337,9 @@ function cleanup(subscriber) {
|
|
|
258
337
|
if (subs) {
|
|
259
338
|
subs.delete(subscriber);
|
|
260
339
|
if (signal2.__f === subscriber) {
|
|
261
|
-
signal2.__f = void 0;
|
|
340
|
+
signal2.__f = subs.size === 1 ? subs.values().next().value : void 0;
|
|
341
|
+
} else if (subs.size === 1 && signal2.__f === void 0) {
|
|
342
|
+
signal2.__f = subs.values().next().value;
|
|
262
343
|
}
|
|
263
344
|
}
|
|
264
345
|
}
|
|
@@ -268,11 +349,32 @@ function cleanup(subscriber) {
|
|
|
268
349
|
// src/reactivity/batch.ts
|
|
269
350
|
var batchDepth = 0;
|
|
270
351
|
var pendingSignals = /* @__PURE__ */ new Set();
|
|
352
|
+
function batch(fn) {
|
|
353
|
+
batchDepth++;
|
|
354
|
+
try {
|
|
355
|
+
return fn();
|
|
356
|
+
} finally {
|
|
357
|
+
batchDepth--;
|
|
358
|
+
if (batchDepth === 0) {
|
|
359
|
+
flushBatch();
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
271
363
|
function enqueueBatchedSignal(signal2) {
|
|
272
364
|
if (batchDepth === 0) return false;
|
|
273
365
|
pendingSignals.add(signal2);
|
|
274
366
|
return true;
|
|
275
367
|
}
|
|
368
|
+
function flushBatch() {
|
|
369
|
+
try {
|
|
370
|
+
for (const signal2 of pendingSignals) {
|
|
371
|
+
queueSignalNotification(signal2);
|
|
372
|
+
}
|
|
373
|
+
} finally {
|
|
374
|
+
pendingSignals.clear();
|
|
375
|
+
}
|
|
376
|
+
drainNotificationQueue();
|
|
377
|
+
}
|
|
276
378
|
|
|
277
379
|
// src/core/signals/signal.ts
|
|
278
380
|
var _g = globalThis;
|
|
@@ -375,9 +477,28 @@ function machine(config) {
|
|
|
375
477
|
}
|
|
376
478
|
|
|
377
479
|
// src/core/ssr-context.ts
|
|
378
|
-
var
|
|
480
|
+
var als = null;
|
|
481
|
+
try {
|
|
482
|
+
if (typeof process !== "undefined" && process.versions && process.versions.node) {
|
|
483
|
+
const req = Function("return typeof require==='function'?require:null")();
|
|
484
|
+
if (req) {
|
|
485
|
+
const mod = req("node:async_hooks");
|
|
486
|
+
als = new mod.AsyncLocalStorage();
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
} catch {
|
|
490
|
+
als = null;
|
|
491
|
+
}
|
|
492
|
+
var fallbackStore = { ssr: false, suspenseIdCounter: 0 };
|
|
493
|
+
function getSSRStore() {
|
|
494
|
+
if (als) {
|
|
495
|
+
const s = als.getStore();
|
|
496
|
+
if (s) return s;
|
|
497
|
+
}
|
|
498
|
+
return fallbackStore;
|
|
499
|
+
}
|
|
379
500
|
function isSSR() {
|
|
380
|
-
return
|
|
501
|
+
return getSSRStore().ssr;
|
|
381
502
|
}
|
|
382
503
|
|
|
383
504
|
// src/core/signals/effect.ts
|
|
@@ -387,26 +508,86 @@ function effect(effectFn, options) {
|
|
|
387
508
|
if (isSSR()) return () => {
|
|
388
509
|
};
|
|
389
510
|
const onError = options?.onError;
|
|
511
|
+
let userCleanups = [];
|
|
512
|
+
const onCleanup = (fn) => {
|
|
513
|
+
userCleanups.push(fn);
|
|
514
|
+
};
|
|
515
|
+
const runUserCleanups = () => {
|
|
516
|
+
if (userCleanups.length === 0) return;
|
|
517
|
+
const list = userCleanups;
|
|
518
|
+
userCleanups = [];
|
|
519
|
+
for (let i = list.length - 1; i >= 0; i--) {
|
|
520
|
+
try {
|
|
521
|
+
list[i]();
|
|
522
|
+
} catch (err) {
|
|
523
|
+
if (typeof console !== "undefined") {
|
|
524
|
+
console.warn("[SibuJS effect] onCleanup threw:", err);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
};
|
|
529
|
+
const invokeBody = () => effectFn(onCleanup);
|
|
390
530
|
const wrappedFn = onError ? () => {
|
|
391
531
|
try {
|
|
392
|
-
|
|
532
|
+
invokeBody();
|
|
393
533
|
} catch (err) {
|
|
394
534
|
onError(err);
|
|
395
535
|
}
|
|
396
|
-
} :
|
|
536
|
+
} : invokeBody;
|
|
397
537
|
let cleanupHandle = () => {
|
|
398
538
|
};
|
|
539
|
+
let running = false;
|
|
399
540
|
const subscriber = () => {
|
|
400
|
-
|
|
401
|
-
|
|
541
|
+
if (running) {
|
|
542
|
+
if (_g2.__SIBU_DEV_WARN__ !== false && typeof console !== "undefined") {
|
|
543
|
+
console.warn(
|
|
544
|
+
"[SibuJS] effect re-entered itself while running \u2014 the triggering update will be ignored. Wrap mutual writes in `batch()` or split the effect to avoid this."
|
|
545
|
+
);
|
|
546
|
+
}
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
running = true;
|
|
550
|
+
try {
|
|
551
|
+
runUserCleanups();
|
|
552
|
+
cleanupHandle();
|
|
553
|
+
cleanupHandle = track(wrappedFn, subscriber);
|
|
554
|
+
} finally {
|
|
555
|
+
running = false;
|
|
556
|
+
}
|
|
402
557
|
};
|
|
403
|
-
|
|
558
|
+
running = true;
|
|
559
|
+
try {
|
|
560
|
+
cleanupHandle = track(wrappedFn, subscriber);
|
|
561
|
+
} finally {
|
|
562
|
+
running = false;
|
|
563
|
+
}
|
|
404
564
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
405
565
|
if (hook) hook.emit("effect:create", { effectFn });
|
|
566
|
+
let disposed = false;
|
|
406
567
|
return () => {
|
|
568
|
+
if (disposed) return;
|
|
569
|
+
disposed = true;
|
|
407
570
|
const h = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
408
|
-
if (h)
|
|
409
|
-
|
|
571
|
+
if (h) {
|
|
572
|
+
try {
|
|
573
|
+
h.emit("effect:destroy", { effectFn });
|
|
574
|
+
} catch {
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
try {
|
|
578
|
+
runUserCleanups();
|
|
579
|
+
} catch (err) {
|
|
580
|
+
if (typeof console !== "undefined") {
|
|
581
|
+
console.warn("[SibuJS effect] onCleanup threw during dispose:", err);
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
try {
|
|
585
|
+
cleanupHandle();
|
|
586
|
+
} catch (err) {
|
|
587
|
+
if (typeof console !== "undefined") {
|
|
588
|
+
console.warn("[SibuJS effect] dispose threw:", err);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
410
591
|
};
|
|
411
592
|
}
|
|
412
593
|
|
|
@@ -414,7 +595,11 @@ function effect(effectFn, options) {
|
|
|
414
595
|
function persisted(key, initial, options = {}) {
|
|
415
596
|
const storage = options.session ? sessionStorage : localStorage;
|
|
416
597
|
const serialize = options.serialize || JSON.stringify;
|
|
417
|
-
const
|
|
598
|
+
const safeReviver = (k, v) => {
|
|
599
|
+
if (k === "__proto__" || k === "constructor" || k === "prototype") return void 0;
|
|
600
|
+
return v;
|
|
601
|
+
};
|
|
602
|
+
const deserialize = options.deserialize || ((raw) => JSON.parse(raw, safeReviver));
|
|
418
603
|
const encrypt = options.encrypt;
|
|
419
604
|
const decrypt = options.decrypt;
|
|
420
605
|
const syncTabs = options.session ? false : options.syncTabs ?? true;
|
|
@@ -518,6 +703,27 @@ function optimisticList(initialValue) {
|
|
|
518
703
|
const [pending, setPending] = signal(false);
|
|
519
704
|
let inflightCount = 0;
|
|
520
705
|
let version = 0;
|
|
706
|
+
let tempIdCounter = 0;
|
|
707
|
+
const itemIds = /* @__PURE__ */ new WeakMap();
|
|
708
|
+
const idToItem = /* @__PURE__ */ new Map();
|
|
709
|
+
function tagItem(item) {
|
|
710
|
+
const id = ++tempIdCounter;
|
|
711
|
+
if (item !== null && typeof item === "object") {
|
|
712
|
+
itemIds.set(item, id);
|
|
713
|
+
}
|
|
714
|
+
idToItem.set(id, item);
|
|
715
|
+
return id;
|
|
716
|
+
}
|
|
717
|
+
function findIndexById(list, id) {
|
|
718
|
+
for (let i = 0; i < list.length; i++) {
|
|
719
|
+
const it = list[i];
|
|
720
|
+
if (it !== null && typeof it === "object" && itemIds.get(it) === id) {
|
|
721
|
+
return i;
|
|
722
|
+
}
|
|
723
|
+
if (Object.is(it, idToItem.get(id))) return i;
|
|
724
|
+
}
|
|
725
|
+
return -1;
|
|
726
|
+
}
|
|
521
727
|
function begin() {
|
|
522
728
|
const v = ++version;
|
|
523
729
|
inflightCount++;
|
|
@@ -533,12 +739,13 @@ function optimisticList(initialValue) {
|
|
|
533
739
|
}
|
|
534
740
|
async function add(item, asyncAction) {
|
|
535
741
|
const prev = items();
|
|
742
|
+
const id = tagItem(item);
|
|
536
743
|
setItems([...prev, item]);
|
|
537
744
|
const myVersion = begin();
|
|
538
745
|
try {
|
|
539
746
|
const result = await asyncAction();
|
|
540
747
|
setItems((current) => {
|
|
541
|
-
const idx = current
|
|
748
|
+
const idx = findIndexById(current, id);
|
|
542
749
|
if (idx >= 0) {
|
|
543
750
|
const next = [...current];
|
|
544
751
|
next[idx] = result;
|
|
@@ -546,8 +753,10 @@ function optimisticList(initialValue) {
|
|
|
546
753
|
}
|
|
547
754
|
return [...current, result];
|
|
548
755
|
});
|
|
756
|
+
idToItem.delete(id);
|
|
549
757
|
end(myVersion);
|
|
550
758
|
} catch {
|
|
759
|
+
idToItem.delete(id);
|
|
551
760
|
end(myVersion, () => setItems(prev));
|
|
552
761
|
}
|
|
553
762
|
}
|
|
@@ -564,12 +773,13 @@ function optimisticList(initialValue) {
|
|
|
564
773
|
}
|
|
565
774
|
async function updateItem(predicate, patch, asyncAction) {
|
|
566
775
|
const prev = items();
|
|
567
|
-
const
|
|
776
|
+
const patchedIds = [];
|
|
568
777
|
setItems(
|
|
569
778
|
prev.map((item) => {
|
|
570
779
|
if (predicate(item)) {
|
|
571
780
|
const patched = { ...item, ...patch };
|
|
572
|
-
|
|
781
|
+
const id = tagItem(patched);
|
|
782
|
+
patchedIds.push(id);
|
|
573
783
|
return patched;
|
|
574
784
|
}
|
|
575
785
|
return item;
|
|
@@ -578,9 +788,19 @@ function optimisticList(initialValue) {
|
|
|
578
788
|
const myVersion = begin();
|
|
579
789
|
try {
|
|
580
790
|
const result = await asyncAction();
|
|
581
|
-
setItems(
|
|
791
|
+
setItems(
|
|
792
|
+
(current) => current.map((item) => {
|
|
793
|
+
if (item !== null && typeof item === "object") {
|
|
794
|
+
const existingId = itemIds.get(item);
|
|
795
|
+
if (existingId !== void 0 && patchedIds.includes(existingId)) return result;
|
|
796
|
+
}
|
|
797
|
+
return item;
|
|
798
|
+
})
|
|
799
|
+
);
|
|
800
|
+
for (const id of patchedIds) idToItem.delete(id);
|
|
582
801
|
end(myVersion);
|
|
583
802
|
} catch {
|
|
803
|
+
for (const id of patchedIds) idToItem.delete(id);
|
|
584
804
|
end(myVersion, () => setItems(prev));
|
|
585
805
|
}
|
|
586
806
|
}
|
|
@@ -589,10 +809,7 @@ function optimisticList(initialValue) {
|
|
|
589
809
|
pending,
|
|
590
810
|
add,
|
|
591
811
|
remove,
|
|
592
|
-
update: updateItem
|
|
593
|
-
addOptimistic: add,
|
|
594
|
-
removeOptimistic: remove,
|
|
595
|
-
updateOptimistic: updateItem
|
|
812
|
+
update: updateItem
|
|
596
813
|
};
|
|
597
814
|
}
|
|
598
815
|
|
|
@@ -600,6 +817,7 @@ function optimisticList(initialValue) {
|
|
|
600
817
|
function derived(getter, options) {
|
|
601
818
|
devAssert(typeof getter === "function", "derived: argument must be a getter function.");
|
|
602
819
|
const debugName = options?.name;
|
|
820
|
+
const equals = options?.equals;
|
|
603
821
|
const cs = {};
|
|
604
822
|
cs._d = false;
|
|
605
823
|
cs._g = getter;
|
|
@@ -610,8 +828,14 @@ function derived(getter, options) {
|
|
|
610
828
|
markDirty._c = 1;
|
|
611
829
|
markDirty._sig = cs;
|
|
612
830
|
track(() => {
|
|
613
|
-
|
|
614
|
-
|
|
831
|
+
let threw = true;
|
|
832
|
+
try {
|
|
833
|
+
cs._v = getter();
|
|
834
|
+
cs._d = false;
|
|
835
|
+
threw = false;
|
|
836
|
+
} finally {
|
|
837
|
+
if (threw) cs._d = true;
|
|
838
|
+
}
|
|
615
839
|
}, markDirty);
|
|
616
840
|
const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
617
841
|
let evaluating = false;
|
|
@@ -624,11 +848,16 @@ function derived(getter, options) {
|
|
|
624
848
|
if (trackingSuspended) {
|
|
625
849
|
if (cs._d) {
|
|
626
850
|
evaluating = true;
|
|
851
|
+
let threw = true;
|
|
627
852
|
try {
|
|
628
|
-
|
|
629
|
-
|
|
853
|
+
retrack(() => {
|
|
854
|
+
cs._v = getter();
|
|
855
|
+
cs._d = false;
|
|
856
|
+
threw = false;
|
|
857
|
+
}, markDirty);
|
|
630
858
|
} finally {
|
|
631
859
|
evaluating = false;
|
|
860
|
+
if (threw) cs._d = true;
|
|
632
861
|
}
|
|
633
862
|
}
|
|
634
863
|
return cs._v;
|
|
@@ -637,13 +866,17 @@ function derived(getter, options) {
|
|
|
637
866
|
if (cs._d) {
|
|
638
867
|
const oldValue = cs._v;
|
|
639
868
|
evaluating = true;
|
|
869
|
+
let threw = true;
|
|
640
870
|
try {
|
|
641
|
-
|
|
871
|
+
retrack(() => {
|
|
872
|
+
const next = getter();
|
|
873
|
+
cs._v = equals && cs._v !== void 0 ? equals(cs._v, next) ? cs._v : next : next;
|
|
642
874
|
cs._d = false;
|
|
643
|
-
|
|
875
|
+
threw = false;
|
|
644
876
|
}, markDirty);
|
|
645
877
|
} finally {
|
|
646
878
|
evaluating = false;
|
|
879
|
+
if (threw) cs._d = true;
|
|
647
880
|
}
|
|
648
881
|
if (hook && oldValue !== cs._v) {
|
|
649
882
|
hook.emit("computed:update", { signal: cs, oldValue, newValue: cs._v });
|
|
@@ -675,14 +908,16 @@ function timeline(initial, maxHistory = 100) {
|
|
|
675
908
|
const idx = index();
|
|
676
909
|
const newHistory = hist.slice(0, idx + 1);
|
|
677
910
|
newHistory.push(newValue);
|
|
678
|
-
|
|
679
|
-
newHistory.
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
911
|
+
batch(() => {
|
|
912
|
+
if (newHistory.length > maxHistory) {
|
|
913
|
+
newHistory.shift();
|
|
914
|
+
setHistory(newHistory);
|
|
915
|
+
setIndex(newHistory.length - 1);
|
|
916
|
+
} else {
|
|
917
|
+
setHistory(newHistory);
|
|
918
|
+
setIndex(idx + 1);
|
|
919
|
+
}
|
|
920
|
+
});
|
|
686
921
|
}
|
|
687
922
|
function undo() {
|
|
688
923
|
if (canUndo()) {
|
|
@@ -695,8 +930,10 @@ function timeline(initial, maxHistory = 100) {
|
|
|
695
930
|
}
|
|
696
931
|
}
|
|
697
932
|
function reset() {
|
|
698
|
-
|
|
699
|
-
|
|
933
|
+
batch(() => {
|
|
934
|
+
setHistory([initial]);
|
|
935
|
+
setIndex(0);
|
|
936
|
+
});
|
|
700
937
|
}
|
|
701
938
|
function jumpTo(targetIndex) {
|
|
702
939
|
const hist = history();
|
|
@@ -708,8 +945,37 @@ function timeline(initial, maxHistory = 100) {
|
|
|
708
945
|
}
|
|
709
946
|
|
|
710
947
|
// src/patterns/globalStore.ts
|
|
948
|
+
function deepClone(value) {
|
|
949
|
+
if (typeof structuredClone === "function") {
|
|
950
|
+
return structuredClone(value);
|
|
951
|
+
}
|
|
952
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
953
|
+
const clone = (v) => {
|
|
954
|
+
if (v === null || typeof v !== "object") return v;
|
|
955
|
+
if (seen.has(v)) throw new Error("deepClone: circular reference");
|
|
956
|
+
seen.add(v);
|
|
957
|
+
if (v instanceof Date) return new Date(v.getTime());
|
|
958
|
+
if (v instanceof Map) {
|
|
959
|
+
const out2 = /* @__PURE__ */ new Map();
|
|
960
|
+
for (const [k, val] of v) out2.set(clone(k), clone(val));
|
|
961
|
+
return out2;
|
|
962
|
+
}
|
|
963
|
+
if (v instanceof Set) {
|
|
964
|
+
const out2 = /* @__PURE__ */ new Set();
|
|
965
|
+
for (const val of v) out2.add(clone(val));
|
|
966
|
+
return out2;
|
|
967
|
+
}
|
|
968
|
+
if (Array.isArray(v)) return v.map(clone);
|
|
969
|
+
const out = {};
|
|
970
|
+
for (const k of Object.keys(v)) {
|
|
971
|
+
out[k] = clone(v[k]);
|
|
972
|
+
}
|
|
973
|
+
return out;
|
|
974
|
+
};
|
|
975
|
+
return clone(value);
|
|
976
|
+
}
|
|
711
977
|
function globalStore(config) {
|
|
712
|
-
const initialState =
|
|
978
|
+
const initialState = deepClone(config.state);
|
|
713
979
|
const [getState, setState] = signal({ ...initialState });
|
|
714
980
|
const listeners = /* @__PURE__ */ new Set();
|
|
715
981
|
const middlewares = config.middleware || [];
|
package/dist/patterns.d.cts
CHANGED
|
@@ -71,19 +71,24 @@ interface PersistOptions<T = unknown> {
|
|
|
71
71
|
* - use XOR with a static key — trivially reversible
|
|
72
72
|
* - roll your own cipher — nearly always broken
|
|
73
73
|
*
|
|
74
|
+
* **Sync only:** because `persisted()` exposes synchronous getters and
|
|
75
|
+
* setters, both `encrypt` and `decrypt` must be SYNCHRONOUS. Async
|
|
76
|
+
* crypto (e.g. `crypto.subtle.encrypt`) is NOT supported here — derive
|
|
77
|
+
* keys ahead of time and use a sync wrapper, or pre/post-process the
|
|
78
|
+
* value yourself before/after `setValue`.
|
|
79
|
+
*
|
|
74
80
|
* @example
|
|
75
81
|
* ```ts
|
|
82
|
+
* // Pre-derived key + sync wrapper
|
|
76
83
|
* persisted("token", "", {
|
|
77
|
-
* encrypt:
|
|
78
|
-
* decrypt:
|
|
84
|
+
* encrypt: (v) => syncAesGcmEncrypt(v, derivedKey),
|
|
85
|
+
* decrypt: (v) => syncAesGcmDecrypt(v, derivedKey),
|
|
79
86
|
* });
|
|
80
87
|
* ```
|
|
81
|
-
*
|
|
82
|
-
* Note that because localStorage is synchronous, any real AES-GCM
|
|
83
|
-
* flow needs pre-derived keys and is inherently best-effort.
|
|
84
88
|
*/
|
|
85
89
|
encrypt?: (value: string) => string;
|
|
86
|
-
/** Decrypt the stored value before deserialization. Required if `encrypt` is set.
|
|
90
|
+
/** Decrypt the stored value before deserialization. Required if `encrypt` is set.
|
|
91
|
+
* Must be synchronous — see `encrypt` docs. */
|
|
87
92
|
decrypt?: (value: string) => string;
|
|
88
93
|
}
|
|
89
94
|
declare function persisted<T>(key: string, initial: T, options?: PersistOptions<T>): [() => T, (next: T | ((prev: T) => T)) => void];
|
|
@@ -141,12 +146,6 @@ declare function optimisticList<T>(initialValue: T[]): {
|
|
|
141
146
|
add: (item: T, asyncAction: () => Promise<T>) => Promise<void>;
|
|
142
147
|
remove: (predicate: (item: T) => boolean, asyncAction: () => Promise<void>) => Promise<void>;
|
|
143
148
|
update: (predicate: (item: T) => boolean, patch: Partial<T>, asyncAction: () => Promise<T>) => Promise<void>;
|
|
144
|
-
/** @deprecated Use `add` instead */
|
|
145
|
-
addOptimistic: (item: T, asyncAction: () => Promise<T>) => Promise<void>;
|
|
146
|
-
/** @deprecated Use `remove` instead */
|
|
147
|
-
removeOptimistic: (predicate: (item: T) => boolean, asyncAction: () => Promise<void>) => Promise<void>;
|
|
148
|
-
/** @deprecated Use `update` instead */
|
|
149
|
-
updateOptimistic: (predicate: (item: T) => boolean, patch: Partial<T>, asyncAction: () => Promise<T>) => Promise<void>;
|
|
150
149
|
};
|
|
151
150
|
|
|
152
151
|
interface TimeTravelReturn<T> {
|