sibujs 3.4.0 → 4.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/LICENSE +21 -21
- package/README.md +118 -15
- package/dist/browser.cjs +410 -101
- package/dist/browser.d.cts +50 -5
- package/dist/browser.d.ts +50 -5
- package/dist/browser.js +8 -6
- package/dist/build.cjs +777 -385
- package/dist/build.js +15 -15
- package/dist/cdn.global.js +11 -7
- package/dist/{chunk-JCO7AHNU.js → chunk-3EKJK5FZ.js} +73 -34
- package/dist/chunk-4MFZMLUU.js +147 -0
- package/dist/chunk-52XFPGSN.js +123 -0
- package/dist/chunk-5INI7D2L.js +194 -0
- package/dist/{chunk-OAVXAFAY.js → chunk-6LG2T7LO.js} +5 -5
- package/dist/{chunk-OOUQUCNN.js → chunk-ACBT6UZS.js} +57 -22
- package/dist/{chunk-F7HW2NI5.js → chunk-AW6HPJ3L.js} +1 -1
- package/dist/chunk-DHDZ7IVN.js +109 -0
- package/dist/{chunk-JNGGM2XE.js → chunk-DQVUBVNX.js} +16 -25
- package/dist/{chunk-AXFWGY32.js → chunk-DR7H6UGM.js} +232 -67
- package/dist/{chunk-WSGLJYFI.js → chunk-E62UADKL.js} +9 -3
- package/dist/{chunk-3Z2NGWQI.js → chunk-ES2GERY2.js} +1 -1
- package/dist/{chunk-S3V6ZXPI.js → chunk-EWEE7NBF.js} +115 -41
- package/dist/{chunk-3DVGCW7O.js → chunk-F64ZPCFE.js} +8 -8
- package/dist/{chunk-APFRCIRI.js → chunk-GCSGGA3Q.js} +295 -198
- package/dist/{chunk-EX77FXTT.js → chunk-HYCCIYNS.js} +228 -51
- package/dist/{chunk-ELXMRSVN.js → chunk-NF3LYCQH.js} +259 -124
- package/dist/chunk-O3QQ3XOL.js +61 -0
- package/dist/{chunk-BUKYCWHX.js → chunk-PBQEW5VW.js} +14 -10
- package/dist/{chunk-H5FI5WDP.js → chunk-RRIDJQ5C.js} +3 -3
- package/dist/{chunk-S3NFJO6L.js → chunk-TIRZCERI.js} +36 -5
- package/dist/{chunk-ODXVQ3CS.js → chunk-VFHIVEPF.js} +309 -188
- package/dist/chunk-VPP2FONR.js +142 -0
- package/dist/{chunk-KZBEVFXZ.js → chunk-W55YHPEP.js} +5 -3
- package/dist/{chunk-FKQG7FTY.js → chunk-WN6WDFCB.js} +4 -4
- package/dist/{chunk-CEBWDD63.js → chunk-WOOMUJFT.js} +228 -86
- package/dist/{chunk-ITWCTZYH.js → chunk-Z2CE42DB.js} +19 -25
- package/dist/{contracts-ey_Qh8ef.d.cts → contracts-Hg6ITAEF.d.cts} +6 -6
- package/dist/{contracts-ey_Qh8ef.d.ts → contracts-Hg6ITAEF.d.ts} +6 -6
- package/dist/{customElement-CPfIrbvg.d.ts → customElement-CKLoO63w.d.cts} +73 -11
- package/dist/{customElement-CPfIrbvg.d.cts → customElement-CKLoO63w.d.ts} +73 -11
- package/dist/data.cjs +483 -205
- package/dist/data.d.cts +139 -7
- package/dist/data.d.ts +139 -7
- package/dist/data.js +9 -9
- package/dist/devtools.cjs +222 -87
- package/dist/devtools.js +8 -8
- package/dist/dispose-4FZ6OFXR.js +19 -0
- package/dist/ecosystem.cjs +419 -175
- package/dist/ecosystem.js +11 -11
- package/dist/extras.cjs +1981 -765
- package/dist/extras.d.cts +7 -7
- package/dist/extras.d.ts +7 -7
- package/dist/extras.js +29 -26
- package/dist/index.cjs +784 -385
- package/dist/index.d.cts +299 -28
- package/dist/index.d.ts +299 -28
- package/dist/index.js +33 -18
- package/dist/motion.cjs +180 -50
- package/dist/motion.d.cts +26 -0
- package/dist/motion.d.ts +26 -0
- package/dist/motion.js +5 -5
- package/dist/patterns.cjs +437 -170
- package/dist/patterns.d.cts +60 -13
- package/dist/patterns.d.ts +60 -13
- package/dist/patterns.js +7 -7
- package/dist/performance.cjs +333 -148
- package/dist/performance.d.cts +55 -7
- package/dist/performance.d.ts +55 -7
- package/dist/performance.js +9 -9
- package/dist/plugins.cjs +1374 -576
- package/dist/plugins.d.cts +227 -9
- package/dist/plugins.d.ts +227 -9
- package/dist/plugins.js +613 -321
- package/dist/{ssr-D62yFwuw.d.cts → ssr-BiPRdZ6n.d.cts} +44 -15
- package/dist/{ssr-D62yFwuw.d.ts → ssr-BiPRdZ6n.d.ts} +44 -15
- package/dist/{ssr-2PPULEK2.js → ssr-JFP5535P.js} +5 -4
- package/dist/ssr.cjs +1104 -443
- package/dist/ssr.d.cts +230 -20
- package/dist/ssr.d.ts +230 -20
- package/dist/ssr.js +15 -12
- package/dist/{startup-0Qv6aosO.d.cts → startup-BMpaiMhP.d.cts} +1 -1
- package/dist/{startup-0Qv6aosO.d.ts → startup-BMpaiMhP.d.ts} +1 -1
- package/dist/testing.cjs +205 -63
- package/dist/testing.d.cts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +8 -10
- package/dist/ui.cjs +640 -199
- package/dist/ui.d.cts +2 -2
- package/dist/ui.d.ts +2 -2
- package/dist/ui.js +10 -10
- package/dist/widgets.cjs +207 -82
- package/dist/widgets.js +9 -9
- package/package.json +12 -7
- package/dist/chunk-5VGSK6D2.js +0 -80
- package/dist/chunk-COY6PUD2.js +0 -34
- package/dist/chunk-K35BAR4P.js +0 -96
- package/dist/chunk-L3GAGWCC.js +0 -111
- package/dist/chunk-RT3IYFN2.js +0 -38
package/dist/build.cjs
CHANGED
|
@@ -1063,8 +1063,9 @@ __export(index_exports, {
|
|
|
1063
1063
|
Fragment: () => Fragment,
|
|
1064
1064
|
KeepAlive: () => KeepAlive,
|
|
1065
1065
|
Loading: () => Loading,
|
|
1066
|
+
MAX_DRAIN_TEARDOWNS: () => MAX_DRAIN_TEARDOWNS,
|
|
1066
1067
|
Portal: () => Portal,
|
|
1067
|
-
SVG_NS: () =>
|
|
1068
|
+
SVG_NS: () => SVG_NS2,
|
|
1068
1069
|
Suspense: () => Suspense,
|
|
1069
1070
|
__resetIdCounter: () => __resetIdCounter,
|
|
1070
1071
|
a: () => a,
|
|
@@ -1140,6 +1141,7 @@ __export(index_exports, {
|
|
|
1140
1141
|
g: () => g,
|
|
1141
1142
|
getAction: () => getAction,
|
|
1142
1143
|
getRequestScopedCache: () => getRequestScopedCache,
|
|
1144
|
+
getRuntimeErrorHandler: () => getRuntimeErrorHandler,
|
|
1143
1145
|
getSSRStore: () => getSSRStore,
|
|
1144
1146
|
getSlot: () => getSlot,
|
|
1145
1147
|
h1: () => h1,
|
|
@@ -1213,6 +1215,9 @@ __export(index_exports, {
|
|
|
1213
1215
|
registerComponent: () => registerComponent,
|
|
1214
1216
|
registerDisposer: () => registerDisposer,
|
|
1215
1217
|
registerIsland: () => registerIsland,
|
|
1218
|
+
replaceChildrenSafely: () => replaceChildrenSafely,
|
|
1219
|
+
reportDrainRunaway: () => reportDrainRunaway,
|
|
1220
|
+
reportError: () => reportError,
|
|
1216
1221
|
resolveComponent: () => resolveComponent,
|
|
1217
1222
|
retrack: () => retrack2,
|
|
1218
1223
|
rp: () => rp,
|
|
@@ -1226,6 +1231,7 @@ __export(index_exports, {
|
|
|
1226
1231
|
select: () => select,
|
|
1227
1232
|
setGlobalErrorHandler: () => setGlobalErrorHandler,
|
|
1228
1233
|
setMaxDrainIterations: () => setMaxDrainIterations2,
|
|
1234
|
+
setRuntimeErrorHandler: () => setRuntimeErrorHandler,
|
|
1229
1235
|
show: () => show,
|
|
1230
1236
|
signal: () => signal,
|
|
1231
1237
|
slot: () => slot,
|
|
@@ -1265,6 +1271,7 @@ __export(index_exports, {
|
|
|
1265
1271
|
u: () => u,
|
|
1266
1272
|
ul: () => ul,
|
|
1267
1273
|
unregisterComponent: () => unregisterComponent,
|
|
1274
|
+
unregisterDisposer: () => unregisterDisposer,
|
|
1268
1275
|
unregisterIsland: () => unregisterIsland,
|
|
1269
1276
|
untracked: () => untracked2,
|
|
1270
1277
|
use: () => use,
|
|
@@ -1276,6 +1283,103 @@ __export(index_exports, {
|
|
|
1276
1283
|
writable: () => writable
|
|
1277
1284
|
});
|
|
1278
1285
|
|
|
1286
|
+
// src/core/errors.ts
|
|
1287
|
+
var ERROR_STATE_KEY = /* @__PURE__ */ Symbol.for("sibujs.runtime-errors.v1");
|
|
1288
|
+
function state() {
|
|
1289
|
+
const g2 = globalThis;
|
|
1290
|
+
const existing = g2[ERROR_STATE_KEY];
|
|
1291
|
+
if (existing) return existing;
|
|
1292
|
+
const created = { handler: null, handlerDepth: 0 };
|
|
1293
|
+
g2[ERROR_STATE_KEY] = created;
|
|
1294
|
+
return created;
|
|
1295
|
+
}
|
|
1296
|
+
function setRuntimeErrorHandler(handler) {
|
|
1297
|
+
const s2 = state();
|
|
1298
|
+
const prev = s2.handler;
|
|
1299
|
+
s2.handler = handler;
|
|
1300
|
+
return prev;
|
|
1301
|
+
}
|
|
1302
|
+
function getRuntimeErrorHandler() {
|
|
1303
|
+
return state().handler;
|
|
1304
|
+
}
|
|
1305
|
+
function normalizeError(value) {
|
|
1306
|
+
if (value instanceof Error) return value;
|
|
1307
|
+
const message = typeof value === "string" ? value : `Non-Error value thrown: ${safeStringify(value)}`;
|
|
1308
|
+
return new Error(message, { cause: value });
|
|
1309
|
+
}
|
|
1310
|
+
function safeStringify(value) {
|
|
1311
|
+
if (typeof value === "symbol") return value.toString();
|
|
1312
|
+
try {
|
|
1313
|
+
return typeof value === "object" && value !== null ? JSON.stringify(value) : String(value);
|
|
1314
|
+
} catch {
|
|
1315
|
+
return Object.prototype.toString.call(value);
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
function describe(context2) {
|
|
1319
|
+
return context2.name ? `${context2.phase} "${context2.name}"` : context2.phase;
|
|
1320
|
+
}
|
|
1321
|
+
var REACTIVE_REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
|
|
1322
|
+
function untrackedRun(fn) {
|
|
1323
|
+
const api = globalThis[REACTIVE_REGISTRY_KEY];
|
|
1324
|
+
return api?.untracked ? api.untracked(fn) : fn();
|
|
1325
|
+
}
|
|
1326
|
+
var PROPAGATE_EVENT = "sibu:error-propagate";
|
|
1327
|
+
function claimedByBoundary(error, context2) {
|
|
1328
|
+
const raw = context2.node;
|
|
1329
|
+
if (!raw || typeof CustomEvent === "undefined") return false;
|
|
1330
|
+
const target = resolveEventTarget(raw);
|
|
1331
|
+
if (!target) return false;
|
|
1332
|
+
try {
|
|
1333
|
+
const event = new CustomEvent(PROPAGATE_EVENT, {
|
|
1334
|
+
bubbles: true,
|
|
1335
|
+
cancelable: true,
|
|
1336
|
+
detail: { error, context: context2 }
|
|
1337
|
+
});
|
|
1338
|
+
return target.dispatchEvent(event) === false;
|
|
1339
|
+
} catch {
|
|
1340
|
+
return false;
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
function resolveEventTarget(node) {
|
|
1344
|
+
const ELEMENT_NODE = 1;
|
|
1345
|
+
let current = node;
|
|
1346
|
+
while (current) {
|
|
1347
|
+
if (current.nodeType === ELEMENT_NODE && typeof current.dispatchEvent === "function") {
|
|
1348
|
+
return current;
|
|
1349
|
+
}
|
|
1350
|
+
current = current.parentNode;
|
|
1351
|
+
}
|
|
1352
|
+
const self = node;
|
|
1353
|
+
return typeof self.dispatchEvent === "function" ? self : null;
|
|
1354
|
+
}
|
|
1355
|
+
function defaultReport(error, context2) {
|
|
1356
|
+
if (typeof console === "undefined") return;
|
|
1357
|
+
console.error(`[SibuJS] Uncaught error during ${describe(context2)}: ${error.message}`, error);
|
|
1358
|
+
}
|
|
1359
|
+
function reportError(error, context2) {
|
|
1360
|
+
const err = normalizeError(error);
|
|
1361
|
+
untrackedRun(() => {
|
|
1362
|
+
if (claimedByBoundary(err, context2)) return;
|
|
1363
|
+
const s2 = state();
|
|
1364
|
+
const handler = s2.handler;
|
|
1365
|
+
if (handler && s2.handlerDepth === 0) {
|
|
1366
|
+
s2.handlerDepth++;
|
|
1367
|
+
try {
|
|
1368
|
+
handler(error instanceof Error ? error : err, context2);
|
|
1369
|
+
return;
|
|
1370
|
+
} catch (handlerError) {
|
|
1371
|
+
if (typeof console !== "undefined") {
|
|
1372
|
+
const detail = handlerError instanceof Error ? handlerError.message : String(handlerError);
|
|
1373
|
+
console.error(`[SibuJS] runtime error handler itself threw: ${detail}`, handlerError);
|
|
1374
|
+
}
|
|
1375
|
+
} finally {
|
|
1376
|
+
s2.handlerDepth--;
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
defaultReport(err, context2);
|
|
1380
|
+
});
|
|
1381
|
+
}
|
|
1382
|
+
|
|
1279
1383
|
// src/core/dev.ts
|
|
1280
1384
|
function isDev() {
|
|
1281
1385
|
return typeof globalThis.__SIBU_DEV__ !== "undefined" ? !!globalThis.__SIBU_DEV__ : (
|
|
@@ -1300,6 +1404,14 @@ function devWarn(message) {
|
|
|
1300
1404
|
|
|
1301
1405
|
// src/core/rendering/dispose.ts
|
|
1302
1406
|
var elementDisposers = /* @__PURE__ */ new WeakMap();
|
|
1407
|
+
var MAX_DRAIN_TEARDOWNS = 1e4;
|
|
1408
|
+
function reportDrainRunaway(label2, executed, remaining) {
|
|
1409
|
+
if (typeof console === "undefined") return;
|
|
1410
|
+
console.error(
|
|
1411
|
+
`[SibuJS ${label2}] runaway cleanup: stopped after running ${executed} teardowns with ${remaining} still queued. Cleanup production did not stabilize before the teardown safety ceiling was reached \u2014 the remaining work was NOT run.`,
|
|
1412
|
+
{ executed, remaining }
|
|
1413
|
+
);
|
|
1414
|
+
}
|
|
1303
1415
|
var _isDev2 = isDev();
|
|
1304
1416
|
var activeBindingCount = 0;
|
|
1305
1417
|
function registerDisposer(node, teardown) {
|
|
@@ -1311,6 +1423,15 @@ function registerDisposer(node, teardown) {
|
|
|
1311
1423
|
disposers.push(teardown);
|
|
1312
1424
|
if (_isDev2) activeBindingCount++;
|
|
1313
1425
|
}
|
|
1426
|
+
function unregisterDisposer(node, teardown) {
|
|
1427
|
+
const disposers = elementDisposers.get(node);
|
|
1428
|
+
if (!disposers) return;
|
|
1429
|
+
const index = disposers.indexOf(teardown);
|
|
1430
|
+
if (index === -1) return;
|
|
1431
|
+
disposers.splice(index, 1);
|
|
1432
|
+
if (_isDev2) activeBindingCount--;
|
|
1433
|
+
if (disposers.length === 0) elementDisposers.delete(node);
|
|
1434
|
+
}
|
|
1314
1435
|
function dispose(node) {
|
|
1315
1436
|
const stack = [node];
|
|
1316
1437
|
const order = [];
|
|
@@ -1324,40 +1445,47 @@ function dispose(node) {
|
|
|
1324
1445
|
}
|
|
1325
1446
|
for (let i2 = order.length - 1; i2 >= 0; i2--) {
|
|
1326
1447
|
const current = order[i2];
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
d();
|
|
1335
|
-
} catch (err) {
|
|
1336
|
-
if (_isDev2 && typeof console !== "undefined") {
|
|
1337
|
-
console.warn("[SibuJS] Disposer threw during cleanup:", err);
|
|
1338
|
-
}
|
|
1339
|
-
}
|
|
1340
|
-
}
|
|
1341
|
-
let extraPasses = 0;
|
|
1342
|
-
while (extraPasses++ < 8) {
|
|
1343
|
-
const added = elementDisposers.get(current);
|
|
1344
|
-
if (!added || added.length === 0) break;
|
|
1345
|
-
const moreSnapshot = added.slice();
|
|
1448
|
+
if (elementDisposers.has(current)) {
|
|
1449
|
+
let executed = 0;
|
|
1450
|
+
let runaway = false;
|
|
1451
|
+
while (!runaway) {
|
|
1452
|
+
const pending = elementDisposers.get(current);
|
|
1453
|
+
if (!pending || pending.length === 0) break;
|
|
1454
|
+
const snapshot = pending.slice();
|
|
1346
1455
|
elementDisposers.delete(current);
|
|
1347
|
-
if (_isDev2) activeBindingCount -=
|
|
1348
|
-
for (
|
|
1456
|
+
if (_isDev2) activeBindingCount -= snapshot.length;
|
|
1457
|
+
for (let i3 = 0; i3 < snapshot.length; i3++) {
|
|
1458
|
+
if (executed >= MAX_DRAIN_TEARDOWNS) {
|
|
1459
|
+
const rest = snapshot.slice(i3);
|
|
1460
|
+
const added = elementDisposers.get(current);
|
|
1461
|
+
elementDisposers.set(current, added ? rest.concat(added) : rest);
|
|
1462
|
+
if (_isDev2) activeBindingCount += rest.length;
|
|
1463
|
+
reportDrainRunaway("dispose", executed, rest.length + (added?.length ?? 0));
|
|
1464
|
+
runaway = true;
|
|
1465
|
+
break;
|
|
1466
|
+
}
|
|
1467
|
+
executed++;
|
|
1349
1468
|
try {
|
|
1350
|
-
|
|
1469
|
+
snapshot[i3]();
|
|
1351
1470
|
} catch (err) {
|
|
1352
|
-
|
|
1353
|
-
console.warn("[SibuJS] Disposer threw during cleanup:", err);
|
|
1354
|
-
}
|
|
1471
|
+
reportError(err, { phase: "cleanup", name: "disposer" });
|
|
1355
1472
|
}
|
|
1356
1473
|
}
|
|
1357
1474
|
}
|
|
1358
1475
|
}
|
|
1359
1476
|
}
|
|
1360
1477
|
}
|
|
1478
|
+
function replaceChildrenSafely(parent, ...next) {
|
|
1479
|
+
for (let i2 = 0; i2 < next.length; i2++) {
|
|
1480
|
+
const node = next[i2];
|
|
1481
|
+
node.parentNode?.removeChild(node);
|
|
1482
|
+
}
|
|
1483
|
+
const current = Array.from(parent.childNodes);
|
|
1484
|
+
for (let i2 = 0; i2 < current.length; i2++) {
|
|
1485
|
+
dispose(current[i2]);
|
|
1486
|
+
}
|
|
1487
|
+
parent.replaceChildren(...next);
|
|
1488
|
+
}
|
|
1361
1489
|
function checkLeaks(warnThreshold = 0) {
|
|
1362
1490
|
if (!_isDev2) return 0;
|
|
1363
1491
|
if (warnThreshold > 0 && activeBindingCount > warnThreshold) {
|
|
@@ -1378,10 +1506,12 @@ function isEventHandlerAttr(name) {
|
|
|
1378
1506
|
return lower[0] === "o" && lower[1] === "n" && lower.charCodeAt(2) >= 97 && lower.charCodeAt(2) <= 122;
|
|
1379
1507
|
}
|
|
1380
1508
|
var SAFE_URL_PROTOCOLS = ["http:", "https:", "mailto:", "tel:", "ftp:"];
|
|
1509
|
+
var OUTER_TRIM = /^[\x00-\x20\x7f-\x9f]+|[\x00-\x20\x7f-\x9f]+$/g;
|
|
1381
1510
|
function sanitizeUrl(url) {
|
|
1382
|
-
const
|
|
1383
|
-
if (!
|
|
1384
|
-
const
|
|
1511
|
+
const probe = stripControlChars(url).trim();
|
|
1512
|
+
if (!probe) return "";
|
|
1513
|
+
const output2 = url.replace(OUTER_TRIM, "");
|
|
1514
|
+
const lower = probe.toLowerCase();
|
|
1385
1515
|
let schemeEnd = -1;
|
|
1386
1516
|
for (let i2 = 0; i2 < lower.length; i2++) {
|
|
1387
1517
|
const ch = lower.charCodeAt(i2);
|
|
@@ -1391,12 +1521,13 @@ function sanitizeUrl(url) {
|
|
|
1391
1521
|
}
|
|
1392
1522
|
if (ch === 47 || ch === 63 || ch === 35) break;
|
|
1393
1523
|
}
|
|
1394
|
-
if (schemeEnd === -1) return
|
|
1524
|
+
if (schemeEnd === -1) return output2;
|
|
1395
1525
|
const scheme = lower.slice(0, schemeEnd + 1);
|
|
1396
|
-
if (!/^[a-z][a-z0-9+.-]*:$/.test(scheme)) return
|
|
1526
|
+
if (!/^[a-z][a-z0-9+.-]*:$/.test(scheme)) return output2;
|
|
1397
1527
|
if (SAFE_URL_PROTOCOLS.indexOf(scheme) === -1) return "";
|
|
1398
|
-
return
|
|
1528
|
+
return output2;
|
|
1399
1529
|
}
|
|
1530
|
+
var SRCSET_DESCRIPTOR = /^\s+\d+(\.\d+)?[wx]$/;
|
|
1400
1531
|
function sanitizeSrcset(value) {
|
|
1401
1532
|
const parts = value.split(",");
|
|
1402
1533
|
const out = [];
|
|
@@ -1405,6 +1536,7 @@ function sanitizeSrcset(value) {
|
|
|
1405
1536
|
if (!part) continue;
|
|
1406
1537
|
const m = part.match(/^(\S+)(\s+.+)?$/);
|
|
1407
1538
|
if (!m) continue;
|
|
1539
|
+
if (m[2] !== void 0 && !SRCSET_DESCRIPTOR.test(m[2])) continue;
|
|
1408
1540
|
const safe = sanitizeUrl(m[1]);
|
|
1409
1541
|
if (!safe) continue;
|
|
1410
1542
|
out.push(m[2] ? `${safe}${m[2]}` : safe);
|
|
@@ -1412,23 +1544,83 @@ function sanitizeSrcset(value) {
|
|
|
1412
1544
|
return out.join(", ");
|
|
1413
1545
|
}
|
|
1414
1546
|
var CSS_DANGER_GATE = /[(:@\\]/;
|
|
1547
|
+
function isCssWhitespace(ch) {
|
|
1548
|
+
return ch === " " || ch === " " || ch === "\n" || ch === "\r" || ch === "\f";
|
|
1549
|
+
}
|
|
1550
|
+
function isHexDigit(ch) {
|
|
1551
|
+
return ch >= "0" && ch <= "9" || ch >= "a" && ch <= "f" || ch >= "A" && ch <= "F";
|
|
1552
|
+
}
|
|
1553
|
+
function decodeCssEscapes(value) {
|
|
1554
|
+
let out = "";
|
|
1555
|
+
for (let i2 = 0; i2 < value.length; i2++) {
|
|
1556
|
+
const ch = value[i2];
|
|
1557
|
+
if (ch !== "\\") {
|
|
1558
|
+
out += ch;
|
|
1559
|
+
continue;
|
|
1560
|
+
}
|
|
1561
|
+
if (i2 + 1 >= value.length) break;
|
|
1562
|
+
const next = value[i2 + 1];
|
|
1563
|
+
if (next === "\n" || next === "\f") {
|
|
1564
|
+
i2 += 1;
|
|
1565
|
+
continue;
|
|
1566
|
+
}
|
|
1567
|
+
if (next === "\r") {
|
|
1568
|
+
i2 += value[i2 + 2] === "\n" ? 2 : 1;
|
|
1569
|
+
continue;
|
|
1570
|
+
}
|
|
1571
|
+
if (isHexDigit(next)) {
|
|
1572
|
+
let hex = "";
|
|
1573
|
+
let j = i2 + 1;
|
|
1574
|
+
while (j < value.length && hex.length < 6 && isHexDigit(value[j])) {
|
|
1575
|
+
hex += value[j];
|
|
1576
|
+
j++;
|
|
1577
|
+
}
|
|
1578
|
+
if (j < value.length && isCssWhitespace(value[j])) {
|
|
1579
|
+
j += value[j] === "\r" && value[j + 1] === "\n" ? 2 : 1;
|
|
1580
|
+
}
|
|
1581
|
+
const code2 = Number.parseInt(hex, 16);
|
|
1582
|
+
const invalid = code2 === 0 || code2 > 1114111 || code2 >= 55296 && code2 <= 57343;
|
|
1583
|
+
out += invalid ? "\uFFFD" : String.fromCodePoint(code2);
|
|
1584
|
+
i2 = j - 1;
|
|
1585
|
+
continue;
|
|
1586
|
+
}
|
|
1587
|
+
out += next;
|
|
1588
|
+
i2 += 1;
|
|
1589
|
+
}
|
|
1590
|
+
return out;
|
|
1591
|
+
}
|
|
1415
1592
|
function sanitizeCSSValue(value) {
|
|
1416
1593
|
if (!CSS_DANGER_GATE.test(value)) return value;
|
|
1417
|
-
const
|
|
1418
|
-
|
|
1419
|
-
if (!Number.isFinite(code2) || code2 < 0 || code2 > 1114111) return "";
|
|
1420
|
-
try {
|
|
1421
|
-
return String.fromCodePoint(code2);
|
|
1422
|
-
} catch {
|
|
1423
|
-
return "";
|
|
1424
|
-
}
|
|
1425
|
-
});
|
|
1426
|
-
const lower = decoded.toLowerCase().replace(/\s+/g, "");
|
|
1594
|
+
const normalized = value.includes("\\") ? decodeCssEscapes(value) : value;
|
|
1595
|
+
const lower = normalized.toLowerCase().replace(/\s+/g, "");
|
|
1427
1596
|
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")) {
|
|
1428
1597
|
return "";
|
|
1429
1598
|
}
|
|
1430
1599
|
return value;
|
|
1431
1600
|
}
|
|
1601
|
+
function sanitizeStyleAttribute(cssText) {
|
|
1602
|
+
const input2 = String(cssText);
|
|
1603
|
+
if (input2.trim() === "") return "";
|
|
1604
|
+
if (typeof document === "undefined") {
|
|
1605
|
+
return sanitizeCSSValue(input2) === "" ? "" : input2;
|
|
1606
|
+
}
|
|
1607
|
+
const probe = document.createElement("div");
|
|
1608
|
+
try {
|
|
1609
|
+
probe.style.cssText = input2;
|
|
1610
|
+
} catch {
|
|
1611
|
+
return "";
|
|
1612
|
+
}
|
|
1613
|
+
const declarations = [];
|
|
1614
|
+
for (let i2 = 0; i2 < probe.style.length; i2++) {
|
|
1615
|
+
const property = probe.style[i2];
|
|
1616
|
+
const value = probe.style.getPropertyValue(property);
|
|
1617
|
+
if (sanitizeCSSValue(value) === "") continue;
|
|
1618
|
+
if (sanitizeCSSValue(`${property}:${value}`) === "") continue;
|
|
1619
|
+
const priority = probe.style.getPropertyPriority(property);
|
|
1620
|
+
declarations.push(`${property}: ${value}${priority ? ` !${priority}` : ""}`);
|
|
1621
|
+
}
|
|
1622
|
+
return declarations.join("; ");
|
|
1623
|
+
}
|
|
1432
1624
|
var URL_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
1433
1625
|
"href",
|
|
1434
1626
|
"xlink:href",
|
|
@@ -1441,20 +1633,101 @@ var URL_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
|
1441
1633
|
"background",
|
|
1442
1634
|
"srcset",
|
|
1443
1635
|
"ping",
|
|
1444
|
-
"data"
|
|
1636
|
+
"data",
|
|
1637
|
+
// `<html manifest>` is a URL sink too. It was carried only by the SSR
|
|
1638
|
+
// serializers' private copy of this set; folding that copy into this one would
|
|
1639
|
+
// otherwise have silently dropped its coverage.
|
|
1640
|
+
"manifest"
|
|
1445
1641
|
]);
|
|
1446
|
-
|
|
1447
|
-
|
|
1642
|
+
var HTML_CONTENT_ATTRIBUTES = /* @__PURE__ */ new Set(["srcdoc"]);
|
|
1643
|
+
function isHtmlContentAttribute(name) {
|
|
1644
|
+
return HTML_CONTENT_ATTRIBUTES.has(name.toLowerCase());
|
|
1448
1645
|
}
|
|
1449
1646
|
function sanitizeAttributeString(attr, value) {
|
|
1450
1647
|
const lower = attr.toLowerCase();
|
|
1451
1648
|
if (lower === "srcset") return sanitizeSrcset(value);
|
|
1452
1649
|
if (URL_ATTRIBUTES.has(lower)) return sanitizeUrl(value);
|
|
1650
|
+
if (lower === "style") return sanitizeStyleAttribute(value);
|
|
1453
1651
|
return value;
|
|
1454
1652
|
}
|
|
1455
1653
|
|
|
1456
|
-
// src/
|
|
1654
|
+
// src/utils/setSafeAttribute.ts
|
|
1457
1655
|
var _isDev3 = isDev();
|
|
1656
|
+
var HTML_NS = "http://www.w3.org/1999/xhtml";
|
|
1657
|
+
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
1658
|
+
var XLINK_NS = "http://www.w3.org/1999/xlink";
|
|
1659
|
+
var XML_NS = "http://www.w3.org/XML/1998/namespace";
|
|
1660
|
+
var BOOLEAN_IDL_ATTRS = /* @__PURE__ */ new Set(["checked", "disabled", "selected"]);
|
|
1661
|
+
function isHtmlElement(el) {
|
|
1662
|
+
return el.namespaceURI === null || el.namespaceURI === HTML_NS;
|
|
1663
|
+
}
|
|
1664
|
+
function setProp(el, key, val) {
|
|
1665
|
+
el[key] = val;
|
|
1666
|
+
}
|
|
1667
|
+
function namespaceFor(el, name) {
|
|
1668
|
+
if (el.namespaceURI !== SVG_NS) return null;
|
|
1669
|
+
const lower = name.toLowerCase();
|
|
1670
|
+
if (lower.startsWith("xlink:")) return XLINK_NS;
|
|
1671
|
+
if (lower.startsWith("xml:")) return XML_NS;
|
|
1672
|
+
return null;
|
|
1673
|
+
}
|
|
1674
|
+
function setSafeAttribute(el, name, value, options = {}) {
|
|
1675
|
+
const ns = namespaceFor(el, name);
|
|
1676
|
+
const localName = ns ? name.slice(name.indexOf(":") + 1) : name;
|
|
1677
|
+
if (isEventHandlerAttr(name)) {
|
|
1678
|
+
if (_isDev3) {
|
|
1679
|
+
devWarn(
|
|
1680
|
+
`${options.label ?? "setSafeAttribute"}: refusing to set event-handler attribute "${name}". Its value would be evaluated as JavaScript. Use on:{ ${name.slice(2)}: fn } instead.`
|
|
1681
|
+
);
|
|
1682
|
+
}
|
|
1683
|
+
if (ns) el.removeAttributeNS(ns, localName);
|
|
1684
|
+
else el.removeAttribute(name);
|
|
1685
|
+
return false;
|
|
1686
|
+
}
|
|
1687
|
+
if (value == null) {
|
|
1688
|
+
if (ns) el.removeAttributeNS(ns, localName);
|
|
1689
|
+
else el.removeAttribute(name);
|
|
1690
|
+
return true;
|
|
1691
|
+
}
|
|
1692
|
+
if (isHtmlContentAttribute(name)) {
|
|
1693
|
+
if (_isDev3) {
|
|
1694
|
+
devWarn(
|
|
1695
|
+
`${options.label ?? "setSafeAttribute"}: refusing to set "${name}". The browser parses this attribute as a nested HTML document, so a generic string value cannot be made safe \u2014 attribute escaping is undone before the parse. Build the frame's content another way.`
|
|
1696
|
+
);
|
|
1697
|
+
}
|
|
1698
|
+
if (ns) el.removeAttributeNS(ns, localName);
|
|
1699
|
+
else el.removeAttribute(name);
|
|
1700
|
+
return false;
|
|
1701
|
+
}
|
|
1702
|
+
const html3 = isHtmlElement(el);
|
|
1703
|
+
const idlName = html3 ? name.toLowerCase() : name;
|
|
1704
|
+
if (typeof value === "boolean") {
|
|
1705
|
+
if (html3 && BOOLEAN_IDL_ATTRS.has(idlName) && idlName in el) {
|
|
1706
|
+
setProp(el, idlName, value);
|
|
1707
|
+
} else if (value) {
|
|
1708
|
+
if (ns) el.setAttributeNS(ns, name, "");
|
|
1709
|
+
else el.setAttribute(name, "");
|
|
1710
|
+
} else if (ns) {
|
|
1711
|
+
el.removeAttributeNS(ns, localName);
|
|
1712
|
+
} else {
|
|
1713
|
+
el.removeAttribute(name);
|
|
1714
|
+
}
|
|
1715
|
+
return true;
|
|
1716
|
+
}
|
|
1717
|
+
const str = String(value);
|
|
1718
|
+
if (options.syncValueProperty !== false && html3 && (idlName === "value" || idlName === "checked") && idlName in el) {
|
|
1719
|
+
setProp(el, idlName, idlName === "checked" ? Boolean(value) : str);
|
|
1720
|
+
return true;
|
|
1721
|
+
}
|
|
1722
|
+
const safe = sanitizeAttributeString(name, str);
|
|
1723
|
+
const current = ns ? el.getAttributeNS(ns, localName) : el.getAttribute(name);
|
|
1724
|
+
if (current === safe) return true;
|
|
1725
|
+
if (ns) el.setAttributeNS(ns, name, safe);
|
|
1726
|
+
else el.setAttribute(name, safe);
|
|
1727
|
+
return true;
|
|
1728
|
+
}
|
|
1729
|
+
|
|
1730
|
+
// src/reactivity/track-core.ts
|
|
1458
1731
|
var POOL_MAX = 4096;
|
|
1459
1732
|
var nodePool = [];
|
|
1460
1733
|
function createNode() {
|
|
@@ -1462,6 +1735,7 @@ function createNode() {
|
|
|
1462
1735
|
sig: null,
|
|
1463
1736
|
sub: null,
|
|
1464
1737
|
epoch: 0,
|
|
1738
|
+
depVersion: 0,
|
|
1465
1739
|
sigPrev: null,
|
|
1466
1740
|
sigNext: null,
|
|
1467
1741
|
subPrev: null,
|
|
@@ -1546,8 +1820,27 @@ function safeInvoke(sub2) {
|
|
|
1546
1820
|
try {
|
|
1547
1821
|
sub2();
|
|
1548
1822
|
} catch (err) {
|
|
1549
|
-
|
|
1823
|
+
const s2 = sub2;
|
|
1824
|
+
reportError(err, { phase: s2._errorPhase ?? "effect", name: s2.__name, node: s2._errorNode });
|
|
1825
|
+
}
|
|
1826
|
+
}
|
|
1827
|
+
function depsChanged(sub2) {
|
|
1828
|
+
let node = sub2.depsHead ?? null;
|
|
1829
|
+
if (node === null) return true;
|
|
1830
|
+
while (node !== null) {
|
|
1831
|
+
const sig = node.sig;
|
|
1832
|
+
if (sig === null) return true;
|
|
1833
|
+
if (sig._d === true && sig._validate !== void 0) {
|
|
1834
|
+
try {
|
|
1835
|
+
sig._validate();
|
|
1836
|
+
} catch {
|
|
1837
|
+
return true;
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
if (node.depVersion !== sig.__v) return true;
|
|
1841
|
+
node = node.subNext;
|
|
1550
1842
|
}
|
|
1843
|
+
return false;
|
|
1551
1844
|
}
|
|
1552
1845
|
var suspendDepth = 0;
|
|
1553
1846
|
var trackingSuspended = false;
|
|
@@ -1629,7 +1922,7 @@ function track(effectFn, subscriber) {
|
|
|
1629
1922
|
const sub2 = subscriber;
|
|
1630
1923
|
return sub2._dispose ?? (sub2._dispose = () => cleanup(subscriber));
|
|
1631
1924
|
}
|
|
1632
|
-
function reactiveBinding(commit) {
|
|
1925
|
+
function reactiveBinding(commit, ownerNode) {
|
|
1633
1926
|
const run = () => {
|
|
1634
1927
|
const s2 = subscriber;
|
|
1635
1928
|
if (s2._disposed || s2._reentrant) return;
|
|
@@ -1645,13 +1938,17 @@ function reactiveBinding(commit) {
|
|
|
1645
1938
|
subscriber.depsTail = null;
|
|
1646
1939
|
subscriber._epoch = 0;
|
|
1647
1940
|
subscriber._structDirty = false;
|
|
1941
|
+
subscriber._hasComputedDep = false;
|
|
1648
1942
|
subscriber._runEpoch = 0;
|
|
1649
1943
|
subscriber._runs = 0;
|
|
1650
1944
|
subscriber._reentrant = false;
|
|
1651
1945
|
subscriber._disposed = false;
|
|
1946
|
+
subscriber._errorPhase = "binding";
|
|
1947
|
+
subscriber._errorNode = ownerNode;
|
|
1652
1948
|
run();
|
|
1653
1949
|
return subscriber._dispose ?? (subscriber._dispose = () => {
|
|
1654
1950
|
subscriber._disposed = true;
|
|
1951
|
+
subscriber._errorNode = void 0;
|
|
1655
1952
|
cleanup(subscriber);
|
|
1656
1953
|
});
|
|
1657
1954
|
}
|
|
@@ -1663,9 +1960,12 @@ function recordDependency(signal2) {
|
|
|
1663
1960
|
const active = sig.__activeNode ?? null;
|
|
1664
1961
|
if (active !== null && active.sub === sub2) {
|
|
1665
1962
|
active.epoch = epoch;
|
|
1963
|
+
active.depVersion = sig.__v ?? Number.NaN;
|
|
1666
1964
|
return;
|
|
1667
1965
|
}
|
|
1966
|
+
if (sig._validate !== void 0) sub2._hasComputedDep = true;
|
|
1668
1967
|
const node = allocNode(signal2, sub2, epoch);
|
|
1968
|
+
node.depVersion = sig.__v ?? Number.NaN;
|
|
1669
1969
|
node.prevActive = active;
|
|
1670
1970
|
sig.__activeNode = node;
|
|
1671
1971
|
linkSub(sub2, node);
|
|
@@ -1684,9 +1984,10 @@ function cleanup(subscriber) {
|
|
|
1684
1984
|
node = next;
|
|
1685
1985
|
}
|
|
1686
1986
|
}
|
|
1687
|
-
var maxSubscriberRepeats =
|
|
1987
|
+
var maxSubscriberRepeats = 1e3;
|
|
1688
1988
|
var maxDrainIterations = 1e6;
|
|
1689
1989
|
var drainEpoch = 0;
|
|
1990
|
+
var quarantined = /* @__PURE__ */ new Set();
|
|
1690
1991
|
function setMaxSubscriberRepeats(n) {
|
|
1691
1992
|
const prev = maxSubscriberRepeats;
|
|
1692
1993
|
if (Number.isFinite(n) && n > 0) maxSubscriberRepeats = Math.floor(n);
|
|
@@ -1708,19 +2009,21 @@ function tickRepeat(sub2) {
|
|
|
1708
2009
|
return s2._runs > maxSubscriberRepeats;
|
|
1709
2010
|
}
|
|
1710
2011
|
function cycleError(sub2) {
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
`
|
|
1715
|
-
)
|
|
1716
|
-
|
|
2012
|
+
const name = sub2.__name ?? "<unnamed>";
|
|
2013
|
+
reportError(
|
|
2014
|
+
new Error(
|
|
2015
|
+
`subscriber "${name}" fired more than ${maxSubscriberRepeats} times \u2014 likely a write-reads-self cycle between effects/signals. This subscriber is quarantined for the rest of this update; other pending work still runs.`
|
|
2016
|
+
),
|
|
2017
|
+
{ phase: "scheduler", name }
|
|
2018
|
+
);
|
|
1717
2019
|
}
|
|
1718
2020
|
function absoluteDrainError() {
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
`
|
|
1722
|
-
)
|
|
1723
|
-
|
|
2021
|
+
reportError(
|
|
2022
|
+
new Error(
|
|
2023
|
+
`Notification drain exceeded ${maxDrainIterations} iterations \u2014 absolute safety net tripped. Breaking to prevent infinite loop.`
|
|
2024
|
+
),
|
|
2025
|
+
{ phase: "scheduler" }
|
|
2026
|
+
);
|
|
1724
2027
|
}
|
|
1725
2028
|
function drainQueue() {
|
|
1726
2029
|
let i2 = 0;
|
|
@@ -1730,11 +2033,14 @@ function drainQueue() {
|
|
|
1730
2033
|
break;
|
|
1731
2034
|
}
|
|
1732
2035
|
const sub2 = pendingQueue[i2++];
|
|
2036
|
+
pendingSet.delete(sub2);
|
|
2037
|
+
if (quarantined.size > 0 && quarantined.has(sub2)) continue;
|
|
2038
|
+
if (sub2._hasComputedDep === true && !depsChanged(sub2)) continue;
|
|
1733
2039
|
if (tickRepeat(sub2)) {
|
|
1734
2040
|
cycleError(sub2);
|
|
1735
|
-
|
|
2041
|
+
quarantined.add(sub2);
|
|
2042
|
+
continue;
|
|
1736
2043
|
}
|
|
1737
|
-
pendingSet.delete(sub2);
|
|
1738
2044
|
safeInvoke(sub2);
|
|
1739
2045
|
}
|
|
1740
2046
|
}
|
|
@@ -1749,6 +2055,7 @@ function drainNotificationQueue() {
|
|
|
1749
2055
|
if (notifyDepth === 0) {
|
|
1750
2056
|
pendingQueue.length = 0;
|
|
1751
2057
|
pendingSet.clear();
|
|
2058
|
+
if (quarantined.size > 0) quarantined.clear();
|
|
1752
2059
|
}
|
|
1753
2060
|
}
|
|
1754
2061
|
}
|
|
@@ -1842,6 +2149,7 @@ function notifySubscribers(signal2) {
|
|
|
1842
2149
|
if (notifyDepth === 0) {
|
|
1843
2150
|
pendingQueue.length = 0;
|
|
1844
2151
|
pendingSet.clear();
|
|
2152
|
+
if (quarantined.size > 0) quarantined.clear();
|
|
1845
2153
|
}
|
|
1846
2154
|
}
|
|
1847
2155
|
}
|
|
@@ -1869,7 +2177,7 @@ function forEachSubscriber(signal2, visit) {
|
|
|
1869
2177
|
|
|
1870
2178
|
// src/reactivity/track.ts
|
|
1871
2179
|
var _isDev4 = isDev();
|
|
1872
|
-
var _runtimeVersion = true ? "
|
|
2180
|
+
var _runtimeVersion = true ? "4.0.0" : "dev";
|
|
1873
2181
|
var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
|
|
1874
2182
|
function resolveReactiveApi() {
|
|
1875
2183
|
const g2 = globalThis;
|
|
@@ -1926,16 +2234,9 @@ var getSubscriberDeps2 = API.getSubscriberDeps;
|
|
|
1926
2234
|
var forEachSubscriber2 = API.forEachSubscriber;
|
|
1927
2235
|
|
|
1928
2236
|
// src/reactivity/bindAttribute.ts
|
|
1929
|
-
var _isDev5 = isDev();
|
|
1930
|
-
function setProp(el, key, val) {
|
|
1931
|
-
el[key] = val;
|
|
1932
|
-
}
|
|
1933
2237
|
function bindAttribute(el, attr, getter) {
|
|
1934
2238
|
if (isEventHandlerAttr(attr)) {
|
|
1935
|
-
|
|
1936
|
-
devWarn(
|
|
1937
|
-
`bindAttribute: refusing to bind event-handler attribute "${attr}". Use on:{ ${attr.slice(2)}: fn } instead.`
|
|
1938
|
-
);
|
|
2239
|
+
setSafeAttribute(el, attr, "", { label: `bindAttribute("${attr}")` });
|
|
1939
2240
|
return () => {
|
|
1940
2241
|
};
|
|
1941
2242
|
}
|
|
@@ -1944,28 +2245,12 @@ function bindAttribute(el, attr, getter) {
|
|
|
1944
2245
|
try {
|
|
1945
2246
|
value = getter();
|
|
1946
2247
|
} catch (err) {
|
|
1947
|
-
|
|
1948
|
-
devWarn(`bindAttribute: getter for "${attr}" threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
2248
|
+
reportError(err, { phase: "binding", name: `bindAttribute("${attr}")`, node: el });
|
|
1949
2249
|
return;
|
|
1950
2250
|
}
|
|
1951
|
-
|
|
1952
|
-
if (attr in el && (attr === "checked" || attr === "disabled" || attr === "selected")) {
|
|
1953
|
-
setProp(el, attr, value);
|
|
1954
|
-
} else if (value) {
|
|
1955
|
-
el.setAttribute(attr, "");
|
|
1956
|
-
} else {
|
|
1957
|
-
el.removeAttribute(attr);
|
|
1958
|
-
}
|
|
1959
|
-
return;
|
|
1960
|
-
}
|
|
1961
|
-
const str = String(value);
|
|
1962
|
-
if ((attr === "value" || attr === "checked") && attr in el) {
|
|
1963
|
-
setProp(el, attr, attr === "checked" ? Boolean(value) : str);
|
|
1964
|
-
} else {
|
|
1965
|
-
el.setAttribute(attr, sanitizeAttributeString(attr, str));
|
|
1966
|
-
}
|
|
2251
|
+
setSafeAttribute(el, attr, value, { label: `bindAttribute("${attr}")` });
|
|
1967
2252
|
}
|
|
1968
|
-
return reactiveBinding2(commit);
|
|
2253
|
+
return reactiveBinding2(commit, el);
|
|
1969
2254
|
}
|
|
1970
2255
|
function bindDynamic(el, nameGetter, valueGetter) {
|
|
1971
2256
|
let prevName = null;
|
|
@@ -1974,29 +2259,24 @@ function bindDynamic(el, nameGetter, valueGetter) {
|
|
|
1974
2259
|
try {
|
|
1975
2260
|
name = typeof nameGetter === "function" ? nameGetter() : nameGetter;
|
|
1976
2261
|
} catch (err) {
|
|
1977
|
-
|
|
2262
|
+
reportError(err, { phase: "binding", name: "bindDynamic (name getter)", node: el });
|
|
1978
2263
|
return;
|
|
1979
2264
|
}
|
|
1980
2265
|
let value;
|
|
1981
2266
|
try {
|
|
1982
2267
|
value = typeof valueGetter === "function" ? valueGetter() : valueGetter;
|
|
1983
2268
|
} catch (err) {
|
|
1984
|
-
|
|
2269
|
+
reportError(err, { phase: "binding", name: "bindDynamic (value getter)", node: el });
|
|
1985
2270
|
return;
|
|
1986
2271
|
}
|
|
1987
|
-
if (isEventHandlerAttr(name)) return;
|
|
1988
2272
|
if (prevName !== null && prevName !== name) {
|
|
1989
2273
|
el.removeAttribute(prevName);
|
|
2274
|
+
prevName = null;
|
|
1990
2275
|
}
|
|
1991
|
-
|
|
1992
|
-
if ((name === "value" || name === "checked") && name in el) {
|
|
1993
|
-
setProp(el, name, name === "checked" ? Boolean(value) : str);
|
|
1994
|
-
} else {
|
|
1995
|
-
el.setAttribute(name, sanitizeAttributeString(name, str));
|
|
1996
|
-
}
|
|
2276
|
+
if (!setSafeAttribute(el, name, value, { label: "bindDynamic" })) return;
|
|
1997
2277
|
prevName = name;
|
|
1998
2278
|
}
|
|
1999
|
-
const teardown = reactiveBinding2(commit);
|
|
2279
|
+
const teardown = reactiveBinding2(commit, el);
|
|
2000
2280
|
return () => {
|
|
2001
2281
|
teardown();
|
|
2002
2282
|
if (prevName !== null) {
|
|
@@ -2006,7 +2286,7 @@ function bindDynamic(el, nameGetter, valueGetter) {
|
|
|
2006
2286
|
}
|
|
2007
2287
|
|
|
2008
2288
|
// src/reactivity/bindChildNode.ts
|
|
2009
|
-
var
|
|
2289
|
+
var _isDev5 = isDev();
|
|
2010
2290
|
function bindChildNode(placeholder, getter) {
|
|
2011
2291
|
let lastNodes = [];
|
|
2012
2292
|
function commit() {
|
|
@@ -2014,7 +2294,7 @@ function bindChildNode(placeholder, getter) {
|
|
|
2014
2294
|
try {
|
|
2015
2295
|
result = getter();
|
|
2016
2296
|
} catch (err) {
|
|
2017
|
-
|
|
2297
|
+
reportError(err, { phase: "binding", name: "bindChildNode", node: placeholder });
|
|
2018
2298
|
return;
|
|
2019
2299
|
}
|
|
2020
2300
|
if (result == null || typeof result === "boolean") {
|
|
@@ -2040,7 +2320,7 @@ function bindChildNode(placeholder, getter) {
|
|
|
2040
2320
|
if (item == null || typeof item === "boolean") continue;
|
|
2041
2321
|
const node = item instanceof Node ? item : document.createTextNode(String(item));
|
|
2042
2322
|
if (seen.has(node)) {
|
|
2043
|
-
if (
|
|
2323
|
+
if (_isDev5)
|
|
2044
2324
|
devWarn("bindChildNode: duplicate node reference in array \u2014 only the first occurrence is rendered.");
|
|
2045
2325
|
continue;
|
|
2046
2326
|
}
|
|
@@ -2075,12 +2355,12 @@ function bindChildNode(placeholder, getter) {
|
|
|
2075
2355
|
}
|
|
2076
2356
|
lastNodes = newNodes;
|
|
2077
2357
|
}
|
|
2078
|
-
return reactiveBinding2(commit);
|
|
2358
|
+
return reactiveBinding2(commit, placeholder);
|
|
2079
2359
|
}
|
|
2080
2360
|
|
|
2081
2361
|
// src/core/rendering/tagFactory.ts
|
|
2082
|
-
var
|
|
2083
|
-
var
|
|
2362
|
+
var SVG_NS2 = "http://www.w3.org/2000/svg";
|
|
2363
|
+
var _isDev6 = isDev();
|
|
2084
2364
|
var BLOCKED_TAGS = /* @__PURE__ */ new Set(["script", "iframe", "object", "embed", "frame", "frameset"]);
|
|
2085
2365
|
function isBlockedTag(tag) {
|
|
2086
2366
|
return BLOCKED_TAGS.has(tag.toLowerCase());
|
|
@@ -2098,9 +2378,6 @@ var CLOBBER_RISKY_IDS = /* @__PURE__ */ new Set([
|
|
|
2098
2378
|
"self",
|
|
2099
2379
|
"frames"
|
|
2100
2380
|
]);
|
|
2101
|
-
function setProp2(el, key, val) {
|
|
2102
|
-
el[key] = val;
|
|
2103
|
-
}
|
|
2104
2381
|
function looksLikeClassList(s2) {
|
|
2105
2382
|
const t = s2.trim();
|
|
2106
2383
|
if (!t) return false;
|
|
@@ -2124,13 +2401,13 @@ function toKebab(prop) {
|
|
|
2124
2401
|
function applyStyle(el, style2) {
|
|
2125
2402
|
if (typeof style2 === "function") {
|
|
2126
2403
|
const teardown = track2(() => {
|
|
2127
|
-
el.setAttribute("style", style2());
|
|
2404
|
+
el.setAttribute("style", sanitizeStyleAttribute(String(style2())));
|
|
2128
2405
|
});
|
|
2129
2406
|
registerDisposer(el, teardown);
|
|
2130
2407
|
return;
|
|
2131
2408
|
}
|
|
2132
2409
|
if (typeof style2 === "string") {
|
|
2133
|
-
el.setAttribute("style", style2);
|
|
2410
|
+
el.setAttribute("style", sanitizeStyleAttribute(style2));
|
|
2134
2411
|
return;
|
|
2135
2412
|
}
|
|
2136
2413
|
const htmlEl = el;
|
|
@@ -2251,7 +2528,7 @@ var tagFactory = (tag, ns) => {
|
|
|
2251
2528
|
appendChildren(el, second);
|
|
2252
2529
|
return el;
|
|
2253
2530
|
}
|
|
2254
|
-
if (
|
|
2531
|
+
if (_isDev6 && looksLikeClassList(first)) {
|
|
2255
2532
|
devWarn(
|
|
2256
2533
|
`tagFactory: lone string "${first}" looks like a class list but is being rendered as TEXT. For a class, use ${tag}({ class: "${first}" }) \u2014 or ${tag}("${first}", children) to set the class AND add children.`
|
|
2257
2534
|
);
|
|
@@ -2272,7 +2549,7 @@ var tagFactory = (tag, ns) => {
|
|
|
2272
2549
|
if (pClass != null) applyClass(el, pClass);
|
|
2273
2550
|
const pId = props.id;
|
|
2274
2551
|
if (pId != null) {
|
|
2275
|
-
if (
|
|
2552
|
+
if (_isDev6 && typeof pId === "string" && CLOBBER_RISKY_IDS.has(pId.toLowerCase())) {
|
|
2276
2553
|
devWarn(
|
|
2277
2554
|
`tagFactory: element id="${pId}" matches a common global and may cause DOM clobbering. Avoid setting ids from untrusted input.`
|
|
2278
2555
|
);
|
|
@@ -2287,7 +2564,7 @@ var tagFactory = (tag, ns) => {
|
|
|
2287
2564
|
const handler = pOn[ev];
|
|
2288
2565
|
if (typeof handler === "function") {
|
|
2289
2566
|
el.addEventListener(ev, handler);
|
|
2290
|
-
} else if (
|
|
2567
|
+
} else if (_isDev6) {
|
|
2291
2568
|
devWarn(
|
|
2292
2569
|
`tagFactory: on.${ev} handler is not a function (got ${typeof handler}). Event listener was not attached.`
|
|
2293
2570
|
);
|
|
@@ -2315,16 +2592,8 @@ var tagFactory = (tag, ns) => {
|
|
|
2315
2592
|
if (isEventHandlerAttr(key)) continue;
|
|
2316
2593
|
if (typeof value === "function") {
|
|
2317
2594
|
registerDisposer(el, bindAttribute(el, key, value));
|
|
2318
|
-
} else if (typeof value === "boolean") {
|
|
2319
|
-
if (key in el && (key === "checked" || key === "disabled" || key === "selected")) {
|
|
2320
|
-
setProp2(el, key, value);
|
|
2321
|
-
} else if (value) {
|
|
2322
|
-
el.setAttribute(key, "");
|
|
2323
|
-
} else {
|
|
2324
|
-
el.removeAttribute(key);
|
|
2325
|
-
}
|
|
2326
2595
|
} else {
|
|
2327
|
-
el
|
|
2596
|
+
setSafeAttribute(el, key, value, { syncValueProperty: false, label: "tagFactory" });
|
|
2328
2597
|
}
|
|
2329
2598
|
}
|
|
2330
2599
|
}
|
|
@@ -2409,7 +2678,7 @@ var param = tagFactory("param");
|
|
|
2409
2678
|
var picture = tagFactory("picture");
|
|
2410
2679
|
var portal = tagFactory("portal");
|
|
2411
2680
|
var source = tagFactory("source");
|
|
2412
|
-
var svg = tagFactory("svg",
|
|
2681
|
+
var svg = tagFactory("svg", SVG_NS2);
|
|
2413
2682
|
var math = tagFactory("math");
|
|
2414
2683
|
var canvas = tagFactory("canvas");
|
|
2415
2684
|
var noscript = tagFactory("noscript");
|
|
@@ -2450,26 +2719,26 @@ var base = tagFactory("base");
|
|
|
2450
2719
|
var link = tagFactory("link");
|
|
2451
2720
|
var meta = tagFactory("meta");
|
|
2452
2721
|
var style = tagFactory("style");
|
|
2453
|
-
var circle = tagFactory("circle",
|
|
2454
|
-
var ellipse = tagFactory("ellipse",
|
|
2455
|
-
var g = tagFactory("g",
|
|
2456
|
-
var line = tagFactory("line",
|
|
2457
|
-
var path = tagFactory("path",
|
|
2458
|
-
var polygon = tagFactory("polygon",
|
|
2459
|
-
var polyline = tagFactory("polyline",
|
|
2460
|
-
var rect = tagFactory("rect",
|
|
2461
|
-
var text = tagFactory("text",
|
|
2462
|
-
var tspan = tagFactory("tspan",
|
|
2463
|
-
var defs = tagFactory("defs",
|
|
2464
|
-
var clipPath = tagFactory("clipPath",
|
|
2465
|
-
var mask = tagFactory("mask",
|
|
2466
|
-
var pattern = tagFactory("pattern",
|
|
2467
|
-
var linearGradient = tagFactory("linearGradient",
|
|
2468
|
-
var radialGradient = tagFactory("radialGradient",
|
|
2469
|
-
var stop = tagFactory("stop",
|
|
2470
|
-
var use = tagFactory("use",
|
|
2471
|
-
var symbol = tagFactory("symbol",
|
|
2472
|
-
var marker = tagFactory("marker",
|
|
2722
|
+
var circle = tagFactory("circle", SVG_NS2);
|
|
2723
|
+
var ellipse = tagFactory("ellipse", SVG_NS2);
|
|
2724
|
+
var g = tagFactory("g", SVG_NS2);
|
|
2725
|
+
var line = tagFactory("line", SVG_NS2);
|
|
2726
|
+
var path = tagFactory("path", SVG_NS2);
|
|
2727
|
+
var polygon = tagFactory("polygon", SVG_NS2);
|
|
2728
|
+
var polyline = tagFactory("polyline", SVG_NS2);
|
|
2729
|
+
var rect = tagFactory("rect", SVG_NS2);
|
|
2730
|
+
var text = tagFactory("text", SVG_NS2);
|
|
2731
|
+
var tspan = tagFactory("tspan", SVG_NS2);
|
|
2732
|
+
var defs = tagFactory("defs", SVG_NS2);
|
|
2733
|
+
var clipPath = tagFactory("clipPath", SVG_NS2);
|
|
2734
|
+
var mask = tagFactory("mask", SVG_NS2);
|
|
2735
|
+
var pattern = tagFactory("pattern", SVG_NS2);
|
|
2736
|
+
var linearGradient = tagFactory("linearGradient", SVG_NS2);
|
|
2737
|
+
var radialGradient = tagFactory("radialGradient", SVG_NS2);
|
|
2738
|
+
var stop = tagFactory("stop", SVG_NS2);
|
|
2739
|
+
var use = tagFactory("use", SVG_NS2);
|
|
2740
|
+
var symbol = tagFactory("symbol", SVG_NS2);
|
|
2741
|
+
var marker = tagFactory("marker", SVG_NS2);
|
|
2473
2742
|
var center = tagFactory("center");
|
|
2474
2743
|
var font = tagFactory("font");
|
|
2475
2744
|
var marquee = tagFactory("marquee");
|
|
@@ -2478,18 +2747,14 @@ var customElement = (tagName) => tagFactory(tagName);
|
|
|
2478
2747
|
// src/core/rendering/lazy.ts
|
|
2479
2748
|
var PENDING_ERROR = "__sibuPendingError";
|
|
2480
2749
|
function dispatchPropagate(node, error) {
|
|
2481
|
-
const
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
return true;
|
|
2486
|
-
} catch {
|
|
2487
|
-
return false;
|
|
2488
|
-
}
|
|
2750
|
+
const report = () => {
|
|
2751
|
+
if (!node.parentNode) return false;
|
|
2752
|
+
reportError(error, { phase: "render", name: "lazy", node });
|
|
2753
|
+
return true;
|
|
2489
2754
|
};
|
|
2490
|
-
if (
|
|
2755
|
+
if (report()) return;
|
|
2491
2756
|
queueMicrotask(() => {
|
|
2492
|
-
if (
|
|
2757
|
+
if (report()) return;
|
|
2493
2758
|
node[PENDING_ERROR] = error;
|
|
2494
2759
|
});
|
|
2495
2760
|
}
|
|
@@ -2514,12 +2779,14 @@ function lazy(importFn) {
|
|
|
2514
2779
|
if (disposed) return;
|
|
2515
2780
|
cached = mod.default;
|
|
2516
2781
|
const rendered = cached();
|
|
2517
|
-
container
|
|
2782
|
+
replaceChildrenSafely(container, rendered);
|
|
2518
2783
|
}).catch((err) => {
|
|
2519
2784
|
if (disposed) return;
|
|
2520
2785
|
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
2521
|
-
|
|
2522
|
-
|
|
2786
|
+
replaceChildrenSafely(
|
|
2787
|
+
container,
|
|
2788
|
+
div({ class: "sibu-lazy-error" }, `Failed to load component: ${errorObj.message}`)
|
|
2789
|
+
);
|
|
2523
2790
|
dispatchPropagate(container, errorObj);
|
|
2524
2791
|
});
|
|
2525
2792
|
container.appendChild(span("sibu-lazy-loading", "Loading..."));
|
|
@@ -2551,7 +2818,7 @@ function Suspense({ nodes, fallback }) {
|
|
|
2551
2818
|
childEl = el;
|
|
2552
2819
|
if (el.classList.contains("sibu-lazy")) {
|
|
2553
2820
|
if (!el.querySelector(".sibu-lazy-loading")) {
|
|
2554
|
-
container
|
|
2821
|
+
replaceChildrenSafely(container, el);
|
|
2555
2822
|
return;
|
|
2556
2823
|
}
|
|
2557
2824
|
observer = new MutationObserver(() => {
|
|
@@ -2560,16 +2827,15 @@ function Suspense({ nodes, fallback }) {
|
|
|
2560
2827
|
if (!loading) {
|
|
2561
2828
|
observer?.disconnect();
|
|
2562
2829
|
observer = null;
|
|
2563
|
-
container
|
|
2830
|
+
replaceChildrenSafely(container, el);
|
|
2564
2831
|
}
|
|
2565
2832
|
});
|
|
2566
2833
|
observer.observe(el, { childList: true, subtree: true });
|
|
2567
2834
|
} else {
|
|
2568
|
-
container
|
|
2835
|
+
replaceChildrenSafely(container, el);
|
|
2569
2836
|
}
|
|
2570
2837
|
} catch (err) {
|
|
2571
2838
|
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
2572
|
-
devWarn(`[SibuJS] Suspense nodes() threw: ${errorObj.message}`);
|
|
2573
2839
|
dispatchPropagate(container, errorObj);
|
|
2574
2840
|
}
|
|
2575
2841
|
});
|
|
@@ -2581,7 +2847,8 @@ function safeCall(cb, hookName) {
|
|
|
2581
2847
|
try {
|
|
2582
2848
|
return cb();
|
|
2583
2849
|
} catch (err) {
|
|
2584
|
-
|
|
2850
|
+
const phase = hookName.toLowerCase().includes("unmount") ? "cleanup" : "effect";
|
|
2851
|
+
reportError(err, { phase, name: hookName });
|
|
2585
2852
|
return void 0;
|
|
2586
2853
|
}
|
|
2587
2854
|
}
|
|
@@ -2815,20 +3082,35 @@ function detectSSRShared() {
|
|
|
2815
3082
|
const getBuiltin = process.getBuiltinModule;
|
|
2816
3083
|
if (typeof getBuiltin === "function") {
|
|
2817
3084
|
mod = getBuiltin("node:async_hooks");
|
|
2818
|
-
} else {
|
|
2819
|
-
|
|
2820
|
-
if (req) mod = req("node:async_hooks");
|
|
3085
|
+
} else if (typeof require === "function") {
|
|
3086
|
+
mod = require("async_hooks");
|
|
2821
3087
|
}
|
|
2822
3088
|
if (mod) detected = new mod.AsyncLocalStorage();
|
|
2823
3089
|
}
|
|
2824
3090
|
} catch {
|
|
2825
3091
|
detected = null;
|
|
2826
3092
|
}
|
|
2827
|
-
return {
|
|
3093
|
+
return {
|
|
3094
|
+
als: detected,
|
|
3095
|
+
fallbackStore: { ssr: false, suspenseIdCounter: 0, locale: void 0 },
|
|
3096
|
+
fallbackDepth: 0
|
|
3097
|
+
};
|
|
2828
3098
|
}
|
|
2829
3099
|
var _shared = globalThis[SSR_KEY] ?? (globalThis[SSR_KEY] = detectSSRShared());
|
|
2830
3100
|
var als = _shared.als;
|
|
2831
3101
|
var fallbackStore = _shared.fallbackStore;
|
|
3102
|
+
_shared.fallbackDepth ?? (_shared.fallbackDepth = 0);
|
|
3103
|
+
var _alsWarned = false;
|
|
3104
|
+
function warnMissingAsyncLocalStorage() {
|
|
3105
|
+
if (_alsWarned || als) return;
|
|
3106
|
+
const isNode = typeof process !== "undefined" && !!process.versions?.node;
|
|
3107
|
+
if (!isNode) return;
|
|
3108
|
+
_alsWarned = true;
|
|
3109
|
+
const version = process.versions.node;
|
|
3110
|
+
devWarn(
|
|
3111
|
+
`SSR request isolation is UNAVAILABLE on this runtime (Node ${version}). AsyncLocalStorage could not be loaded, so concurrent requests share one SSR store: request state and the query cache can bleed between them. Node >= 22.3 is required for isolated SSR under ESM; the CommonJS build works on older versions. A fully synchronous render is unaffected.`
|
|
3112
|
+
);
|
|
3113
|
+
}
|
|
2832
3114
|
function getSSRStore() {
|
|
2833
3115
|
if (als) {
|
|
2834
3116
|
const s2 = als.getStore();
|
|
@@ -2857,19 +3139,25 @@ function disableSSR() {
|
|
|
2857
3139
|
getSSRStore().ssr = false;
|
|
2858
3140
|
}
|
|
2859
3141
|
function runInSSRContext(fn) {
|
|
2860
|
-
const store2 = { ssr: true, suspenseIdCounter: 0 };
|
|
3142
|
+
const store2 = { ssr: true, suspenseIdCounter: 0, locale: void 0 };
|
|
2861
3143
|
if (als) {
|
|
2862
3144
|
return als.run(store2, fn);
|
|
2863
3145
|
}
|
|
3146
|
+
warnMissingAsyncLocalStorage();
|
|
2864
3147
|
const prevSSR = fallbackStore.ssr;
|
|
2865
3148
|
const prevCounter = fallbackStore.suspenseIdCounter;
|
|
3149
|
+
const prevLocale = fallbackStore.locale;
|
|
2866
3150
|
fallbackStore.ssr = true;
|
|
2867
3151
|
fallbackStore.suspenseIdCounter = 0;
|
|
3152
|
+
fallbackStore.locale = void 0;
|
|
3153
|
+
_shared.fallbackDepth++;
|
|
2868
3154
|
try {
|
|
2869
3155
|
return fn();
|
|
2870
3156
|
} finally {
|
|
3157
|
+
_shared.fallbackDepth--;
|
|
2871
3158
|
fallbackStore.ssr = prevSSR;
|
|
2872
3159
|
fallbackStore.suspenseIdCounter = prevCounter;
|
|
3160
|
+
fallbackStore.locale = prevLocale;
|
|
2873
3161
|
}
|
|
2874
3162
|
}
|
|
2875
3163
|
function withSSR(fn) {
|
|
@@ -2910,7 +3198,7 @@ function flushUserCleanups(ctx) {
|
|
|
2910
3198
|
try {
|
|
2911
3199
|
list[i2]();
|
|
2912
3200
|
} catch (err) {
|
|
2913
|
-
|
|
3201
|
+
reportError(err, { phase: "cleanup" });
|
|
2914
3202
|
}
|
|
2915
3203
|
}
|
|
2916
3204
|
}
|
|
@@ -2923,11 +3211,12 @@ function drainReruns(ctx) {
|
|
|
2923
3211
|
} while (ctx.rerunPending && ++reruns <= MAX_RERUNS);
|
|
2924
3212
|
if (ctx.rerunPending) {
|
|
2925
3213
|
ctx.rerunPending = false;
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
`
|
|
2929
|
-
)
|
|
2930
|
-
|
|
3214
|
+
reportError(
|
|
3215
|
+
new Error(
|
|
3216
|
+
`effect re-requested itself ${MAX_RERUNS}+ times \u2014 likely a write-reads-self cycle. Breaking to prevent infinite loop.`
|
|
3217
|
+
),
|
|
3218
|
+
{ phase: "effect" }
|
|
3219
|
+
);
|
|
2931
3220
|
}
|
|
2932
3221
|
}
|
|
2933
3222
|
function disposeEffect(ctx) {
|
|
@@ -3004,6 +3293,8 @@ function effect(effectFn, options) {
|
|
|
3004
3293
|
sub2.depsTail = null;
|
|
3005
3294
|
sub2._epoch = 0;
|
|
3006
3295
|
sub2._structDirty = false;
|
|
3296
|
+
sub2._hasComputedDep = false;
|
|
3297
|
+
sub2._errorPhase = "effect";
|
|
3007
3298
|
sub2._runEpoch = 0;
|
|
3008
3299
|
sub2._runs = 0;
|
|
3009
3300
|
ctx.subscriber = sub2;
|
|
@@ -3072,70 +3363,72 @@ var isBatching = API2.isBatching;
|
|
|
3072
3363
|
|
|
3073
3364
|
// src/core/signals/signal.ts
|
|
3074
3365
|
var _g2 = globalThis;
|
|
3075
|
-
var
|
|
3366
|
+
var _isDev7 = isDev();
|
|
3076
3367
|
function signal(initial, options) {
|
|
3077
|
-
const
|
|
3368
|
+
const state2 = {
|
|
3078
3369
|
value: initial,
|
|
3079
3370
|
__v: 0,
|
|
3080
3371
|
__sc: 0,
|
|
3081
3372
|
subsHead: null,
|
|
3082
3373
|
subsTail: null,
|
|
3083
3374
|
__activeNode: null,
|
|
3084
|
-
__name: void 0
|
|
3375
|
+
__name: void 0,
|
|
3376
|
+
_d: false,
|
|
3377
|
+
_validate: void 0
|
|
3085
3378
|
};
|
|
3086
|
-
const debugName =
|
|
3379
|
+
const debugName = _isDev7 ? options?.name : void 0;
|
|
3087
3380
|
const equalsFn = options?.equals;
|
|
3088
|
-
if (debugName)
|
|
3381
|
+
if (debugName) state2.__name = debugName;
|
|
3089
3382
|
function get() {
|
|
3090
|
-
recordDependency2(
|
|
3091
|
-
return
|
|
3383
|
+
recordDependency2(state2);
|
|
3384
|
+
return state2.value;
|
|
3092
3385
|
}
|
|
3093
|
-
get.__signal =
|
|
3386
|
+
get.__signal = state2;
|
|
3094
3387
|
if (debugName) get.__name = debugName;
|
|
3095
3388
|
let set;
|
|
3096
3389
|
if (equalsFn) {
|
|
3097
3390
|
set = (next) => {
|
|
3098
|
-
const prev =
|
|
3391
|
+
const prev = state2.value;
|
|
3099
3392
|
const newValue = typeof next === "function" ? next(prev) : next;
|
|
3100
3393
|
if (equalsFn(prev, newValue)) return;
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
if (
|
|
3394
|
+
state2.value = newValue;
|
|
3395
|
+
state2.__v++;
|
|
3396
|
+
if (_isDev7) {
|
|
3104
3397
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
3105
|
-
if (hook) hook.emit("signal:update", { signal:
|
|
3398
|
+
if (hook) hook.emit("signal:update", { signal: state2, name: debugName, oldValue: prev, newValue });
|
|
3106
3399
|
}
|
|
3107
|
-
if (!enqueueBatchedSignal(
|
|
3108
|
-
notifySubscribers2(
|
|
3400
|
+
if (!enqueueBatchedSignal(state2)) {
|
|
3401
|
+
notifySubscribers2(state2);
|
|
3109
3402
|
}
|
|
3110
3403
|
};
|
|
3111
|
-
} else if (
|
|
3404
|
+
} else if (_isDev7) {
|
|
3112
3405
|
set = (next) => {
|
|
3113
|
-
const prev =
|
|
3406
|
+
const prev = state2.value;
|
|
3114
3407
|
const newValue = typeof next === "function" ? next(prev) : next;
|
|
3115
3408
|
if (Object.is(newValue, prev)) return;
|
|
3116
|
-
|
|
3117
|
-
|
|
3409
|
+
state2.value = newValue;
|
|
3410
|
+
state2.__v++;
|
|
3118
3411
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
3119
|
-
if (hook) hook.emit("signal:update", { signal:
|
|
3120
|
-
if (!enqueueBatchedSignal(
|
|
3121
|
-
notifySubscribers2(
|
|
3412
|
+
if (hook) hook.emit("signal:update", { signal: state2, name: debugName, oldValue: prev, newValue });
|
|
3413
|
+
if (!enqueueBatchedSignal(state2)) {
|
|
3414
|
+
notifySubscribers2(state2);
|
|
3122
3415
|
}
|
|
3123
3416
|
};
|
|
3124
3417
|
} else {
|
|
3125
3418
|
set = (next) => {
|
|
3126
|
-
const prev =
|
|
3419
|
+
const prev = state2.value;
|
|
3127
3420
|
const newValue = typeof next === "function" ? next(prev) : next;
|
|
3128
3421
|
if (Object.is(newValue, prev)) return;
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
if (!enqueueBatchedSignal(
|
|
3132
|
-
notifySubscribers2(
|
|
3422
|
+
state2.value = newValue;
|
|
3423
|
+
state2.__v++;
|
|
3424
|
+
if (!enqueueBatchedSignal(state2)) {
|
|
3425
|
+
notifySubscribers2(state2);
|
|
3133
3426
|
}
|
|
3134
3427
|
};
|
|
3135
3428
|
}
|
|
3136
|
-
if (
|
|
3429
|
+
if (_isDev7) {
|
|
3137
3430
|
const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
3138
|
-
if (hook) hook.emit("signal:create", { signal:
|
|
3431
|
+
if (hook) hook.emit("signal:create", { signal: state2, name: debugName, getter: get, initial });
|
|
3139
3432
|
}
|
|
3140
3433
|
return [get, set];
|
|
3141
3434
|
}
|
|
@@ -3347,14 +3640,14 @@ function parseStack(stack) {
|
|
|
3347
3640
|
}
|
|
3348
3641
|
return frames;
|
|
3349
3642
|
}
|
|
3350
|
-
function
|
|
3643
|
+
function normalizeError2(err) {
|
|
3351
3644
|
if (err instanceof Error) {
|
|
3352
3645
|
const code2 = err.code ?? err.name ?? "ERROR";
|
|
3353
3646
|
const message = err.message || "Unknown error";
|
|
3354
3647
|
const stack = err.stack ?? "";
|
|
3355
3648
|
const frames = parseStack(stack);
|
|
3356
3649
|
const rawCause = err.cause;
|
|
3357
|
-
const cause = rawCause != null ?
|
|
3650
|
+
const cause = rawCause != null ? normalizeError2(rawCause) : null;
|
|
3358
3651
|
return { code: code2, message, stack, frames, cause };
|
|
3359
3652
|
}
|
|
3360
3653
|
return {
|
|
@@ -3450,7 +3743,7 @@ function renderMetadata(meta2) {
|
|
|
3450
3743
|
function ErrorDisplay(props) {
|
|
3451
3744
|
injectStyles();
|
|
3452
3745
|
const severity = props.severity ?? "error";
|
|
3453
|
-
const normalized =
|
|
3746
|
+
const normalized = normalizeError2(props.error);
|
|
3454
3747
|
const showDetails = props.alwaysShowDetails ?? isDev();
|
|
3455
3748
|
const headline = props.title ?? normalized.message;
|
|
3456
3749
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
|
|
@@ -3700,6 +3993,7 @@ var errorBoundaryStyles = `
|
|
|
3700
3993
|
background: #3a3a4e;
|
|
3701
3994
|
}
|
|
3702
3995
|
`;
|
|
3996
|
+
var RESET_KEY_THREW = /* @__PURE__ */ Symbol("sibujs.ErrorBoundary.resetKeyThrew");
|
|
3703
3997
|
var stylesInjected = false;
|
|
3704
3998
|
function injectStyles2() {
|
|
3705
3999
|
if (!stylesInjected && typeof document !== "undefined") {
|
|
@@ -3708,29 +4002,6 @@ function injectStyles2() {
|
|
|
3708
4002
|
stylesInjected = true;
|
|
3709
4003
|
}
|
|
3710
4004
|
}
|
|
3711
|
-
var FALLBACK_CACHE_MAX = 50;
|
|
3712
|
-
var fallbackCache = /* @__PURE__ */ new WeakMap();
|
|
3713
|
-
function getMemoizedFallback(fallbackFn, error, retry) {
|
|
3714
|
-
let cache2 = fallbackCache.get(fallbackFn);
|
|
3715
|
-
if (!cache2) {
|
|
3716
|
-
cache2 = /* @__PURE__ */ new Map();
|
|
3717
|
-
fallbackCache.set(fallbackFn, cache2);
|
|
3718
|
-
}
|
|
3719
|
-
const key = error.message;
|
|
3720
|
-
let factory = cache2.get(key);
|
|
3721
|
-
if (factory) {
|
|
3722
|
-
cache2.delete(key);
|
|
3723
|
-
cache2.set(key, factory);
|
|
3724
|
-
} else {
|
|
3725
|
-
factory = () => fallbackFn(error, retry);
|
|
3726
|
-
cache2.set(key, factory);
|
|
3727
|
-
if (cache2.size > FALLBACK_CACHE_MAX) {
|
|
3728
|
-
const oldestKey = cache2.keys().next().value;
|
|
3729
|
-
if (oldestKey !== void 0) cache2.delete(oldestKey);
|
|
3730
|
-
}
|
|
3731
|
-
}
|
|
3732
|
-
return factory();
|
|
3733
|
-
}
|
|
3734
4005
|
function ErrorBoundary(optionsOrChildren, maybeChildren) {
|
|
3735
4006
|
const children = typeof optionsOrChildren === "function" ? optionsOrChildren : maybeChildren;
|
|
3736
4007
|
const options = typeof optionsOrChildren === "function" ? {} : optionsOrChildren;
|
|
@@ -3738,43 +4009,61 @@ function ErrorBoundary(optionsOrChildren, maybeChildren) {
|
|
|
3738
4009
|
injectStyles2();
|
|
3739
4010
|
const [error, setError] = signal(null);
|
|
3740
4011
|
const retry = () => {
|
|
3741
|
-
|
|
3742
|
-
const cur = error();
|
|
3743
|
-
const inner = fallbackCache.get(fallback);
|
|
3744
|
-
if (cur && inner) inner.delete(cur.message);
|
|
3745
|
-
}
|
|
4012
|
+
stopResetKeysWatcher();
|
|
3746
4013
|
setError(null);
|
|
3747
4014
|
};
|
|
3748
4015
|
let resetKeysTeardown = null;
|
|
3749
|
-
|
|
3750
|
-
|
|
4016
|
+
const stopResetKeysWatcher = () => {
|
|
4017
|
+
if (!resetKeysTeardown) return;
|
|
4018
|
+
const teardown = resetKeysTeardown;
|
|
4019
|
+
resetKeysTeardown = null;
|
|
4020
|
+
teardown();
|
|
4021
|
+
};
|
|
4022
|
+
const readResetKeyValues = (keys) => {
|
|
4023
|
+
const values = new Array(keys.length);
|
|
4024
|
+
for (let i2 = 0; i2 < keys.length; i2++) {
|
|
4025
|
+
try {
|
|
4026
|
+
values[i2] = keys[i2]();
|
|
4027
|
+
} catch (err) {
|
|
4028
|
+
reportError(err, { phase: "effect", name: "ErrorBoundary.resetKeys" });
|
|
4029
|
+
values[i2] = RESET_KEY_THREW;
|
|
4030
|
+
}
|
|
4031
|
+
}
|
|
4032
|
+
return values;
|
|
4033
|
+
};
|
|
4034
|
+
const startResetKeysWatcher = () => {
|
|
4035
|
+
const keys = resetKeys;
|
|
4036
|
+
if (!keys || keys.length === 0) return;
|
|
4037
|
+
stopResetKeysWatcher();
|
|
4038
|
+
let baseline = null;
|
|
3751
4039
|
resetKeysTeardown = effect(() => {
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
4040
|
+
const current = readResetKeyValues(keys);
|
|
4041
|
+
if (baseline === null) {
|
|
4042
|
+
baseline = current;
|
|
4043
|
+
return;
|
|
4044
|
+
}
|
|
4045
|
+
let changed = current.length !== baseline.length;
|
|
4046
|
+
if (!changed) {
|
|
4047
|
+
for (let i2 = 0; i2 < current.length; i2++) {
|
|
4048
|
+
if (!Object.is(current[i2], baseline[i2])) {
|
|
4049
|
+
changed = true;
|
|
4050
|
+
break;
|
|
3758
4051
|
}
|
|
3759
4052
|
}
|
|
3760
4053
|
}
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
return;
|
|
3764
|
-
}
|
|
3765
|
-
if (error() !== null) retry();
|
|
4054
|
+
baseline = current;
|
|
4055
|
+
if (changed) retry();
|
|
3766
4056
|
});
|
|
3767
|
-
}
|
|
4057
|
+
};
|
|
3768
4058
|
const handleError = (e) => {
|
|
3769
|
-
const errorObj =
|
|
4059
|
+
const errorObj = normalizeError(e);
|
|
3770
4060
|
setError(errorObj);
|
|
4061
|
+
startResetKeysWatcher();
|
|
3771
4062
|
if (onError) {
|
|
3772
4063
|
try {
|
|
3773
4064
|
onError(errorObj);
|
|
3774
4065
|
} catch (cbErr) {
|
|
3775
|
-
|
|
3776
|
-
console.error("[SibuJS ErrorBoundary] onError callback threw:", cbErr);
|
|
3777
|
-
}
|
|
4066
|
+
reportError(cbErr, { phase: "render", name: "ErrorBoundary onError callback" });
|
|
3778
4067
|
}
|
|
3779
4068
|
}
|
|
3780
4069
|
return errorObj;
|
|
@@ -3785,18 +4074,14 @@ function ErrorBoundary(optionsOrChildren, maybeChildren) {
|
|
|
3785
4074
|
const tryRenderFallback = (err) => {
|
|
3786
4075
|
const fn = fallback || defaultFallback;
|
|
3787
4076
|
try {
|
|
3788
|
-
return
|
|
4077
|
+
return fn(err, retry);
|
|
3789
4078
|
} catch (fallbackError) {
|
|
3790
|
-
const propagateError = fallbackError instanceof Error ? fallbackError : new Error(String(fallbackError));
|
|
3791
4079
|
queueMicrotask(() => {
|
|
3792
|
-
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
})
|
|
3798
|
-
);
|
|
3799
|
-
}
|
|
4080
|
+
reportError(fallbackError, {
|
|
4081
|
+
phase: "render",
|
|
4082
|
+
name: "ErrorBoundary fallback",
|
|
4083
|
+
node: container.parentNode ? container : void 0
|
|
4084
|
+
});
|
|
3800
4085
|
});
|
|
3801
4086
|
return document.createComment("error-boundary-failed");
|
|
3802
4087
|
}
|
|
@@ -3813,11 +4098,20 @@ function ErrorBoundary(optionsOrChildren, maybeChildren) {
|
|
|
3813
4098
|
if (result && typeof result.then === "function") {
|
|
3814
4099
|
const asyncContainer = div({ class: "sibu-error-async" });
|
|
3815
4100
|
asyncContainer.appendChild(span({ class: "sibu-lazy-loading", nodes: "Loading..." }));
|
|
4101
|
+
let asyncDisposed = false;
|
|
4102
|
+
registerDisposer(asyncContainer, () => {
|
|
4103
|
+
asyncDisposed = true;
|
|
4104
|
+
});
|
|
3816
4105
|
result.then((el) => {
|
|
3817
|
-
|
|
4106
|
+
if (asyncDisposed) {
|
|
4107
|
+
dispose(el);
|
|
4108
|
+
return;
|
|
4109
|
+
}
|
|
4110
|
+
replaceChildrenSafely(asyncContainer, el);
|
|
3818
4111
|
}).catch((e) => {
|
|
4112
|
+
if (asyncDisposed) return;
|
|
3819
4113
|
const err = handleError(e);
|
|
3820
|
-
asyncContainer
|
|
4114
|
+
replaceChildrenSafely(asyncContainer, tryRenderFallback(err));
|
|
3821
4115
|
});
|
|
3822
4116
|
return asyncContainer;
|
|
3823
4117
|
}
|
|
@@ -3830,12 +4124,12 @@ function ErrorBoundary(optionsOrChildren, maybeChildren) {
|
|
|
3830
4124
|
});
|
|
3831
4125
|
const propagateListener = (e) => {
|
|
3832
4126
|
if (error()) return;
|
|
3833
|
-
e.stopPropagation();
|
|
3834
4127
|
const customEvent = e;
|
|
3835
4128
|
const propagatedError = customEvent.detail?.error;
|
|
3836
|
-
if (propagatedError)
|
|
3837
|
-
|
|
3838
|
-
|
|
4129
|
+
if (!propagatedError) return;
|
|
4130
|
+
e.preventDefault();
|
|
4131
|
+
e.stopPropagation();
|
|
4132
|
+
handleError(propagatedError);
|
|
3839
4133
|
};
|
|
3840
4134
|
container.addEventListener("sibu:error-propagate", propagateListener);
|
|
3841
4135
|
onMount(() => {
|
|
@@ -3863,7 +4157,7 @@ function ErrorBoundary(optionsOrChildren, maybeChildren) {
|
|
|
3863
4157
|
return void 0;
|
|
3864
4158
|
}, container);
|
|
3865
4159
|
registerDisposer(container, () => {
|
|
3866
|
-
|
|
4160
|
+
stopResetKeysWatcher();
|
|
3867
4161
|
container.removeEventListener("sibu:error-propagate", propagateListener);
|
|
3868
4162
|
});
|
|
3869
4163
|
return container;
|
|
@@ -4113,10 +4407,18 @@ function setGlobalErrorHandler(handler) {
|
|
|
4113
4407
|
}
|
|
4114
4408
|
|
|
4115
4409
|
// src/core/rendering/context.ts
|
|
4410
|
+
var _isDev8 = isDev();
|
|
4116
4411
|
function context(defaultValue) {
|
|
4117
4412
|
const [getValue, setValue] = signal(defaultValue);
|
|
4413
|
+
const warnIfSSR = (method) => {
|
|
4414
|
+
if (!_isDev8 || !isSSR()) return;
|
|
4415
|
+
devWarn(
|
|
4416
|
+
`context.${method}() called during SSR. SibuJS context() is application-global \u2014 it is NOT isolated per request, so a concurrent request can observe this value. Do not use context() for request-specific SSR data; pass it explicitly or use request-scoped storage instead.`
|
|
4417
|
+
);
|
|
4418
|
+
};
|
|
4118
4419
|
const ctx = {
|
|
4119
4420
|
provide(value) {
|
|
4421
|
+
warnIfSSR("provide");
|
|
4120
4422
|
const previous = getValue();
|
|
4121
4423
|
setValue(value);
|
|
4122
4424
|
return () => setValue(previous);
|
|
@@ -4128,13 +4430,21 @@ function context(defaultValue) {
|
|
|
4128
4430
|
return getValue();
|
|
4129
4431
|
},
|
|
4130
4432
|
set(value) {
|
|
4433
|
+
warnIfSSR("set");
|
|
4131
4434
|
setValue(value);
|
|
4132
4435
|
},
|
|
4133
4436
|
withContext(value, fn) {
|
|
4437
|
+
warnIfSSR("withContext");
|
|
4134
4438
|
const previous = getValue();
|
|
4135
4439
|
setValue(value);
|
|
4136
4440
|
try {
|
|
4137
|
-
|
|
4441
|
+
const result = fn();
|
|
4442
|
+
if (_isDev8 && result !== null && typeof result?.then === "function") {
|
|
4443
|
+
devWarn(
|
|
4444
|
+
"context.withContext() received an async callback. Scoping is synchronous only \u2014 the previous value is restored as soon as the callback returns its promise, so anything after an `await` runs outside the scope."
|
|
4445
|
+
);
|
|
4446
|
+
}
|
|
4447
|
+
return result;
|
|
4138
4448
|
} finally {
|
|
4139
4449
|
setValue(previous);
|
|
4140
4450
|
}
|
|
@@ -4255,10 +4565,7 @@ function DynamicComponent(is) {
|
|
|
4255
4565
|
} else {
|
|
4256
4566
|
el = resolveComponent(target);
|
|
4257
4567
|
}
|
|
4258
|
-
|
|
4259
|
-
dispose(child);
|
|
4260
|
-
}
|
|
4261
|
-
container.replaceChildren(el);
|
|
4568
|
+
replaceChildrenSafely(container, el);
|
|
4262
4569
|
}
|
|
4263
4570
|
const untrack = track2(render);
|
|
4264
4571
|
registerDisposer(container, untrack);
|
|
@@ -4319,6 +4626,10 @@ function each(getArray, render, options) {
|
|
|
4319
4626
|
let oldLen = 0;
|
|
4320
4627
|
let nodeMap = /* @__PURE__ */ new Map();
|
|
4321
4628
|
let workMap = /* @__PURE__ */ new Map();
|
|
4629
|
+
const pendingRows = [];
|
|
4630
|
+
const pendingItems = [];
|
|
4631
|
+
const pendingIndices = [];
|
|
4632
|
+
let pendingCount = 0;
|
|
4322
4633
|
let newNodes = [];
|
|
4323
4634
|
let newKeysBuf = [];
|
|
4324
4635
|
let isStableBuf = new Uint8Array(0);
|
|
@@ -4328,8 +4639,10 @@ function each(getArray, render, options) {
|
|
|
4328
4639
|
const keyIndexMap = /* @__PURE__ */ new Map();
|
|
4329
4640
|
let initialized = false;
|
|
4330
4641
|
let sentinelInserted = false;
|
|
4642
|
+
let rangeDisposed = false;
|
|
4331
4643
|
const keyFn = options.key;
|
|
4332
4644
|
const update = () => {
|
|
4645
|
+
if (rangeDisposed) return;
|
|
4333
4646
|
const arr = getArray();
|
|
4334
4647
|
const newLen = arr.length;
|
|
4335
4648
|
const parent = anchor.parentNode;
|
|
@@ -4358,49 +4671,44 @@ function each(getArray, render, options) {
|
|
|
4358
4671
|
}
|
|
4359
4672
|
keyIndexMap.set(newKeys[i2], i2);
|
|
4360
4673
|
}
|
|
4674
|
+
pendingCount = 0;
|
|
4361
4675
|
for (let i2 = 0; i2 < newLen; i2++) {
|
|
4362
4676
|
const key = newKeys[i2];
|
|
4363
4677
|
const existing = nodeMap.get(key);
|
|
4364
|
-
let
|
|
4678
|
+
let row;
|
|
4365
4679
|
if (existing !== void 0) {
|
|
4366
|
-
|
|
4680
|
+
row = existing;
|
|
4681
|
+
pendingRows[pendingCount] = row;
|
|
4682
|
+
pendingItems[pendingCount] = arr[i2];
|
|
4683
|
+
pendingIndices[pendingCount] = i2;
|
|
4684
|
+
pendingCount++;
|
|
4367
4685
|
} else {
|
|
4368
|
-
const
|
|
4369
|
-
const
|
|
4370
|
-
|
|
4686
|
+
const [itemGetter, setItem] = signal(arr[i2]);
|
|
4687
|
+
const [indexGetter, setIndex] = signal(i2);
|
|
4688
|
+
let node;
|
|
4371
4689
|
try {
|
|
4372
4690
|
node = resolveNodeChild(render(itemGetter, indexGetter));
|
|
4373
4691
|
} catch (err) {
|
|
4374
|
-
|
|
4375
|
-
devWarn(
|
|
4376
|
-
`each: render threw for item at index ${i2} (key="${newKeys[i2]}"): ${err instanceof Error ? err.message : String(err)}`
|
|
4377
|
-
);
|
|
4378
|
-
}
|
|
4692
|
+
const key2 = newKeys[i2];
|
|
4379
4693
|
node = document.createComment(`each:error:${i2}`);
|
|
4380
|
-
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
4381
4694
|
queueMicrotask(() => {
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
);
|
|
4388
|
-
} else if (_isDev9) {
|
|
4389
|
-
devWarn(`each: error not surfaced \u2014 anchor detached: ${errorObj.message}`);
|
|
4390
|
-
}
|
|
4391
|
-
} catch {
|
|
4392
|
-
}
|
|
4695
|
+
reportError(err, {
|
|
4696
|
+
phase: "render",
|
|
4697
|
+
name: `each row (key="${String(key2)}")`,
|
|
4698
|
+
node: anchor.parentNode ? anchor : void 0
|
|
4699
|
+
});
|
|
4393
4700
|
});
|
|
4394
4701
|
}
|
|
4702
|
+
row = { node, item: itemGetter, setItem, index: indexGetter, setIndex };
|
|
4395
4703
|
}
|
|
4396
|
-
workMap.set(key,
|
|
4397
|
-
newNodes[i2] = node;
|
|
4704
|
+
workMap.set(key, row);
|
|
4705
|
+
newNodes[i2] = row.node;
|
|
4398
4706
|
}
|
|
4399
|
-
for (const [key,
|
|
4707
|
+
for (const [key, row] of nodeMap) {
|
|
4400
4708
|
if (!workMap.has(key)) {
|
|
4401
|
-
dispose(node);
|
|
4402
|
-
if (node.parentNode) {
|
|
4403
|
-
parent.removeChild(node);
|
|
4709
|
+
dispose(row.node);
|
|
4710
|
+
if (row.node.parentNode) {
|
|
4711
|
+
parent.removeChild(row.node);
|
|
4404
4712
|
}
|
|
4405
4713
|
}
|
|
4406
4714
|
}
|
|
@@ -4409,6 +4717,8 @@ function each(getArray, render, options) {
|
|
|
4409
4717
|
const tmp2 = nodeMap;
|
|
4410
4718
|
nodeMap = workMap;
|
|
4411
4719
|
workMap = tmp2;
|
|
4720
|
+
initialized = true;
|
|
4721
|
+
pendingCount = 0;
|
|
4412
4722
|
return;
|
|
4413
4723
|
}
|
|
4414
4724
|
oldKeyIndex.clear();
|
|
@@ -4458,12 +4768,47 @@ function each(getArray, render, options) {
|
|
|
4458
4768
|
nodeMap = workMap;
|
|
4459
4769
|
workMap = tmp;
|
|
4460
4770
|
initialized = true;
|
|
4771
|
+
flushRowCells();
|
|
4461
4772
|
};
|
|
4773
|
+
function flushRowCells() {
|
|
4774
|
+
if (pendingCount === 0) return;
|
|
4775
|
+
const count = pendingCount;
|
|
4776
|
+
pendingCount = 0;
|
|
4777
|
+
batch(() => {
|
|
4778
|
+
for (let i2 = 0; i2 < count; i2++) {
|
|
4779
|
+
const row = pendingRows[i2];
|
|
4780
|
+
row.setItem(pendingItems[i2]);
|
|
4781
|
+
row.setIndex(pendingIndices[i2]);
|
|
4782
|
+
pendingRows[i2] = void 0;
|
|
4783
|
+
pendingItems[i2] = void 0;
|
|
4784
|
+
}
|
|
4785
|
+
});
|
|
4786
|
+
}
|
|
4462
4787
|
const untrack = track2(update);
|
|
4463
|
-
|
|
4788
|
+
const disposeRange = () => {
|
|
4789
|
+
if (rangeDisposed) return;
|
|
4790
|
+
rangeDisposed = true;
|
|
4791
|
+
untrack();
|
|
4792
|
+
for (const row of nodeMap.values()) {
|
|
4793
|
+
dispose(row.node);
|
|
4794
|
+
row.node.parentNode?.removeChild(row.node);
|
|
4795
|
+
}
|
|
4796
|
+
if (end.parentNode) end.parentNode.removeChild(end);
|
|
4797
|
+
sentinelInserted = false;
|
|
4798
|
+
nodeMap.clear();
|
|
4799
|
+
workMap.clear();
|
|
4800
|
+
keyIndexMap.clear();
|
|
4801
|
+
oldKeyIndex.clear();
|
|
4802
|
+
oldLen = 0;
|
|
4803
|
+
pendingRows.length = 0;
|
|
4804
|
+
pendingItems.length = 0;
|
|
4805
|
+
pendingIndices.length = 0;
|
|
4806
|
+
pendingCount = 0;
|
|
4807
|
+
};
|
|
4808
|
+
registerDisposer(anchor, disposeRange);
|
|
4464
4809
|
if (!initialized) {
|
|
4465
4810
|
queueMicrotask(() => {
|
|
4466
|
-
if (!initialized && anchor.parentNode) {
|
|
4811
|
+
if (!initialized && !rangeDisposed && anchor.parentNode) {
|
|
4467
4812
|
update();
|
|
4468
4813
|
}
|
|
4469
4814
|
});
|
|
@@ -4753,7 +5098,7 @@ function parseTemplate(strings) {
|
|
|
4753
5098
|
return parseChildren();
|
|
4754
5099
|
}
|
|
4755
5100
|
function executeElement(tmpl, values) {
|
|
4756
|
-
const el = tmpl.svg ? document.createElementNS(
|
|
5101
|
+
const el = tmpl.svg ? document.createElementNS(SVG_NS2, tmpl.tag) : document.createElement(tmpl.tag);
|
|
4757
5102
|
for (let i2 = 0; i2 < tmpl.attrs.length; i2++) {
|
|
4758
5103
|
const attr = tmpl.attrs[i2];
|
|
4759
5104
|
switch (attr.t) {
|
|
@@ -4762,20 +5107,11 @@ function executeElement(tmpl, values) {
|
|
|
4762
5107
|
break;
|
|
4763
5108
|
case 1: {
|
|
4764
5109
|
const name = attr.name;
|
|
4765
|
-
const lname = name.toLowerCase();
|
|
4766
|
-
if (isEventHandlerAttr(name)) break;
|
|
4767
5110
|
const val = values[attr.idx];
|
|
4768
5111
|
if (typeof val === "function") {
|
|
4769
5112
|
registerDisposer(el, bindAttribute(el, name, val));
|
|
4770
|
-
} else
|
|
4771
|
-
|
|
4772
|
-
if (lname === "srcset") {
|
|
4773
|
-
el.setAttribute(name, sanitizeSrcset(str));
|
|
4774
|
-
} else if (isUrlAttribute(lname)) {
|
|
4775
|
-
el.setAttribute(name, sanitizeUrl(str));
|
|
4776
|
-
} else {
|
|
4777
|
-
el.setAttribute(name, str);
|
|
4778
|
-
}
|
|
5113
|
+
} else {
|
|
5114
|
+
setSafeAttribute(el, name, val, { syncValueProperty: false, label: "html" });
|
|
4779
5115
|
}
|
|
4780
5116
|
break;
|
|
4781
5117
|
}
|
|
@@ -4785,14 +5121,7 @@ function executeElement(tmpl, values) {
|
|
|
4785
5121
|
const ev = values[attr.exprs[j]];
|
|
4786
5122
|
val += (ev == null ? "" : String(ev)) + attr.statics[j + 1];
|
|
4787
5123
|
}
|
|
4788
|
-
|
|
4789
|
-
if (lname2 === "srcset") {
|
|
4790
|
-
el.setAttribute(attr.name, sanitizeSrcset(val));
|
|
4791
|
-
} else if (isUrlAttribute(lname2)) {
|
|
4792
|
-
el.setAttribute(attr.name, sanitizeUrl(val));
|
|
4793
|
-
} else {
|
|
4794
|
-
el.setAttribute(attr.name, val);
|
|
4795
|
-
}
|
|
5124
|
+
setSafeAttribute(el, attr.name, val, { syncValueProperty: false, label: "html" });
|
|
4796
5125
|
break;
|
|
4797
5126
|
}
|
|
4798
5127
|
case 3: {
|
|
@@ -5018,20 +5347,12 @@ function Portal(nodes, target) {
|
|
|
5018
5347
|
portalContent = nodes();
|
|
5019
5348
|
container.appendChild(portalContent);
|
|
5020
5349
|
} catch (err) {
|
|
5021
|
-
if (typeof console !== "undefined") {
|
|
5022
|
-
console.error("[Portal] Render error:", err);
|
|
5023
|
-
}
|
|
5024
|
-
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
5025
5350
|
queueMicrotask(() => {
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
|
|
5031
|
-
);
|
|
5032
|
-
}
|
|
5033
|
-
} catch {
|
|
5034
|
-
}
|
|
5351
|
+
reportError(err, {
|
|
5352
|
+
phase: "render",
|
|
5353
|
+
name: "Portal",
|
|
5354
|
+
node: anchor.parentNode ? anchor : void 0
|
|
5355
|
+
});
|
|
5035
5356
|
});
|
|
5036
5357
|
}
|
|
5037
5358
|
});
|
|
@@ -5128,9 +5449,10 @@ function array(initial = []) {
|
|
|
5128
5449
|
function reactiveArray(initial = []) {
|
|
5129
5450
|
let data2 = [...initial];
|
|
5130
5451
|
let snapshot = null;
|
|
5131
|
-
const signal2 = {};
|
|
5452
|
+
const signal2 = { __v: 0 };
|
|
5132
5453
|
function notify() {
|
|
5133
5454
|
snapshot = null;
|
|
5455
|
+
signal2.__v++;
|
|
5134
5456
|
if (!enqueueBatchedSignal(signal2)) {
|
|
5135
5457
|
notifySubscribers2(signal2);
|
|
5136
5458
|
}
|
|
@@ -5250,17 +5572,34 @@ function asyncDerived(factory, initial) {
|
|
|
5250
5572
|
const [error, setError] = signal(null);
|
|
5251
5573
|
const [tick, setTick] = signal(0);
|
|
5252
5574
|
let runId = 0;
|
|
5253
|
-
|
|
5575
|
+
let disposed = false;
|
|
5576
|
+
let controller = null;
|
|
5577
|
+
const abortInFlight = () => {
|
|
5578
|
+
if (controller === null) return;
|
|
5579
|
+
const c = controller;
|
|
5580
|
+
controller = null;
|
|
5581
|
+
try {
|
|
5582
|
+
c.abort();
|
|
5583
|
+
} catch {
|
|
5584
|
+
}
|
|
5585
|
+
};
|
|
5586
|
+
const stopEffect = effect(() => {
|
|
5254
5587
|
tick();
|
|
5588
|
+
if (disposed) return;
|
|
5589
|
+
abortInFlight();
|
|
5255
5590
|
const currentRun = ++runId;
|
|
5591
|
+
const ac = typeof AbortController !== "undefined" ? new AbortController() : null;
|
|
5592
|
+
controller = ac;
|
|
5256
5593
|
batch(() => {
|
|
5257
5594
|
setLoading(true);
|
|
5258
5595
|
setError(null);
|
|
5259
5596
|
});
|
|
5597
|
+
const stale = () => disposed || currentRun !== runId;
|
|
5260
5598
|
let promise;
|
|
5261
5599
|
try {
|
|
5262
|
-
promise = factory();
|
|
5600
|
+
promise = factory({ signal: ac ? ac.signal : void 0 });
|
|
5263
5601
|
} catch (err) {
|
|
5602
|
+
if (stale()) return;
|
|
5264
5603
|
batch(() => {
|
|
5265
5604
|
setError(err);
|
|
5266
5605
|
setLoading(false);
|
|
@@ -5269,14 +5608,16 @@ function asyncDerived(factory, initial) {
|
|
|
5269
5608
|
}
|
|
5270
5609
|
promise.then(
|
|
5271
5610
|
(result) => {
|
|
5272
|
-
if (
|
|
5611
|
+
if (stale()) return;
|
|
5612
|
+
controller = null;
|
|
5273
5613
|
batch(() => {
|
|
5274
5614
|
setValue(result);
|
|
5275
5615
|
setLoading(false);
|
|
5276
5616
|
});
|
|
5277
5617
|
},
|
|
5278
5618
|
(err) => {
|
|
5279
|
-
if (
|
|
5619
|
+
if (stale()) return;
|
|
5620
|
+
controller = null;
|
|
5280
5621
|
batch(() => {
|
|
5281
5622
|
setError(err);
|
|
5282
5623
|
setLoading(false);
|
|
@@ -5288,7 +5629,16 @@ function asyncDerived(factory, initial) {
|
|
|
5288
5629
|
value,
|
|
5289
5630
|
loading,
|
|
5290
5631
|
error,
|
|
5291
|
-
refresh: () =>
|
|
5632
|
+
refresh: () => {
|
|
5633
|
+
if (disposed) return;
|
|
5634
|
+
setTick((n) => n + 1);
|
|
5635
|
+
},
|
|
5636
|
+
dispose: () => {
|
|
5637
|
+
if (disposed) return;
|
|
5638
|
+
disposed = true;
|
|
5639
|
+
stopEffect();
|
|
5640
|
+
abortInFlight();
|
|
5641
|
+
}
|
|
5292
5642
|
};
|
|
5293
5643
|
}
|
|
5294
5644
|
|
|
@@ -5408,6 +5758,21 @@ function derived(getter, options) {
|
|
|
5408
5758
|
}, markDirty);
|
|
5409
5759
|
const hook = globalThis.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
|
|
5410
5760
|
let evaluating = false;
|
|
5761
|
+
const validate = () => {
|
|
5762
|
+
if (!cs._d) return;
|
|
5763
|
+
const oldValue = cs._v;
|
|
5764
|
+
evaluating = true;
|
|
5765
|
+
try {
|
|
5766
|
+
retrack2(recompute, markDirty);
|
|
5767
|
+
if (!Object.is(oldValue, cs._v)) cs.__v++;
|
|
5768
|
+
} finally {
|
|
5769
|
+
evaluating = false;
|
|
5770
|
+
}
|
|
5771
|
+
if (hook && !Object.is(oldValue, cs._v)) {
|
|
5772
|
+
hook.emit("computed:update", { signal: cs, oldValue, newValue: cs._v });
|
|
5773
|
+
}
|
|
5774
|
+
};
|
|
5775
|
+
cs._validate = validate;
|
|
5411
5776
|
function computedGetter() {
|
|
5412
5777
|
if (evaluating) {
|
|
5413
5778
|
throw new Error(
|
|
@@ -5415,32 +5780,11 @@ function derived(getter, options) {
|
|
|
5415
5780
|
);
|
|
5416
5781
|
}
|
|
5417
5782
|
if (isTrackingSuspended2()) {
|
|
5418
|
-
if (cs._d)
|
|
5419
|
-
const prev = cs._v;
|
|
5420
|
-
evaluating = true;
|
|
5421
|
-
try {
|
|
5422
|
-
retrack2(recompute, markDirty);
|
|
5423
|
-
if (!Object.is(prev, cs._v)) cs.__v++;
|
|
5424
|
-
} finally {
|
|
5425
|
-
evaluating = false;
|
|
5426
|
-
}
|
|
5427
|
-
}
|
|
5783
|
+
if (cs._d) validate();
|
|
5428
5784
|
return cs._v;
|
|
5429
5785
|
}
|
|
5786
|
+
if (cs._d) validate();
|
|
5430
5787
|
recordDependency2(cs);
|
|
5431
|
-
if (cs._d) {
|
|
5432
|
-
const oldValue = cs._v;
|
|
5433
|
-
evaluating = true;
|
|
5434
|
-
try {
|
|
5435
|
-
retrack2(recompute, markDirty);
|
|
5436
|
-
if (!Object.is(oldValue, cs._v)) cs.__v++;
|
|
5437
|
-
} finally {
|
|
5438
|
-
evaluating = false;
|
|
5439
|
-
}
|
|
5440
|
-
if (hook && oldValue !== cs._v) {
|
|
5441
|
-
hook.emit("computed:update", { signal: cs, oldValue, newValue: cs._v });
|
|
5442
|
-
}
|
|
5443
|
-
}
|
|
5444
5788
|
return cs._v;
|
|
5445
5789
|
}
|
|
5446
5790
|
if (debugName) {
|
|
@@ -5630,6 +5974,28 @@ function strictEffect(fn) {
|
|
|
5630
5974
|
}
|
|
5631
5975
|
|
|
5632
5976
|
// src/platform/enhance.ts
|
|
5977
|
+
var ENHANCED_ATTR = "data-sibu-enhanced";
|
|
5978
|
+
var enhancementOwner = /* @__PURE__ */ new WeakMap();
|
|
5979
|
+
function drainTeardowns(teardowns, label2) {
|
|
5980
|
+
let executed = 0;
|
|
5981
|
+
while (teardowns.length > 0) {
|
|
5982
|
+
const batch2 = teardowns.splice(0);
|
|
5983
|
+
for (let i2 = 0; i2 < batch2.length; i2++) {
|
|
5984
|
+
if (executed >= MAX_DRAIN_TEARDOWNS) {
|
|
5985
|
+
const remaining = batch2.length - i2 + teardowns.length;
|
|
5986
|
+
teardowns.length = 0;
|
|
5987
|
+
reportDrainRunaway(label2, executed, remaining);
|
|
5988
|
+
return;
|
|
5989
|
+
}
|
|
5990
|
+
executed++;
|
|
5991
|
+
try {
|
|
5992
|
+
batch2[i2]();
|
|
5993
|
+
} catch (err) {
|
|
5994
|
+
if (typeof console !== "undefined") console.error(`[SibuJS ${label2}] teardown error:`, err);
|
|
5995
|
+
}
|
|
5996
|
+
}
|
|
5997
|
+
}
|
|
5998
|
+
}
|
|
5633
5999
|
function resolveTarget(root, target) {
|
|
5634
6000
|
if (target == null) return root;
|
|
5635
6001
|
if (typeof target !== "string") return target;
|
|
@@ -5672,7 +6038,7 @@ function enhance(target, setup) {
|
|
|
5672
6038
|
return () => {
|
|
5673
6039
|
};
|
|
5674
6040
|
}
|
|
5675
|
-
if (root.getAttribute(
|
|
6041
|
+
if (root.getAttribute(ENHANCED_ATTR) === "true") {
|
|
5676
6042
|
if (isDev() && typeof console !== "undefined") {
|
|
5677
6043
|
console.warn("[SibuJS enhance] element is already enhanced; ignoring re-enhance.", root);
|
|
5678
6044
|
}
|
|
@@ -5680,6 +6046,7 @@ function enhance(target, setup) {
|
|
|
5680
6046
|
};
|
|
5681
6047
|
}
|
|
5682
6048
|
const teardowns = [];
|
|
6049
|
+
const owner = /* @__PURE__ */ Symbol("sibujs.enhance");
|
|
5683
6050
|
let disposed = false;
|
|
5684
6051
|
const bind = (target_, fn) => {
|
|
5685
6052
|
const el = resolveTarget(root, target_);
|
|
@@ -5726,11 +6093,7 @@ function enhance(target, setup) {
|
|
|
5726
6093
|
effect(() => {
|
|
5727
6094
|
const v = value();
|
|
5728
6095
|
const next = v == null ? null : String(v);
|
|
5729
|
-
|
|
5730
|
-
if (el.hasAttribute(name)) el.removeAttribute(name);
|
|
5731
|
-
} else if (el.getAttribute(name) !== next) {
|
|
5732
|
-
el.setAttribute(name, next);
|
|
5733
|
-
}
|
|
6096
|
+
setSafeAttribute(el, name, next, { syncValueProperty: false, label: "enhance attr()" });
|
|
5734
6097
|
})
|
|
5735
6098
|
);
|
|
5736
6099
|
});
|
|
@@ -5757,10 +6120,10 @@ function enhance(target, setup) {
|
|
|
5757
6120
|
});
|
|
5758
6121
|
});
|
|
5759
6122
|
},
|
|
5760
|
-
model: (t,
|
|
6123
|
+
model: (t, state2, options) => {
|
|
5761
6124
|
bind(t, (el) => {
|
|
5762
6125
|
const control = el;
|
|
5763
|
-
const [get, set] =
|
|
6126
|
+
const [get, set] = state2;
|
|
5764
6127
|
const evt = options?.event ?? (control instanceof HTMLSelectElement || control instanceof HTMLInputElement && (control.type === "checkbox" || control.type === "radio") ? "change" : "input");
|
|
5765
6128
|
teardowns.push(
|
|
5766
6129
|
effect(() => {
|
|
@@ -5776,29 +6139,50 @@ function enhance(target, setup) {
|
|
|
5776
6139
|
teardowns.push(fn);
|
|
5777
6140
|
}
|
|
5778
6141
|
};
|
|
5779
|
-
|
|
6142
|
+
let extra;
|
|
6143
|
+
try {
|
|
6144
|
+
extra = setup(ctx);
|
|
6145
|
+
} catch (err) {
|
|
6146
|
+
drainTeardowns(teardowns, "enhance");
|
|
6147
|
+
throw err;
|
|
6148
|
+
}
|
|
5780
6149
|
if (typeof extra === "function") teardowns.push(extra);
|
|
5781
6150
|
const dispose2 = () => {
|
|
5782
6151
|
if (disposed) return;
|
|
5783
6152
|
disposed = true;
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
} catch (err) {
|
|
5788
|
-
if (typeof console !== "undefined") console.error("[SibuJS enhance] teardown error:", err);
|
|
5789
|
-
}
|
|
6153
|
+
if (enhancementOwner.get(root) === owner) {
|
|
6154
|
+
enhancementOwner.delete(root);
|
|
6155
|
+
root.removeAttribute(ENHANCED_ATTR);
|
|
5790
6156
|
}
|
|
6157
|
+
unregisterDisposer(root, dispose2);
|
|
6158
|
+
drainTeardowns(teardowns, "enhance");
|
|
5791
6159
|
};
|
|
5792
6160
|
registerDisposer(root, dispose2);
|
|
5793
|
-
|
|
6161
|
+
enhancementOwner.set(root, owner);
|
|
6162
|
+
root.setAttribute(ENHANCED_ATTR, "true");
|
|
5794
6163
|
return dispose2;
|
|
5795
6164
|
}
|
|
5796
6165
|
function enhanceAll(selector, setup) {
|
|
5797
6166
|
if (typeof document === "undefined") return () => {
|
|
5798
6167
|
};
|
|
5799
|
-
const disposers =
|
|
6168
|
+
const disposers = [];
|
|
6169
|
+
try {
|
|
6170
|
+
for (const el of Array.from(document.querySelectorAll(selector))) {
|
|
6171
|
+
disposers.push(enhance(el, setup));
|
|
6172
|
+
}
|
|
6173
|
+
} catch (err) {
|
|
6174
|
+
for (let i2 = disposers.length - 1; i2 >= 0; i2--) {
|
|
6175
|
+
try {
|
|
6176
|
+
disposers[i2]();
|
|
6177
|
+
} catch (rollbackErr) {
|
|
6178
|
+
if (typeof console !== "undefined") console.error("[SibuJS enhanceAll] rollback error:", rollbackErr);
|
|
6179
|
+
}
|
|
6180
|
+
}
|
|
6181
|
+
disposers.length = 0;
|
|
6182
|
+
throw err;
|
|
6183
|
+
}
|
|
5800
6184
|
return () => {
|
|
5801
|
-
for (const d of disposers) d();
|
|
6185
|
+
for (const d of disposers.splice(0)) d();
|
|
5802
6186
|
};
|
|
5803
6187
|
}
|
|
5804
6188
|
|
|
@@ -5838,6 +6222,7 @@ function mountIslands(root = typeof document !== "undefined" ? document : null,
|
|
|
5838
6222
|
};
|
|
5839
6223
|
const cancels = [];
|
|
5840
6224
|
const disposers = [];
|
|
6225
|
+
let torndown = false;
|
|
5841
6226
|
for (const el of Array.from(root.querySelectorAll("[data-sibu-island]"))) {
|
|
5842
6227
|
if (el.getAttribute("data-sibu-enhanced") === "true") continue;
|
|
5843
6228
|
const name = el.getAttribute("data-sibu-island") ?? "";
|
|
@@ -5851,17 +6236,23 @@ function mountIslands(root = typeof document !== "undefined" ? document : null,
|
|
|
5851
6236
|
}
|
|
5852
6237
|
let activated = false;
|
|
5853
6238
|
const activate = () => {
|
|
5854
|
-
if (activated) return;
|
|
6239
|
+
if (activated || torndown) return;
|
|
5855
6240
|
activated = true;
|
|
5856
6241
|
const reg = registry.get(name);
|
|
5857
6242
|
if (!reg) return;
|
|
5858
6243
|
resolveSetup(reg).then((setup) => {
|
|
6244
|
+
if (torndown) return;
|
|
5859
6245
|
if (!setup) {
|
|
5860
6246
|
if (typeof console !== "undefined") console.warn(`[SibuJS islands] "${name}" loader produced no setup.`);
|
|
5861
6247
|
return;
|
|
5862
6248
|
}
|
|
5863
6249
|
try {
|
|
5864
|
-
|
|
6250
|
+
const disposeIsland = enhance(el, setup);
|
|
6251
|
+
if (torndown) {
|
|
6252
|
+
disposeIsland();
|
|
6253
|
+
return;
|
|
6254
|
+
}
|
|
6255
|
+
disposers.push(disposeIsland);
|
|
5865
6256
|
el.setAttribute("data-sibu-hydrated", "true");
|
|
5866
6257
|
} catch (err) {
|
|
5867
6258
|
if (typeof console !== "undefined") console.error(`[SibuJS islands] "${name}" failed to mount:`, err);
|
|
@@ -5874,6 +6265,7 @@ function mountIslands(root = typeof document !== "undefined" ? document : null,
|
|
|
5874
6265
|
cancels.push(schedule(strategy, el, activate, options));
|
|
5875
6266
|
}
|
|
5876
6267
|
return () => {
|
|
6268
|
+
torndown = true;
|
|
5877
6269
|
for (const c of cancels.splice(0)) c();
|
|
5878
6270
|
for (const d of disposers.splice(0)) d();
|
|
5879
6271
|
};
|