sibujs 1.4.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/README.md +105 -119
- package/dist/browser.cjs +288 -80
- package/dist/browser.d.cts +19 -9
- package/dist/browser.d.ts +19 -9
- package/dist/browser.js +6 -6
- package/dist/build.cjs +1019 -313
- package/dist/build.d.cts +1 -1
- package/dist/build.d.ts +1 -1
- 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-ZWKZCBO6.js → chunk-3LR7GLWQ.js} +154 -33
- package/dist/{chunk-3AIRKM3B.js → chunk-3NSGB5JN.js} +115 -34
- package/dist/{chunk-3ARAQO7B.js → chunk-52YJLLRO.js} +29 -6
- package/dist/chunk-54EDRCEF.js +93 -0
- 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-WR5D4EGH.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-JAKHTMQU.js → chunk-JA6667UN.js} +206 -46
- package/dist/{chunk-77L6NL3X.js → chunk-JXMMDLBY.js} +306 -183
- package/dist/{chunk-3X2YG6YM.js → chunk-JYD2PWXH.js} +59 -28
- package/dist/{chunk-F3FA4F32.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-TSOKIX5Z.js → chunk-MIUAXB7K.js} +126 -74
- package/dist/{chunk-QWZG56ET.js → chunk-ND2664SF.js} +558 -190
- package/dist/{chunk-JCI5M6U6.js → chunk-O2MNQFLP.js} +261 -79
- package/dist/{chunk-EWFVA3TJ.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-ZD6OAMTH.js → chunk-VLPPXTYG.js} +90 -35
- package/dist/{chunk-OUZZEE4S.js → chunk-WOMYAHHI.js} +17 -11
- package/dist/{contracts-xo5ckdRP.d.cts → contracts-ey_Qh8ef.d.cts} +7 -8
- package/dist/{contracts-xo5ckdRP.d.ts → contracts-ey_Qh8ef.d.ts} +7 -8
- package/dist/{customElement-D2DJp_xn.d.cts → customElement-CPfIrbvg.d.cts} +18 -9
- package/dist/{customElement-D2DJp_xn.d.ts → customElement-CPfIrbvg.d.ts} +18 -9
- package/dist/data.cjs +452 -100
- package/dist/data.d.cts +20 -2
- package/dist/data.d.ts +20 -2
- package/dist/data.js +11 -9
- package/dist/devtools.cjs +535 -247
- package/dist/devtools.d.cts +1 -1
- package/dist/devtools.d.ts +1 -1
- package/dist/devtools.js +34 -30
- package/dist/ecosystem.cjs +499 -143
- package/dist/ecosystem.d.cts +13 -11
- package/dist/ecosystem.d.ts +13 -11
- package/dist/ecosystem.js +12 -11
- package/dist/extras.cjs +3639 -1629
- package/dist/extras.d.cts +11 -11
- package/dist/extras.d.ts +11 -11
- package/dist/extras.js +58 -45
- package/dist/index.cjs +1023 -313
- package/dist/index.d.cts +128 -55
- package/dist/index.d.ts +128 -55
- 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 +90 -36
- package/dist/motion.d.cts +1 -1
- package/dist/motion.d.ts +1 -1
- package/dist/motion.js +4 -4
- package/dist/patterns.cjs +414 -81
- package/dist/patterns.d.cts +53 -20
- package/dist/patterns.d.ts +53 -20
- package/dist/patterns.js +7 -7
- package/dist/performance.cjs +364 -108
- package/dist/performance.d.cts +29 -17
- package/dist/performance.d.ts +29 -17
- package/dist/performance.js +13 -6
- package/dist/plugin-D30wlGW5.d.cts +71 -0
- package/dist/plugin-D30wlGW5.d.ts +71 -0
- package/dist/plugins.cjs +652 -271
- package/dist/plugins.d.cts +13 -6
- package/dist/plugins.d.ts +13 -6
- package/dist/plugins.js +116 -50
- 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 +648 -219
- package/dist/ssr.d.cts +27 -7
- package/dist/ssr.d.ts +27 -7
- package/dist/ssr.js +12 -11
- package/dist/{tagFactory-DaJ0YWX6.d.ts → tagFactory-S17H2qxu.d.cts} +9 -1
- package/dist/{tagFactory-DaJ0YWX6.d.cts → 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 +576 -168
- package/dist/ui.d.cts +13 -16
- package/dist/ui.d.ts +13 -16
- package/dist/ui.js +20 -17
- package/dist/widgets.cjs +1001 -93
- 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-3CRQALYP.js +0 -877
- package/dist/chunk-4EI4AG32.js +0 -482
- package/dist/chunk-4MYMUBRS.js +0 -21
- package/dist/chunk-6HLLIF3K.js +0 -398
- package/dist/chunk-6LSNVCS2.js +0 -937
- package/dist/chunk-6SA3QQES.js +0 -61
- 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-BGN5ZMP4.js +0 -26
- 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-FGOEVHY3.js +0 -60
- package/dist/chunk-G3BOQPVO.js +0 -365
- package/dist/chunk-GCOK2LC3.js +0 -282
- package/dist/chunk-HGMJFBC7.js +0 -654
- 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-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-N6IZB6KJ.js +0 -567
- package/dist/chunk-NEKUBFPT.js +0 -60
- package/dist/chunk-NHUC2QWH.js +0 -282
- package/dist/chunk-NMRUZALC.js +0 -1097
- package/dist/chunk-NYVAC6P5.js +0 -37
- package/dist/chunk-OF7UZIVB.js +0 -725
- package/dist/chunk-P6W3STU4.js +0 -2249
- package/dist/chunk-PBHF5WKN.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-RQGQSLQK.js +0 -725
- package/dist/chunk-SDLZDHKP.js +0 -107
- package/dist/chunk-TNQWPPE6.js +0 -37
- 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-VRW3FULF.js +0 -725
- package/dist/chunk-WADYRCO2.js +0 -304
- package/dist/chunk-WILQZRO4.js +0 -282
- 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/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/customElement-BKQfbSZQ.d.cts +0 -262
- package/dist/customElement-BKQfbSZQ.d.ts +0 -262
- 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/index.cjs
CHANGED
|
@@ -99,6 +99,7 @@ __export(index_exports, {
|
|
|
99
99
|
footer: () => footer,
|
|
100
100
|
form: () => form,
|
|
101
101
|
g: () => g,
|
|
102
|
+
getSSRStore: () => getSSRStore,
|
|
102
103
|
getSlot: () => getSlot,
|
|
103
104
|
h1: () => h1,
|
|
104
105
|
h2: () => h2,
|
|
@@ -171,6 +172,7 @@ __export(index_exports, {
|
|
|
171
172
|
rp: () => rp,
|
|
172
173
|
rt: () => rt,
|
|
173
174
|
ruby: () => ruby,
|
|
175
|
+
runInSSRContext: () => runInSSRContext,
|
|
174
176
|
s: () => s,
|
|
175
177
|
samp: () => samp,
|
|
176
178
|
script: () => script,
|
|
@@ -196,6 +198,7 @@ __export(index_exports, {
|
|
|
196
198
|
symbol: () => symbol,
|
|
197
199
|
table: () => table,
|
|
198
200
|
tagFactory: () => tagFactory,
|
|
201
|
+
takePendingError: () => takePendingError,
|
|
199
202
|
tbody: () => tbody,
|
|
200
203
|
td: () => td,
|
|
201
204
|
template: () => template,
|
|
@@ -210,6 +213,7 @@ __export(index_exports, {
|
|
|
210
213
|
track: () => track2,
|
|
211
214
|
transition: () => transition,
|
|
212
215
|
trapFocus: () => trapFocus,
|
|
216
|
+
trustHTML: () => trustHTML,
|
|
213
217
|
tspan: () => tspan,
|
|
214
218
|
u: () => u,
|
|
215
219
|
ul: () => ul,
|
|
@@ -232,33 +236,80 @@ function isDev() {
|
|
|
232
236
|
var _isDev = isDev();
|
|
233
237
|
function devAssert(condition, message) {
|
|
234
238
|
if (_isDev && !condition) {
|
|
235
|
-
throw new Error(`[
|
|
239
|
+
throw new Error(`[SibuJS] ${message}`);
|
|
236
240
|
}
|
|
237
241
|
}
|
|
238
242
|
function devWarn(message) {
|
|
239
243
|
if (_isDev) {
|
|
240
|
-
console.warn(`[
|
|
244
|
+
console.warn(`[SibuJS] ${message}`);
|
|
241
245
|
}
|
|
242
246
|
}
|
|
243
247
|
|
|
244
248
|
// src/utils/sanitize.ts
|
|
249
|
+
var SAFE_URL_PROTOCOLS = ["http:", "https:", "mailto:", "tel:", "ftp:"];
|
|
245
250
|
function sanitizeUrl(url) {
|
|
246
251
|
const trimmed = url.replace(/[\x00-\x20\x7f-\x9f]+/g, "").trim();
|
|
247
252
|
if (!trimmed) return "";
|
|
248
253
|
const lower = trimmed.toLowerCase();
|
|
249
|
-
|
|
250
|
-
|
|
254
|
+
let schemeEnd = -1;
|
|
255
|
+
for (let i2 = 0; i2 < lower.length; i2++) {
|
|
256
|
+
const ch = lower.charCodeAt(i2);
|
|
257
|
+
if (ch === 58) {
|
|
258
|
+
schemeEnd = i2;
|
|
259
|
+
break;
|
|
260
|
+
}
|
|
261
|
+
if (ch === 47 || ch === 63 || ch === 35) break;
|
|
251
262
|
}
|
|
263
|
+
if (schemeEnd === -1) return trimmed;
|
|
264
|
+
const scheme = lower.slice(0, schemeEnd + 1);
|
|
265
|
+
if (!/^[a-z][a-z0-9+.-]*:$/.test(scheme)) return trimmed;
|
|
266
|
+
if (SAFE_URL_PROTOCOLS.indexOf(scheme) === -1) return "";
|
|
252
267
|
return trimmed;
|
|
253
268
|
}
|
|
269
|
+
function sanitizeSrcset(value) {
|
|
270
|
+
const parts = value.split(",");
|
|
271
|
+
const out = [];
|
|
272
|
+
for (let i2 = 0; i2 < parts.length; i2++) {
|
|
273
|
+
const part = parts[i2].trim();
|
|
274
|
+
if (!part) continue;
|
|
275
|
+
const m = part.match(/^(\S+)(\s+.+)?$/);
|
|
276
|
+
if (!m) continue;
|
|
277
|
+
const safe = sanitizeUrl(m[1]);
|
|
278
|
+
if (!safe) continue;
|
|
279
|
+
out.push(m[2] ? `${safe}${m[2]}` : safe);
|
|
280
|
+
}
|
|
281
|
+
return out.join(", ");
|
|
282
|
+
}
|
|
254
283
|
function sanitizeCSSValue(value) {
|
|
255
|
-
const
|
|
256
|
-
|
|
284
|
+
const decoded = value.replace(/\\([0-9a-fA-F]{1,6})\s?/g, (_m, hex) => {
|
|
285
|
+
const code2 = Number.parseInt(hex, 16);
|
|
286
|
+
if (!Number.isFinite(code2) || code2 < 0 || code2 > 1114111) return "";
|
|
287
|
+
try {
|
|
288
|
+
return String.fromCodePoint(code2);
|
|
289
|
+
} catch {
|
|
290
|
+
return "";
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
const lower = decoded.toLowerCase().replace(/\s+/g, "");
|
|
294
|
+
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")) {
|
|
257
295
|
return "";
|
|
258
296
|
}
|
|
259
297
|
return value;
|
|
260
298
|
}
|
|
261
|
-
var URL_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
299
|
+
var URL_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
300
|
+
"href",
|
|
301
|
+
"xlink:href",
|
|
302
|
+
"src",
|
|
303
|
+
"action",
|
|
304
|
+
"formaction",
|
|
305
|
+
"formtarget",
|
|
306
|
+
"cite",
|
|
307
|
+
"poster",
|
|
308
|
+
"background",
|
|
309
|
+
"srcset",
|
|
310
|
+
"ping",
|
|
311
|
+
"data"
|
|
312
|
+
]);
|
|
262
313
|
function isUrlAttribute(attr) {
|
|
263
314
|
return URL_ATTRIBUTES.has(attr);
|
|
264
315
|
}
|
|
@@ -269,11 +320,11 @@ var subscriberStack = new Array(32);
|
|
|
269
320
|
var stackCapacity = 32;
|
|
270
321
|
var stackTop = -1;
|
|
271
322
|
var currentSubscriber = null;
|
|
272
|
-
var signalSubscribers = /* @__PURE__ */ new WeakMap();
|
|
273
323
|
var SUBS = "__s";
|
|
274
324
|
var notifyDepth = 0;
|
|
275
325
|
var pendingQueue = [];
|
|
276
326
|
var pendingSet = /* @__PURE__ */ new Set();
|
|
327
|
+
var propagateStack = [];
|
|
277
328
|
function safeInvoke(sub2) {
|
|
278
329
|
try {
|
|
279
330
|
sub2();
|
|
@@ -283,6 +334,15 @@ function safeInvoke(sub2) {
|
|
|
283
334
|
}
|
|
284
335
|
var suspendDepth = 0;
|
|
285
336
|
var trackingSuspended = false;
|
|
337
|
+
function retrack(effectFn, subscriber) {
|
|
338
|
+
const prev = currentSubscriber;
|
|
339
|
+
currentSubscriber = subscriber;
|
|
340
|
+
try {
|
|
341
|
+
effectFn();
|
|
342
|
+
} finally {
|
|
343
|
+
currentSubscriber = prev;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
286
346
|
function track(effectFn, subscriber) {
|
|
287
347
|
if (!subscriber) subscriber = effectFn;
|
|
288
348
|
cleanup(subscriber);
|
|
@@ -350,7 +410,6 @@ function recordDependency(signal2) {
|
|
|
350
410
|
let subs = signal2[SUBS];
|
|
351
411
|
if (!subs) {
|
|
352
412
|
subs = /* @__PURE__ */ new Set();
|
|
353
|
-
signalSubscribers.set(signal2, subs);
|
|
354
413
|
signal2[SUBS] = subs;
|
|
355
414
|
}
|
|
356
415
|
subs.add(currentSubscriber);
|
|
@@ -372,57 +431,71 @@ function queueSignalNotification(signal2) {
|
|
|
372
431
|
}
|
|
373
432
|
}
|
|
374
433
|
}
|
|
434
|
+
var maxDrainIterations = 1e5;
|
|
375
435
|
function drainNotificationQueue() {
|
|
376
436
|
if (notifyDepth > 0) return;
|
|
377
437
|
notifyDepth++;
|
|
378
438
|
try {
|
|
379
439
|
let i2 = 0;
|
|
380
440
|
while (i2 < pendingQueue.length) {
|
|
441
|
+
if (i2 >= maxDrainIterations) {
|
|
442
|
+
if (typeof console !== "undefined") {
|
|
443
|
+
console.error(
|
|
444
|
+
`[SibuJS] Notification queue exceeded ${maxDrainIterations} iterations \u2014 likely an effect that writes to a signal it reads. Breaking to prevent infinite loop.`
|
|
445
|
+
);
|
|
446
|
+
}
|
|
447
|
+
break;
|
|
448
|
+
}
|
|
381
449
|
safeInvoke(pendingQueue[i2]);
|
|
382
450
|
i2++;
|
|
383
451
|
}
|
|
384
452
|
} finally {
|
|
385
|
-
pendingQueue.length = 0;
|
|
386
|
-
pendingSet.clear();
|
|
387
453
|
notifyDepth--;
|
|
454
|
+
if (notifyDepth === 0) {
|
|
455
|
+
pendingQueue.length = 0;
|
|
456
|
+
pendingSet.clear();
|
|
457
|
+
}
|
|
388
458
|
}
|
|
389
459
|
}
|
|
390
460
|
function propagateDirty(sub2) {
|
|
391
461
|
sub2();
|
|
392
|
-
|
|
393
|
-
|
|
462
|
+
const rootSig = sub2._sig;
|
|
463
|
+
if (!rootSig) return;
|
|
464
|
+
const stack = propagateStack;
|
|
465
|
+
const baseLen = stack.length;
|
|
466
|
+
stack.push(rootSig);
|
|
467
|
+
while (stack.length > baseLen) {
|
|
468
|
+
const sig = stack.pop();
|
|
394
469
|
const first = sig.__f;
|
|
395
470
|
if (first) {
|
|
396
471
|
if (first._c) {
|
|
397
472
|
const nSig = first._sig;
|
|
398
|
-
nSig._d
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
if (!pendingSet.has(first)) {
|
|
473
|
+
if (!nSig._d) {
|
|
474
|
+
nSig._d = true;
|
|
475
|
+
stack.push(nSig);
|
|
476
|
+
}
|
|
477
|
+
} else if (!pendingSet.has(first)) {
|
|
403
478
|
pendingSet.add(first);
|
|
404
479
|
pendingQueue.push(first);
|
|
405
480
|
}
|
|
406
|
-
|
|
481
|
+
continue;
|
|
407
482
|
}
|
|
408
483
|
const subs = sig[SUBS];
|
|
409
|
-
if (!subs)
|
|
410
|
-
let nextSig;
|
|
484
|
+
if (!subs) continue;
|
|
411
485
|
for (const s2 of subs) {
|
|
412
486
|
if (s2._c) {
|
|
413
|
-
s2();
|
|
414
487
|
const nSig = s2._sig;
|
|
415
|
-
if (nSig && !
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
488
|
+
if (nSig && !nSig._d) {
|
|
489
|
+
nSig._d = true;
|
|
490
|
+
stack.push(nSig);
|
|
491
|
+
} else if (!nSig) {
|
|
492
|
+
s2();
|
|
419
493
|
}
|
|
420
494
|
} else if (!pendingSet.has(s2)) {
|
|
421
495
|
pendingSet.add(s2);
|
|
422
496
|
pendingQueue.push(s2);
|
|
423
497
|
}
|
|
424
498
|
}
|
|
425
|
-
sig = nextSig;
|
|
426
499
|
}
|
|
427
500
|
}
|
|
428
501
|
function notifySubscribers(signal2) {
|
|
@@ -446,13 +519,23 @@ function notifySubscribers(signal2) {
|
|
|
446
519
|
}
|
|
447
520
|
let i2 = 0;
|
|
448
521
|
while (i2 < pendingQueue.length) {
|
|
522
|
+
if (i2 >= maxDrainIterations) {
|
|
523
|
+
if (typeof console !== "undefined") {
|
|
524
|
+
console.error(
|
|
525
|
+
`[SibuJS] Notification queue exceeded ${maxDrainIterations} iterations \u2014 likely an effect that writes to a signal it reads. Breaking to prevent infinite loop.`
|
|
526
|
+
);
|
|
527
|
+
}
|
|
528
|
+
break;
|
|
529
|
+
}
|
|
449
530
|
safeInvoke(pendingQueue[i2]);
|
|
450
531
|
i2++;
|
|
451
532
|
}
|
|
452
533
|
} finally {
|
|
453
|
-
pendingQueue.length = 0;
|
|
454
|
-
pendingSet.clear();
|
|
455
534
|
notifyDepth--;
|
|
535
|
+
if (notifyDepth === 0) {
|
|
536
|
+
pendingQueue.length = 0;
|
|
537
|
+
pendingSet.clear();
|
|
538
|
+
}
|
|
456
539
|
}
|
|
457
540
|
return;
|
|
458
541
|
}
|
|
@@ -472,30 +555,48 @@ function notifySubscribers(signal2) {
|
|
|
472
555
|
notifyDepth++;
|
|
473
556
|
try {
|
|
474
557
|
let directCount = 0;
|
|
558
|
+
let hasComputedSub = false;
|
|
475
559
|
for (const sub2 of subs) {
|
|
560
|
+
if (sub2._c) hasComputedSub = true;
|
|
476
561
|
pendingQueue[directCount++] = sub2;
|
|
477
562
|
}
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
563
|
+
if (!hasComputedSub) {
|
|
564
|
+
for (let i3 = 0; i3 < directCount; i3++) {
|
|
565
|
+
safeInvoke(pendingQueue[i3]);
|
|
481
566
|
}
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
567
|
+
} else {
|
|
568
|
+
for (let i3 = 0; i3 < directCount; i3++) {
|
|
569
|
+
if (pendingQueue[i3]._c) {
|
|
570
|
+
propagateDirty(pendingQueue[i3]);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
for (let i3 = 0; i3 < directCount; i3++) {
|
|
574
|
+
const sub2 = pendingQueue[i3];
|
|
575
|
+
if (!sub2._c && !pendingSet.has(sub2)) {
|
|
576
|
+
pendingSet.add(sub2);
|
|
577
|
+
safeInvoke(sub2);
|
|
487
578
|
}
|
|
488
579
|
}
|
|
489
580
|
}
|
|
490
581
|
let i2 = directCount;
|
|
491
582
|
while (i2 < pendingQueue.length) {
|
|
583
|
+
if (i2 - directCount >= maxDrainIterations) {
|
|
584
|
+
if (typeof console !== "undefined") {
|
|
585
|
+
console.error(
|
|
586
|
+
`[SibuJS] Notification queue exceeded ${maxDrainIterations} iterations \u2014 likely an effect that writes to a signal it reads. Breaking to prevent infinite loop.`
|
|
587
|
+
);
|
|
588
|
+
}
|
|
589
|
+
break;
|
|
590
|
+
}
|
|
492
591
|
safeInvoke(pendingQueue[i2]);
|
|
493
592
|
i2++;
|
|
494
593
|
}
|
|
495
594
|
} finally {
|
|
496
|
-
pendingQueue.length = 0;
|
|
497
|
-
pendingSet.clear();
|
|
498
595
|
notifyDepth--;
|
|
596
|
+
if (notifyDepth === 0) {
|
|
597
|
+
pendingQueue.length = 0;
|
|
598
|
+
pendingSet.clear();
|
|
599
|
+
}
|
|
499
600
|
}
|
|
500
601
|
}
|
|
501
602
|
function cleanup(subscriber) {
|
|
@@ -506,7 +607,9 @@ function cleanup(subscriber) {
|
|
|
506
607
|
if (subs) {
|
|
507
608
|
subs.delete(subscriber);
|
|
508
609
|
if (singleDep.__f === subscriber) {
|
|
509
|
-
singleDep.__f = void 0;
|
|
610
|
+
singleDep.__f = subs.size === 1 ? subs.values().next().value : void 0;
|
|
611
|
+
} else if (subs.size === 1 && singleDep.__f === void 0) {
|
|
612
|
+
singleDep.__f = subs.values().next().value;
|
|
510
613
|
}
|
|
511
614
|
}
|
|
512
615
|
sub2._dep = void 0;
|
|
@@ -519,7 +622,9 @@ function cleanup(subscriber) {
|
|
|
519
622
|
if (subs) {
|
|
520
623
|
subs.delete(subscriber);
|
|
521
624
|
if (signal2.__f === subscriber) {
|
|
522
|
-
signal2.__f = void 0;
|
|
625
|
+
signal2.__f = subs.size === 1 ? subs.values().next().value : void 0;
|
|
626
|
+
} else if (subs.size === 1 && signal2.__f === void 0) {
|
|
627
|
+
signal2.__f = subs.values().next().value;
|
|
523
628
|
}
|
|
524
629
|
}
|
|
525
630
|
}
|
|
@@ -528,6 +633,9 @@ function cleanup(subscriber) {
|
|
|
528
633
|
|
|
529
634
|
// src/reactivity/bindAttribute.ts
|
|
530
635
|
var _isDev3 = isDev();
|
|
636
|
+
function setProp(el, key, val) {
|
|
637
|
+
el[key] = val;
|
|
638
|
+
}
|
|
531
639
|
function isEventHandlerAttr(name) {
|
|
532
640
|
if (name.length < 3) return false;
|
|
533
641
|
const lower = name.toLowerCase();
|
|
@@ -553,7 +661,7 @@ function bindAttribute(el, attr, getter) {
|
|
|
553
661
|
}
|
|
554
662
|
if (typeof value === "boolean") {
|
|
555
663
|
if (attr in el && (attr === "checked" || attr === "disabled" || attr === "selected")) {
|
|
556
|
-
el
|
|
664
|
+
setProp(el, attr, value);
|
|
557
665
|
} else if (value) {
|
|
558
666
|
el.setAttribute(attr, "");
|
|
559
667
|
} else {
|
|
@@ -563,7 +671,7 @@ function bindAttribute(el, attr, getter) {
|
|
|
563
671
|
}
|
|
564
672
|
const str = String(value);
|
|
565
673
|
if ((attr === "value" || attr === "checked") && attr in el) {
|
|
566
|
-
el
|
|
674
|
+
setProp(el, attr, attr === "checked" ? Boolean(value) : str);
|
|
567
675
|
} else {
|
|
568
676
|
el.setAttribute(attr, isUrlAttribute(attr) ? sanitizeUrl(str) : str);
|
|
569
677
|
}
|
|
@@ -594,7 +702,7 @@ function bindDynamic(el, nameGetter, valueGetter) {
|
|
|
594
702
|
}
|
|
595
703
|
const str = String(value);
|
|
596
704
|
if ((name === "value" || name === "checked") && name in el) {
|
|
597
|
-
el
|
|
705
|
+
setProp(el, name, name === "checked" ? Boolean(value) : str);
|
|
598
706
|
} else {
|
|
599
707
|
el.setAttribute(name, isUrlAttribute(name) ? sanitizeUrl(str) : str);
|
|
600
708
|
}
|
|
@@ -637,24 +745,29 @@ function bindChildNode(placeholder, getter) {
|
|
|
637
745
|
let newNodes;
|
|
638
746
|
if (Array.isArray(result)) {
|
|
639
747
|
newNodes = [];
|
|
748
|
+
const seen = /* @__PURE__ */ new Set();
|
|
640
749
|
for (let i2 = 0; i2 < result.length; i2++) {
|
|
641
750
|
const item = result[i2];
|
|
642
751
|
if (item == null || typeof item === "boolean") continue;
|
|
643
|
-
|
|
752
|
+
const node = item instanceof Node ? item : document.createTextNode(String(item));
|
|
753
|
+
if (seen.has(node)) {
|
|
754
|
+
if (_isDev4)
|
|
755
|
+
devWarn("bindChildNode: duplicate node reference in array \u2014 only the first occurrence is rendered.");
|
|
756
|
+
continue;
|
|
757
|
+
}
|
|
758
|
+
seen.add(node);
|
|
759
|
+
newNodes.push(node);
|
|
644
760
|
}
|
|
645
761
|
} else {
|
|
646
762
|
const node = result instanceof Node ? result : document.createTextNode(String(result));
|
|
647
763
|
newNodes = [node];
|
|
648
764
|
}
|
|
649
|
-
|
|
650
|
-
if (
|
|
765
|
+
let reused;
|
|
766
|
+
if (lastNodes.length > 0 && newNodes.length > 0) {
|
|
767
|
+
const lastSet = new Set(lastNodes);
|
|
768
|
+
reused = /* @__PURE__ */ new Set();
|
|
651
769
|
for (let i2 = 0; i2 < newNodes.length; i2++) {
|
|
652
|
-
|
|
653
|
-
if (newNodes[i2] === lastNodes[j]) {
|
|
654
|
-
reused.add(newNodes[i2]);
|
|
655
|
-
break;
|
|
656
|
-
}
|
|
657
|
-
}
|
|
770
|
+
if (lastSet.has(newNodes[i2])) reused.add(newNodes[i2]);
|
|
658
771
|
}
|
|
659
772
|
}
|
|
660
773
|
for (let i2 = 0; i2 < lastNodes.length; i2++) {
|
|
@@ -697,7 +810,7 @@ function dispose(node) {
|
|
|
697
810
|
while (stack.length > 0) {
|
|
698
811
|
const current = stack.pop();
|
|
699
812
|
order.push(current);
|
|
700
|
-
const children = current.childNodes;
|
|
813
|
+
const children = Array.from(current.childNodes);
|
|
701
814
|
for (let i2 = 0; i2 < children.length; i2++) {
|
|
702
815
|
stack.push(children[i2]);
|
|
703
816
|
}
|
|
@@ -706,9 +819,35 @@ function dispose(node) {
|
|
|
706
819
|
const current = order[i2];
|
|
707
820
|
const disposers = elementDisposers.get(current);
|
|
708
821
|
if (disposers) {
|
|
709
|
-
|
|
710
|
-
for (const d of disposers) d();
|
|
822
|
+
const snapshot = disposers.slice();
|
|
711
823
|
elementDisposers.delete(current);
|
|
824
|
+
if (_isDev5) activeBindingCount -= snapshot.length;
|
|
825
|
+
for (const d of snapshot) {
|
|
826
|
+
try {
|
|
827
|
+
d();
|
|
828
|
+
} catch (err) {
|
|
829
|
+
if (_isDev5 && typeof console !== "undefined") {
|
|
830
|
+
console.warn("[SibuJS] Disposer threw during cleanup:", err);
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
let extraPasses = 0;
|
|
835
|
+
while (extraPasses++ < 8) {
|
|
836
|
+
const added = elementDisposers.get(current);
|
|
837
|
+
if (!added || added.length === 0) break;
|
|
838
|
+
const moreSnapshot = added.slice();
|
|
839
|
+
elementDisposers.delete(current);
|
|
840
|
+
if (_isDev5) activeBindingCount -= moreSnapshot.length;
|
|
841
|
+
for (const d of moreSnapshot) {
|
|
842
|
+
try {
|
|
843
|
+
d();
|
|
844
|
+
} catch (err) {
|
|
845
|
+
if (_isDev5 && typeof console !== "undefined") {
|
|
846
|
+
console.warn("[SibuJS] Disposer threw during cleanup:", err);
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
}
|
|
712
851
|
}
|
|
713
852
|
}
|
|
714
853
|
}
|
|
@@ -724,6 +863,30 @@ function checkLeaks(warnThreshold = 0) {
|
|
|
724
863
|
|
|
725
864
|
// src/core/rendering/tagFactory.ts
|
|
726
865
|
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
866
|
+
var _isDev6 = isDev();
|
|
867
|
+
var BLOCKED_TAGS = /* @__PURE__ */ new Set(["script", "iframe", "object", "embed", "frame", "frameset"]);
|
|
868
|
+
function validateTagName(tag) {
|
|
869
|
+
const lower = tag.toLowerCase();
|
|
870
|
+
if (BLOCKED_TAGS.has(lower)) {
|
|
871
|
+
throw new Error(`tagFactory: refusing to create <${tag}> \u2014 tag is blocked for security reasons.`);
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
var CLOBBER_RISKY_IDS = /* @__PURE__ */ new Set([
|
|
875
|
+
"config",
|
|
876
|
+
"location",
|
|
877
|
+
"history",
|
|
878
|
+
"document",
|
|
879
|
+
"window",
|
|
880
|
+
"navigator",
|
|
881
|
+
"name",
|
|
882
|
+
"top",
|
|
883
|
+
"parent",
|
|
884
|
+
"self",
|
|
885
|
+
"frames"
|
|
886
|
+
]);
|
|
887
|
+
function setProp2(el, key, val) {
|
|
888
|
+
el[key] = val;
|
|
889
|
+
}
|
|
727
890
|
var kebabCache = /* @__PURE__ */ new Map();
|
|
728
891
|
function toKebab(prop) {
|
|
729
892
|
let cached = kebabCache.get(prop);
|
|
@@ -848,79 +1011,103 @@ function appendChildren(el, nodes) {
|
|
|
848
1011
|
}
|
|
849
1012
|
}
|
|
850
1013
|
}
|
|
851
|
-
var tagFactory = (tag, ns) =>
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
if (
|
|
856
|
-
|
|
857
|
-
|
|
1014
|
+
var tagFactory = (tag, ns) => {
|
|
1015
|
+
return (first, second) => {
|
|
1016
|
+
validateTagName(tag);
|
|
1017
|
+
const el = ns ? document.createElementNS(ns, tag) : document.createElement(tag);
|
|
1018
|
+
if (first === void 0) return el;
|
|
1019
|
+
if (typeof first === "string") {
|
|
1020
|
+
if (second !== void 0) {
|
|
1021
|
+
el.setAttribute("class", first);
|
|
1022
|
+
appendChildren(el, second);
|
|
1023
|
+
return el;
|
|
1024
|
+
}
|
|
1025
|
+
el.textContent = first;
|
|
858
1026
|
return el;
|
|
859
1027
|
}
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
1028
|
+
if (typeof first === "number") {
|
|
1029
|
+
el.textContent = String(first);
|
|
1030
|
+
return el;
|
|
1031
|
+
}
|
|
1032
|
+
if (Array.isArray(first) || first instanceof Node || typeof first === "function") {
|
|
1033
|
+
appendChildren(el, first);
|
|
1034
|
+
return el;
|
|
1035
|
+
}
|
|
1036
|
+
const props = first;
|
|
1037
|
+
const pClass = props.class;
|
|
1038
|
+
if (pClass != null) applyClass(el, pClass);
|
|
1039
|
+
const pId = props.id;
|
|
1040
|
+
if (pId != null) {
|
|
1041
|
+
if (_isDev6 && typeof pId === "string" && CLOBBER_RISKY_IDS.has(pId.toLowerCase())) {
|
|
1042
|
+
devWarn(
|
|
1043
|
+
`tagFactory: element id="${pId}" matches a common global and may cause DOM clobbering. Avoid setting ids from untrusted input.`
|
|
1044
|
+
);
|
|
1045
|
+
}
|
|
1046
|
+
el.id = pId;
|
|
1047
|
+
}
|
|
1048
|
+
const pNodes = second !== void 0 ? second : props.nodes;
|
|
1049
|
+
if (pNodes != null) appendChildren(el, pNodes);
|
|
1050
|
+
const pOn = props.on;
|
|
1051
|
+
if (pOn) {
|
|
1052
|
+
for (const ev in pOn) {
|
|
1053
|
+
const handler = pOn[ev];
|
|
1054
|
+
if (typeof handler === "function") {
|
|
1055
|
+
el.addEventListener(ev, handler);
|
|
1056
|
+
} else if (_isDev6) {
|
|
1057
|
+
devWarn(
|
|
1058
|
+
`tagFactory: on.${ev} handler is not a function (got ${typeof handler}). Event listener was not attached.`
|
|
1059
|
+
);
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
const pStyle = props.style;
|
|
1064
|
+
if (pStyle != null) applyStyle(el, pStyle);
|
|
1065
|
+
const pRef = props.ref;
|
|
1066
|
+
if (pRef) pRef.current = el;
|
|
1067
|
+
for (const key in props) {
|
|
1068
|
+
switch (key) {
|
|
1069
|
+
case "class":
|
|
1070
|
+
case "id":
|
|
1071
|
+
case "nodes":
|
|
1072
|
+
case "on":
|
|
1073
|
+
case "style":
|
|
1074
|
+
case "ref":
|
|
1075
|
+
case "onElement":
|
|
1076
|
+
continue;
|
|
1077
|
+
// already handled above / below
|
|
1078
|
+
default: {
|
|
1079
|
+
const value = props[key];
|
|
1080
|
+
if (value == null) continue;
|
|
1081
|
+
const lkey = key.toLowerCase();
|
|
1082
|
+
if (lkey[0] === "o" && lkey[1] === "n") continue;
|
|
1083
|
+
if (typeof value === "function") {
|
|
1084
|
+
registerDisposer(el, bindAttribute(el, key, value));
|
|
1085
|
+
} else if (typeof value === "boolean") {
|
|
1086
|
+
if (key in el && (key === "checked" || key === "disabled" || key === "selected")) {
|
|
1087
|
+
setProp2(el, key, value);
|
|
1088
|
+
} else if (value) {
|
|
1089
|
+
el.setAttribute(key, "");
|
|
1090
|
+
} else {
|
|
1091
|
+
el.removeAttribute(key);
|
|
1092
|
+
}
|
|
910
1093
|
} else {
|
|
911
|
-
|
|
1094
|
+
const str = String(value);
|
|
1095
|
+
if (lkey === "srcset") {
|
|
1096
|
+
el.setAttribute(key, sanitizeSrcset(str));
|
|
1097
|
+
} else if (isUrlAttribute(lkey)) {
|
|
1098
|
+
el.setAttribute(key, sanitizeUrl(str));
|
|
1099
|
+
} else {
|
|
1100
|
+
el.setAttribute(key, str);
|
|
1101
|
+
}
|
|
912
1102
|
}
|
|
913
|
-
} else {
|
|
914
|
-
const str = String(value);
|
|
915
|
-
el.setAttribute(key, isUrlAttribute(key) ? sanitizeUrl(str) : str);
|
|
916
1103
|
}
|
|
917
1104
|
}
|
|
918
1105
|
}
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
1106
|
+
if (props.onElement && typeof props.onElement === "function") {
|
|
1107
|
+
props.onElement(el);
|
|
1108
|
+
}
|
|
1109
|
+
return el;
|
|
1110
|
+
};
|
|
924
1111
|
};
|
|
925
1112
|
|
|
926
1113
|
// src/core/rendering/html.ts
|
|
@@ -1063,6 +1250,8 @@ var marquee = tagFactory("marquee");
|
|
|
1063
1250
|
var customElement = (tagName) => tagFactory(tagName);
|
|
1064
1251
|
|
|
1065
1252
|
// src/core/rendering/htm.ts
|
|
1253
|
+
var _isDev7 = isDev();
|
|
1254
|
+
var RAW_TEXT_TAGS = /* @__PURE__ */ new Set(["script", "style"]);
|
|
1066
1255
|
var VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
1067
1256
|
"area",
|
|
1068
1257
|
"base",
|
|
@@ -1247,6 +1436,15 @@ function parseTemplate(strings) {
|
|
|
1247
1436
|
children.push({ t: 0, el: { tag, svg: SVG_TAGS.has(tag), attrs, children: [] } });
|
|
1248
1437
|
} else {
|
|
1249
1438
|
const inner = parseChildren();
|
|
1439
|
+
if (RAW_TEXT_TAGS.has(tag.toLowerCase())) {
|
|
1440
|
+
for (let i2 = 0; i2 < inner.length; i2++) {
|
|
1441
|
+
if (inner[i2].t === 2) {
|
|
1442
|
+
throw new Error(
|
|
1443
|
+
`html: dynamic \${...} expressions are not allowed inside <${tag}> (raw-text context). Build the content separately and append it as a Node.`
|
|
1444
|
+
);
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1250
1448
|
if (template2[pos] === "<" && pos + 1 < len && template2[pos + 1] === "/") {
|
|
1251
1449
|
pos += 2;
|
|
1252
1450
|
readTagName();
|
|
@@ -1273,27 +1471,50 @@ function executeElement(tmpl, values) {
|
|
|
1273
1471
|
break;
|
|
1274
1472
|
case 1: {
|
|
1275
1473
|
const name = attr.name;
|
|
1276
|
-
|
|
1474
|
+
const lname = name.toLowerCase();
|
|
1475
|
+
if (lname[0] === "o" && lname[1] === "n") break;
|
|
1277
1476
|
const val = values[attr.idx];
|
|
1278
1477
|
if (typeof val === "function") {
|
|
1279
1478
|
registerDisposer(el, bindAttribute(el, name, val));
|
|
1280
1479
|
} else if (val != null) {
|
|
1281
1480
|
const str = String(val);
|
|
1282
|
-
|
|
1481
|
+
if (lname === "srcset") {
|
|
1482
|
+
el.setAttribute(name, sanitizeSrcset(str));
|
|
1483
|
+
} else if (isUrlAttribute(lname)) {
|
|
1484
|
+
el.setAttribute(name, sanitizeUrl(str));
|
|
1485
|
+
} else {
|
|
1486
|
+
el.setAttribute(name, str);
|
|
1487
|
+
}
|
|
1283
1488
|
}
|
|
1284
1489
|
break;
|
|
1285
1490
|
}
|
|
1286
1491
|
case 2: {
|
|
1287
1492
|
let val = attr.statics[0];
|
|
1288
1493
|
for (let j = 0; j < attr.exprs.length; j++) {
|
|
1289
|
-
|
|
1494
|
+
const ev = values[attr.exprs[j]];
|
|
1495
|
+
val += (ev == null ? "" : String(ev)) + attr.statics[j + 1];
|
|
1496
|
+
}
|
|
1497
|
+
const lname2 = attr.name.toLowerCase();
|
|
1498
|
+
if (lname2 === "srcset") {
|
|
1499
|
+
el.setAttribute(attr.name, sanitizeSrcset(val));
|
|
1500
|
+
} else if (isUrlAttribute(lname2)) {
|
|
1501
|
+
el.setAttribute(attr.name, sanitizeUrl(val));
|
|
1502
|
+
} else {
|
|
1503
|
+
el.setAttribute(attr.name, val);
|
|
1290
1504
|
}
|
|
1291
|
-
el.setAttribute(attr.name, val);
|
|
1292
1505
|
break;
|
|
1293
1506
|
}
|
|
1294
|
-
case 3:
|
|
1295
|
-
|
|
1507
|
+
case 3: {
|
|
1508
|
+
const fn = values[attr.idx];
|
|
1509
|
+
if (typeof fn === "function") {
|
|
1510
|
+
el.addEventListener(attr.name, fn);
|
|
1511
|
+
} else if (_isDev7) {
|
|
1512
|
+
devWarn(
|
|
1513
|
+
`html: on:${attr.name} handler is not a function (got ${typeof fn}). Event listener was not attached.`
|
|
1514
|
+
);
|
|
1515
|
+
}
|
|
1296
1516
|
break;
|
|
1517
|
+
}
|
|
1297
1518
|
case 4:
|
|
1298
1519
|
el.setAttribute(attr.name, "");
|
|
1299
1520
|
break;
|
|
@@ -1387,7 +1608,7 @@ function html2(strings, ...values) {
|
|
|
1387
1608
|
function mount(component, container) {
|
|
1388
1609
|
if (!container) {
|
|
1389
1610
|
throw new Error(
|
|
1390
|
-
"[
|
|
1611
|
+
"[SibuJS mount] container element not found. Make sure the DOM element exists before calling mount()."
|
|
1391
1612
|
);
|
|
1392
1613
|
}
|
|
1393
1614
|
devAssert(
|
|
@@ -1415,7 +1636,7 @@ function mount(component, container) {
|
|
|
1415
1636
|
}
|
|
1416
1637
|
|
|
1417
1638
|
// src/core/rendering/each.ts
|
|
1418
|
-
var
|
|
1639
|
+
var _isDev8 = isDev();
|
|
1419
1640
|
function resolveNodeChild(child) {
|
|
1420
1641
|
if (typeof child === "function") {
|
|
1421
1642
|
return resolveNodeChild(child());
|
|
@@ -1510,17 +1731,31 @@ function each(getArray, render, options) {
|
|
|
1510
1731
|
node = existing;
|
|
1511
1732
|
} else {
|
|
1512
1733
|
const itemKey = key;
|
|
1513
|
-
const itemGetter = () => getArray()[keyIndexMap.get(itemKey)];
|
|
1734
|
+
const itemGetter = () => untracked(() => getArray()[keyIndexMap.get(itemKey)]);
|
|
1514
1735
|
const indexGetter = () => keyIndexMap.get(itemKey);
|
|
1515
1736
|
try {
|
|
1516
1737
|
node = resolveNodeChild(render(itemGetter, indexGetter));
|
|
1517
1738
|
} catch (err) {
|
|
1518
|
-
if (
|
|
1739
|
+
if (_isDev8) {
|
|
1519
1740
|
devWarn(
|
|
1520
1741
|
`each: render threw for item at index ${i2} (key="${newKeys[i2]}"): ${err instanceof Error ? err.message : String(err)}`
|
|
1521
1742
|
);
|
|
1522
1743
|
}
|
|
1523
1744
|
node = document.createComment(`each:error:${i2}`);
|
|
1745
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
1746
|
+
queueMicrotask(() => {
|
|
1747
|
+
try {
|
|
1748
|
+
const target = anchor.parentNode;
|
|
1749
|
+
if (target?.dispatchEvent) {
|
|
1750
|
+
target.dispatchEvent(
|
|
1751
|
+
new CustomEvent("sibu:error-propagate", { bubbles: true, detail: { error: errorObj } })
|
|
1752
|
+
);
|
|
1753
|
+
} else if (_isDev8) {
|
|
1754
|
+
devWarn(`each: error not surfaced \u2014 anchor detached: ${errorObj.message}`);
|
|
1755
|
+
}
|
|
1756
|
+
} catch {
|
|
1757
|
+
}
|
|
1758
|
+
});
|
|
1524
1759
|
}
|
|
1525
1760
|
}
|
|
1526
1761
|
workMap.set(key, node);
|
|
@@ -1589,7 +1824,8 @@ function each(getArray, render, options) {
|
|
|
1589
1824
|
workMap = tmp;
|
|
1590
1825
|
initialized = true;
|
|
1591
1826
|
};
|
|
1592
|
-
track(update);
|
|
1827
|
+
const untrack = track(update);
|
|
1828
|
+
registerDisposer(anchor, untrack);
|
|
1593
1829
|
if (!initialized) {
|
|
1594
1830
|
queueMicrotask(() => {
|
|
1595
1831
|
if (!initialized && anchor.parentNode) {
|
|
@@ -1636,24 +1872,36 @@ function Portal(nodes, target) {
|
|
|
1636
1872
|
const anchor = document.createComment("portal");
|
|
1637
1873
|
const container = target || document.body;
|
|
1638
1874
|
let portalContent = null;
|
|
1875
|
+
let disposed = false;
|
|
1639
1876
|
queueMicrotask(() => {
|
|
1877
|
+
if (disposed) return;
|
|
1640
1878
|
try {
|
|
1641
1879
|
portalContent = nodes();
|
|
1642
1880
|
container.appendChild(portalContent);
|
|
1643
1881
|
} catch (err) {
|
|
1644
|
-
|
|
1882
|
+
if (typeof console !== "undefined") {
|
|
1883
|
+
console.error("[Portal] Render error:", err);
|
|
1884
|
+
}
|
|
1885
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
1886
|
+
queueMicrotask(() => {
|
|
1887
|
+
try {
|
|
1888
|
+
const target2 = anchor.parentNode;
|
|
1889
|
+
if (target2?.dispatchEvent) {
|
|
1890
|
+
target2.dispatchEvent(
|
|
1891
|
+
new CustomEvent("sibu:error-propagate", { bubbles: true, detail: { error: errorObj } })
|
|
1892
|
+
);
|
|
1893
|
+
}
|
|
1894
|
+
} catch {
|
|
1895
|
+
}
|
|
1896
|
+
});
|
|
1645
1897
|
}
|
|
1646
1898
|
});
|
|
1647
|
-
|
|
1648
|
-
|
|
1899
|
+
registerDisposer(anchor, () => {
|
|
1900
|
+
disposed = true;
|
|
1901
|
+
if (portalContent) {
|
|
1902
|
+
dispose(portalContent);
|
|
1649
1903
|
portalContent.remove();
|
|
1650
1904
|
portalContent = null;
|
|
1651
|
-
observer.disconnect();
|
|
1652
|
-
}
|
|
1653
|
-
});
|
|
1654
|
-
queueMicrotask(() => {
|
|
1655
|
-
if (anchor.parentNode) {
|
|
1656
|
-
observer.observe(anchor.parentNode, { childList: true });
|
|
1657
1905
|
}
|
|
1658
1906
|
});
|
|
1659
1907
|
return anchor;
|
|
@@ -1689,7 +1937,8 @@ function DynamicComponent(is) {
|
|
|
1689
1937
|
}
|
|
1690
1938
|
container.replaceChildren(el);
|
|
1691
1939
|
}
|
|
1692
|
-
track(render);
|
|
1940
|
+
const untrack = track(render);
|
|
1941
|
+
registerDisposer(container, untrack);
|
|
1693
1942
|
return container;
|
|
1694
1943
|
}
|
|
1695
1944
|
|
|
@@ -1779,11 +2028,16 @@ function KeepAlive(activeKey, cases, options) {
|
|
|
1779
2028
|
const anchor = document.createComment("keep-alive");
|
|
1780
2029
|
const cache2 = /* @__PURE__ */ new Map();
|
|
1781
2030
|
const lruOrder = [];
|
|
1782
|
-
const max = options?.max ??
|
|
2031
|
+
const max = options?.max ?? 10;
|
|
2032
|
+
if (max === 0 && isDev()) {
|
|
2033
|
+
devWarn("KeepAlive: unbounded cache (max: 0). Cached subtrees will never be evicted \u2014 set `max` to bound memory.");
|
|
2034
|
+
}
|
|
1783
2035
|
let currentKey;
|
|
1784
2036
|
let currentNode = null;
|
|
1785
2037
|
let initialized = false;
|
|
2038
|
+
let disposed = false;
|
|
1786
2039
|
const update = () => {
|
|
2040
|
+
if (disposed) return;
|
|
1787
2041
|
const key = activeKey();
|
|
1788
2042
|
const parent = anchor.parentNode;
|
|
1789
2043
|
if (!parent) return;
|
|
@@ -1823,12 +2077,23 @@ function KeepAlive(activeKey, cases, options) {
|
|
|
1823
2077
|
currentNode = node;
|
|
1824
2078
|
initialized = true;
|
|
1825
2079
|
};
|
|
1826
|
-
track(update);
|
|
2080
|
+
const untrack = track(update);
|
|
1827
2081
|
if (!initialized) {
|
|
1828
2082
|
queueMicrotask(() => {
|
|
1829
2083
|
if (!initialized && anchor.parentNode) update();
|
|
1830
2084
|
});
|
|
1831
2085
|
}
|
|
2086
|
+
registerDisposer(anchor, () => {
|
|
2087
|
+
disposed = true;
|
|
2088
|
+
untrack();
|
|
2089
|
+
for (const node of cache2.values()) {
|
|
2090
|
+
dispose(node);
|
|
2091
|
+
if (node.parentNode) node.parentNode.removeChild(node);
|
|
2092
|
+
}
|
|
2093
|
+
cache2.clear();
|
|
2094
|
+
lruOrder.length = 0;
|
|
2095
|
+
currentNode = null;
|
|
2096
|
+
});
|
|
1832
2097
|
return anchor;
|
|
1833
2098
|
}
|
|
1834
2099
|
|
|
@@ -1990,19 +2255,22 @@ function isBatching() {
|
|
|
1990
2255
|
return batchDepth > 0;
|
|
1991
2256
|
}
|
|
1992
2257
|
function flushBatch() {
|
|
1993
|
-
|
|
1994
|
-
|
|
2258
|
+
try {
|
|
2259
|
+
for (const signal2 of pendingSignals) {
|
|
2260
|
+
queueSignalNotification(signal2);
|
|
2261
|
+
}
|
|
2262
|
+
} finally {
|
|
2263
|
+
pendingSignals.clear();
|
|
1995
2264
|
}
|
|
1996
|
-
pendingSignals.clear();
|
|
1997
2265
|
drainNotificationQueue();
|
|
1998
2266
|
}
|
|
1999
2267
|
|
|
2000
2268
|
// src/core/signals/signal.ts
|
|
2001
2269
|
var _g = globalThis;
|
|
2002
|
-
var
|
|
2270
|
+
var _isDev9 = isDev();
|
|
2003
2271
|
function signal(initial, options) {
|
|
2004
2272
|
const state = { value: initial };
|
|
2005
|
-
const debugName =
|
|
2273
|
+
const debugName = _isDev9 ? options?.name : void 0;
|
|
2006
2274
|
const equalsFn = options?.equals;
|
|
2007
2275
|
if (debugName) {
|
|
2008
2276
|
state.__name = debugName;
|
|
@@ -2016,7 +2284,7 @@ function signal(initial, options) {
|
|
|
2016
2284
|
function set(next) {
|
|
2017
2285
|
const newValue = typeof next === "function" ? next(state.value) : next;
|
|
2018
2286
|
if (equalsFn ? equalsFn(state.value, newValue) : Object.is(newValue, state.value)) return;
|
|
2019
|
-
if (
|
|
2287
|
+
if (_isDev9) {
|
|
2020
2288
|
const oldValue = state.value;
|
|
2021
2289
|
state.value = newValue;
|
|
2022
2290
|
const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
@@ -2028,7 +2296,7 @@ function signal(initial, options) {
|
|
|
2028
2296
|
notifySubscribers(state);
|
|
2029
2297
|
}
|
|
2030
2298
|
}
|
|
2031
|
-
if (
|
|
2299
|
+
if (_isDev9) {
|
|
2032
2300
|
const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
2033
2301
|
if (hook) hook.emit("signal:create", { signal: state, name: debugName, getter: get, initial });
|
|
2034
2302
|
}
|
|
@@ -2036,23 +2304,59 @@ function signal(initial, options) {
|
|
|
2036
2304
|
}
|
|
2037
2305
|
|
|
2038
2306
|
// src/core/ssr-context.ts
|
|
2039
|
-
var
|
|
2307
|
+
var als = null;
|
|
2308
|
+
try {
|
|
2309
|
+
if (typeof process !== "undefined" && process.versions && process.versions.node) {
|
|
2310
|
+
const req = Function("return typeof require==='function'?require:null")();
|
|
2311
|
+
if (req) {
|
|
2312
|
+
const mod = req("node:async_hooks");
|
|
2313
|
+
als = new mod.AsyncLocalStorage();
|
|
2314
|
+
}
|
|
2315
|
+
}
|
|
2316
|
+
} catch {
|
|
2317
|
+
als = null;
|
|
2318
|
+
}
|
|
2319
|
+
var fallbackStore = { ssr: false, suspenseIdCounter: 0 };
|
|
2320
|
+
function getSSRStore() {
|
|
2321
|
+
if (als) {
|
|
2322
|
+
const s2 = als.getStore();
|
|
2323
|
+
if (s2) return s2;
|
|
2324
|
+
}
|
|
2325
|
+
return fallbackStore;
|
|
2326
|
+
}
|
|
2040
2327
|
function isSSR() {
|
|
2041
|
-
return
|
|
2328
|
+
return getSSRStore().ssr;
|
|
2042
2329
|
}
|
|
2043
2330
|
function enableSSR() {
|
|
2044
|
-
|
|
2331
|
+
getSSRStore().ssr = true;
|
|
2045
2332
|
}
|
|
2046
2333
|
function disableSSR() {
|
|
2047
|
-
|
|
2334
|
+
getSSRStore().ssr = false;
|
|
2335
|
+
}
|
|
2336
|
+
function runInSSRContext(fn) {
|
|
2337
|
+
const store2 = { ssr: true, suspenseIdCounter: 0 };
|
|
2338
|
+
if (als) {
|
|
2339
|
+
return als.run(store2, fn);
|
|
2340
|
+
}
|
|
2341
|
+
const prevSSR = fallbackStore.ssr;
|
|
2342
|
+
const prevCounter = fallbackStore.suspenseIdCounter;
|
|
2343
|
+
fallbackStore.ssr = true;
|
|
2344
|
+
fallbackStore.suspenseIdCounter = 0;
|
|
2345
|
+
try {
|
|
2346
|
+
return fn();
|
|
2347
|
+
} finally {
|
|
2348
|
+
fallbackStore.ssr = prevSSR;
|
|
2349
|
+
fallbackStore.suspenseIdCounter = prevCounter;
|
|
2350
|
+
}
|
|
2048
2351
|
}
|
|
2049
2352
|
function withSSR(fn) {
|
|
2050
|
-
const
|
|
2051
|
-
|
|
2353
|
+
const store2 = getSSRStore();
|
|
2354
|
+
const wasSSR = store2.ssr;
|
|
2355
|
+
store2.ssr = true;
|
|
2052
2356
|
try {
|
|
2053
2357
|
return fn();
|
|
2054
2358
|
} finally {
|
|
2055
|
-
if (!wasSSR)
|
|
2359
|
+
if (!wasSSR) store2.ssr = false;
|
|
2056
2360
|
}
|
|
2057
2361
|
}
|
|
2058
2362
|
|
|
@@ -2079,26 +2383,86 @@ function effect(effectFn, options) {
|
|
|
2079
2383
|
if (isSSR()) return () => {
|
|
2080
2384
|
};
|
|
2081
2385
|
const onError = options?.onError;
|
|
2386
|
+
let userCleanups = [];
|
|
2387
|
+
const onCleanup2 = (fn) => {
|
|
2388
|
+
userCleanups.push(fn);
|
|
2389
|
+
};
|
|
2390
|
+
const runUserCleanups = () => {
|
|
2391
|
+
if (userCleanups.length === 0) return;
|
|
2392
|
+
const list = userCleanups;
|
|
2393
|
+
userCleanups = [];
|
|
2394
|
+
for (let i2 = list.length - 1; i2 >= 0; i2--) {
|
|
2395
|
+
try {
|
|
2396
|
+
list[i2]();
|
|
2397
|
+
} catch (err) {
|
|
2398
|
+
if (typeof console !== "undefined") {
|
|
2399
|
+
console.warn("[SibuJS effect] onCleanup threw:", err);
|
|
2400
|
+
}
|
|
2401
|
+
}
|
|
2402
|
+
}
|
|
2403
|
+
};
|
|
2404
|
+
const invokeBody = () => effectFn(onCleanup2);
|
|
2082
2405
|
const wrappedFn = onError ? () => {
|
|
2083
2406
|
try {
|
|
2084
|
-
|
|
2407
|
+
invokeBody();
|
|
2085
2408
|
} catch (err) {
|
|
2086
2409
|
onError(err);
|
|
2087
2410
|
}
|
|
2088
|
-
} :
|
|
2411
|
+
} : invokeBody;
|
|
2089
2412
|
let cleanupHandle = () => {
|
|
2090
2413
|
};
|
|
2414
|
+
let running = false;
|
|
2091
2415
|
const subscriber = () => {
|
|
2092
|
-
|
|
2093
|
-
|
|
2416
|
+
if (running) {
|
|
2417
|
+
if (_g2.__SIBU_DEV_WARN__ !== false && typeof console !== "undefined") {
|
|
2418
|
+
console.warn(
|
|
2419
|
+
"[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."
|
|
2420
|
+
);
|
|
2421
|
+
}
|
|
2422
|
+
return;
|
|
2423
|
+
}
|
|
2424
|
+
running = true;
|
|
2425
|
+
try {
|
|
2426
|
+
runUserCleanups();
|
|
2427
|
+
cleanupHandle();
|
|
2428
|
+
cleanupHandle = track(wrappedFn, subscriber);
|
|
2429
|
+
} finally {
|
|
2430
|
+
running = false;
|
|
2431
|
+
}
|
|
2094
2432
|
};
|
|
2095
|
-
|
|
2433
|
+
running = true;
|
|
2434
|
+
try {
|
|
2435
|
+
cleanupHandle = track(wrappedFn, subscriber);
|
|
2436
|
+
} finally {
|
|
2437
|
+
running = false;
|
|
2438
|
+
}
|
|
2096
2439
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
2097
2440
|
if (hook) hook.emit("effect:create", { effectFn });
|
|
2441
|
+
let disposed = false;
|
|
2098
2442
|
return () => {
|
|
2443
|
+
if (disposed) return;
|
|
2444
|
+
disposed = true;
|
|
2099
2445
|
const h = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
2100
|
-
if (h)
|
|
2101
|
-
|
|
2446
|
+
if (h) {
|
|
2447
|
+
try {
|
|
2448
|
+
h.emit("effect:destroy", { effectFn });
|
|
2449
|
+
} catch {
|
|
2450
|
+
}
|
|
2451
|
+
}
|
|
2452
|
+
try {
|
|
2453
|
+
runUserCleanups();
|
|
2454
|
+
} catch (err) {
|
|
2455
|
+
if (typeof console !== "undefined") {
|
|
2456
|
+
console.warn("[SibuJS effect] onCleanup threw during dispose:", err);
|
|
2457
|
+
}
|
|
2458
|
+
}
|
|
2459
|
+
try {
|
|
2460
|
+
cleanupHandle();
|
|
2461
|
+
} catch (err) {
|
|
2462
|
+
if (typeof console !== "undefined") {
|
|
2463
|
+
console.warn("[SibuJS effect] dispose threw:", err);
|
|
2464
|
+
}
|
|
2465
|
+
}
|
|
2102
2466
|
};
|
|
2103
2467
|
}
|
|
2104
2468
|
|
|
@@ -2106,6 +2470,7 @@ function effect(effectFn, options) {
|
|
|
2106
2470
|
function derived(getter, options) {
|
|
2107
2471
|
devAssert(typeof getter === "function", "derived: argument must be a getter function.");
|
|
2108
2472
|
const debugName = options?.name;
|
|
2473
|
+
const equals = options?.equals;
|
|
2109
2474
|
const cs = {};
|
|
2110
2475
|
cs._d = false;
|
|
2111
2476
|
cs._g = getter;
|
|
@@ -2116,25 +2481,56 @@ function derived(getter, options) {
|
|
|
2116
2481
|
markDirty._c = 1;
|
|
2117
2482
|
markDirty._sig = cs;
|
|
2118
2483
|
track(() => {
|
|
2119
|
-
|
|
2120
|
-
|
|
2484
|
+
let threw = true;
|
|
2485
|
+
try {
|
|
2486
|
+
cs._v = getter();
|
|
2487
|
+
cs._d = false;
|
|
2488
|
+
threw = false;
|
|
2489
|
+
} finally {
|
|
2490
|
+
if (threw) cs._d = true;
|
|
2491
|
+
}
|
|
2121
2492
|
}, markDirty);
|
|
2122
2493
|
const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
2494
|
+
let evaluating = false;
|
|
2123
2495
|
function computedGetter() {
|
|
2496
|
+
if (evaluating) {
|
|
2497
|
+
throw new Error(
|
|
2498
|
+
`[SibuJS] Circular dependency detected in derived${debugName ? ` "${debugName}"` : ""}. A derived signal cannot read itself (directly or through a chain).`
|
|
2499
|
+
);
|
|
2500
|
+
}
|
|
2124
2501
|
if (trackingSuspended) {
|
|
2125
2502
|
if (cs._d) {
|
|
2126
|
-
|
|
2127
|
-
|
|
2503
|
+
evaluating = true;
|
|
2504
|
+
let threw = true;
|
|
2505
|
+
try {
|
|
2506
|
+
retrack(() => {
|
|
2507
|
+
cs._v = getter();
|
|
2508
|
+
cs._d = false;
|
|
2509
|
+
threw = false;
|
|
2510
|
+
}, markDirty);
|
|
2511
|
+
} finally {
|
|
2512
|
+
evaluating = false;
|
|
2513
|
+
if (threw) cs._d = true;
|
|
2514
|
+
}
|
|
2128
2515
|
}
|
|
2129
2516
|
return cs._v;
|
|
2130
2517
|
}
|
|
2131
2518
|
recordDependency(cs);
|
|
2132
2519
|
if (cs._d) {
|
|
2133
2520
|
const oldValue = cs._v;
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2521
|
+
evaluating = true;
|
|
2522
|
+
let threw = true;
|
|
2523
|
+
try {
|
|
2524
|
+
retrack(() => {
|
|
2525
|
+
const next = getter();
|
|
2526
|
+
cs._v = equals && cs._v !== void 0 ? equals(cs._v, next) ? cs._v : next : next;
|
|
2527
|
+
cs._d = false;
|
|
2528
|
+
threw = false;
|
|
2529
|
+
}, markDirty);
|
|
2530
|
+
} finally {
|
|
2531
|
+
evaluating = false;
|
|
2532
|
+
if (threw) cs._d = true;
|
|
2533
|
+
}
|
|
2138
2534
|
if (hook && oldValue !== cs._v) {
|
|
2139
2535
|
hook.emit("computed:update", { signal: cs, oldValue, newValue: cs._v });
|
|
2140
2536
|
}
|
|
@@ -2195,7 +2591,7 @@ function store(initialState) {
|
|
|
2195
2591
|
},
|
|
2196
2592
|
set() {
|
|
2197
2593
|
throw new Error(
|
|
2198
|
-
"[
|
|
2594
|
+
"[SibuJS store] Direct mutation is not allowed. Use actions.setState() to update store properties."
|
|
2199
2595
|
);
|
|
2200
2596
|
}
|
|
2201
2597
|
});
|
|
@@ -2209,16 +2605,20 @@ function store(initialState) {
|
|
|
2209
2605
|
const setState = (patch) => {
|
|
2210
2606
|
const current = getSnapshot();
|
|
2211
2607
|
const nextState = typeof patch === "function" ? patch(current) : patch;
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
signals
|
|
2215
|
-
|
|
2608
|
+
batch(() => {
|
|
2609
|
+
Object.entries(nextState).forEach(([key, value]) => {
|
|
2610
|
+
if (key in signals) {
|
|
2611
|
+
signals[key][1](value);
|
|
2612
|
+
}
|
|
2613
|
+
});
|
|
2216
2614
|
});
|
|
2217
2615
|
};
|
|
2218
2616
|
const reset = () => {
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2617
|
+
batch(() => {
|
|
2618
|
+
Object.keys(initialState).forEach((key) => {
|
|
2619
|
+
const setter = signals[key][1];
|
|
2620
|
+
setter(initialState[key]);
|
|
2621
|
+
});
|
|
2222
2622
|
});
|
|
2223
2623
|
};
|
|
2224
2624
|
const subscribe = (callback) => {
|
|
@@ -2352,7 +2752,8 @@ function reactiveArray(initial = []) {
|
|
|
2352
2752
|
function get() {
|
|
2353
2753
|
recordDependency(signal2);
|
|
2354
2754
|
if (snapshot === null) {
|
|
2355
|
-
|
|
2755
|
+
const copy = data2.slice();
|
|
2756
|
+
snapshot = Object.freeze(copy);
|
|
2356
2757
|
}
|
|
2357
2758
|
return snapshot;
|
|
2358
2759
|
}
|
|
@@ -2462,21 +2863,67 @@ function deepEqual(a2, b2, seen) {
|
|
|
2462
2863
|
if (a2 == null || b2 == null) return false;
|
|
2463
2864
|
if (typeof a2 !== typeof b2) return false;
|
|
2464
2865
|
if (typeof a2 !== "object") return false;
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
if (
|
|
2468
|
-
if (
|
|
2469
|
-
|
|
2866
|
+
const objA = a2;
|
|
2867
|
+
const objB = b2;
|
|
2868
|
+
if (objA.constructor !== objB.constructor) return false;
|
|
2869
|
+
if (a2 instanceof Date) return a2.getTime() === b2.getTime();
|
|
2870
|
+
if (a2 instanceof RegExp) {
|
|
2871
|
+
const rb = b2;
|
|
2872
|
+
return a2.source === rb.source && a2.flags === rb.flags;
|
|
2873
|
+
}
|
|
2874
|
+
if (!seen) seen = /* @__PURE__ */ new Map();
|
|
2875
|
+
let peers = seen.get(objA);
|
|
2876
|
+
if (peers?.has(objB)) return true;
|
|
2877
|
+
if (!peers) {
|
|
2878
|
+
peers = /* @__PURE__ */ new Set();
|
|
2879
|
+
seen.set(objA, peers);
|
|
2880
|
+
}
|
|
2881
|
+
peers.add(objB);
|
|
2882
|
+
if (a2 instanceof Map) {
|
|
2883
|
+
const mb = b2;
|
|
2884
|
+
if (a2.size !== mb.size) return false;
|
|
2885
|
+
for (const [k, v] of a2) {
|
|
2886
|
+
if (!mb.has(k)) return false;
|
|
2887
|
+
if (!deepEqual(v, mb.get(k), seen)) return false;
|
|
2888
|
+
}
|
|
2889
|
+
return true;
|
|
2890
|
+
}
|
|
2891
|
+
if (a2 instanceof Set) {
|
|
2892
|
+
const sb = b2;
|
|
2893
|
+
if (a2.size !== sb.size) return false;
|
|
2894
|
+
for (const item of a2) {
|
|
2895
|
+
if (!sb.has(item)) return false;
|
|
2896
|
+
}
|
|
2897
|
+
return true;
|
|
2898
|
+
}
|
|
2899
|
+
if (a2 instanceof ArrayBuffer) {
|
|
2900
|
+
const viewA = new Uint8Array(a2);
|
|
2901
|
+
const viewB = new Uint8Array(b2);
|
|
2902
|
+
if (viewA.length !== viewB.length) return false;
|
|
2903
|
+
for (let i2 = 0; i2 < viewA.length; i2++) {
|
|
2904
|
+
if (viewA[i2] !== viewB[i2]) return false;
|
|
2905
|
+
}
|
|
2906
|
+
return true;
|
|
2907
|
+
}
|
|
2908
|
+
if (ArrayBuffer.isView(a2) && ArrayBuffer.isView(b2)) {
|
|
2909
|
+
const ta = a2;
|
|
2910
|
+
const tb = b2;
|
|
2911
|
+
if (ta.length !== tb.length) return false;
|
|
2912
|
+
for (let i2 = 0; i2 < ta.length; i2++) {
|
|
2913
|
+
if (ta[i2] !== tb[i2]) return false;
|
|
2914
|
+
}
|
|
2915
|
+
return true;
|
|
2916
|
+
}
|
|
2470
2917
|
if (Array.isArray(a2)) {
|
|
2471
2918
|
if (!Array.isArray(b2)) return false;
|
|
2472
2919
|
if (a2.length !== b2.length) return false;
|
|
2473
2920
|
return a2.every((val, i2) => deepEqual(val, b2[i2], seen));
|
|
2474
2921
|
}
|
|
2475
|
-
const keysA = Object.keys(
|
|
2476
|
-
const keysB = Object.keys(
|
|
2922
|
+
const keysA = Object.keys(objA);
|
|
2923
|
+
const keysB = Object.keys(objB);
|
|
2477
2924
|
if (keysA.length !== keysB.length) return false;
|
|
2478
2925
|
return keysA.every(
|
|
2479
|
-
(key) => deepEqual(
|
|
2926
|
+
(key) => deepEqual(objA[key], objB[key], seen)
|
|
2480
2927
|
);
|
|
2481
2928
|
}
|
|
2482
2929
|
function deepSignal(initial) {
|
|
@@ -2502,26 +2949,34 @@ function asyncDerived(factory, initial) {
|
|
|
2502
2949
|
effect(() => {
|
|
2503
2950
|
tick();
|
|
2504
2951
|
const currentRun = ++runId;
|
|
2505
|
-
|
|
2506
|
-
|
|
2952
|
+
batch(() => {
|
|
2953
|
+
setLoading(true);
|
|
2954
|
+
setError(null);
|
|
2955
|
+
});
|
|
2507
2956
|
let promise;
|
|
2508
2957
|
try {
|
|
2509
2958
|
promise = factory();
|
|
2510
2959
|
} catch (err) {
|
|
2511
|
-
|
|
2512
|
-
|
|
2960
|
+
batch(() => {
|
|
2961
|
+
setError(err);
|
|
2962
|
+
setLoading(false);
|
|
2963
|
+
});
|
|
2513
2964
|
return;
|
|
2514
2965
|
}
|
|
2515
2966
|
promise.then(
|
|
2516
2967
|
(result) => {
|
|
2517
2968
|
if (currentRun !== runId) return;
|
|
2518
|
-
|
|
2519
|
-
|
|
2969
|
+
batch(() => {
|
|
2970
|
+
setValue(result);
|
|
2971
|
+
setLoading(false);
|
|
2972
|
+
});
|
|
2520
2973
|
},
|
|
2521
2974
|
(err) => {
|
|
2522
2975
|
if (currentRun !== runId) return;
|
|
2523
|
-
|
|
2524
|
-
|
|
2976
|
+
batch(() => {
|
|
2977
|
+
setError(err);
|
|
2978
|
+
setLoading(false);
|
|
2979
|
+
});
|
|
2525
2980
|
}
|
|
2526
2981
|
);
|
|
2527
2982
|
});
|
|
@@ -2536,32 +2991,198 @@ function asyncDerived(factory, initial) {
|
|
|
2536
2991
|
// src/core/rendering/lifecycle.ts
|
|
2537
2992
|
function safeCall(cb, hookName) {
|
|
2538
2993
|
try {
|
|
2539
|
-
cb();
|
|
2994
|
+
return cb();
|
|
2540
2995
|
} catch (err) {
|
|
2541
2996
|
devWarn(`${hookName}: callback threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
2997
|
+
return void 0;
|
|
2998
|
+
}
|
|
2999
|
+
}
|
|
3000
|
+
function runMountCallback(callback, hookName, element) {
|
|
3001
|
+
const cleanup2 = safeCall(callback, hookName);
|
|
3002
|
+
if (typeof cleanup2 === "function" && element) {
|
|
3003
|
+
registerDisposer(element, cleanup2);
|
|
3004
|
+
}
|
|
3005
|
+
}
|
|
3006
|
+
var mountWatchers = /* @__PURE__ */ new WeakMap();
|
|
3007
|
+
var unmountWatchers = /* @__PURE__ */ new WeakMap();
|
|
3008
|
+
var watchedMountElements = /* @__PURE__ */ new Set();
|
|
3009
|
+
var watchedUnmountElements = /* @__PURE__ */ new Set();
|
|
3010
|
+
var sharedObserver = null;
|
|
3011
|
+
var mutationCounter = 0;
|
|
3012
|
+
var FULL_SWEEP_INTERVAL = 256;
|
|
3013
|
+
function fireMount(el) {
|
|
3014
|
+
const cbs = mountWatchers.get(el);
|
|
3015
|
+
if (!cbs) return;
|
|
3016
|
+
mountWatchers.delete(el);
|
|
3017
|
+
watchedMountElements.delete(el);
|
|
3018
|
+
for (const cb of cbs) {
|
|
3019
|
+
try {
|
|
3020
|
+
cb();
|
|
3021
|
+
} catch {
|
|
3022
|
+
}
|
|
3023
|
+
}
|
|
3024
|
+
}
|
|
3025
|
+
function fireUnmount(el) {
|
|
3026
|
+
const cbs = unmountWatchers.get(el);
|
|
3027
|
+
if (!cbs) return;
|
|
3028
|
+
queueMicrotask(() => {
|
|
3029
|
+
if (el.isConnected) return;
|
|
3030
|
+
const stillCbs = unmountWatchers.get(el);
|
|
3031
|
+
if (!stillCbs) return;
|
|
3032
|
+
unmountWatchers.delete(el);
|
|
3033
|
+
watchedUnmountElements.delete(el);
|
|
3034
|
+
for (const cb of stillCbs) {
|
|
3035
|
+
try {
|
|
3036
|
+
cb();
|
|
3037
|
+
} catch {
|
|
3038
|
+
}
|
|
3039
|
+
}
|
|
3040
|
+
});
|
|
3041
|
+
}
|
|
3042
|
+
function visitAddedNode(node) {
|
|
3043
|
+
if (watchedMountElements.size === 0) return;
|
|
3044
|
+
if (node.nodeType !== 1) return;
|
|
3045
|
+
const el = node;
|
|
3046
|
+
if (watchedMountElements.has(el) && el.isConnected) {
|
|
3047
|
+
fireMount(el);
|
|
3048
|
+
}
|
|
3049
|
+
if (el.firstElementChild) {
|
|
3050
|
+
for (const watched of Array.from(watchedMountElements)) {
|
|
3051
|
+
if (watched !== el && watched.isConnected && el.contains(watched)) {
|
|
3052
|
+
fireMount(watched);
|
|
3053
|
+
}
|
|
3054
|
+
}
|
|
3055
|
+
}
|
|
3056
|
+
}
|
|
3057
|
+
function visitRemovedNode(node) {
|
|
3058
|
+
if (watchedUnmountElements.size === 0) return;
|
|
3059
|
+
if (node.nodeType !== 1) return;
|
|
3060
|
+
const el = node;
|
|
3061
|
+
if (watchedUnmountElements.has(el) && !el.isConnected) {
|
|
3062
|
+
fireUnmount(el);
|
|
3063
|
+
}
|
|
3064
|
+
if (el.firstElementChild) {
|
|
3065
|
+
for (const watched of Array.from(watchedUnmountElements)) {
|
|
3066
|
+
if (watched !== el && !watched.isConnected && el.contains(watched)) {
|
|
3067
|
+
fireUnmount(watched);
|
|
3068
|
+
}
|
|
3069
|
+
}
|
|
3070
|
+
}
|
|
3071
|
+
}
|
|
3072
|
+
function fullSweep() {
|
|
3073
|
+
if (watchedMountElements.size > 0) {
|
|
3074
|
+
for (const el of Array.from(watchedMountElements)) {
|
|
3075
|
+
if (el.isConnected) fireMount(el);
|
|
3076
|
+
}
|
|
3077
|
+
}
|
|
3078
|
+
if (watchedUnmountElements.size > 0) {
|
|
3079
|
+
for (const el of Array.from(watchedUnmountElements)) {
|
|
3080
|
+
if (!el.isConnected) fireUnmount(el);
|
|
3081
|
+
}
|
|
2542
3082
|
}
|
|
2543
3083
|
}
|
|
3084
|
+
function ensureObserver() {
|
|
3085
|
+
if (sharedObserver || typeof document === "undefined") return;
|
|
3086
|
+
sharedObserver = new MutationObserver((mutations) => {
|
|
3087
|
+
for (const m of mutations) {
|
|
3088
|
+
if (m.type !== "childList") continue;
|
|
3089
|
+
if (m.addedNodes.length > 0) {
|
|
3090
|
+
for (let i2 = 0; i2 < m.addedNodes.length; i2++) {
|
|
3091
|
+
visitAddedNode(m.addedNodes[i2]);
|
|
3092
|
+
}
|
|
3093
|
+
}
|
|
3094
|
+
if (m.removedNodes.length > 0) {
|
|
3095
|
+
for (let i2 = 0; i2 < m.removedNodes.length; i2++) {
|
|
3096
|
+
visitRemovedNode(m.removedNodes[i2]);
|
|
3097
|
+
}
|
|
3098
|
+
}
|
|
3099
|
+
}
|
|
3100
|
+
mutationCounter += mutations.length;
|
|
3101
|
+
if (mutationCounter >= FULL_SWEEP_INTERVAL) {
|
|
3102
|
+
mutationCounter = 0;
|
|
3103
|
+
fullSweep();
|
|
3104
|
+
}
|
|
3105
|
+
maybeDisconnectObserver();
|
|
3106
|
+
});
|
|
3107
|
+
sharedObserver.observe(document.body, { childList: true, subtree: true });
|
|
3108
|
+
}
|
|
3109
|
+
function maybeDisconnectObserver() {
|
|
3110
|
+
if (!sharedObserver) return;
|
|
3111
|
+
if (watchedMountElements.size === 0 && watchedUnmountElements.size === 0) {
|
|
3112
|
+
sharedObserver.disconnect();
|
|
3113
|
+
sharedObserver = null;
|
|
3114
|
+
mutationCounter = 0;
|
|
3115
|
+
}
|
|
3116
|
+
}
|
|
3117
|
+
function registerMountWatcher(element, cb) {
|
|
3118
|
+
let list = mountWatchers.get(element);
|
|
3119
|
+
if (!list) {
|
|
3120
|
+
list = [];
|
|
3121
|
+
mountWatchers.set(element, list);
|
|
3122
|
+
}
|
|
3123
|
+
list.push(cb);
|
|
3124
|
+
watchedMountElements.add(element);
|
|
3125
|
+
ensureObserver();
|
|
3126
|
+
return () => {
|
|
3127
|
+
const cbs = mountWatchers.get(element);
|
|
3128
|
+
if (cbs) {
|
|
3129
|
+
const idx = cbs.indexOf(cb);
|
|
3130
|
+
if (idx !== -1) cbs.splice(idx, 1);
|
|
3131
|
+
if (cbs.length === 0) {
|
|
3132
|
+
mountWatchers.delete(element);
|
|
3133
|
+
watchedMountElements.delete(element);
|
|
3134
|
+
}
|
|
3135
|
+
}
|
|
3136
|
+
maybeDisconnectObserver();
|
|
3137
|
+
};
|
|
3138
|
+
}
|
|
3139
|
+
function registerUnmountWatcher(element, cb) {
|
|
3140
|
+
let list = unmountWatchers.get(element);
|
|
3141
|
+
if (!list) {
|
|
3142
|
+
list = [];
|
|
3143
|
+
unmountWatchers.set(element, list);
|
|
3144
|
+
}
|
|
3145
|
+
list.push(cb);
|
|
3146
|
+
watchedUnmountElements.add(element);
|
|
3147
|
+
ensureObserver();
|
|
3148
|
+
return () => {
|
|
3149
|
+
const cbs = unmountWatchers.get(element);
|
|
3150
|
+
if (cbs) {
|
|
3151
|
+
const idx = cbs.indexOf(cb);
|
|
3152
|
+
if (idx !== -1) cbs.splice(idx, 1);
|
|
3153
|
+
if (cbs.length === 0) {
|
|
3154
|
+
unmountWatchers.delete(element);
|
|
3155
|
+
watchedUnmountElements.delete(element);
|
|
3156
|
+
}
|
|
3157
|
+
}
|
|
3158
|
+
maybeDisconnectObserver();
|
|
3159
|
+
};
|
|
3160
|
+
}
|
|
2544
3161
|
function onMount(callback, element) {
|
|
2545
3162
|
if (typeof document === "undefined") return;
|
|
2546
3163
|
if (element) {
|
|
3164
|
+
let disposed = false;
|
|
3165
|
+
registerDisposer(element, () => {
|
|
3166
|
+
disposed = true;
|
|
3167
|
+
});
|
|
2547
3168
|
if (element.isConnected) {
|
|
2548
3169
|
queueMicrotask(() => {
|
|
2549
|
-
|
|
3170
|
+
if (disposed) return;
|
|
3171
|
+
runMountCallback(callback, "onMount", element);
|
|
2550
3172
|
});
|
|
2551
3173
|
return;
|
|
2552
3174
|
}
|
|
2553
|
-
const observer = new MutationObserver(() => {
|
|
2554
|
-
if (element.isConnected) {
|
|
2555
|
-
observer.disconnect();
|
|
2556
|
-
safeCall(callback, "onMount");
|
|
2557
|
-
}
|
|
2558
|
-
});
|
|
2559
3175
|
queueMicrotask(() => {
|
|
3176
|
+
if (disposed) return;
|
|
2560
3177
|
if (element.isConnected) {
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
observer.observe(document.body, { childList: true, subtree: true });
|
|
3178
|
+
runMountCallback(callback, "onMount", element);
|
|
3179
|
+
return;
|
|
2564
3180
|
}
|
|
3181
|
+
const unregister = registerMountWatcher(element, () => {
|
|
3182
|
+
if (disposed) return;
|
|
3183
|
+
runMountCallback(callback, "onMount", element);
|
|
3184
|
+
});
|
|
3185
|
+
registerDisposer(element, unregister);
|
|
2565
3186
|
});
|
|
2566
3187
|
} else {
|
|
2567
3188
|
queueMicrotask(() => {
|
|
@@ -2570,20 +3191,24 @@ function onMount(callback, element) {
|
|
|
2570
3191
|
}
|
|
2571
3192
|
}
|
|
2572
3193
|
function onUnmount(callback, element) {
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
3194
|
+
if (typeof document === "undefined") return;
|
|
3195
|
+
let fired = false;
|
|
3196
|
+
const fireOnce = () => {
|
|
3197
|
+
if (fired) return;
|
|
3198
|
+
fired = true;
|
|
3199
|
+
safeCall(callback, "onUnmount");
|
|
3200
|
+
};
|
|
3201
|
+
registerDisposer(element, fireOnce);
|
|
3202
|
+
const startWatching = () => {
|
|
3203
|
+
if (fired) return;
|
|
3204
|
+
const unregister = registerUnmountWatcher(element, fireOnce);
|
|
3205
|
+
registerDisposer(element, unregister);
|
|
2581
3206
|
};
|
|
2582
3207
|
if (element.isConnected) {
|
|
2583
|
-
|
|
3208
|
+
startWatching();
|
|
2584
3209
|
} else {
|
|
2585
3210
|
onMount(() => {
|
|
2586
|
-
|
|
3211
|
+
startWatching();
|
|
2587
3212
|
return void 0;
|
|
2588
3213
|
}, element);
|
|
2589
3214
|
}
|
|
@@ -2595,9 +3220,11 @@ function onCleanup(callback, element) {
|
|
|
2595
3220
|
// src/core/rendering/context.ts
|
|
2596
3221
|
function context(defaultValue) {
|
|
2597
3222
|
const [getValue, setValue] = signal(defaultValue);
|
|
2598
|
-
|
|
3223
|
+
const ctx = {
|
|
2599
3224
|
provide(value) {
|
|
3225
|
+
const previous = getValue();
|
|
2600
3226
|
setValue(value);
|
|
3227
|
+
return () => setValue(previous);
|
|
2601
3228
|
},
|
|
2602
3229
|
use() {
|
|
2603
3230
|
return getValue;
|
|
@@ -2607,8 +3234,18 @@ function context(defaultValue) {
|
|
|
2607
3234
|
},
|
|
2608
3235
|
set(value) {
|
|
2609
3236
|
setValue(value);
|
|
3237
|
+
},
|
|
3238
|
+
withContext(value, fn) {
|
|
3239
|
+
const previous = getValue();
|
|
3240
|
+
setValue(value);
|
|
3241
|
+
try {
|
|
3242
|
+
return fn();
|
|
3243
|
+
} finally {
|
|
3244
|
+
setValue(previous);
|
|
3245
|
+
}
|
|
2610
3246
|
}
|
|
2611
3247
|
};
|
|
3248
|
+
return ctx;
|
|
2612
3249
|
}
|
|
2613
3250
|
|
|
2614
3251
|
// src/core/strict.ts
|
|
@@ -2619,7 +3256,7 @@ function strict(fn) {
|
|
|
2619
3256
|
try {
|
|
2620
3257
|
fn();
|
|
2621
3258
|
} catch (err) {
|
|
2622
|
-
console.warn("[
|
|
3259
|
+
console.warn("[SibuJS strict] second run threw:", err);
|
|
2623
3260
|
}
|
|
2624
3261
|
});
|
|
2625
3262
|
}
|
|
@@ -2635,7 +3272,7 @@ function strictEffect(fn) {
|
|
|
2635
3272
|
try {
|
|
2636
3273
|
secondTeardown = effect(fn);
|
|
2637
3274
|
} catch (err) {
|
|
2638
|
-
console.warn("[
|
|
3275
|
+
console.warn("[SibuJS strictEffect] second run threw:", err);
|
|
2639
3276
|
}
|
|
2640
3277
|
});
|
|
2641
3278
|
return () => {
|
|
@@ -2661,9 +3298,11 @@ function nextTick() {
|
|
|
2661
3298
|
function defer(getter) {
|
|
2662
3299
|
const [value, setValue] = signal(getter());
|
|
2663
3300
|
let pending = false;
|
|
3301
|
+
let disposed = false;
|
|
2664
3302
|
let latest = value();
|
|
2665
3303
|
const flush = () => {
|
|
2666
3304
|
pending = false;
|
|
3305
|
+
if (disposed) return;
|
|
2667
3306
|
setValue(latest);
|
|
2668
3307
|
};
|
|
2669
3308
|
const schedule = () => {
|
|
@@ -2677,11 +3316,17 @@ function defer(getter) {
|
|
|
2677
3316
|
}
|
|
2678
3317
|
});
|
|
2679
3318
|
};
|
|
2680
|
-
track(() => {
|
|
3319
|
+
const teardown = track(() => {
|
|
2681
3320
|
latest = getter();
|
|
2682
3321
|
schedule();
|
|
2683
3322
|
});
|
|
2684
|
-
|
|
3323
|
+
const accessor = (() => value());
|
|
3324
|
+
accessor.dispose = () => {
|
|
3325
|
+
if (disposed) return;
|
|
3326
|
+
disposed = true;
|
|
3327
|
+
teardown();
|
|
3328
|
+
};
|
|
3329
|
+
return accessor;
|
|
2685
3330
|
}
|
|
2686
3331
|
var IDLE_FALLBACK_MS = 16;
|
|
2687
3332
|
function scheduleIdle(fn) {
|
|
@@ -2722,32 +3367,56 @@ function transition() {
|
|
|
2722
3367
|
}
|
|
2723
3368
|
|
|
2724
3369
|
// src/core/rendering/lazy.ts
|
|
3370
|
+
var PENDING_ERROR = "__sibuPendingError";
|
|
3371
|
+
function dispatchPropagate(node, error) {
|
|
3372
|
+
const fire = () => {
|
|
3373
|
+
try {
|
|
3374
|
+
if (!node.parentNode) return false;
|
|
3375
|
+
node.dispatchEvent(new CustomEvent("sibu:error-propagate", { bubbles: true, detail: { error } }));
|
|
3376
|
+
return true;
|
|
3377
|
+
} catch {
|
|
3378
|
+
return false;
|
|
3379
|
+
}
|
|
3380
|
+
};
|
|
3381
|
+
if (node.parentNode && fire()) return;
|
|
3382
|
+
queueMicrotask(() => {
|
|
3383
|
+
if (fire()) return;
|
|
3384
|
+
node[PENDING_ERROR] = error;
|
|
3385
|
+
});
|
|
3386
|
+
}
|
|
3387
|
+
function takePendingError(node) {
|
|
3388
|
+
const rec = node;
|
|
3389
|
+
const err = rec[PENDING_ERROR];
|
|
3390
|
+
if (err instanceof Error) {
|
|
3391
|
+
delete rec[PENDING_ERROR];
|
|
3392
|
+
return err;
|
|
3393
|
+
}
|
|
3394
|
+
return void 0;
|
|
3395
|
+
}
|
|
2725
3396
|
function lazy(importFn) {
|
|
2726
3397
|
let cached = null;
|
|
2727
3398
|
return function LazyComponent() {
|
|
2728
3399
|
if (cached) {
|
|
2729
3400
|
return cached();
|
|
2730
3401
|
}
|
|
2731
|
-
const [_status, setStatus] = signal("loading");
|
|
2732
|
-
const [_error, setError] = signal(null);
|
|
2733
3402
|
const container = div({ class: "sibu-lazy" });
|
|
3403
|
+
let disposed = false;
|
|
2734
3404
|
importFn().then((mod) => {
|
|
3405
|
+
if (disposed) return;
|
|
2735
3406
|
cached = mod.default;
|
|
2736
3407
|
const rendered = cached();
|
|
2737
3408
|
container.replaceChildren(rendered);
|
|
2738
|
-
setStatus("loaded");
|
|
2739
3409
|
}).catch((err) => {
|
|
3410
|
+
if (disposed) return;
|
|
2740
3411
|
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
container
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
);
|
|
3412
|
+
devWarn(`[SibuJS] lazy() failed to load component: ${errorObj.message}`);
|
|
3413
|
+
container.replaceChildren(div({ class: "sibu-lazy-error" }, `Failed to load component: ${errorObj.message}`));
|
|
3414
|
+
dispatchPropagate(container, errorObj);
|
|
3415
|
+
});
|
|
3416
|
+
container.appendChild(span("sibu-lazy-loading", "Loading..."));
|
|
3417
|
+
registerDisposer(container, () => {
|
|
3418
|
+
disposed = true;
|
|
2749
3419
|
});
|
|
2750
|
-
container.appendChild(span({ class: "sibu-lazy-loading", nodes: "Loading..." }));
|
|
2751
3420
|
return container;
|
|
2752
3421
|
};
|
|
2753
3422
|
}
|
|
@@ -2755,32 +3424,55 @@ function Suspense({ nodes, fallback }) {
|
|
|
2755
3424
|
const container = div({ class: "sibu-suspense" });
|
|
2756
3425
|
const fallbackEl = fallback();
|
|
2757
3426
|
container.appendChild(fallbackEl);
|
|
3427
|
+
let suspenseDisposed = false;
|
|
3428
|
+
let observer = null;
|
|
3429
|
+
registerDisposer(container, () => {
|
|
3430
|
+
suspenseDisposed = true;
|
|
3431
|
+
if (observer) {
|
|
3432
|
+
observer.disconnect();
|
|
3433
|
+
observer = null;
|
|
3434
|
+
}
|
|
3435
|
+
});
|
|
2758
3436
|
queueMicrotask(() => {
|
|
3437
|
+
if (suspenseDisposed) return;
|
|
2759
3438
|
try {
|
|
2760
3439
|
const childEl = nodes();
|
|
2761
3440
|
if (childEl.classList.contains("sibu-lazy")) {
|
|
2762
|
-
|
|
3441
|
+
if (!childEl.querySelector(".sibu-lazy-loading")) {
|
|
3442
|
+
container.replaceChildren(childEl);
|
|
3443
|
+
return;
|
|
3444
|
+
}
|
|
3445
|
+
observer = new MutationObserver(() => {
|
|
3446
|
+
if (suspenseDisposed) return;
|
|
2763
3447
|
const loading = childEl.querySelector(".sibu-lazy-loading");
|
|
2764
3448
|
if (!loading) {
|
|
2765
|
-
observer
|
|
3449
|
+
observer?.disconnect();
|
|
3450
|
+
observer = null;
|
|
2766
3451
|
container.replaceChildren(childEl);
|
|
2767
3452
|
}
|
|
2768
3453
|
});
|
|
2769
3454
|
observer.observe(childEl, { childList: true, subtree: true });
|
|
2770
|
-
if (!childEl.querySelector(".sibu-lazy-loading")) {
|
|
2771
|
-
container.replaceChildren(childEl);
|
|
2772
|
-
}
|
|
2773
3455
|
} else {
|
|
2774
3456
|
container.replaceChildren(childEl);
|
|
2775
3457
|
}
|
|
2776
|
-
} catch {
|
|
3458
|
+
} catch (err) {
|
|
3459
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
3460
|
+
devWarn(`[SibuJS] Suspense nodes() threw: ${errorObj.message}`);
|
|
3461
|
+
dispatchPropagate(container, errorObj);
|
|
2777
3462
|
}
|
|
2778
3463
|
});
|
|
2779
3464
|
return container;
|
|
2780
3465
|
}
|
|
2781
3466
|
|
|
3467
|
+
// src/platform/ssr.ts
|
|
3468
|
+
var _isDev10 = isDev();
|
|
3469
|
+
function trustHTML(html3) {
|
|
3470
|
+
return html3;
|
|
3471
|
+
}
|
|
3472
|
+
var DEFAULT_MAX_SSR_BYTES = 1024 * 1024;
|
|
3473
|
+
|
|
2782
3474
|
// src/components/ErrorDisplay.ts
|
|
2783
|
-
var
|
|
3475
|
+
var _isDev11 = isDev();
|
|
2784
3476
|
var STYLES = `
|
|
2785
3477
|
.sibu-error-display {
|
|
2786
3478
|
border: 1px solid var(--sibu-err-border, #e5484d);
|
|
@@ -2866,20 +3558,21 @@ var STYLES = `
|
|
|
2866
3558
|
font-weight: 600;
|
|
2867
3559
|
}
|
|
2868
3560
|
.sibu-error-display .sibu-err-copy-btn {
|
|
2869
|
-
background:
|
|
2870
|
-
border: 1px solid
|
|
3561
|
+
background: rgba(0, 0, 0, 0.22);
|
|
3562
|
+
border: 1px solid rgba(255, 255, 255, 0.15);
|
|
2871
3563
|
border-radius: 4px;
|
|
2872
|
-
color:
|
|
3564
|
+
color: rgba(255, 255, 255, 0.85);
|
|
2873
3565
|
cursor: pointer;
|
|
2874
3566
|
padding: 2px 10px;
|
|
2875
|
-
font-size: 0.
|
|
3567
|
+
font-size: 0.78em;
|
|
2876
3568
|
font-family: inherit;
|
|
2877
3569
|
transition: all 0.12s ease;
|
|
3570
|
+
flex-shrink: 0;
|
|
2878
3571
|
}
|
|
2879
3572
|
.sibu-error-display .sibu-err-copy-btn:hover {
|
|
2880
|
-
background:
|
|
2881
|
-
color:
|
|
2882
|
-
border-color:
|
|
3573
|
+
background: rgba(0, 0, 0, 0.35);
|
|
3574
|
+
color: white;
|
|
3575
|
+
border-color: rgba(255, 255, 255, 0.3);
|
|
2883
3576
|
}
|
|
2884
3577
|
|
|
2885
3578
|
.sibu-error-display .sibu-err-stack {
|
|
@@ -3004,21 +3697,25 @@ function normalizeError(err) {
|
|
|
3004
3697
|
cause: null
|
|
3005
3698
|
};
|
|
3006
3699
|
}
|
|
3007
|
-
function buildCopyText(err, meta2) {
|
|
3700
|
+
function buildCopyText(err, meta2, headline) {
|
|
3008
3701
|
const lines = [];
|
|
3702
|
+
lines.push(headline);
|
|
3009
3703
|
lines.push(`[${err.code}] ${err.message}`);
|
|
3010
3704
|
if (err.stack) {
|
|
3011
3705
|
lines.push("");
|
|
3706
|
+
lines.push("Stack Trace:");
|
|
3012
3707
|
lines.push(err.stack);
|
|
3013
3708
|
}
|
|
3014
|
-
|
|
3709
|
+
let cause = err.cause;
|
|
3710
|
+
while (cause) {
|
|
3015
3711
|
lines.push("");
|
|
3016
3712
|
lines.push("Caused by:");
|
|
3017
|
-
lines.push(` [${
|
|
3018
|
-
if (
|
|
3019
|
-
const indented =
|
|
3713
|
+
lines.push(` [${cause.code}] ${cause.message}`);
|
|
3714
|
+
if (cause.stack) {
|
|
3715
|
+
const indented = cause.stack.split("\n").map((l) => ` ${l}`).join("\n");
|
|
3020
3716
|
lines.push(indented);
|
|
3021
3717
|
}
|
|
3718
|
+
cause = cause.cause;
|
|
3022
3719
|
}
|
|
3023
3720
|
if (meta2 && Object.keys(meta2).length > 0) {
|
|
3024
3721
|
lines.push("");
|
|
@@ -3028,9 +3725,13 @@ function buildCopyText(err, meta2) {
|
|
|
3028
3725
|
}
|
|
3029
3726
|
}
|
|
3030
3727
|
lines.push("");
|
|
3031
|
-
lines.push(
|
|
3728
|
+
lines.push("Environment:");
|
|
3729
|
+
lines.push(` Timestamp: ${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
3730
|
+
if (typeof location !== "undefined") {
|
|
3731
|
+
lines.push(` URL: ${location.href}`);
|
|
3732
|
+
}
|
|
3032
3733
|
if (typeof navigator !== "undefined" && navigator.userAgent) {
|
|
3033
|
-
lines.push(`
|
|
3734
|
+
lines.push(` User Agent: ${navigator.userAgent}`);
|
|
3034
3735
|
}
|
|
3035
3736
|
return lines.join("\n");
|
|
3036
3737
|
}
|
|
@@ -3082,7 +3783,7 @@ function ErrorDisplay(props) {
|
|
|
3082
3783
|
injectStyles();
|
|
3083
3784
|
const severity = props.severity ?? "error";
|
|
3084
3785
|
const normalized = normalizeError(props.error);
|
|
3085
|
-
const showDetails = props.alwaysShowDetails ??
|
|
3786
|
+
const showDetails = props.alwaysShowDetails ?? _isDev11;
|
|
3086
3787
|
const headline = props.title ?? normalized.message;
|
|
3087
3788
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
|
|
3088
3789
|
const [copyLabel, setCopyLabel] = signal("Copy");
|
|
@@ -3091,7 +3792,7 @@ function ErrorDisplay(props) {
|
|
|
3091
3792
|
nodes: () => copyLabel(),
|
|
3092
3793
|
on: {
|
|
3093
3794
|
click: () => {
|
|
3094
|
-
const text2 = buildCopyText(normalized, props.metadata);
|
|
3795
|
+
const text2 = buildCopyText(normalized, props.metadata, headline);
|
|
3095
3796
|
if (typeof navigator !== "undefined" && navigator.clipboard) {
|
|
3096
3797
|
navigator.clipboard.writeText(text2).then(
|
|
3097
3798
|
() => {
|
|
@@ -3112,6 +3813,7 @@ function ErrorDisplay(props) {
|
|
|
3112
3813
|
nodes: [
|
|
3113
3814
|
code({ class: "sibu-err-icon", nodes: normalized.code }),
|
|
3114
3815
|
h3({ class: "sibu-err-title", nodes: headline }),
|
|
3816
|
+
copyBtn,
|
|
3115
3817
|
span({ class: "sibu-err-timestamp", nodes: timestamp })
|
|
3116
3818
|
]
|
|
3117
3819
|
});
|
|
@@ -3123,25 +3825,12 @@ function ErrorDisplay(props) {
|
|
|
3123
3825
|
nodes: [
|
|
3124
3826
|
div({
|
|
3125
3827
|
class: "sibu-err-section-head",
|
|
3126
|
-
nodes: [span({ nodes: "Stack Trace" })
|
|
3828
|
+
nodes: [span({ nodes: "Stack Trace" })]
|
|
3127
3829
|
}),
|
|
3128
3830
|
renderFrames(normalized.frames)
|
|
3129
3831
|
]
|
|
3130
3832
|
})
|
|
3131
3833
|
);
|
|
3132
|
-
} else if (showDetails) {
|
|
3133
|
-
bodyChildren.push(
|
|
3134
|
-
div({
|
|
3135
|
-
class: "sibu-err-section",
|
|
3136
|
-
nodes: [
|
|
3137
|
-
div({
|
|
3138
|
-
class: "sibu-err-section-head",
|
|
3139
|
-
nodes: [span({ nodes: "Details" }), copyBtn]
|
|
3140
|
-
}),
|
|
3141
|
-
div({ class: "sibu-err-stack", nodes: "(no stack available)" })
|
|
3142
|
-
]
|
|
3143
|
-
})
|
|
3144
|
-
);
|
|
3145
3834
|
}
|
|
3146
3835
|
if (showDetails) {
|
|
3147
3836
|
bodyChildren.push(...renderCauseChain(normalized.cause));
|
|
@@ -3157,37 +3846,6 @@ function ErrorDisplay(props) {
|
|
|
3157
3846
|
})
|
|
3158
3847
|
);
|
|
3159
3848
|
}
|
|
3160
|
-
if (showDetails && typeof navigator !== "undefined" && navigator.userAgent) {
|
|
3161
|
-
bodyChildren.push(
|
|
3162
|
-
div({
|
|
3163
|
-
class: "sibu-err-section",
|
|
3164
|
-
nodes: [
|
|
3165
|
-
div({ class: "sibu-err-section-head", nodes: [span({ nodes: "Environment" })] }),
|
|
3166
|
-
div({
|
|
3167
|
-
class: "sibu-err-meta",
|
|
3168
|
-
nodes: (() => {
|
|
3169
|
-
const dl2 = document.createElement("dl");
|
|
3170
|
-
dl2.className = "sibu-err-meta";
|
|
3171
|
-
const entries = [
|
|
3172
|
-
["User Agent", navigator.userAgent],
|
|
3173
|
-
["URL", typeof location !== "undefined" ? location.href : "(n/a)"],
|
|
3174
|
-
["Timestamp", (/* @__PURE__ */ new Date()).toISOString()]
|
|
3175
|
-
];
|
|
3176
|
-
for (const [k, v] of entries) {
|
|
3177
|
-
const dt2 = document.createElement("dt");
|
|
3178
|
-
dt2.textContent = k;
|
|
3179
|
-
const dd2 = document.createElement("dd");
|
|
3180
|
-
dd2.textContent = v;
|
|
3181
|
-
dl2.appendChild(dt2);
|
|
3182
|
-
dl2.appendChild(dd2);
|
|
3183
|
-
}
|
|
3184
|
-
return dl2;
|
|
3185
|
-
})()
|
|
3186
|
-
})
|
|
3187
|
-
]
|
|
3188
|
-
})
|
|
3189
|
-
);
|
|
3190
|
-
}
|
|
3191
3849
|
const actionButtons = [];
|
|
3192
3850
|
if (props.onRetry) {
|
|
3193
3851
|
actionButtons.push(
|
|
@@ -3382,6 +4040,7 @@ function injectStyles2() {
|
|
|
3382
4040
|
stylesInjected = true;
|
|
3383
4041
|
}
|
|
3384
4042
|
}
|
|
4043
|
+
var FALLBACK_CACHE_MAX = 50;
|
|
3385
4044
|
var fallbackCache = /* @__PURE__ */ new WeakMap();
|
|
3386
4045
|
function getMemoizedFallback(fallbackFn, error, retry) {
|
|
3387
4046
|
let cache2 = fallbackCache.get(fallbackFn);
|
|
@@ -3390,27 +4049,42 @@ function getMemoizedFallback(fallbackFn, error, retry) {
|
|
|
3390
4049
|
fallbackCache.set(fallbackFn, cache2);
|
|
3391
4050
|
}
|
|
3392
4051
|
const key = error.message;
|
|
3393
|
-
|
|
3394
|
-
|
|
4052
|
+
let factory = cache2.get(key);
|
|
4053
|
+
if (factory) {
|
|
4054
|
+
cache2.delete(key);
|
|
4055
|
+
cache2.set(key, factory);
|
|
4056
|
+
} else {
|
|
4057
|
+
factory = () => fallbackFn(error, retry);
|
|
4058
|
+
cache2.set(key, factory);
|
|
4059
|
+
if (cache2.size > FALLBACK_CACHE_MAX) {
|
|
4060
|
+
const oldestKey = cache2.keys().next().value;
|
|
4061
|
+
if (oldestKey !== void 0) cache2.delete(oldestKey);
|
|
4062
|
+
}
|
|
3395
4063
|
}
|
|
3396
|
-
return
|
|
4064
|
+
return factory();
|
|
3397
4065
|
}
|
|
3398
4066
|
function ErrorBoundary({ nodes, fallback, onError, resetKeys }) {
|
|
3399
4067
|
injectStyles2();
|
|
3400
4068
|
const [error, setError] = signal(null);
|
|
3401
4069
|
const retry = () => {
|
|
3402
4070
|
if (fallback) {
|
|
3403
|
-
|
|
4071
|
+
const cur = error();
|
|
4072
|
+
const inner = fallbackCache.get(fallback);
|
|
4073
|
+
if (cur && inner) inner.delete(cur.message);
|
|
3404
4074
|
}
|
|
3405
4075
|
setError(null);
|
|
3406
4076
|
};
|
|
4077
|
+
let resetKeysTeardown = null;
|
|
3407
4078
|
if (resetKeys && resetKeys.length > 0) {
|
|
3408
4079
|
let initialized = false;
|
|
3409
|
-
effect(() => {
|
|
4080
|
+
resetKeysTeardown = effect(() => {
|
|
3410
4081
|
for (const k of resetKeys) {
|
|
3411
4082
|
try {
|
|
3412
4083
|
k();
|
|
3413
|
-
} catch {
|
|
4084
|
+
} catch (err) {
|
|
4085
|
+
if (typeof console !== "undefined") {
|
|
4086
|
+
console.warn("[SibuJS ErrorBoundary] resetKeys getter threw:", err);
|
|
4087
|
+
}
|
|
3414
4088
|
}
|
|
3415
4089
|
}
|
|
3416
4090
|
if (!initialized) {
|
|
@@ -3423,7 +4097,15 @@ function ErrorBoundary({ nodes, fallback, onError, resetKeys }) {
|
|
|
3423
4097
|
const handleError = (e) => {
|
|
3424
4098
|
const errorObj = e instanceof Error ? e : new Error(String(e));
|
|
3425
4099
|
setError(errorObj);
|
|
3426
|
-
onError
|
|
4100
|
+
if (onError) {
|
|
4101
|
+
try {
|
|
4102
|
+
onError(errorObj);
|
|
4103
|
+
} catch (cbErr) {
|
|
4104
|
+
if (typeof console !== "undefined") {
|
|
4105
|
+
console.error("[SibuJS ErrorBoundary] onError callback threw:", cbErr);
|
|
4106
|
+
}
|
|
4107
|
+
}
|
|
4108
|
+
}
|
|
3427
4109
|
return errorObj;
|
|
3428
4110
|
};
|
|
3429
4111
|
const defaultFallback = (err, retryFn) => {
|
|
@@ -3475,7 +4157,7 @@ function ErrorBoundary({ nodes, fallback, onError, resetKeys }) {
|
|
|
3475
4157
|
}
|
|
3476
4158
|
}
|
|
3477
4159
|
});
|
|
3478
|
-
|
|
4160
|
+
const propagateListener = (e) => {
|
|
3479
4161
|
if (error()) return;
|
|
3480
4162
|
e.stopPropagation();
|
|
3481
4163
|
const customEvent = e;
|
|
@@ -3483,6 +4165,30 @@ function ErrorBoundary({ nodes, fallback, onError, resetKeys }) {
|
|
|
3483
4165
|
if (propagatedError) {
|
|
3484
4166
|
handleError(propagatedError);
|
|
3485
4167
|
}
|
|
4168
|
+
};
|
|
4169
|
+
container.addEventListener("sibu:error-propagate", propagateListener);
|
|
4170
|
+
onMount(() => {
|
|
4171
|
+
const walker = document.createTreeWalker(container, NodeFilter.SHOW_ELEMENT);
|
|
4172
|
+
const collected = [];
|
|
4173
|
+
let node = walker.currentNode;
|
|
4174
|
+
while (node) {
|
|
4175
|
+
const pending = takePendingError(node);
|
|
4176
|
+
if (pending) collected.push(pending);
|
|
4177
|
+
node = walker.nextNode();
|
|
4178
|
+
}
|
|
4179
|
+
if (collected.length === 1) {
|
|
4180
|
+
handleError(collected[0]);
|
|
4181
|
+
} else if (collected.length > 1) {
|
|
4182
|
+
const Agg = globalThis.AggregateError;
|
|
4183
|
+
handleError(
|
|
4184
|
+
Agg ? new Agg(collected, `${collected.length} pre-mount errors caught by ErrorBoundary`) : new Error(collected.map((e) => e.message).join("; "))
|
|
4185
|
+
);
|
|
4186
|
+
}
|
|
4187
|
+
return void 0;
|
|
4188
|
+
}, container);
|
|
4189
|
+
registerDisposer(container, () => {
|
|
4190
|
+
if (resetKeysTeardown) resetKeysTeardown();
|
|
4191
|
+
container.removeEventListener("sibu:error-propagate", propagateListener);
|
|
3486
4192
|
});
|
|
3487
4193
|
return container;
|
|
3488
4194
|
}
|
|
@@ -3658,6 +4364,7 @@ function Loading(props = {}) {
|
|
|
3658
4364
|
footer,
|
|
3659
4365
|
form,
|
|
3660
4366
|
g,
|
|
4367
|
+
getSSRStore,
|
|
3661
4368
|
getSlot,
|
|
3662
4369
|
h1,
|
|
3663
4370
|
h2,
|
|
@@ -3730,6 +4437,7 @@ function Loading(props = {}) {
|
|
|
3730
4437
|
rp,
|
|
3731
4438
|
rt,
|
|
3732
4439
|
ruby,
|
|
4440
|
+
runInSSRContext,
|
|
3733
4441
|
s,
|
|
3734
4442
|
samp,
|
|
3735
4443
|
script,
|
|
@@ -3755,6 +4463,7 @@ function Loading(props = {}) {
|
|
|
3755
4463
|
symbol,
|
|
3756
4464
|
table,
|
|
3757
4465
|
tagFactory,
|
|
4466
|
+
takePendingError,
|
|
3758
4467
|
tbody,
|
|
3759
4468
|
td,
|
|
3760
4469
|
template,
|
|
@@ -3769,6 +4478,7 @@ function Loading(props = {}) {
|
|
|
3769
4478
|
track,
|
|
3770
4479
|
transition,
|
|
3771
4480
|
trapFocus,
|
|
4481
|
+
trustHTML,
|
|
3772
4482
|
tspan,
|
|
3773
4483
|
u,
|
|
3774
4484
|
ul,
|