sibujs 4.14.0 → 4.15.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.
Files changed (93) hide show
  1. package/dist/browser.cjs +297 -45
  2. package/dist/browser.js +6 -7
  3. package/dist/build.cjs +2189 -573
  4. package/dist/build.js +16 -15
  5. package/dist/cdn.dev.global.js +13 -12
  6. package/dist/cdn.full.dev.global.js +14 -13
  7. package/dist/cdn.full.global.js +12 -12
  8. package/dist/cdn.global.js +12 -12
  9. package/dist/{chunk-RVR5NPFL.js → chunk-2VKTFA7C.js} +1 -1
  10. package/dist/{chunk-7ILEHTVX.js → chunk-4AEFGRYW.js} +1 -1
  11. package/dist/{chunk-4TQDTWWN.js → chunk-6IV5ZRG6.js} +5 -7
  12. package/dist/{chunk-GVAMIU6K.js → chunk-75EAQH3U.js} +2 -2
  13. package/dist/{chunk-TLS4NVIB.js → chunk-7JO7DPSS.js} +4 -4
  14. package/dist/{chunk-SVULV7O4.js → chunk-AQH7WDSE.js} +6 -8
  15. package/dist/{chunk-S37PZD6I.js → chunk-BF3WBJJQ.js} +60 -10
  16. package/dist/{chunk-LJMX4SQ7.js → chunk-BG4BP44S.js} +3 -3
  17. package/dist/{chunk-N7A6FKWW.js → chunk-D44TAGCT.js} +2 -2
  18. package/dist/{chunk-CCKUNHVU.js → chunk-DAEXQJQA.js} +1 -1
  19. package/dist/chunk-DNCQDFJJ.js +22 -0
  20. package/dist/{chunk-BKZ5N6NK.js → chunk-DNCT2UXB.js} +4 -4
  21. package/dist/{chunk-BOYKGGVD.js → chunk-DRWOD7RZ.js} +4 -4
  22. package/dist/chunk-DS5V2PRE.js +64 -0
  23. package/dist/{chunk-VM2U5LEL.js → chunk-EHSJESRN.js} +595 -123
  24. package/dist/{chunk-MIRKTVH4.js → chunk-GFM5WWPU.js} +252 -5
  25. package/dist/{chunk-52XFPGSN.js → chunk-HTPOIAAL.js} +1 -1
  26. package/dist/{chunk-3HEX6QJQ.js → chunk-I2R5QALY.js} +2 -4
  27. package/dist/{chunk-4FJSAUKB.js → chunk-IUBV5WO5.js} +1 -1
  28. package/dist/{chunk-A454RAEK.js → chunk-KIDETDMU.js} +5 -7
  29. package/dist/{chunk-JTFQ7IL4.js → chunk-KPAXG5IR.js} +7 -9
  30. package/dist/{chunk-AE32RGWX.js → chunk-LGUXYHTZ.js} +3 -3
  31. package/dist/{chunk-Y4LUM2XS.js → chunk-LQWLPQOK.js} +6 -8
  32. package/dist/{chunk-CNPT6NKV.js → chunk-MINLMJUY.js} +48 -9
  33. package/dist/{chunk-BNXRWZZV.js → chunk-OURTGOJT.js} +8 -10
  34. package/dist/{chunk-F67F77IA.js → chunk-TQ24Y3IV.js} +2 -2
  35. package/dist/{chunk-2TTRW2TE.js → chunk-UM3M5PXS.js} +8 -8
  36. package/dist/{chunk-CJ7KS3DF.js → chunk-VSTX3XSX.js} +205 -15
  37. package/dist/{chunk-HQIAL7F2.js → chunk-XPDZ2LDR.js} +2 -2
  38. package/dist/{chunk-UUIKJJIK.js → chunk-Y7JM7GY2.js} +5 -7
  39. package/dist/{chunk-QS6GMWDD.js → chunk-YAFITBOK.js} +1269 -162
  40. package/dist/data.cjs +285 -33
  41. package/dist/data.js +6 -7
  42. package/dist/devtools.cjs +289 -39
  43. package/dist/devtools.js +5 -6
  44. package/dist/{dispose-EIHHHDC7.js → dispose-3WDBYJMH.js} +3 -1
  45. package/dist/ecosystem.cjs +345 -61
  46. package/dist/ecosystem.d.cts +1 -1
  47. package/dist/ecosystem.d.ts +1 -1
  48. package/dist/ecosystem.js +10 -10
  49. package/dist/extras.cjs +568 -248
  50. package/dist/extras.d.cts +1 -1
  51. package/dist/extras.d.ts +1 -1
  52. package/dist/extras.js +27 -27
  53. package/dist/index.cjs +2134 -515
  54. package/dist/index.d.cts +628 -211
  55. package/dist/index.d.ts +628 -211
  56. package/dist/index.js +22 -15
  57. package/dist/motion.cjs +286 -30
  58. package/dist/motion.js +4 -4
  59. package/dist/patterns.cjs +301 -43
  60. package/dist/patterns.js +6 -6
  61. package/dist/performance.cjs +286 -36
  62. package/dist/performance.js +9 -9
  63. package/dist/plugins.cjs +1237 -291
  64. package/dist/plugins.d.cts +3 -1
  65. package/dist/plugins.d.ts +3 -1
  66. package/dist/plugins.js +20 -19
  67. package/dist/{renderRoute-fxgsm2Ir.d.ts → renderRoute-B84MONaO.d.cts} +2 -2
  68. package/dist/{renderRoute-DP20XwMS.d.cts → renderRoute-_yxPuEQY.d.ts} +2 -2
  69. package/dist/{routeHead-CE9SV-cH.d.cts → routeHead-DLxlq15W.d.cts} +94 -0
  70. package/dist/{routeHead-DzVxPviY.d.ts → routeHead-w8nANZ3M.d.ts} +94 -0
  71. package/dist/{ssr-NECEU4X4.js → ssr-EF3IUHTE.js} +6 -6
  72. package/dist/ssr-dom.cjs +64 -9
  73. package/dist/ssr-dom.d.cts +2 -0
  74. package/dist/ssr-dom.d.ts +2 -0
  75. package/dist/ssr-dom.js +2 -1
  76. package/dist/ssr.cjs +850 -170
  77. package/dist/ssr.d.cts +5 -3
  78. package/dist/ssr.d.ts +5 -3
  79. package/dist/ssr.js +16 -15
  80. package/dist/{tagFactory-DkytnJws.d.cts → tagFactory-BfEh69VF.d.cts} +7 -0
  81. package/dist/{tagFactory-Bnd_Nph9.d.ts → tagFactory-pSYiLYyh.d.ts} +7 -0
  82. package/dist/testing.cjs +817 -132
  83. package/dist/testing.d.cts +4 -2
  84. package/dist/testing.d.ts +4 -2
  85. package/dist/testing.js +18 -17
  86. package/dist/track-core-0edROAF5.d.ts +187 -0
  87. package/dist/track-core-DN5fYLWi.d.cts +187 -0
  88. package/dist/ui.cjs +293 -43
  89. package/dist/ui.js +10 -12
  90. package/dist/widgets.cjs +285 -27
  91. package/dist/widgets.js +7 -7
  92. package/package.json +1 -1
  93. package/dist/chunk-7ZHH77QA.js +0 -9
package/dist/plugins.cjs CHANGED
@@ -751,6 +751,17 @@ var init_elementPolicy = __esm({
751
751
  }
752
752
  });
753
753
 
754
+ // src/utils/globalSingleton.ts
755
+ function globalSingleton(key, create) {
756
+ const g2 = globalThis;
757
+ return g2[key] ?? (g2[key] = create());
758
+ }
759
+ var init_globalSingleton = __esm({
760
+ "src/utils/globalSingleton.ts"() {
761
+ "use strict";
762
+ }
763
+ });
764
+
754
765
  // src/core/rendering/adoptScope.ts
755
766
  function inAdoptScope() {
756
767
  return current?.s.on === true;
@@ -889,6 +900,7 @@ __export(dispose_exports, {
889
900
  registerDisposer: () => registerDisposer,
890
901
  replaceChildrenSafely: () => replaceChildrenSafely,
891
902
  reportDrainRunaway: () => reportDrainRunaway,
903
+ stageReplaceChildren: () => stageReplaceChildren,
892
904
  unregisterDisposer: () => unregisterDisposer,
893
905
  withDisposerRollback: () => withDisposerRollback
894
906
  });
@@ -922,7 +934,7 @@ function registerDisposer(node, teardown) {
922
934
  elementDisposers.set(node, disposers);
923
935
  }
924
936
  disposers.push(teardown);
925
- if (DEV) activeBindingCount++;
937
+ if (DEV) bindings.count++;
926
938
  const capture = resolveCapture(registrationCaptures[registrationCaptures.length - 1]);
927
939
  if (capture) capture.entries.push([node, teardown]);
928
940
  }
@@ -975,7 +987,7 @@ function unregisterDisposer(node, teardown) {
975
987
  const index = disposers.indexOf(teardown);
976
988
  if (index === -1) return false;
977
989
  disposers.splice(index, 1);
978
- if (DEV) activeBindingCount--;
990
+ if (DEV) bindings.count--;
979
991
  if (disposers.length === 0) elementDisposers.delete(node);
980
992
  return true;
981
993
  }
@@ -999,17 +1011,17 @@ function disposeNodeOwn(node) {
999
1011
  let executed = 0;
1000
1012
  let runaway = false;
1001
1013
  while (!runaway) {
1002
- const pending = elementDisposers.get(node);
1003
- if (!pending || pending.length === 0) break;
1004
- const snapshot = pending.slice();
1014
+ const pending2 = elementDisposers.get(node);
1015
+ if (!pending2 || pending2.length === 0) break;
1016
+ const snapshot = pending2.slice();
1005
1017
  elementDisposers.delete(node);
1006
- if (DEV) activeBindingCount -= snapshot.length;
1018
+ if (DEV) bindings.count -= snapshot.length;
1007
1019
  for (let i2 = 0; i2 < snapshot.length; i2++) {
1008
1020
  if (executed >= MAX_DRAIN_TEARDOWNS) {
1009
1021
  const rest = snapshot.slice(i2);
1010
1022
  const added = elementDisposers.get(node);
1011
1023
  elementDisposers.set(node, added ? rest.concat(added) : rest);
1012
- if (DEV) activeBindingCount += rest.length;
1024
+ if (DEV) bindings.count += rest.length;
1013
1025
  reportDrainRunaway("dispose", executed, rest.length + (added?.length ?? 0));
1014
1026
  runaway = true;
1015
1027
  break;
@@ -1048,26 +1060,69 @@ function replaceChildrenSafely(parent, ...next) {
1048
1060
  }
1049
1061
  parent.replaceChildren(...next);
1050
1062
  }
1063
+ function stageReplaceChildren(parent, next) {
1064
+ const done = /* @__PURE__ */ new Set();
1065
+ const adopted = () => {
1066
+ if (!isHydrating() || next.length === 0 || next[0] !== parent.firstChild) return false;
1067
+ for (let i2 = 1; i2 < next.length; i2++) if (next[i2 - 1].nextSibling !== next[i2]) return false;
1068
+ return true;
1069
+ };
1070
+ const outgoing = () => {
1071
+ if (adopted()) {
1072
+ const out = [];
1073
+ for (let n = next[next.length - 1].nextSibling; n !== null; n = n.nextSibling) out.push(n);
1074
+ return out;
1075
+ }
1076
+ for (let i2 = 0; i2 < next.length; i2++) next[i2].parentNode?.removeChild(next[i2]);
1077
+ return Array.from(parent.childNodes);
1078
+ };
1079
+ return {
1080
+ teardown: () => {
1081
+ let ran = false;
1082
+ for (const node of outgoing()) {
1083
+ if (done.has(node)) continue;
1084
+ done.add(node);
1085
+ ran = true;
1086
+ dispose(node);
1087
+ }
1088
+ return ran;
1089
+ },
1090
+ insert: () => {
1091
+ if (!adopted()) {
1092
+ parent.replaceChildren(...next);
1093
+ return;
1094
+ }
1095
+ const last = next[next.length - 1];
1096
+ while (last.nextSibling) parent.removeChild(last.nextSibling);
1097
+ }
1098
+ };
1099
+ }
1051
1100
  function checkLeaks(warnThreshold = 0) {
1052
1101
  if (!DEV) return 0;
1053
- if (warnThreshold > 0 && activeBindingCount > warnThreshold) {
1102
+ if (warnThreshold > 0 && bindings.count > warnThreshold) {
1054
1103
  devWarn(
1055
- `checkLeaks: ${activeBindingCount} active DOM bindings detected. Expected \u2264${warnThreshold}. This may indicate a component was removed from the DOM without calling dispose().`
1104
+ `checkLeaks: ${bindings.count} active DOM bindings detected. Expected \u2264${warnThreshold}. This may indicate a component was removed from the DOM without calling dispose().`
1056
1105
  );
1057
1106
  }
1058
- return activeBindingCount;
1107
+ return bindings.count;
1059
1108
  }
1060
- var elementDisposers, MAX_DRAIN_TEARDOWNS, activeBindingCount, registrationCaptures;
1109
+ var state2, elementDisposers, MAX_DRAIN_TEARDOWNS, bindings, registrationCaptures;
1061
1110
  var init_dispose = __esm({
1062
1111
  "src/core/rendering/dispose.ts"() {
1063
1112
  "use strict";
1113
+ init_globalSingleton();
1064
1114
  init_dev();
1065
1115
  init_errors();
1066
1116
  init_hydrationHooks();
1067
- elementDisposers = /* @__PURE__ */ new WeakMap();
1117
+ state2 = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.disposers.v1"), () => ({
1118
+ disposers: /* @__PURE__ */ new WeakMap(),
1119
+ captures: [],
1120
+ bindings: { count: 0 }
1121
+ }));
1122
+ elementDisposers = state2.disposers;
1068
1123
  MAX_DRAIN_TEARDOWNS = 1e4;
1069
- activeBindingCount = 0;
1070
- registrationCaptures = [];
1124
+ bindings = state2.bindings;
1125
+ registrationCaptures = state2.captures;
1071
1126
  }
1072
1127
  });
1073
1128
 
@@ -1222,6 +1277,178 @@ function bindOwnerScope(fn) {
1222
1277
  if (scope === null) return fn;
1223
1278
  return (...args) => runWithOwnerScope(scope, () => fn(...args));
1224
1279
  }
1280
+ function ownerState(tok) {
1281
+ let state5 = ACTIVE;
1282
+ for (let t2 = tok; t2 !== null; ) {
1283
+ const o = t2.sub;
1284
+ if (o === null) return ENDED;
1285
+ if (o._frozen === true) state5 = PAUSED;
1286
+ t2 = o._owner ?? null;
1287
+ }
1288
+ return state5;
1289
+ }
1290
+ function queueStateCheck() {
1291
+ if (stateCheckQueued || stateWatchers.size === 0) return;
1292
+ stateCheckQueued = true;
1293
+ queueMicrotask(() => {
1294
+ stateCheckQueued = false;
1295
+ for (const watcher of [...stateWatchers]) {
1296
+ if (!stateWatchers.has(watcher)) continue;
1297
+ const state5 = watcher.check.state();
1298
+ if (state5 === ENDED) stateWatchers.delete(watcher);
1299
+ if (state5 === ENDED || state5 === watcher.last) continue;
1300
+ watcher.last = state5;
1301
+ try {
1302
+ watcher.listener(state5);
1303
+ } catch (err) {
1304
+ reportError(err, { phase: "effect" });
1305
+ }
1306
+ }
1307
+ });
1308
+ }
1309
+ function captureFrozen() {
1310
+ const tok = currentStructOwner;
1311
+ if (tok === null) return ALWAYS_ACTIVE;
1312
+ const state5 = () => ownerState(tok);
1313
+ const check = Object.assign(() => state5() !== ACTIVE, {
1314
+ state: state5,
1315
+ wait: (onActive, onEnd) => {
1316
+ const now = state5();
1317
+ if (now !== PAUSED) {
1318
+ (now === ACTIVE ? onActive : onEnd)();
1319
+ return NOOP;
1320
+ }
1321
+ const waiter = { check, onActive, onEnd };
1322
+ waiters.add(waiter);
1323
+ return () => {
1324
+ waiters.delete(waiter);
1325
+ };
1326
+ },
1327
+ onEnd: (onEnd) => {
1328
+ if (state5() === ENDED) {
1329
+ onEnd();
1330
+ return NOOP;
1331
+ }
1332
+ const watcher = { check, onActive: NOOP, onEnd };
1333
+ endWatchers.add(watcher);
1334
+ return () => {
1335
+ endWatchers.delete(watcher);
1336
+ };
1337
+ },
1338
+ run: (fn) => {
1339
+ const prev = currentStructOwner;
1340
+ currentStructOwner = tok.sub === null ? null : tok;
1341
+ try {
1342
+ return fn();
1343
+ } finally {
1344
+ currentStructOwner = prev;
1345
+ }
1346
+ },
1347
+ onChange: (listener) => {
1348
+ const last = state5();
1349
+ if (last === ENDED) return NOOP;
1350
+ const watcher = { check, last, listener };
1351
+ stateWatchers.add(watcher);
1352
+ return () => {
1353
+ stateWatchers.delete(watcher);
1354
+ };
1355
+ },
1356
+ within: (owner) => {
1357
+ const target = owner.run(() => currentStructOwner);
1358
+ if (target === null) return false;
1359
+ for (let t2 = tok; t2 !== null; ) {
1360
+ if (t2 === target) return true;
1361
+ const o = t2.sub;
1362
+ if (o === null) return false;
1363
+ t2 = o._owner ?? null;
1364
+ }
1365
+ return false;
1366
+ }
1367
+ });
1368
+ return check;
1369
+ }
1370
+ function holdSubtree(root) {
1371
+ heldRoots.add(root);
1372
+ return () => {
1373
+ if (heldRoots.delete(root)) settleHeld();
1374
+ };
1375
+ }
1376
+ function isHeld(sub2) {
1377
+ if (frozenOwners !== 0 && hasFrozenOwner(sub2)) return true;
1378
+ if (heldRoots.size !== 0) {
1379
+ const node = sub2._errorNode;
1380
+ if (node != null) {
1381
+ for (const root of heldRoots) if (root.contains(node)) return true;
1382
+ }
1383
+ }
1384
+ return false;
1385
+ }
1386
+ function notifyEnded() {
1387
+ for (const watcher of stateWatchers) if (watcher.check.state() === ENDED) stateWatchers.delete(watcher);
1388
+ let ended = null;
1389
+ for (const watcher of endWatchers) {
1390
+ if (watcher.check.state() !== ENDED) continue;
1391
+ endWatchers.delete(watcher);
1392
+ (ended ?? (ended = [])).push(watcher);
1393
+ }
1394
+ if (ended === null) return;
1395
+ for (const watcher of ended) {
1396
+ try {
1397
+ watcher.onEnd();
1398
+ } catch (err) {
1399
+ reportError(err, { phase: "cleanup" });
1400
+ }
1401
+ }
1402
+ }
1403
+ function dropReleasedSkipped() {
1404
+ for (const sub2 of skippedWhileHeld) {
1405
+ if (sub2._disposed === true || sub2.depsHead == null) skippedWhileHeld.delete(sub2);
1406
+ }
1407
+ }
1408
+ function settleHeld() {
1409
+ for (const sub2 of skippedWhileHeld) {
1410
+ if (sub2._disposed === true) skippedWhileHeld.delete(sub2);
1411
+ else if (!isHeld(sub2)) {
1412
+ skippedWhileHeld.delete(sub2);
1413
+ if (!pendingSet.has(sub2)) {
1414
+ pendingSet.add(sub2);
1415
+ pendingQueue.push(sub2);
1416
+ }
1417
+ }
1418
+ }
1419
+ if (frozenOwners === 0 && heldRoots.size === 0) skippedWhileHeld.clear();
1420
+ let ready = null;
1421
+ for (const waiter of waiters) {
1422
+ if (waiter.check.state() === PAUSED) continue;
1423
+ waiters.delete(waiter);
1424
+ (ready ?? (ready = [])).push(waiter);
1425
+ }
1426
+ if (ready !== null) {
1427
+ const settle = ready;
1428
+ queueMicrotask(() => {
1429
+ for (const waiter of settle) {
1430
+ const state5 = waiter.check.state();
1431
+ if (state5 === PAUSED) waiters.add(waiter);
1432
+ else
1433
+ try {
1434
+ (state5 === ACTIVE ? waiter.onActive : waiter.onEnd)();
1435
+ } catch (err) {
1436
+ reportError(err, { phase: "effect" });
1437
+ }
1438
+ }
1439
+ });
1440
+ }
1441
+ if (pendingQueue.length > 0) drainNotificationQueue();
1442
+ }
1443
+ function hasFrozenOwner(sub2) {
1444
+ for (let t2 = sub2._owner ?? null; t2 !== null; ) {
1445
+ const o = t2.sub;
1446
+ if (o === null) return false;
1447
+ if (o._frozen === true) return true;
1448
+ t2 = o._owner ?? null;
1449
+ }
1450
+ return false;
1451
+ }
1225
1452
  function retrack(effectFn, subscriber) {
1226
1453
  const prev = currentSubscriber;
1227
1454
  let savedDepth = 0;
@@ -1328,6 +1555,20 @@ function structuralBinding(commit, ownerNode) {
1328
1555
  } finally {
1329
1556
  currentStructOwner = prev;
1330
1557
  }
1558
+ },
1559
+ freeze: () => {
1560
+ const s2 = sub2;
1561
+ if (s2._disposed || s2._frozen) return;
1562
+ s2._frozen = true;
1563
+ frozenOwners++;
1564
+ queueStateCheck();
1565
+ },
1566
+ thaw: () => {
1567
+ if (!sub2._frozen) return;
1568
+ sub2._frozen = false;
1569
+ frozenOwners--;
1570
+ queueStateCheck();
1571
+ settleHeld();
1331
1572
  }
1332
1573
  };
1333
1574
  }
@@ -1356,20 +1597,34 @@ function createBinding(commit, ownerNode, structural) {
1356
1597
  subscriber._errorNode = ownerNode;
1357
1598
  subscriber._tok = null;
1358
1599
  subscriber._owner = null;
1600
+ subscriber._frozen = false;
1359
1601
  if (structural) subscriber._tok = { sub: subscriber };
1360
1602
  try {
1361
1603
  run();
1362
1604
  } catch (err) {
1363
1605
  subscriber._disposed = true;
1364
1606
  subscriber._errorNode = void 0;
1365
- if (subscriber._tok != null) subscriber._tok.sub = null;
1607
+ if (subscriber._tok != null) {
1608
+ subscriber._tok.sub = null;
1609
+ if (endWatchers.size !== 0 || stateWatchers.size !== 0) notifyEnded();
1610
+ }
1366
1611
  cleanup(subscriber);
1367
1612
  throw err;
1368
1613
  }
1369
1614
  subscriber._dispose = () => {
1370
1615
  subscriber._disposed = true;
1616
+ const wasFrozen = subscriber._frozen === true;
1617
+ if (wasFrozen) {
1618
+ subscriber._frozen = false;
1619
+ frozenOwners--;
1620
+ }
1371
1621
  subscriber._errorNode = void 0;
1372
- if (subscriber._tok != null) subscriber._tok.sub = null;
1622
+ if (subscriber._tok != null) {
1623
+ subscriber._tok.sub = null;
1624
+ if (endWatchers.size !== 0 || stateWatchers.size !== 0) notifyEnded();
1625
+ if (skippedWhileHeld.size !== 0) dropReleasedSkipped();
1626
+ if (wasFrozen || waiters.size !== 0) settleHeld();
1627
+ }
1373
1628
  cleanup(subscriber);
1374
1629
  };
1375
1630
  return subscriber;
@@ -1475,6 +1730,10 @@ function runPendingOwners(sub2) {
1475
1730
  }
1476
1731
  }
1477
1732
  function runQueued(sub2) {
1733
+ if ((frozenOwners !== 0 || heldRoots.size !== 0) && isHeld(sub2)) {
1734
+ skippedWhileHeld.add(sub2);
1735
+ return;
1736
+ }
1478
1737
  if (quarantined.size > 0 && quarantined.has(sub2)) return;
1479
1738
  if (sub2._hasComputedDep === true && !depsChanged(sub2)) return;
1480
1739
  if (tickRepeat(sub2)) {
@@ -1620,7 +1879,7 @@ function forEachSubscriber(signal2, visit) {
1620
1879
  node = node.sigNext;
1621
1880
  }
1622
1881
  }
1623
- var POOL_MAX, nodePool, currentSubscriber, suspendSavedSub, notifyDepth, pendingQueue, pendingSet, propagateStack, suspendDepth, trackingSuspended, currentOwnerScope, currentStructOwner, subscriberEpochCounter, maxSubscriberRepeats, maxDrainIterations, drainEpoch, quarantined;
1882
+ var POOL_MAX, nodePool, currentSubscriber, suspendSavedSub, notifyDepth, pendingQueue, pendingSet, propagateStack, suspendDepth, trackingSuspended, currentOwnerScope, currentStructOwner, frozenOwners, ACTIVE, PAUSED, ENDED, NOOP, skippedWhileHeld, waiters, heldRoots, endWatchers, stateWatchers, stateCheckQueued, ALWAYS_ACTIVE, subscriberEpochCounter, maxSubscriberRepeats, maxDrainIterations, drainEpoch, quarantined;
1624
1883
  var init_track_core = __esm({
1625
1884
  "src/reactivity/track-core.ts"() {
1626
1885
  "use strict";
@@ -1638,6 +1897,29 @@ var init_track_core = __esm({
1638
1897
  trackingSuspended = false;
1639
1898
  currentOwnerScope = null;
1640
1899
  currentStructOwner = null;
1900
+ frozenOwners = 0;
1901
+ ACTIVE = 0;
1902
+ PAUSED = 1;
1903
+ ENDED = 2;
1904
+ NOOP = () => {
1905
+ };
1906
+ skippedWhileHeld = /* @__PURE__ */ new Set();
1907
+ waiters = /* @__PURE__ */ new Set();
1908
+ heldRoots = /* @__PURE__ */ new Set();
1909
+ endWatchers = /* @__PURE__ */ new Set();
1910
+ stateWatchers = /* @__PURE__ */ new Set();
1911
+ stateCheckQueued = false;
1912
+ ALWAYS_ACTIVE = Object.assign(() => false, {
1913
+ state: () => ACTIVE,
1914
+ wait: (onActive) => {
1915
+ onActive();
1916
+ return NOOP;
1917
+ },
1918
+ onEnd: () => NOOP,
1919
+ run: (fn) => fn(),
1920
+ onChange: () => NOOP,
1921
+ within: () => false
1922
+ });
1641
1923
  subscriberEpochCounter = 0;
1642
1924
  maxSubscriberRepeats = 1e3;
1643
1925
  maxDrainIterations = 1e6;
@@ -1681,18 +1963,20 @@ function resolveReactiveApi() {
1681
1963
  runWithOwnerScope,
1682
1964
  bindOwnerScope,
1683
1965
  structuralBinding,
1966
+ captureFrozen,
1967
+ holdSubtree,
1684
1968
  version: _runtimeVersion
1685
1969
  };
1686
1970
  g2[REGISTRY_KEY] = local;
1687
1971
  return local;
1688
1972
  }
1689
- var _runtimeVersion, REGISTRY_KEY, API, suspendTracking2, resumeTracking2, isTrackingSuspended2, untracked2, retrack2, track2, reactiveBinding2, recordDependency2, cleanup2, setMaxSubscriberRepeats2, setMaxDrainIterations2, drainNotificationQueue2, queueSignalNotification2, notifySubscribers2, getSubscriberCount2, getSubscriberDeps2, forEachSubscriber2, getOwnerScope2, runWithOwnerScope2, bindOwnerScope2, structuralBinding2;
1973
+ var _runtimeVersion, REGISTRY_KEY, API, suspendTracking2, resumeTracking2, isTrackingSuspended2, untracked2, retrack2, track2, reactiveBinding2, recordDependency2, cleanup2, setMaxSubscriberRepeats2, setMaxDrainIterations2, drainNotificationQueue2, queueSignalNotification2, notifySubscribers2, getSubscriberCount2, getSubscriberDeps2, forEachSubscriber2, getOwnerScope2, runWithOwnerScope2, bindOwnerScope2, structuralBinding2, captureFrozen2, holdSubtree2;
1690
1974
  var init_track = __esm({
1691
1975
  "src/reactivity/track.ts"() {
1692
1976
  "use strict";
1693
1977
  init_dev();
1694
1978
  init_track_core();
1695
- _runtimeVersion = true ? "4.14.0" : "dev";
1979
+ _runtimeVersion = true ? "4.15.0" : "dev";
1696
1980
  REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
1697
1981
  API = resolveReactiveApi();
1698
1982
  suspendTracking2 = API.suspendTracking;
@@ -1716,30 +2000,46 @@ var init_track = __esm({
1716
2000
  runWithOwnerScope2 = API.runWithOwnerScope ?? runWithOwnerScope;
1717
2001
  bindOwnerScope2 = API.bindOwnerScope ?? bindOwnerScope;
1718
2002
  structuralBinding2 = API.structuralBinding ?? ((commit, ownerNode) => ({ stop: API.reactiveBinding(commit, ownerNode), run: (fn) => fn() }));
2003
+ captureFrozen2 = API.captureFrozen ?? (() => Object.assign(() => false, {
2004
+ state: () => 0,
2005
+ wait: (onActive) => {
2006
+ onActive();
2007
+ return () => {
2008
+ };
2009
+ },
2010
+ onEnd: () => () => {
2011
+ },
2012
+ run: (fn) => fn(),
2013
+ onChange: () => () => {
2014
+ },
2015
+ within: () => false
2016
+ }));
2017
+ holdSubtree2 = API.holdSubtree ?? (() => () => {
2018
+ });
1719
2019
  }
1720
2020
  });
1721
2021
 
1722
2022
  // src/core/rendering/streamBoundary.ts
1723
2023
  function currentBoundary() {
1724
- return slot3.current;
2024
+ return slot2.current;
1725
2025
  }
1726
2026
  function runInBoundary(boundary, fn) {
1727
- const prev = slot3.current;
1728
- slot3.current = boundary;
2027
+ const prev = slot2.current;
2028
+ slot2.current = boundary;
1729
2029
  try {
1730
2030
  return fn();
1731
2031
  } finally {
1732
- slot3.current = prev;
2032
+ slot2.current = prev;
1733
2033
  }
1734
2034
  }
1735
2035
  function setBoundaryHook(hook) {
1736
- slot3.hook = hook;
2036
+ slot2.hook = hook;
1737
2037
  }
1738
- var _a2, slot3;
2038
+ var _a2, slot2;
1739
2039
  var init_streamBoundary = __esm({
1740
2040
  "src/core/rendering/streamBoundary.ts"() {
1741
2041
  "use strict";
1742
- slot3 = globalThis[_a2 = /* @__PURE__ */ Symbol.for("sibujs.streamBoundary.v1")] ?? (globalThis[_a2] = { hook: null, current: null });
2042
+ slot2 = globalThis[_a2 = /* @__PURE__ */ Symbol.for("sibujs.streamBoundary.v1")] ?? (globalThis[_a2] = { hook: null, current: null });
1743
2043
  }
1744
2044
  });
1745
2045
 
@@ -1836,14 +2136,14 @@ function runInSSRContext(fn) {
1836
2136
  }
1837
2137
  function trackPending(promise, label2, hydration = true) {
1838
2138
  const store = getRequestStore();
1839
- const pending = store?.pending;
1840
- const sessions = pending || !hydration ? [] : hydrationOwners();
1841
- if (!pending && sessions.length === 0) return promise;
2139
+ const pending2 = store?.pending;
2140
+ const sessions = pending2 || !hydration ? [] : hydrationOwners();
2141
+ if (!pending2 && sessions.length === 0) return promise;
1842
2142
  const entry = { label: label2, since: Date.now(), boundary: currentBoundary() ?? void 0 };
1843
- pending?.add(entry);
2143
+ pending2?.add(entry);
1844
2144
  const release = holdHydration(sessions, entry);
1845
2145
  const done = () => {
1846
- pending?.delete(entry);
2146
+ pending2?.delete(entry);
1847
2147
  store?.wake?.();
1848
2148
  release();
1849
2149
  };
@@ -1871,14 +2171,28 @@ var init_ssr_context = __esm({
1871
2171
  }
1872
2172
  });
1873
2173
 
1874
- // src/utils/globalSingleton.ts
1875
- function globalSingleton(key, create) {
1876
- const g2 = globalThis;
1877
- return g2[key] ?? (g2[key] = create());
1878
- }
1879
- var init_globalSingleton = __esm({
1880
- "src/utils/globalSingleton.ts"() {
2174
+ // src/utils/styleKey.ts
2175
+ function styleKeyToProperty(key) {
2176
+ let name = cache.get(key);
2177
+ if (name !== void 0) return name;
2178
+ if (key.startsWith("--")) name = key;
2179
+ else if (Object.hasOwn(EXCEPTIONS, key)) name = EXCEPTIONS[key];
2180
+ else {
2181
+ name = key.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
2182
+ if (VENDOR_PREFIX.test(name)) name = `-${name}`;
2183
+ }
2184
+ if (cache.size >= CACHE_MAX) cache.clear();
2185
+ cache.set(key, name);
2186
+ return name;
2187
+ }
2188
+ var EXCEPTIONS, VENDOR_PREFIX, cache, CACHE_MAX;
2189
+ var init_styleKey = __esm({
2190
+ "src/utils/styleKey.ts"() {
1881
2191
  "use strict";
2192
+ EXCEPTIONS = { cssFloat: "float" };
2193
+ VENDOR_PREFIX = /^(webkit|moz|ms|o)-/;
2194
+ cache = /* @__PURE__ */ new Map();
2195
+ CACHE_MAX = 1e3;
1882
2196
  }
1883
2197
  });
1884
2198
 
@@ -2019,7 +2333,7 @@ var init_serverHead = __esm({
2019
2333
  // src/utils/embedPolicy.ts
2020
2334
  function currentEmbedAllowlist() {
2021
2335
  const scoped = getRequestStore()?.caches?.get(REQUEST_CACHE)?.get("allowed");
2022
- return scoped ?? state2.allowed;
2336
+ return scoped ?? state4.allowed;
2023
2337
  }
2024
2338
  function resolveEmbedSrc(value, allowed = currentEmbedAllowlist()) {
2025
2339
  if (typeof value !== "string" || sanitizeUrl(value) === "") return null;
@@ -2062,7 +2376,7 @@ function narrowEmbedAllow(value) {
2062
2376
  return granted.filter((feature) => !denied.includes(feature)).join("; ");
2063
2377
  }
2064
2378
  function getEmbedRecord(frame) {
2065
- return state2.frames.get(frame);
2379
+ return state4.frames.get(frame);
2066
2380
  }
2067
2381
  function intersect(current2, permitted, separator) {
2068
2382
  const allowed = permitted.split(separator);
@@ -2107,14 +2421,14 @@ function embedSerializationTail(record, seen) {
2107
2421
  if (seen.fullscreen) tail += ' allowfullscreen=""';
2108
2422
  return tail;
2109
2423
  }
2110
- var state2, REQUEST_CACHE, DEFAULT_EMBED_SANDBOX, EMBED_FEATURES;
2424
+ var state4, REQUEST_CACHE, DEFAULT_EMBED_SANDBOX, EMBED_FEATURES;
2111
2425
  var init_embedPolicy = __esm({
2112
2426
  "src/utils/embedPolicy.ts"() {
2113
2427
  "use strict";
2114
2428
  init_ssr_context();
2115
2429
  init_globalSingleton();
2116
2430
  init_sanitize();
2117
- state2 = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.embed.v2"), () => ({
2431
+ state4 = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.embed.v2"), () => ({
2118
2432
  allowed: [],
2119
2433
  frames: /* @__PURE__ */ new WeakMap()
2120
2434
  }));
@@ -2277,23 +2591,18 @@ function splitDeclarations(text2) {
2277
2591
  out.push(text2.slice(start));
2278
2592
  return out;
2279
2593
  }
2280
- function toKebab2(prop) {
2281
- if (prop.startsWith("--")) return prop;
2282
- if (Object.hasOwn(CAMEL_EXCEPTIONS, prop)) return CAMEL_EXCEPTIONS[prop];
2283
- return prop.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`).replace(/^(webkit|moz|ms)-/, "-$1-");
2284
- }
2285
2594
  function styleProxy(style2) {
2286
2595
  return new Proxy(style2, {
2287
2596
  get(target, key, receiver) {
2288
2597
  if (typeof key === "string" && !(key in target)) {
2289
2598
  if (/^\d+$/.test(key)) return target.item(Number(key));
2290
- return target.getPropertyValue(toKebab2(key));
2599
+ return target.getPropertyValue(styleKeyToProperty(key));
2291
2600
  }
2292
2601
  return Reflect.get(target, key, receiver);
2293
2602
  },
2294
2603
  set(target, key, value, receiver) {
2295
2604
  if (typeof key === "string" && !(key in target)) {
2296
- target.setProperty(toKebab2(key), value == null ? "" : String(value));
2605
+ target.setProperty(styleKeyToProperty(key), value == null ? "" : String(value));
2297
2606
  return true;
2298
2607
  }
2299
2608
  return Reflect.set(target, key, value, receiver);
@@ -2314,6 +2623,11 @@ function reflectDisabled(proto) {
2314
2623
  configurable: true
2315
2624
  });
2316
2625
  }
2626
+ function singleSelectOf(option2) {
2627
+ let parent = option2.parentNode;
2628
+ if (parent instanceof ServerElement && parent.localName === "optgroup") parent = parent.parentNode;
2629
+ return parent instanceof ServerSelectElement && !parent.hasAttribute("multiple") ? parent : null;
2630
+ }
2317
2631
  function cssEscapeIdent(value) {
2318
2632
  return value.replace(/([^A-Za-z0-9_-])/g, "\\$1");
2319
2633
  }
@@ -2330,21 +2644,21 @@ function compileSelector(selector) {
2330
2644
  const tokens = text2.match(/(?:\\.|\[[^\]]*\]|[^\s>])+|>/g) ?? [];
2331
2645
  const compounds = [];
2332
2646
  const combinators = [];
2333
- let pending = " ";
2647
+ let pending2 = " ";
2334
2648
  let scoped = false;
2335
2649
  for (const token of tokens) {
2336
2650
  if (token === ">") {
2337
- pending = ">";
2651
+ pending2 = ">";
2338
2652
  continue;
2339
2653
  }
2340
2654
  if (token === ":scope") {
2341
2655
  scoped = true;
2342
- pending = " ";
2656
+ pending2 = " ";
2343
2657
  continue;
2344
2658
  }
2345
- if (compounds.length > 0) combinators.unshift(pending);
2659
+ if (compounds.length > 0) combinators.unshift(pending2);
2346
2660
  compounds.unshift(parseCompound(token, selector));
2347
- pending = " ";
2661
+ pending2 = " ";
2348
2662
  }
2349
2663
  if (compounds.length === 0) throw syntaxError(selector);
2350
2664
  groups.push({ compounds, combinators, scoped });
@@ -2570,12 +2884,13 @@ function explainServerError(err) {
2570
2884
  function ensureServerDom() {
2571
2885
  if (typeof document === "undefined") installServerDom();
2572
2886
  }
2573
- var HTML_NS3, SVG_NS4, MATHML_NS, ELEMENT_NODE, ATTRIBUTE_NODE, TEXT_NODE, COMMENT_NODE, DOCUMENT_NODE, DOCUMENT_FRAGMENT_NODE, warnedSites, NAME_RE, ServerNodeList, observations, ServerMutationObserver, _ServerNode, ServerNode, ServerCharacterData, ServerText, ServerComment, ServerDocumentFragment, ServerAttr, ServerNamedNodeMap, CAMEL_EXCEPTIONS, ServerStyle, ServerTokenList, ServerElement, ServerHTMLElement, ServerInputElement, ServerTextAreaElement, ServerOptionElement, ServerSelectElement, ServerButtonElement, ServerDisableableElement, ServerCanvasElement, ServerDialogElement, ServerMediaElement, ServerTemplateElement, ServerSVGElement, ServerMathMLElement, HTML_CLASSES, NODE_FILTER, ServerTreeWalker, ServerDocument, selectorCache, VOID, INSTALLED, BROWSER_GLOBALS, WATCHED, BROWSER_ONLY_NAMES;
2887
+ var HTML_NS3, SVG_NS4, MATHML_NS, ELEMENT_NODE, ATTRIBUTE_NODE, TEXT_NODE, COMMENT_NODE, DOCUMENT_NODE, DOCUMENT_FRAGMENT_NODE, warnedSites, NAME_RE, ServerNodeList, observations, ServerMutationObserver, _ServerNode, ServerNode, ServerCharacterData, ServerText, ServerComment, ServerDocumentFragment, ServerAttr, ServerNamedNodeMap, ServerStyle, ServerTokenList, ServerElement, ServerHTMLElement, ServerInputElement, ServerTextAreaElement, ServerOptionElement, ServerSelectElement, ServerButtonElement, ServerDisableableElement, ServerCanvasElement, ServerDialogElement, ServerMediaElement, ServerTemplateElement, ServerSVGElement, ServerMathMLElement, HTML_CLASSES, NODE_FILTER, ServerTreeWalker, ServerDocument, selectorCache, VOID, INSTALLED, BROWSER_GLOBALS, WATCHED, BROWSER_ONLY_NAMES;
2574
2888
  var init_serverDom = __esm({
2575
2889
  "src/platform/serverDom.ts"() {
2576
2890
  "use strict";
2577
2891
  init_dev();
2578
2892
  init_ssr_context();
2893
+ init_styleKey();
2579
2894
  HTML_NS3 = "http://www.w3.org/1999/xhtml";
2580
2895
  SVG_NS4 = "http://www.w3.org/2000/svg";
2581
2896
  MATHML_NS = "http://www.w3.org/1998/Math/MathML";
@@ -3147,9 +3462,15 @@ var init_serverDom = __esm({
3147
3462
  get nodeValue() {
3148
3463
  return this._value;
3149
3464
  }
3465
+ set nodeValue(v) {
3466
+ this.value = v;
3467
+ }
3150
3468
  get textContent() {
3151
3469
  return this._value;
3152
3470
  }
3471
+ set textContent(v) {
3472
+ this.value = v;
3473
+ }
3153
3474
  };
3154
3475
  ServerNamedNodeMap = class extends Array {
3155
3476
  static get [Symbol.species]() {
@@ -3165,7 +3486,6 @@ var init_serverDom = __esm({
3165
3486
  return this.find((a2) => a2.namespaceURI === (ns || null) && a2.localName === localName) ?? null;
3166
3487
  }
3167
3488
  };
3168
- CAMEL_EXCEPTIONS = { cssFloat: "float" };
3169
3489
  ServerStyle = class {
3170
3490
  constructor(el) {
3171
3491
  this.el = el;
@@ -3639,6 +3959,10 @@ var init_serverDom = __esm({
3639
3959
  get defaultChecked() {
3640
3960
  return this.hasAttribute("checked");
3641
3961
  }
3962
+ /** Reflects to the `checked` attribute; `checked` follows it until written (dirty checkedness). */
3963
+ set defaultChecked(v) {
3964
+ this.toggleAttribute("checked", !!v);
3965
+ }
3642
3966
  get type() {
3643
3967
  return (this.getAttribute("type") ?? "text").toLowerCase();
3644
3968
  }
@@ -3696,8 +4020,10 @@ var init_serverDom = __esm({
3696
4020
  ServerOptionElement = class extends ServerHTMLElement {
3697
4021
  constructor() {
3698
4022
  super(...arguments);
3699
- /** @internal */
4023
+ /** Selectedness; `null` while it follows the `selected` attribute. @internal */
3700
4024
  this._selected = null;
4025
+ /** Set by a `selected` write: the attribute no longer decides selectedness. @internal */
4026
+ this._dirty = false;
3701
4027
  }
3702
4028
  get value() {
3703
4029
  return this.getAttribute("value") ?? this.text;
@@ -3714,18 +4040,43 @@ var init_serverDom = __esm({
3714
4040
  get label() {
3715
4041
  return this.getAttribute("label") ?? this.text;
3716
4042
  }
4043
+ set label(v) {
4044
+ this.setAttribute("label", v);
4045
+ }
3717
4046
  get selected() {
3718
4047
  return this._selected ?? this.hasAttribute("selected");
3719
4048
  }
3720
4049
  set selected(v) {
3721
4050
  this._selected = !!v;
4051
+ this._dirty = true;
4052
+ const select2 = singleSelectOf(this);
4053
+ if (select2 && v) {
4054
+ for (const o of select2.options) if (o !== this) o._selected = false;
4055
+ }
3722
4056
  }
3723
4057
  get defaultSelected() {
3724
4058
  return this.hasAttribute("selected");
3725
4059
  }
4060
+ /** Reflects to the `selected` attribute; `selected` follows it unless written. */
4061
+ set defaultSelected(v) {
4062
+ this.toggleAttribute("selected", !!v);
4063
+ if (this._dirty) return;
4064
+ this._selected = null;
4065
+ const select2 = singleSelectOf(this);
4066
+ if (!select2) return;
4067
+ let last = null;
4068
+ for (const o of select2.options) if (o.selected) last = o;
4069
+ for (const o of select2.options) if (o !== last && o.selected) o._selected = false;
4070
+ }
3726
4071
  };
3727
4072
  reflectDisabled(ServerOptionElement.prototype);
3728
4073
  ServerSelectElement = class extends ServerHTMLElement {
4074
+ get multiple() {
4075
+ return this.hasAttribute("multiple");
4076
+ }
4077
+ set multiple(v) {
4078
+ this.toggleAttribute("multiple", !!v);
4079
+ }
3729
4080
  get options() {
3730
4081
  return this.querySelectorAll("option");
3731
4082
  }
@@ -4222,12 +4573,12 @@ async function hydrateAdopt(component, container, options = {}) {
4222
4573
  inScope(rootScope, () => session.place(container, tree));
4223
4574
  }
4224
4575
  const deadline = Date.now() + (options.timeout ?? 1e4);
4225
- const { pending, wake } = hydration;
4576
+ const { pending: pending2, wake } = hydration;
4226
4577
  for (; ; ) {
4227
4578
  await macrotask();
4228
- if (pending.size === 0) {
4579
+ if (pending2.size === 0) {
4229
4580
  await macrotask();
4230
- if (pending.size === 0) break;
4581
+ if (pending2.size === 0) break;
4231
4582
  continue;
4232
4583
  }
4233
4584
  const remaining = deadline - Date.now();
@@ -4693,9 +5044,9 @@ function installHook() {
4693
5044
  if (hookInstalled) return;
4694
5045
  hookInstalled = true;
4695
5046
  setBoundaryHook((container) => {
4696
- const state3 = requestSlot("stream");
5047
+ const state5 = requestSlot("stream");
4697
5048
  const store = getRequestStore();
4698
- if (!state3 || !store) return null;
5049
+ if (!state5 || !store) return null;
4699
5050
  const id = `sibu-sus-${store.suspenseIdCounter++}`;
4700
5051
  container.setAttribute("data-sibu-suspense-id", id);
4701
5052
  const record = {
@@ -4706,8 +5057,8 @@ function installHook() {
4706
5057
  fallbackHtml: null,
4707
5058
  api: {
4708
5059
  enter: (fn) => {
4709
- if (record.fallbackHtml === null && state3.serialize) {
4710
- record.fallbackHtml = Array.from(container.childNodes, (n) => state3.serialize?.(n) ?? "").join("");
5060
+ if (record.fallbackHtml === null && state5.serialize) {
5061
+ record.fallbackHtml = Array.from(container.childNodes, (n) => state5.serialize?.(n) ?? "").join("");
4711
5062
  }
4712
5063
  return runInBoundary(record.api, fn);
4713
5064
  },
@@ -4717,7 +5068,7 @@ function installHook() {
4717
5068
  }
4718
5069
  }
4719
5070
  };
4720
- state3.boundaries.push(record);
5071
+ state5.boundaries.push(record);
4721
5072
  return record.api;
4722
5073
  });
4723
5074
  }
@@ -4798,9 +5149,9 @@ async function waitFor(ready, deadline, stop2) {
4798
5149
  });
4799
5150
  }
4800
5151
  }
4801
- function pendingFor(pending, boundary) {
4802
- if (!pending) return false;
4803
- for (const work of pending) if (work.boundary === boundary) return true;
5152
+ function pendingFor(pending2, boundary) {
5153
+ if (!pending2) return false;
5154
+ for (const work of pending2) if (work.boundary === boundary) return true;
4804
5155
  return false;
4805
5156
  }
4806
5157
  function streamPage(input2, options = {}) {
@@ -4813,8 +5164,8 @@ function streamPage(input2, options = {}) {
4813
5164
  const MARK_END = "<sibu-stream-end>";
4814
5165
  void runInSSRContext(async () => {
4815
5166
  const store = getRequestStore();
4816
- const state3 = { boundaries: [], serialize: null };
4817
- requestSlot("stream", () => state3);
5167
+ const state5 = { boundaries: [], serialize: null };
5168
+ requestSlot("stream", () => state5);
4818
5169
  const errors = [];
4819
5170
  if (store) store.errors = errors;
4820
5171
  let holder = null;
@@ -4835,13 +5186,13 @@ function streamPage(input2, options = {}) {
4835
5186
  throw explainServerError(err);
4836
5187
  }
4837
5188
  const serialize = (node) => renderToStringWith(node, { marker: options.marker ?? "root", ids });
4838
- state3.serialize = serialize;
5189
+ state5.serialize = serialize;
4839
5190
  holder = document.createDocumentFragment();
4840
5191
  holder.appendChild(root);
4841
5192
  const ready = (b2) => b2.done && !pendingFor(store?.pending, b2.api);
4842
5193
  const serializeWithFallbacks = (node) => {
4843
5194
  const held = [];
4844
- for (const b2 of state3.boundaries) {
5195
+ for (const b2 of state5.boundaries) {
4845
5196
  if (ready(b2) || b2.container === node || !node.contains(b2.container)) continue;
4846
5197
  if (held.some((h) => h.b.container.contains(b2.container))) continue;
4847
5198
  const nodes = Array.from(b2.container.childNodes);
@@ -4863,9 +5214,9 @@ function streamPage(input2, options = {}) {
4863
5214
  await waitFor(() => !pendingFor(store?.pending, void 0), shellDeadline, stopWaiting);
4864
5215
  failIfErrored();
4865
5216
  if (channel.cancelled) return;
4866
- for (const b2 of state3.boundaries) {
5217
+ for (const b2 of state5.boundaries) {
4867
5218
  const inline = (x) => x.done && !pendingFor(store?.pending, x.api);
4868
- const enclosing = state3.boundaries.filter((a2) => a2 !== b2 && a2.container.contains(b2.container));
5219
+ const enclosing = state5.boundaries.filter((a2) => a2 !== b2 && a2.container.contains(b2.container));
4869
5220
  if (inline(b2) && enclosing.every(inline)) b2.emitted = true;
4870
5221
  }
4871
5222
  const shell = serializeWithFallbacks(holder);
@@ -4886,8 +5237,8 @@ function streamPage(input2, options = {}) {
4886
5237
  if (channel.cancelled) return;
4887
5238
  failIfErrored();
4888
5239
  const deadline = Date.now() + (options.timeout ?? 1e4);
4889
- const outstanding = () => state3.boundaries.filter((b2) => !b2.emitted);
4890
- const ancestorsOf = (b2) => state3.boundaries.filter((a2) => a2 !== b2 && a2.container.contains(b2.container));
5240
+ const outstanding = () => state5.boundaries.filter((b2) => !b2.emitted);
5241
+ const ancestorsOf = (b2) => state5.boundaries.filter((a2) => a2 !== b2 && a2.container.contains(b2.container));
4891
5242
  const emittable = (b2) => ready(b2) && ancestorsOf(b2).every((a2) => a2.emitted);
4892
5243
  let bodyClosed = false;
4893
5244
  for (; ; ) {
@@ -4911,7 +5262,7 @@ function streamPage(input2, options = {}) {
4911
5262
  if (channel.cancelled) return;
4912
5263
  failIfErrored();
4913
5264
  }
4914
- for (const b2 of state3.boundaries) {
5265
+ for (const b2 of state5.boundaries) {
4915
5266
  if (b2 === next || !next.container.contains(b2.container) || !ready(b2)) continue;
4916
5267
  const between2 = ancestorsOf(b2).filter((a2) => a2 !== next && next.container.contains(a2.container));
4917
5268
  if (between2.every(ready)) b2.emitted = true;
@@ -5580,12 +5931,12 @@ async function* renderToSuspenseStream(element, pendingBoundaries = [], options)
5580
5931
  function escapeScriptJson(json) {
5581
5932
  return json.replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
5582
5933
  }
5583
- function serializeState(state3, nonce, options) {
5934
+ function serializeState(state5, nonce, options) {
5584
5935
  const globalName = options?.global ?? SSR_DATA_ATTR;
5585
5936
  if (!SAFE_GLOBAL_NAME.test(globalName)) {
5586
5937
  throw new Error(`[SibuJS SSR] serializeState: global must be an identifier (got: ${JSON.stringify(globalName)})`);
5587
5938
  }
5588
- const rawJson = JSON.stringify(state3);
5939
+ const rawJson = JSON.stringify(state5);
5589
5940
  const maxBytes = options?.maxBytes ?? DEFAULT_MAX_SSR_BYTES;
5590
5941
  const byteLen = typeof TextEncoder !== "undefined" ? new TextEncoder().encode(rawJson).byteLength : Buffer.byteLength(rawJson, "utf8");
5591
5942
  if (byteLen > maxBytes) {
@@ -5978,8 +6329,8 @@ function commitSafeAttribute(el, name, value, options) {
5978
6329
  else el.removeAttribute(name);
5979
6330
  return false;
5980
6331
  }
5981
- const pending = value == null || value === false ? null : value === true ? "" : String(value);
5982
- const refusal = contextualAttributeRefusal(el, name, pending, options.reactive ? "reactive" : "runtime");
6332
+ const pending2 = value == null || value === false ? null : value === true ? "" : String(value);
6333
+ const refusal = contextualAttributeRefusal(el, name, pending2, options.reactive ? "reactive" : "runtime");
5983
6334
  if (refusal !== ContextualRefusal.None) {
5984
6335
  warnContextualRefusal(options.label ?? "setSafeAttribute", name, refusal);
5985
6336
  if (ns) el.removeAttributeNS(ns, localName);
@@ -6145,7 +6496,7 @@ function restoreFocusWithin(snapshot, nodes, where, policy) {
6145
6496
  const active = document.activeElement;
6146
6497
  if (active === snapshot.el) return;
6147
6498
  if (active && active !== document.body && active !== document.documentElement) return;
6148
- if (snapshot.el.isConnected) {
6499
+ if (snapshot.el.isConnected && !snapshot.el.closest("[inert]")) {
6149
6500
  refocus(snapshot.el, snapshot);
6150
6501
  return;
6151
6502
  }
@@ -6172,9 +6523,81 @@ function restoreFocusWithin(snapshot, nodes, where, policy) {
6172
6523
  });
6173
6524
  }
6174
6525
 
6526
+ // src/core/rendering/range.ts
6527
+ init_globalSingleton();
6528
+ init_ssr_context();
6529
+ var state3 = globalSingleton(/* @__PURE__ */ Symbol.for("sibujs.ranges.v1"), () => ({
6530
+ ends: /* @__PURE__ */ new WeakMap(),
6531
+ pending: /* @__PURE__ */ new WeakMap(),
6532
+ registrations: /* @__PURE__ */ new Set(),
6533
+ listeners: /* @__PURE__ */ new Set(),
6534
+ notice: { queued: false, batch: [] }
6535
+ }));
6536
+ var ends = state3.ends;
6537
+ function registerRange(start, last) {
6538
+ ends.set(start, last);
6539
+ }
6540
+ var pending = state3.pending;
6541
+ var NOTHING = () => {
6542
+ };
6543
+ var registrations = state3.registrations;
6544
+ var loadListeners = state3.listeners;
6545
+ var notice = state3.notice;
6546
+ function notifyLoad(settled) {
6547
+ if (loadListeners.size === 0) return;
6548
+ if (settled !== null) notice.batch.push(settled);
6549
+ if (notice.queued) return;
6550
+ notice.queued = true;
6551
+ queueMicrotask(() => {
6552
+ notice.queued = false;
6553
+ const batch2 = notice.batch;
6554
+ notice.batch = [];
6555
+ for (const listener of [...loadListeners]) listener(batch2);
6556
+ });
6557
+ }
6558
+ function beginPending(at, held) {
6559
+ const entry = { at, held, settled: false, cancelled: false, committed: null };
6560
+ registrations.add(entry);
6561
+ notifyLoad(null);
6562
+ const settle = (cancelled, committed) => {
6563
+ if (entry.settled) return;
6564
+ entry.settled = true;
6565
+ entry.cancelled = cancelled;
6566
+ entry.committed = committed;
6567
+ registrations.delete(entry);
6568
+ notifyLoad(entry);
6569
+ };
6570
+ return {
6571
+ entry,
6572
+ done: (committed) => settle(false, committed ?? null),
6573
+ cancel: () => settle(true, null)
6574
+ };
6575
+ }
6576
+ var INERT = { done: NOTHING, cancel: NOTHING };
6577
+ function beginLoading(anchor) {
6578
+ if (isServer()) return INERT;
6579
+ const { done, cancel } = beginPending(anchor, null);
6580
+ return { done: () => done(), cancel };
6581
+ }
6582
+ function registerNodesRange(anchor, nodes) {
6583
+ registerRange(anchor, () => {
6584
+ const parent = anchor.parentNode;
6585
+ const wanted = nodes().filter((n) => n !== null && n.parentNode === parent);
6586
+ let last = null;
6587
+ let left = wanted.length;
6588
+ for (let n = anchor.nextSibling; n !== null && left > 0; n = n.nextSibling) {
6589
+ if (wanted.includes(n)) {
6590
+ last = n;
6591
+ left--;
6592
+ }
6593
+ }
6594
+ return last;
6595
+ });
6596
+ }
6597
+
6175
6598
  // src/reactivity/bindChildNode.ts
6176
6599
  init_track();
6177
- function bindChildNode(placeholder, getter) {
6600
+ function bindChildNode(placeholder, getter, exposeNodes) {
6178
6601
  let lastNodes = [];
6179
6602
  const scope = captureScope();
6180
6603
  function commit() {
@@ -6245,6 +6668,12 @@ function bindChildNode(placeholder, getter) {
6245
6668
  lastNodes = newNodes;
6246
6669
  restoreFocusWithin(focused, newNodes, "bindChildNode");
6247
6670
  }
6671
+ if (exposeNodes) {
6672
+ registerRange(placeholder, () => {
6673
+ for (let i2 = lastNodes.length - 1; i2 >= 0; i2--) if (lastNodes[i2].parentNode !== null) return lastNodes[i2];
6674
+ return null;
6675
+ });
6676
+ }
6248
6677
  return reactiveBinding2(commit, placeholder, true);
6249
6678
  }
6250
6679
 
@@ -6252,6 +6681,7 @@ function bindChildNode(placeholder, getter) {
6252
6681
  init_track();
6253
6682
  init_elementPolicy();
6254
6683
  init_sanitize();
6684
+ init_styleKey();
6255
6685
  init_adoptScope();
6256
6686
  init_dispose();
6257
6687
 
@@ -6281,14 +6711,6 @@ var CLOBBER_RISKY_IDS = /* @__PURE__ */ new Set([
6281
6711
  var warnedLoneStrings = /* @__PURE__ */ new Set();
6282
6712
  var MAX_WARNED_LONE_STRINGS = 100;
6283
6713
  var loneStringCapAnnounced = false;
6284
- var kebabCache = /* @__PURE__ */ new Map();
6285
- function toKebab(prop) {
6286
- let cached = kebabCache.get(prop);
6287
- if (cached !== void 0) return cached;
6288
- cached = prop.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
6289
- kebabCache.set(prop, cached);
6290
- return cached;
6291
- }
6292
6714
  function applyStyle(el, style2) {
6293
6715
  if (typeof style2 === "function") {
6294
6716
  const getter = style2;
@@ -6312,7 +6734,7 @@ function applyStyle(el, style2) {
6312
6734
  if (!Object.hasOwn(value, prop)) continue;
6313
6735
  const val = value[prop];
6314
6736
  if (val == null) continue;
6315
- const name = toKebab(prop);
6737
+ const name = styleKeyToProperty(prop);
6316
6738
  next.push(name);
6317
6739
  decl.setProperty(name, sanitizeCSSDeclaration(name, String(val), { element: el }));
6318
6740
  }
@@ -6332,7 +6754,7 @@ function applyStyle(el, style2) {
6332
6754
  for (const prop in style2) {
6333
6755
  if (!Object.hasOwn(style2, prop)) continue;
6334
6756
  const val = style2[prop];
6335
- const name = toKebab(prop);
6757
+ const name = styleKeyToProperty(prop);
6336
6758
  if (typeof val === "function") {
6337
6759
  const getter = val;
6338
6760
  const teardown = reactiveBinding2(() => {
@@ -6667,7 +7089,7 @@ var details = tagFactory("details");
6667
7089
  var dialog = tagFactory("dialog");
6668
7090
  var menu = tagFactory("menu");
6669
7091
  var summary = tagFactory("summary");
6670
- var slot2 = tagFactory("slot");
7092
+ var slot3 = tagFactory("slot");
6671
7093
  var template = tagFactory("template");
6672
7094
  var base = tagFactory("base");
6673
7095
  var link = tagFactory("link");
@@ -6763,7 +7185,7 @@ function emitDevtools(hook, event, payload) {
6763
7185
  // src/core/signals/signal.ts
6764
7186
  var _g = globalThis;
6765
7187
  function signal(initial, options) {
6766
- const state3 = {
7188
+ const state5 = {
6767
7189
  value: initial,
6768
7190
  __v: 0,
6769
7191
  __sc: 0,
@@ -6776,57 +7198,57 @@ function signal(initial, options) {
6776
7198
  };
6777
7199
  const debugName = DEV ? options?.name : void 0;
6778
7200
  const equalsFn = options?.equals;
6779
- if (debugName) state3.__name = debugName;
7201
+ if (debugName) state5.__name = debugName;
6780
7202
  function get() {
6781
- recordDependency2(state3);
6782
- return state3.value;
7203
+ recordDependency2(state5);
7204
+ return state5.value;
6783
7205
  }
6784
- get.__signal = state3;
7206
+ get.__signal = state5;
6785
7207
  if (debugName) get.__name = debugName;
6786
7208
  let set;
6787
7209
  if (equalsFn) {
6788
7210
  set = (next) => {
6789
- const prev = state3.value;
7211
+ const prev = state5.value;
6790
7212
  const newValue = typeof next === "function" ? next(prev) : next;
6791
7213
  if (equalsFn(prev, newValue)) return;
6792
- state3.value = newValue;
6793
- state3.__v++;
7214
+ state5.value = newValue;
7215
+ state5.__v++;
6794
7216
  if (DEV) {
6795
7217
  const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
6796
- if (hook) emitDevtools(hook, "signal:update", { signal: state3, name: debugName, oldValue: prev, newValue });
7218
+ if (hook) emitDevtools(hook, "signal:update", { signal: state5, name: debugName, oldValue: prev, newValue });
6797
7219
  }
6798
- if (!enqueueBatchedSignal(state3)) {
6799
- notifySubscribers2(state3);
7220
+ if (!enqueueBatchedSignal(state5)) {
7221
+ notifySubscribers2(state5);
6800
7222
  }
6801
7223
  };
6802
7224
  } else if (DEV) {
6803
7225
  set = (next) => {
6804
- const prev = state3.value;
7226
+ const prev = state5.value;
6805
7227
  const newValue = typeof next === "function" ? next(prev) : next;
6806
7228
  if (Object.is(newValue, prev)) return;
6807
- state3.value = newValue;
6808
- state3.__v++;
7229
+ state5.value = newValue;
7230
+ state5.__v++;
6809
7231
  const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
6810
- if (hook) emitDevtools(hook, "signal:update", { signal: state3, name: debugName, oldValue: prev, newValue });
6811
- if (!enqueueBatchedSignal(state3)) {
6812
- notifySubscribers2(state3);
7232
+ if (hook) emitDevtools(hook, "signal:update", { signal: state5, name: debugName, oldValue: prev, newValue });
7233
+ if (!enqueueBatchedSignal(state5)) {
7234
+ notifySubscribers2(state5);
6813
7235
  }
6814
7236
  };
6815
7237
  } else {
6816
7238
  set = (next) => {
6817
- const prev = state3.value;
7239
+ const prev = state5.value;
6818
7240
  const newValue = typeof next === "function" ? next(prev) : next;
6819
7241
  if (Object.is(newValue, prev)) return;
6820
- state3.value = newValue;
6821
- state3.__v++;
6822
- if (!enqueueBatchedSignal(state3)) {
6823
- notifySubscribers2(state3);
7242
+ state5.value = newValue;
7243
+ state5.__v++;
7244
+ if (!enqueueBatchedSignal(state5)) {
7245
+ notifySubscribers2(state5);
6824
7246
  }
6825
7247
  };
6826
7248
  }
6827
7249
  if (DEV) {
6828
7250
  const hook = _g.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
6829
- if (hook) emitDevtools(hook, "signal:create", { signal: state3, name: debugName, getter: get, initial });
7251
+ if (hook) emitDevtools(hook, "signal:create", { signal: state5, name: debugName, getter: get, initial });
6830
7252
  }
6831
7253
  return [get, set];
6832
7254
  }
@@ -6988,16 +7410,16 @@ function createModuleRegistry() {
6988
7410
  };
6989
7411
  }
6990
7412
  function createBundle(modules) {
6991
- const cache = /* @__PURE__ */ new Map();
7413
+ const cache2 = /* @__PURE__ */ new Map();
6992
7414
  const bundle = {};
6993
7415
  for (const key of Object.keys(modules)) {
6994
7416
  Object.defineProperty(bundle, key, {
6995
7417
  get() {
6996
- if (cache.has(key)) {
6997
- return cache.get(key);
7418
+ if (cache2.has(key)) {
7419
+ return cache2.get(key);
6998
7420
  }
6999
7421
  const value = modules[key]();
7000
- cache.set(key, value);
7422
+ cache2.set(key, value);
7001
7423
  return value;
7002
7424
  },
7003
7425
  enumerable: true,
@@ -7066,7 +7488,7 @@ var CDN_ENTRY_POINTS = {
7066
7488
  };
7067
7489
  var packageInfo = {
7068
7490
  name: "sibujs",
7069
- version: true ? "4.14.0" : "dev",
7491
+ version: true ? "4.15.0" : "dev",
7070
7492
  entryPoints: MODULE_ENTRY_POINTS,
7071
7493
  /**
7072
7494
  * Generate the package.json `exports` map. Module entries resolve to the
@@ -7213,18 +7635,18 @@ function createPluginRegistry() {
7213
7635
  return true;
7214
7636
  };
7215
7637
  installStack.add(p2.name);
7216
- let pending;
7638
+ let pending2;
7217
7639
  try {
7218
- pending = adoptThenable(p2.install(ctx, options));
7640
+ pending2 = adoptThenable(p2.install(ctx, options));
7219
7641
  } finally {
7220
7642
  installStack.delete(p2.name);
7221
7643
  }
7222
- if (!pending) {
7644
+ if (!pending2) {
7223
7645
  if (!commit()) throw new PluginInstallCancelledError(p2.name);
7224
7646
  return;
7225
7647
  }
7226
7648
  if (myGeneration === generation) pendingInstalls.set(p2.name, myGeneration);
7227
- const settled = pending.then(
7649
+ const settled = pending2.then(
7228
7650
  () => {
7229
7651
  if (commit()) return;
7230
7652
  if (pendingInstalls.get(p2.name) === myGeneration) pendingInstalls.delete(p2.name);
@@ -7863,6 +8285,66 @@ function sameAttrs(el, attrs) {
7863
8285
  init_dev();
7864
8286
  init_adoptScope();
7865
8287
  init_dispose();
8288
+
8289
+ // src/core/rendering/heldCommit.ts
8290
+ init_track();
8291
+ var NOOP2 = () => {
8292
+ };
8293
+ function commitWhenActive(slot4, c) {
8294
+ let over = false;
8295
+ let unhold = null;
8296
+ let drop = NOOP2;
8297
+ const finish = () => {
8298
+ over = true;
8299
+ if (slot4.cancel === cancel) slot4.cancel = NOOP2;
8300
+ drop();
8301
+ drop = NOOP2;
8302
+ };
8303
+ const cancel = () => {
8304
+ if (over) return;
8305
+ finish();
8306
+ const release = unhold;
8307
+ unhold = null;
8308
+ try {
8309
+ c.discard();
8310
+ } finally {
8311
+ release?.();
8312
+ }
8313
+ };
8314
+ const attempt = () => {
8315
+ drop = NOOP2;
8316
+ let clean = false;
8317
+ while (!over) {
8318
+ const state5 = c.held.state();
8319
+ if (state5 === 2 || c.owned !== void 0 && !c.owned()) {
8320
+ cancel();
8321
+ return;
8322
+ }
8323
+ if (state5 === 1) {
8324
+ if (c.node !== null && unhold === null) unhold = holdSubtree2(c.node);
8325
+ drop = c.held.wait(attempt, attempt);
8326
+ return;
8327
+ }
8328
+ if (unhold !== null) {
8329
+ const release = unhold;
8330
+ unhold = null;
8331
+ release();
8332
+ continue;
8333
+ }
8334
+ if (!clean) {
8335
+ clean = c.teardown?.() !== true;
8336
+ continue;
8337
+ }
8338
+ finish();
8339
+ c.insert();
8340
+ return;
8341
+ }
8342
+ };
8343
+ slot4.cancel = cancel;
8344
+ attempt();
8345
+ }
8346
+
8347
+ // src/plugins/router.ts
7866
8348
  init_hydrationHooks();
7867
8349
  init_ssr_context();
7868
8350
  init_serverHead();
@@ -8430,15 +8912,15 @@ var _ComponentLoader = class _ComponentLoader {
8430
8912
  const cached = this.planCache.get(cacheKey);
8431
8913
  if (cached && cached.kind === "factory") return cached.component;
8432
8914
  this.assertNotHot(cacheKey);
8433
- let pending = this.moduleLoads.get(cacheKey);
8434
- const owner = pending === void 0;
8435
- if (pending === void 0) {
8436
- pending = plan.load();
8437
- this.moduleLoads.set(cacheKey, pending);
8915
+ let pending2 = this.moduleLoads.get(cacheKey);
8916
+ const owner = pending2 === void 0;
8917
+ if (pending2 === void 0) {
8918
+ pending2 = plan.load();
8919
+ this.moduleLoads.set(cacheKey, pending2);
8438
8920
  }
8439
8921
  let resolved;
8440
8922
  try {
8441
- resolved = await pending;
8923
+ resolved = await pending2;
8442
8924
  } catch (error) {
8443
8925
  this.noteError(cacheKey);
8444
8926
  throw error;
@@ -8460,7 +8942,14 @@ var _ComponentLoader = class _ComponentLoader {
8460
8942
  * is a configuration error, not something to chase.
8461
8943
  */
8462
8944
  async instantiateFactory(component, route2, routePath, scope, depth = 0) {
8463
- const build = () => scope ? runWithOwnerScope2(scope, component) : component();
8945
+ const gate = scope?.gate;
8946
+ if (gate) {
8947
+ while (gate.held()) if (!await gate.until()) throw gate.cancellation();
8948
+ if (scope?.current?.() === false) throw gate.cancellation();
8949
+ }
8950
+ const owner = scope?.owner;
8951
+ const invoke = () => scope ? runWithOwnerScope2(scope, component) : component();
8952
+ const build = owner ? () => owner.run(invoke) : invoke;
8464
8953
  const result = scope?.adopt ? inScope(scope.adopt, build) : build();
8465
8954
  const value = this.isThenable(result) ? await result : result;
8466
8955
  if (this.isElement(value)) return value;
@@ -8669,7 +9158,7 @@ var _SibuRouter = class _SibuRouter {
8669
9158
  return this.loadedPromise;
8670
9159
  }
8671
9160
  createInitialRoute() {
8672
- return {
9161
+ const route2 = {
8673
9162
  path: "/",
8674
9163
  params: {},
8675
9164
  query: {},
@@ -8678,6 +9167,8 @@ var _SibuRouter = class _SibuRouter {
8678
9167
  meta: {},
8679
9168
  matched: []
8680
9169
  };
9170
+ bootstrapRoutes.add(route2);
9171
+ return route2;
8681
9172
  }
8682
9173
  handleLocationChange(skipHistory = true, initialResolution = false) {
8683
9174
  const path2 = this.getCurrentPath();
@@ -8718,8 +9209,31 @@ var _SibuRouter = class _SibuRouter {
8718
9209
  matched
8719
9210
  };
8720
9211
  }
9212
+ /**
9213
+ * Once no navigation is in flight: if the route is still the placeholder
9214
+ * the router started with — every navigation that could have replaced it
9215
+ * was cancelled by a guard, failed, or was a duplicate — that IS the
9216
+ * outcome, and the outlets that rendered nothing for it settle (see
9217
+ * `settleEmpty`). Checked when a navigation has definitively completed,
9218
+ * never from `isReady` (set before the guards run). A navigation still
9219
+ * pending — a newer one, or a guard that never resolves — keeps them
9220
+ * pending; an outlet's enter is bounded by its own deadline then.
9221
+ */
9222
+ settleBootstrap() {
9223
+ if (this.destroyed || this.navigator.isNavigating) return;
9224
+ const current2 = untracked2(() => this.currentRouteGetter());
9225
+ if (!bootstrapRoutes.delete(current2)) return;
9226
+ const waiting = bootstrapWaiters.get(current2);
9227
+ bootstrapWaiters.delete(current2);
9228
+ if (waiting) for (const settle of waiting) settle();
9229
+ }
8721
9230
  // Public API
8722
9231
  async navigate(to, options = {}) {
9232
+ const result = await this.attemptNavigation(to, options);
9233
+ this.settleBootstrap();
9234
+ return result;
9235
+ }
9236
+ async attemptNavigation(to, options) {
8723
9237
  try {
8724
9238
  await this.navigator.navigate(async (signal2) => {
8725
9239
  const targetPath = this.resolvePath(to);
@@ -8973,6 +9487,13 @@ var _SibuRouter = class _SibuRouter {
8973
9487
  /**
8974
9488
  * Create exactly one real instance from an already-resolved plan. With a
8975
9489
  * `scope`, the factory runs in it (see `RouteScope`).
9490
+ *
9491
+ * When the scope belongs to an outlet whose branch is paused (playing a
9492
+ * leave it may still be taken back from), a lazy module that resolves does
9493
+ * not run its factory yet: the promise stays pending and continues once the
9494
+ * branch resumes. If the branch ends, or the outlet's pass was superseded
9495
+ * meanwhile, it rejects with a `DOMException` named `"AbortError"`. Genuine
9496
+ * loader and component failures reject with their own error, as before.
8976
9497
  */
8977
9498
  async instantiateComponent(plan, route2, routePath, scope) {
8978
9499
  return prerenderWait(this.loader.instantiate(plan, route2, routePath, scope), `router:render ${route2.path}`);
@@ -9221,6 +9742,21 @@ var RouteScope = class {
9221
9742
  constructor(route2) {
9222
9743
  /** Creation scope the instance is built in (adopting hydration); see `adoptScope`. */
9223
9744
  this.adopt = null;
9745
+ /**
9746
+ * The outlet's pause gate: while the branch holding the outlet is paused (it
9747
+ * began a leave and may still be taken back), a lazy module that resolves
9748
+ * does not get its factory invoked yet; instantiation waits for the branch
9749
+ * to resume, and is cancelled if it ends.
9750
+ */
9751
+ this.gate = null;
9752
+ /** Whether the outlet pass this instance is for is still the current one. */
9753
+ this.current = null;
9754
+ /**
9755
+ * The instance's structural owner, nested under the outlet's: its factory
9756
+ * runs as it, so what it creates is paused with the branch holding the
9757
+ * outlet, and ends (`lifecycleScope()` work included) with the instance.
9758
+ */
9759
+ this.owner = null;
9224
9760
  this.released = false;
9225
9761
  const [get, set] = signal(route2);
9226
9762
  this.get = get;
@@ -9247,6 +9783,112 @@ var RouteScope = class {
9247
9783
  queueMicrotask(() => this.set(null));
9248
9784
  }
9249
9785
  };
9786
+ var NOOP3 = () => {
9787
+ };
9788
+ var bootstrapRoutes = /* @__PURE__ */ new WeakSet();
9789
+ var bootstrapWaiters = /* @__PURE__ */ new WeakMap();
9790
+ function settleEmpty(route2, loaded, current2) {
9791
+ if (!bootstrapRoutes.has(route2)) {
9792
+ loaded.done();
9793
+ return;
9794
+ }
9795
+ let waiting = bootstrapWaiters.get(route2);
9796
+ if (waiting === void 0) bootstrapWaiters.set(route2, waiting = /* @__PURE__ */ new Set());
9797
+ waiting.add(() => {
9798
+ if (current2()) loaded.done();
9799
+ });
9800
+ }
9801
+ var cancellations = /* @__PURE__ */ new WeakSet();
9802
+ function pauseGate(frozen) {
9803
+ let closed = false;
9804
+ const pending2 = /* @__PURE__ */ new Set();
9805
+ return {
9806
+ held: () => closed || frozen(),
9807
+ until: () => {
9808
+ if (closed) return Promise.resolve(false);
9809
+ return new Promise((resolve) => {
9810
+ const settle = (active) => {
9811
+ pending2.delete(cancel);
9812
+ resolve(active && !closed);
9813
+ };
9814
+ const drop = frozen.wait(
9815
+ () => settle(true),
9816
+ () => settle(false)
9817
+ );
9818
+ const cancel = () => {
9819
+ drop();
9820
+ settle(false);
9821
+ };
9822
+ pending2.add(cancel);
9823
+ });
9824
+ },
9825
+ cancellation: () => {
9826
+ const error = new DOMException("Route instantiation cancelled: its branch was released", "AbortError");
9827
+ cancellations.add(error);
9828
+ return error;
9829
+ },
9830
+ close: () => {
9831
+ closed = true;
9832
+ for (const cancel of [...pending2]) cancel();
9833
+ },
9834
+ run: frozen.run,
9835
+ frozen,
9836
+ closed: () => closed,
9837
+ onClose: (fn) => {
9838
+ pending2.add(fn);
9839
+ return () => {
9840
+ pending2.delete(fn);
9841
+ };
9842
+ }
9843
+ };
9844
+ }
9845
+ function whenActive(gate, fn) {
9846
+ if (!gate.held()) fn();
9847
+ else
9848
+ void gate.until().then((active) => {
9849
+ if (active) whenActive(gate, fn);
9850
+ });
9851
+ }
9852
+ function commitPass(gate, c) {
9853
+ const frozen = gate.frozen;
9854
+ const held = {
9855
+ state: frozen.state,
9856
+ wait: (onActive, onEnd) => {
9857
+ let live = true;
9858
+ const later = (fn) => () => {
9859
+ void Promise.resolve().then(() => {
9860
+ if (live) fn();
9861
+ });
9862
+ };
9863
+ const drop = frozen.wait(later(onActive), later(onEnd));
9864
+ return () => {
9865
+ live = false;
9866
+ drop();
9867
+ };
9868
+ }
9869
+ };
9870
+ return new Promise((resolve, reject) => {
9871
+ const slot4 = { cancel: NOOP3 };
9872
+ const untrack = gate.onClose(() => slot4.cancel());
9873
+ const settle = (fn) => () => {
9874
+ untrack();
9875
+ try {
9876
+ fn();
9877
+ resolve();
9878
+ } catch (error) {
9879
+ reject(error);
9880
+ }
9881
+ };
9882
+ commitWhenActive(slot4, {
9883
+ held,
9884
+ node: c.node,
9885
+ owned: () => !gate.closed() && c.owned(),
9886
+ teardown: c.teardown,
9887
+ insert: settle(c.insert),
9888
+ discard: settle(c.discard)
9889
+ });
9890
+ });
9891
+ }
9250
9892
  function activeRouteScope() {
9251
9893
  const scope = getOwnerScope2();
9252
9894
  return scope instanceof RouteScope ? scope : null;
@@ -9260,14 +9902,27 @@ function scopedRoute(router2) {
9260
9902
  return router2.currentRoute;
9261
9903
  }
9262
9904
  var instanceScopes = /* @__PURE__ */ new WeakMap();
9263
- async function instantiateScoped(router2, plan, routeDef, routePath, route2, adopt = null) {
9905
+ async function instantiateScoped(router2, plan, routeDef, routePath, route2, adopt = null, gate = null, current2 = null) {
9264
9906
  const scope = new RouteScope(route2);
9265
9907
  scope.adopt = adopt;
9266
- const node = await router2.instantiateComponent(plan, routeDef, routePath, scope);
9908
+ scope.gate = gate;
9909
+ scope.current = current2;
9910
+ const owner = gate ? gate.run(() => structuralBinding2(NOOP3)) : structuralBinding2(NOOP3);
9911
+ scope.owner = owner;
9912
+ let node;
9913
+ try {
9914
+ node = await router2.instantiateComponent(plan, routeDef, routePath, scope);
9915
+ } catch (error) {
9916
+ owner.stop();
9917
+ throw error;
9918
+ }
9267
9919
  if (node) {
9268
9920
  instanceScopes.set(node, scope);
9269
- registerDisposer(node, () => scope.release());
9270
- }
9921
+ registerDisposer(node, () => {
9922
+ owner.stop();
9923
+ scope.release();
9924
+ });
9925
+ } else owner.stop();
9271
9926
  return node;
9272
9927
  }
9273
9928
  function updateInstanceRoute(node, route2) {
@@ -9366,6 +10021,8 @@ function instanceKey(owner, records, route2) {
9366
10021
  function Route() {
9367
10022
  const anchor = document.createComment("route-outlet");
9368
10023
  const adoptScope = captureScope();
10024
+ const frozen = captureFrozen2();
10025
+ const gate = pauseGate(frozen);
9369
10026
  let currentNode = null;
9370
10027
  let loadingNode = null;
9371
10028
  let errorNode = null;
@@ -9373,6 +10030,7 @@ function Route() {
9373
10030
  let currentTopRoute = null;
9374
10031
  let currentKey = null;
9375
10032
  let routeTorn = false;
10033
+ const loaded = beginLoading(anchor);
9376
10034
  const commitTarget = (seq) => routeTorn || seq !== navSeq ? null : anchor.parentNode;
9377
10035
  const retryIfDetached = (seq) => {
9378
10036
  if (!routeTorn && seq === navSeq && !anchor.parentNode) attachWait.request();
@@ -9417,24 +10075,54 @@ function Route() {
9417
10075
  loadingNode = null;
9418
10076
  }
9419
10077
  };
9420
- const showError = (error, routeDef) => {
10078
+ const showError = (seq, error, routeDef) => {
9421
10079
  if (!anchor.parentNode) return;
9422
- cleanupNodes();
9423
- errorNode = document.createElement("div");
9424
- errorNode.className = "route-error";
9425
- errorNode.setAttribute("role", "alert");
9426
- errorNode.setAttribute("aria-live", "assertive");
10080
+ const view = errorView(error, routeDef);
10081
+ void commitPass(gate, {
10082
+ node: view,
10083
+ owned: () => !routeTorn && seq === navSeq,
10084
+ discard: () => dispose(view),
10085
+ teardown: () => {
10086
+ if (!anchor.parentNode || !(currentNode || loadingNode || errorNode)) return false;
10087
+ cleanupNodes();
10088
+ return true;
10089
+ },
10090
+ insert: () => {
10091
+ const parent = anchor.parentNode;
10092
+ if (!parent) {
10093
+ dispose(view);
10094
+ unshownFailure = { seq, error, routeDef };
10095
+ attachWait.request();
10096
+ return;
10097
+ }
10098
+ errorNode = view;
10099
+ try {
10100
+ parent.insertBefore(view, anchor.nextSibling);
10101
+ } catch (err) {
10102
+ if (errorNode === view) errorNode = null;
10103
+ release(view);
10104
+ throw err;
10105
+ }
10106
+ if (!routeTorn && seq === navSeq) loaded.done();
10107
+ }
10108
+ }).catch((err) => console.error("[Route] Error view failed:", err));
10109
+ };
10110
+ const errorView = (error, routeDef) => {
10111
+ const errorNode2 = document.createElement("div");
10112
+ errorNode2.className = "route-error";
10113
+ errorNode2.setAttribute("role", "alert");
10114
+ errorNode2.setAttribute("aria-live", "assertive");
9427
10115
  if (routeDef && "component" in routeDef) {
9428
10116
  const src = routeDef.component.toString();
9429
10117
  const importMatch = src.match(/import\(["']([^"']+)["']\)/);
9430
10118
  if (importMatch) {
9431
- errorNode.setAttribute("data-component-source", importMatch[1]);
10119
+ errorNode2.setAttribute("data-component-source", importMatch[1]);
9432
10120
  }
9433
10121
  if (routeDef.component.name) {
9434
- errorNode.setAttribute("data-component-name", routeDef.component.name);
10122
+ errorNode2.setAttribute("data-component-name", routeDef.component.name);
9435
10123
  }
9436
10124
  }
9437
- errorNode.__routeError = error;
10125
+ errorNode2.__routeError = error;
9438
10126
  const title2 = document.createElement("h3");
9439
10127
  title2.textContent = "Route Error";
9440
10128
  title2.className = "route-error-title";
@@ -9453,10 +10141,10 @@ function Route() {
9453
10141
  };
9454
10142
  retryButton.addEventListener("click", onRetryClick);
9455
10143
  registerDisposer(retryButton, () => retryButton.removeEventListener("click", onRetryClick));
9456
- errorNode.appendChild(title2);
9457
- errorNode.appendChild(message);
9458
- errorNode.appendChild(retryButton);
9459
- anchor.parentNode.insertBefore(errorNode, anchor.nextSibling);
10144
+ errorNode2.appendChild(title2);
10145
+ errorNode2.appendChild(message);
10146
+ errorNode2.appendChild(retryButton);
10147
+ return errorNode2;
9460
10148
  };
9461
10149
  const update = async () => {
9462
10150
  routerRevision();
@@ -9469,12 +10157,14 @@ function Route() {
9469
10157
  currentTopRoute = null;
9470
10158
  currentKey = null;
9471
10159
  cleanupNodes();
10160
+ settleEmpty(route2, loaded, () => !routeTorn && seq === navSeq);
9472
10161
  return;
9473
10162
  }
9474
10163
  const routeDef = match.matched[0] || match.route;
9475
10164
  const key = instanceKey(routeDef, [routeDef], route2);
9476
10165
  if (routeDef === currentTopRoute && key === currentKey && currentNode) {
9477
10166
  updateInstanceRoute(currentNode, route2);
10167
+ loaded.done();
9478
10168
  return;
9479
10169
  }
9480
10170
  if ("redirect" in routeDef) {
@@ -9493,6 +10183,7 @@ function Route() {
9493
10183
  showLoading();
9494
10184
  }
9495
10185
  const plan = await _routerRef.current.loadPlan(routeDef, route2.path);
10186
+ while (gate.held()) if (!await gate.until()) return;
9496
10187
  if (!commitTarget(seq)) {
9497
10188
  retryIfDetached(seq);
9498
10189
  return;
@@ -9503,28 +10194,57 @@ function Route() {
9503
10194
  routeDef,
9504
10195
  route2.path,
9505
10196
  route2,
9506
- keyedScope(adoptScope, routeDef.path)
10197
+ keyedScope(adoptScope, routeDef.path),
10198
+ gate,
10199
+ () => commitTarget(seq) !== null
9507
10200
  );
9508
- const parent = commitTarget(seq);
9509
- if (!parent) {
9510
- release(node);
9511
- retryIfDetached(seq);
9512
- return;
9513
- }
9514
- if (node) {
9515
- currentTopRoute = routeDef;
9516
- currentKey = key;
9517
- cleanupNodes();
9518
- parent.insertBefore(node, anchor.nextSibling);
9519
- currentNode = node;
9520
- }
10201
+ await commitPass(gate, {
10202
+ node,
10203
+ owned: () => !routeTorn && seq === navSeq,
10204
+ discard: () => release(node),
10205
+ // The outgoing views go first — only when there is a page to
10206
+ // show, and a parent to show it in.
10207
+ teardown: () => {
10208
+ if (!node || !anchor.parentNode || !(currentNode || loadingNode || errorNode)) return false;
10209
+ cleanupNodes();
10210
+ return true;
10211
+ },
10212
+ insert: () => {
10213
+ const parent = commitTarget(seq);
10214
+ if (!parent) {
10215
+ release(node);
10216
+ retryIfDetached(seq);
10217
+ return;
10218
+ }
10219
+ if (node) {
10220
+ currentTopRoute = routeDef;
10221
+ currentKey = key;
10222
+ currentNode = node;
10223
+ try {
10224
+ parent.insertBefore(node, anchor.nextSibling);
10225
+ } catch (error) {
10226
+ if (currentNode === node) {
10227
+ currentNode = null;
10228
+ currentTopRoute = null;
10229
+ currentKey = null;
10230
+ }
10231
+ release(node);
10232
+ throw error;
10233
+ }
10234
+ }
10235
+ if (!routeTorn && seq === navSeq) loaded.done();
10236
+ }
10237
+ });
9521
10238
  } catch (error) {
10239
+ if (cancellations.has(error)) return;
9522
10240
  if (routeTorn || seq !== navSeq) return;
9523
- hideLoading();
9524
10241
  console.error("[Route] Component error:", error);
10242
+ while (gate.held()) if (!await gate.until()) return;
10243
+ if (routeTorn || seq !== navSeq) return;
10244
+ hideLoading();
9525
10245
  fail(seq, error, routeDef);
9526
10246
  }
9527
- }
10247
+ } else settleEmpty(route2, loaded, () => !routeTorn && seq === navSeq);
9528
10248
  } catch (error) {
9529
10249
  if (seq !== navSeq) return;
9530
10250
  if (routeTorn) return;
@@ -9536,16 +10256,20 @@ function Route() {
9536
10256
  const fail = (seq, error, routeDef) => {
9537
10257
  const err = error instanceof Error ? error : new Error(String(error));
9538
10258
  if (anchor.parentNode) {
9539
- showError(err, routeDef);
10259
+ showError(seq, err, routeDef);
9540
10260
  return;
9541
10261
  }
9542
10262
  unshownFailure = { seq, error: err, routeDef };
9543
10263
  attachWait.request();
9544
10264
  };
9545
10265
  const onAttached = () => {
10266
+ if (gate.held()) {
10267
+ void gate.until().then((active) => active && onAttached());
10268
+ return;
10269
+ }
9546
10270
  const failure = unshownFailure;
9547
10271
  unshownFailure = null;
9548
- if (failure && failure.seq === navSeq) showError(failure.error, failure.routeDef);
10272
+ if (failure && failure.seq === navSeq) showError(failure.seq, failure.error, failure.routeDef);
9549
10273
  else update();
9550
10274
  };
9551
10275
  let routeInitialized = false;
@@ -9555,11 +10279,16 @@ function Route() {
9555
10279
  routeInitialized = true;
9556
10280
  };
9557
10281
  const attachWait = attachRetry(anchor, onAttached);
9558
- const routeTeardown = track2(wrappedUpdate);
10282
+ const routeTeardown = reactiveBinding2(wrappedUpdate, anchor);
9559
10283
  if (!routeInitialized) {
9560
10284
  queueMicrotask(
9561
10285
  bindOwnerScope2(() => {
9562
- if (!routeInitialized && anchor.parentNode) wrappedUpdate();
10286
+ whenActive(
10287
+ gate,
10288
+ bindOwnerScope2(() => {
10289
+ if (!routeInitialized && anchor.parentNode) wrappedUpdate();
10290
+ })
10291
+ );
9563
10292
  })
9564
10293
  );
9565
10294
  }
@@ -9567,6 +10296,8 @@ function Route() {
9567
10296
  if (routeTorn) return;
9568
10297
  routeTorn = true;
9569
10298
  navSeq++;
10299
+ gate.close();
10300
+ loaded.cancel();
9570
10301
  routeTeardown();
9571
10302
  attachWait.cancel();
9572
10303
  unshownFailure = null;
@@ -9574,6 +10305,7 @@ function Route() {
9574
10305
  currentTopRoute = null;
9575
10306
  currentKey = null;
9576
10307
  };
10308
+ registerNodesRange(anchor, () => [currentNode, loadingNode, errorNode]);
9577
10309
  registerDisposer(anchor, routeCleanup);
9578
10310
  routeCleanups.push(routeCleanup);
9579
10311
  return anchor;
@@ -9581,17 +10313,44 @@ function Route() {
9581
10313
  function KeepAliveRoute(options) {
9582
10314
  if (!_routerRef.current) throw new Error("Router not initialized. Call createRouter() first.");
9583
10315
  const anchor = document.createComment("keep-alive-route");
9584
- const cache = /* @__PURE__ */ new Map();
10316
+ const cache2 = /* @__PURE__ */ new Map();
9585
10317
  const lruOrder = [];
10318
+ const frozen = captureFrozen2();
10319
+ const gate = pauseGate(frozen);
9586
10320
  const routerOpts = _routerRef.current["options"];
9587
10321
  const keepAliveOpt = routerOpts.keepAlive;
9588
10322
  const maxCache = options?.max ?? (typeof keepAliveOpt === "number" ? keepAliveOpt : 20);
9589
10323
  const includeNames = options?.include ?? (Array.isArray(keepAliveOpt) ? keepAliveOpt : void 0);
10324
+ const suspendInactive = options?.suspendInactive === true;
10325
+ const suspended = /* @__PURE__ */ new Map();
10326
+ const suspend = (node) => {
10327
+ if (!suspendInactive || suspended.has(node)) return;
10328
+ const owner = instanceScopes.get(node)?.owner ?? null;
10329
+ owner?.freeze?.();
10330
+ suspended.set(node, { owner, unhold: holdSubtree2(node) });
10331
+ };
10332
+ const activate = (node) => {
10333
+ const paused = suspended.get(node);
10334
+ if (paused === void 0) return;
10335
+ suspended.delete(node);
10336
+ paused.unhold();
10337
+ paused.owner?.thaw?.();
10338
+ };
10339
+ const disposeCached = (node) => {
10340
+ const paused = suspended.get(node);
10341
+ suspended.delete(node);
10342
+ try {
10343
+ disposeOwned(node);
10344
+ } finally {
10345
+ paused?.unhold();
10346
+ }
10347
+ };
9590
10348
  let currentNode = null;
9591
10349
  let currentKey = "";
9592
10350
  let currentCached = false;
9593
10351
  let updateSeq = 0;
9594
10352
  let kaTorn = false;
10353
+ const loaded = beginLoading(anchor);
9595
10354
  const update = async () => {
9596
10355
  routerRevision();
9597
10356
  if (kaTorn || !_routerRef.current) return;
@@ -9599,7 +10358,10 @@ function KeepAliveRoute(options) {
9599
10358
  const router2 = _routerRef.current;
9600
10359
  const route2 = scopedRoute(router2);
9601
10360
  const match = router2["matcher"].match(route2.path);
9602
- if (!match) return;
10361
+ if (!match) {
10362
+ settleEmpty(route2, loaded, () => !kaTorn && seq === updateSeq);
10363
+ return;
10364
+ }
9603
10365
  const { route: routeDef } = match;
9604
10366
  if ("redirect" in routeDef) {
9605
10367
  const redirectPath = typeof routeDef.redirect === "function" ? routeDef.redirect(route2) : routeDef.redirect;
@@ -9610,11 +10372,15 @@ function KeepAliveRoute(options) {
9610
10372
  });
9611
10373
  return;
9612
10374
  }
9613
- if (!("component" in routeDef)) return;
10375
+ if (!("component" in routeDef)) {
10376
+ settleEmpty(route2, loaded, () => !kaTorn && seq === updateSeq);
10377
+ return;
10378
+ }
9614
10379
  const cacheKey = JSON.stringify([route2.path, queryIdentity(route2.queryAll), route2.hash]);
9615
10380
  const shouldCache = !includeNames || routeDef.name != null && includeNames.includes(routeDef.name);
9616
10381
  if (cacheKey === currentKey && currentNode) {
9617
10382
  updateInstanceRoute(currentNode, route2);
10383
+ loaded.done();
9618
10384
  return;
9619
10385
  }
9620
10386
  if (!anchor.parentNode) {
@@ -9623,87 +10389,148 @@ function KeepAliveRoute(options) {
9623
10389
  }
9624
10390
  let node = null;
9625
10391
  let fromCache = false;
9626
- if (shouldCache && cache.has(cacheKey)) {
9627
- node = cache.get(cacheKey);
10392
+ if (shouldCache && cache2.has(cacheKey)) {
10393
+ node = cache2.get(cacheKey);
9628
10394
  fromCache = true;
9629
10395
  } else {
9630
10396
  try {
9631
10397
  const plan = await router2.loadPlan(routeDef, route2.path);
10398
+ while (gate.held()) if (!await gate.until()) return;
9632
10399
  if (kaTorn || seq !== updateSeq) return;
9633
- node = await instantiateScoped(router2, plan, routeDef, route2.path, route2);
10400
+ node = await instantiateScoped(
10401
+ router2,
10402
+ plan,
10403
+ routeDef,
10404
+ route2.path,
10405
+ route2,
10406
+ null,
10407
+ gate,
10408
+ () => !kaTorn && seq === updateSeq
10409
+ );
9634
10410
  } catch (error) {
9635
- if (kaTorn || seq !== updateSeq) return;
10411
+ if (cancellations.has(error) || kaTorn || seq !== updateSeq) return;
9636
10412
  console.error("[KeepAliveRoute] Component error:", error);
10413
+ loaded.cancel();
9637
10414
  return;
9638
10415
  }
9639
- if (!node) return;
9640
- if (kaTorn || seq !== updateSeq) {
9641
- disposeOwned(node);
10416
+ if (!node) {
10417
+ if (!kaTorn && seq === updateSeq) loaded.done();
9642
10418
  return;
9643
10419
  }
9644
10420
  }
9645
- const parent = anchor.parentNode;
9646
- if (!parent) {
10421
+ await commit(seq, node, fromCache, cacheKey, shouldCache, route2);
10422
+ };
10423
+ const commit = (seq, node, fromCache, cacheKey, shouldCache, route2) => commitPass(gate, {
10424
+ node: fromCache ? null : node,
10425
+ owned: () => !kaTorn && seq === updateSeq,
10426
+ discard: () => {
9647
10427
  if (!fromCache) disposeOwned(node);
9648
- attachWait.request();
9649
- return;
9650
- }
9651
- if (currentNode && currentNode !== node) {
9652
- if (currentNode.parentNode) currentNode.parentNode.removeChild(currentNode);
9653
- if (!currentCached) disposeOwned(currentNode);
9654
- }
9655
- if (fromCache) {
9656
- updateInstanceRoute(node, route2);
9657
- const idx = lruOrder.indexOf(cacheKey);
9658
- if (idx !== -1) lruOrder.splice(idx, 1);
9659
- lruOrder.push(cacheKey);
9660
- } else if (shouldCache) {
9661
- cache.set(cacheKey, node);
9662
- lruOrder.push(cacheKey);
9663
- while (lruOrder.length > maxCache) {
10428
+ },
10429
+ // The outgoing view goes first: detached, and disposed unless it is
10430
+ // cached (then paused, with `suspendInactive`). Once only: it is no
10431
+ // longer the current view afterwards.
10432
+ teardown: () => {
10433
+ const outgoing = currentNode;
10434
+ if (outgoing === null || outgoing === node || !anchor.parentNode) return false;
10435
+ const wasCached = currentCached;
10436
+ currentNode = null;
10437
+ currentKey = "";
10438
+ currentCached = false;
10439
+ outgoing.parentNode?.removeChild(outgoing);
10440
+ if (!wasCached) disposeOwned(outgoing);
10441
+ else if (!kaTorn) suspend(outgoing);
10442
+ return true;
10443
+ },
10444
+ insert: () => {
10445
+ const parent = anchor.parentNode;
10446
+ if (!parent) {
10447
+ if (!fromCache) disposeOwned(node);
10448
+ attachWait.request();
10449
+ return;
10450
+ }
10451
+ if (fromCache) {
10452
+ updateInstanceRoute(node, route2);
10453
+ const idx = lruOrder.indexOf(cacheKey);
10454
+ if (idx !== -1) lruOrder.splice(idx, 1);
10455
+ lruOrder.push(cacheKey);
10456
+ } else if (shouldCache) {
10457
+ cache2.set(cacheKey, node);
10458
+ lruOrder.push(cacheKey);
10459
+ }
10460
+ currentNode = node;
10461
+ currentCached = fromCache || shouldCache;
10462
+ currentKey = cacheKey;
10463
+ try {
10464
+ parent.insertBefore(node, anchor.nextSibling);
10465
+ } catch (error) {
10466
+ if (currentNode === node) {
10467
+ currentNode = null;
10468
+ currentKey = "";
10469
+ currentCached = false;
10470
+ }
10471
+ if (!fromCache) {
10472
+ if (cache2.get(cacheKey) === node) {
10473
+ cache2.delete(cacheKey);
10474
+ const at = lruOrder.lastIndexOf(cacheKey);
10475
+ if (at !== -1) lruOrder.splice(at, 1);
10476
+ }
10477
+ disposeOwned(node);
10478
+ }
10479
+ console.error("[KeepAliveRoute] Component error:", error);
10480
+ if (!kaTorn && seq === updateSeq) loaded.cancel();
10481
+ return;
10482
+ }
10483
+ if (kaTorn) return;
10484
+ if (seq === updateSeq) loaded.done();
10485
+ if (fromCache) activate(node);
10486
+ while (!kaTorn && lruOrder.length > maxCache) {
9664
10487
  const evictKey = lruOrder.shift();
9665
10488
  if (evictKey === cacheKey) {
9666
10489
  lruOrder.push(evictKey);
9667
10490
  break;
9668
10491
  }
9669
- const evictNode = cache.get(evictKey);
10492
+ const evictNode = cache2.get(evictKey);
10493
+ cache2.delete(evictKey);
9670
10494
  if (evictNode) {
9671
- disposeOwned(evictNode);
9672
- if (evictNode.parentNode) evictNode.parentNode.removeChild(evictNode);
9673
- cache.delete(evictKey);
10495
+ disposeCached(evictNode);
10496
+ evictNode.parentNode?.removeChild(evictNode);
9674
10497
  }
9675
10498
  }
9676
10499
  }
9677
- currentNode = node;
9678
- currentCached = fromCache || shouldCache;
9679
- currentKey = cacheKey;
9680
- parent.insertBefore(node, anchor.nextSibling);
9681
- };
10500
+ });
9682
10501
  let initialized = false;
9683
10502
  const wrappedUpdate = async () => {
9684
10503
  await update();
9685
10504
  initialized = true;
9686
10505
  };
9687
- const attachWait = attachRetry(anchor, update);
9688
- const kaTeardown = track2(wrappedUpdate);
10506
+ const attachWait = attachRetry(anchor, () => whenActive(gate, update));
10507
+ const kaTeardown = reactiveBinding2(wrappedUpdate, anchor);
9689
10508
  if (!initialized) {
9690
10509
  queueMicrotask(
9691
10510
  bindOwnerScope2(() => {
9692
- if (!initialized && anchor.parentNode) wrappedUpdate();
10511
+ whenActive(
10512
+ gate,
10513
+ bindOwnerScope2(() => {
10514
+ if (!initialized && anchor.parentNode) wrappedUpdate();
10515
+ })
10516
+ );
9693
10517
  })
9694
10518
  );
9695
10519
  }
9696
10520
  const kaCleanup = () => {
9697
10521
  if (kaTorn) return;
9698
10522
  kaTorn = true;
10523
+ gate.close();
10524
+ loaded.cancel();
9699
10525
  updateSeq++;
9700
10526
  kaTeardown();
9701
10527
  attachWait.cancel();
9702
- for (const node of cache.values()) {
9703
- disposeOwned(node);
10528
+ for (const node of cache2.values()) {
10529
+ disposeCached(node);
9704
10530
  if (node.parentNode) node.parentNode.removeChild(node);
9705
10531
  }
9706
- cache.clear();
10532
+ cache2.clear();
10533
+ suspended.clear();
9707
10534
  lruOrder.length = 0;
9708
10535
  if (currentNode?.parentNode) currentNode.parentNode.removeChild(currentNode);
9709
10536
  if (currentNode && !currentCached) disposeOwned(currentNode);
@@ -9711,6 +10538,7 @@ function KeepAliveRoute(options) {
9711
10538
  currentKey = "";
9712
10539
  currentCached = false;
9713
10540
  };
10541
+ registerNodesRange(anchor, () => [currentNode]);
9714
10542
  registerDisposer(anchor, kaCleanup);
9715
10543
  routeCleanups.push(kaCleanup);
9716
10544
  return anchor;
@@ -9786,6 +10614,15 @@ function Suspense(props) {
9786
10614
  const anchor = document.createComment("suspense-boundary");
9787
10615
  let currentNode = null;
9788
10616
  let fallbackNode = null;
10617
+ const frozen = captureFrozen2();
10618
+ let contentOwner = structuralBinding2(NOOP3);
10619
+ let fallbackOwner = null;
10620
+ const endContent = () => {
10621
+ const owner = contentOwner;
10622
+ contentOwner = null;
10623
+ owner?.stop();
10624
+ };
10625
+ const loaded = beginLoading(anchor);
9789
10626
  let isLoading = false;
9790
10627
  let generation = 0;
9791
10628
  let tornDown = false;
@@ -9800,21 +10637,36 @@ function Suspense(props) {
9800
10637
  release(fallbackNode);
9801
10638
  currentNode = null;
9802
10639
  fallbackNode = null;
10640
+ endFallback();
10641
+ };
10642
+ const endFallback = () => {
10643
+ const owner = fallbackOwner;
10644
+ fallbackOwner = null;
10645
+ owner?.stop();
9803
10646
  };
9804
10647
  const showFallback = (myGeneration) => {
9805
10648
  if (fallbackNode || !props.fallback || tornDown) return;
9806
10649
  if (!anchor.parentNode) return;
9807
10650
  let fallback;
9808
10651
  try {
9809
- fallback = typeof props.fallback === "function" ? props.fallback() : props.fallback;
10652
+ const factory = props.fallback;
10653
+ if (typeof factory === "function") {
10654
+ const owner = fallbackOwner = frozen.run(() => structuralBinding2(NOOP3));
10655
+ fallback = owner.run(factory);
10656
+ } else fallback = factory;
9810
10657
  } catch (error) {
9811
10658
  console.error("[Suspense] Fallback error:", error);
10659
+ endFallback();
10660
+ return;
10661
+ }
10662
+ if (!fallback || fallback.nodeType !== 1) {
10663
+ endFallback();
9812
10664
  return;
9813
10665
  }
9814
- if (!fallback || fallback.nodeType !== 1) return;
9815
10666
  const parent = commitTarget(myGeneration);
9816
10667
  if (!parent) {
9817
10668
  release(fallback);
10669
+ endFallback();
9818
10670
  return;
9819
10671
  }
9820
10672
  fallbackNode = fallback;
@@ -9825,7 +10677,9 @@ function Suspense(props) {
9825
10677
  isLoading = true;
9826
10678
  const myGeneration = ++generation;
9827
10679
  try {
9828
- const result = props.nodes();
10680
+ const owner = contentOwner;
10681
+ if (owner === null) return;
10682
+ const result = owner.run(props.nodes);
9829
10683
  let element;
9830
10684
  const isNode = typeof result?.nodeType === "number";
9831
10685
  if (!isNode && result != null && typeof result.then === "function") {
@@ -9834,35 +10688,84 @@ function Suspense(props) {
9834
10688
  } else {
9835
10689
  element = result;
9836
10690
  }
9837
- const parent = commitTarget(myGeneration);
9838
- if (!parent) {
9839
- release(element);
9840
- cleanupNodes();
9841
- return;
9842
- }
9843
- cleanupNodes();
9844
- parent.insertBefore(element, anchor.nextSibling);
9845
- currentNode = element;
10691
+ settle(myGeneration, true, element);
9846
10692
  } catch (error) {
9847
10693
  console.error("[Suspense] Nodes error:", error);
9848
- const parent = commitTarget(myGeneration);
9849
- cleanupNodes();
9850
- if (!parent) return;
9851
- const errorElement = document.createElement("div");
9852
- errorElement.className = "suspense-error";
9853
- errorElement.textContent = error instanceof Error ? error.message : "Failed to load";
9854
- parent.insertBefore(errorElement, anchor.nextSibling);
9855
- currentNode = errorElement;
10694
+ endContent();
10695
+ settle(myGeneration, false, error);
9856
10696
  } finally {
9857
10697
  isLoading = false;
9858
10698
  }
9859
10699
  };
10700
+ const committing = { cancel: NOOP3 };
10701
+ let dropWait = null;
10702
+ const settle = (myGeneration, ok, value) => {
10703
+ let view;
10704
+ if (ok) view = value;
10705
+ else {
10706
+ view = document.createElement("div");
10707
+ view.className = "suspense-error";
10708
+ view.textContent = value instanceof Error ? value.message : "Failed to load";
10709
+ }
10710
+ commitWhenActive(committing, {
10711
+ held: frozen,
10712
+ node: view,
10713
+ owned: () => !tornDown && myGeneration === generation,
10714
+ // Never shown: the content (or what is left of it) is abandoned.
10715
+ discard: () => {
10716
+ release(view);
10717
+ endContent();
10718
+ loaded.cancel();
10719
+ },
10720
+ teardown: () => {
10721
+ if (!anchor.parentNode || !(currentNode || fallbackNode || fallbackOwner)) return false;
10722
+ cleanupNodes();
10723
+ return true;
10724
+ },
10725
+ insert: () => {
10726
+ const parent = commitTarget(myGeneration);
10727
+ if (!parent) {
10728
+ release(view);
10729
+ cleanupNodes();
10730
+ endContent();
10731
+ loaded.cancel();
10732
+ return;
10733
+ }
10734
+ currentNode = view;
10735
+ try {
10736
+ parent.insertBefore(view, anchor.nextSibling);
10737
+ } catch (error) {
10738
+ if (currentNode === view) currentNode = null;
10739
+ release(view);
10740
+ endContent();
10741
+ console.error("[Suspense] Nodes error:", error);
10742
+ if (ok) settle(myGeneration, false, error);
10743
+ else loaded.cancel();
10744
+ return;
10745
+ }
10746
+ if (!tornDown && myGeneration === generation) loaded.done();
10747
+ }
10748
+ });
10749
+ };
10750
+ registerNodesRange(anchor, () => [currentNode, fallbackNode]);
9860
10751
  registerDisposer(anchor, () => {
9861
10752
  tornDown = true;
9862
10753
  generation++;
10754
+ dropWait?.();
10755
+ dropWait = null;
10756
+ committing.cancel();
9863
10757
  cleanupNodes();
10758
+ endContent();
10759
+ loaded.cancel();
10760
+ });
10761
+ const renderInScope = bindOwnerScope2(() => {
10762
+ if (!tornDown) render();
9864
10763
  });
9865
- queueMicrotask(bindOwnerScope2(render));
10764
+ queueMicrotask(
10765
+ bindOwnerScope2(() => {
10766
+ dropWait = frozen.wait(renderInScope, NOOP3);
10767
+ })
10768
+ );
9866
10769
  return anchor;
9867
10770
  }
9868
10771
  var LAZY_MARKER = /* @__PURE__ */ Symbol.for("sibujs:lazy");
@@ -9924,11 +10827,14 @@ function __removeRouterPagehideHandler() {
9924
10827
  function Outlet() {
9925
10828
  const anchor = document.createComment("route-outlet-nested");
9926
10829
  const adoptScope = captureScope();
10830
+ const frozen = captureFrozen2();
10831
+ const gate = pauseGate(frozen);
9927
10832
  let currentNode = null;
9928
10833
  let currentChild = null;
9929
10834
  let currentKey = null;
9930
10835
  let navSeq = 0;
9931
10836
  let outletTorn = false;
10837
+ const loaded = beginLoading(anchor);
9932
10838
  const clearCurrent = () => {
9933
10839
  if (currentNode) {
9934
10840
  disposeOwned(currentNode);
@@ -9954,21 +10860,25 @@ function Outlet() {
9954
10860
  const route2 = scopedRoute(_routerRef.current);
9955
10861
  if (route2.matched.length < 2) {
9956
10862
  clearCurrent();
10863
+ settleEmpty(route2, loaded, () => !outletTorn && seq === navSeq);
9957
10864
  return;
9958
10865
  }
9959
10866
  const childRoute = route2.matched[route2.matched.length - 1];
9960
10867
  if (!childRoute || !("component" in childRoute)) {
9961
10868
  clearCurrent();
10869
+ loaded.done();
9962
10870
  return;
9963
10871
  }
9964
10872
  const key = instanceKey(childRoute, route2.matched.slice(1), route2);
9965
10873
  if (childRoute === currentChild && key === currentKey && currentNode) {
9966
10874
  updateInstanceRoute(currentNode, route2);
10875
+ loaded.done();
9967
10876
  return;
9968
10877
  }
9969
10878
  try {
9970
10879
  const cacheKey = `${route2.path}\0${childRoute.path}`;
9971
10880
  const plan = await _routerRef.current.loadPlan(childRoute, cacheKey);
10881
+ while (gate.held()) if (!await gate.until()) return;
9972
10882
  if (!commitTarget(seq)) {
9973
10883
  retryIfDetached(seq);
9974
10884
  return;
@@ -9979,31 +10889,64 @@ function Outlet() {
9979
10889
  childRoute,
9980
10890
  cacheKey,
9981
10891
  route2,
9982
- keyedScope(adoptScope, childRoute.path)
10892
+ keyedScope(adoptScope, childRoute.path),
10893
+ gate,
10894
+ () => commitTarget(seq) !== null
9983
10895
  );
9984
- const parent = commitTarget(seq);
9985
- if (!parent) {
9986
- release(node);
9987
- retryIfDetached(seq);
9988
- return;
9989
- }
9990
- if (!node) return;
9991
- clearCurrent();
9992
- parent.insertBefore(node, anchor.nextSibling);
9993
- currentNode = node;
9994
- currentChild = childRoute;
9995
- currentKey = key;
10896
+ await commitPass(gate, {
10897
+ node,
10898
+ owned: () => !outletTorn && seq === navSeq,
10899
+ discard: () => release(node),
10900
+ teardown: () => {
10901
+ if (!node || !anchor.parentNode || !currentNode) return false;
10902
+ clearCurrent();
10903
+ return true;
10904
+ },
10905
+ insert: () => {
10906
+ const parent = commitTarget(seq);
10907
+ if (!parent) {
10908
+ release(node);
10909
+ retryIfDetached(seq);
10910
+ return;
10911
+ }
10912
+ if (node) {
10913
+ currentNode = node;
10914
+ currentChild = childRoute;
10915
+ currentKey = key;
10916
+ try {
10917
+ parent.insertBefore(node, anchor.nextSibling);
10918
+ } catch (error) {
10919
+ if (currentNode === node) {
10920
+ currentNode = null;
10921
+ currentChild = null;
10922
+ currentKey = null;
10923
+ }
10924
+ release(node);
10925
+ throw error;
10926
+ }
10927
+ }
10928
+ if (!outletTorn && seq === navSeq) loaded.done();
10929
+ }
10930
+ });
9996
10931
  } catch (error) {
9997
- if (outletTorn || seq !== navSeq) return;
10932
+ if (cancellations.has(error) || outletTorn || seq !== navSeq) return;
9998
10933
  console.error("[Outlet] Failed to render child route:", error);
10934
+ loaded.cancel();
9999
10935
  }
10000
10936
  };
10001
- const attachWait = attachRetry(anchor, update);
10002
- const outletTeardown = track2(update);
10937
+ const attachWait = attachRetry(anchor, () => whenActive(gate, update));
10938
+ const outletTeardown = reactiveBinding2(() => {
10939
+ void update();
10940
+ }, anchor);
10003
10941
  if (!anchor.parentNode) {
10004
10942
  queueMicrotask(
10005
10943
  bindOwnerScope2(() => {
10006
- if (anchor.parentNode) update();
10944
+ whenActive(
10945
+ gate,
10946
+ bindOwnerScope2(() => {
10947
+ if (anchor.parentNode) update();
10948
+ })
10949
+ );
10007
10950
  })
10008
10951
  );
10009
10952
  }
@@ -10011,6 +10954,8 @@ function Outlet() {
10011
10954
  if (outletTorn) return;
10012
10955
  outletTorn = true;
10013
10956
  navSeq++;
10957
+ gate.close();
10958
+ loaded.cancel();
10014
10959
  outletTeardown();
10015
10960
  attachWait.cancel();
10016
10961
  if (currentNode) {
@@ -10021,6 +10966,7 @@ function Outlet() {
10021
10966
  currentChild = null;
10022
10967
  currentKey = null;
10023
10968
  };
10969
+ registerNodesRange(anchor, () => [currentNode]);
10024
10970
  registerDisposer(anchor, outletCleanup);
10025
10971
  routeCleanups.push(outletCleanup);
10026
10972
  return anchor;
@@ -10283,7 +11229,7 @@ function renderRouteToString(url, routes, _options) {
10283
11229
  };
10284
11230
  }
10285
11231
  function renderRouteToDocument(url, routes, options) {
10286
- const { html: html2, state: state3 } = renderRouteToString(url, routes, options);
11232
+ const { html: html2, state: state5 } = renderRouteToString(url, routes, options);
10287
11233
  const opts = options || {};
10288
11234
  const metaTags = (opts.meta || []).map((attrs) => serializeHeadEntry("meta", attrs)).filter(Boolean).join("\n ");
10289
11235
  const linkTags = (opts.links || []).map((attrs) => serializeHeadEntry("link", attrs)).filter(Boolean).join("\n ");
@@ -10292,7 +11238,7 @@ function renderRouteToDocument(url, routes, options) {
10292
11238
  if (!safe) return "";
10293
11239
  return `<script src="${escapeAttrLocal(safe)}"></script>`;
10294
11240
  }).filter(Boolean).join("\n ");
10295
- const stateScript = serializeRouteState(state3, opts.nonce);
11241
+ const stateScript = serializeRouteState(state5, opts.nonce);
10296
11242
  return `<!DOCTYPE html>
10297
11243
  <html>
10298
11244
  <head>
@@ -10310,8 +11256,8 @@ function renderRouteToDocument(url, routes, options) {
10310
11256
  </body>
10311
11257
  </html>`;
10312
11258
  }
10313
- function serializeRouteState(state3, nonce) {
10314
- const json = escapeScriptJson(JSON.stringify(state3));
11259
+ function serializeRouteState(state5, nonce) {
11260
+ const json = escapeScriptJson(JSON.stringify(state5));
10315
11261
  const nonceAttr = nonce ? ` nonce="${escapeAttrLocal(nonce)}"` : "";
10316
11262
  return `<script${nonceAttr}>window.${SSR_ROUTE_STATE_KEY}=${json}</script>`;
10317
11263
  }
@@ -10394,24 +11340,24 @@ function assertCacheSize(name, value) {
10394
11340
  throw new RangeError(`[Startup] ${name} must be a non-negative integer, got ${value}`);
10395
11341
  }
10396
11342
  }
10397
- function makeRoomFor(cache, key, maxSize, isValid) {
11343
+ function makeRoomFor(cache2, key, maxSize, isValid) {
10398
11344
  if (maxSize === 0) return false;
10399
- if (cache.has(key)) return true;
10400
- if (cache.size < maxSize) return true;
10401
- for (const [k, entry] of cache) {
10402
- if (!isValid(entry)) cache.delete(k);
11345
+ if (cache2.has(key)) return true;
11346
+ if (cache2.size < maxSize) return true;
11347
+ for (const [k, entry] of cache2) {
11348
+ if (!isValid(entry)) cache2.delete(k);
10403
11349
  }
10404
- while (cache.size >= maxSize) {
11350
+ while (cache2.size >= maxSize) {
10405
11351
  let oldestKey = null;
10406
11352
  let oldestTime = Infinity;
10407
- for (const [k, entry] of cache) {
11353
+ for (const [k, entry] of cache2) {
10408
11354
  if (entry.timestamp < oldestTime) {
10409
11355
  oldestTime = entry.timestamp;
10410
11356
  oldestKey = k;
10411
11357
  }
10412
11358
  }
10413
11359
  if (oldestKey === null) break;
10414
- cache.delete(oldestKey);
11360
+ cache2.delete(oldestKey);
10415
11361
  }
10416
11362
  return true;
10417
11363
  }
@@ -10419,57 +11365,57 @@ function prerenderRoutes(routes, options) {
10419
11365
  const maxCacheSize = options?.maxCacheSize ?? 50;
10420
11366
  const cacheTTL = options?.cacheTTL ?? 0;
10421
11367
  assertCacheSize("maxCacheSize", maxCacheSize);
10422
- const cache = /* @__PURE__ */ new Map();
11368
+ const cache2 = /* @__PURE__ */ new Map();
10423
11369
  function isValid(entry) {
10424
11370
  if (cacheTTL === 0) return true;
10425
11371
  return Date.now() - entry.timestamp < cacheTTL;
10426
11372
  }
10427
11373
  for (const route2 of routes) {
10428
- if (!makeRoomFor(cache, route2.path, maxCacheSize, isValid)) break;
11374
+ if (!makeRoomFor(cache2, route2.path, maxCacheSize, isValid)) break;
10429
11375
  const html2 = renderToString(route2.component());
10430
- cache.set(route2.path, { html: html2, timestamp: Date.now() });
11376
+ cache2.set(route2.path, { html: html2, timestamp: Date.now() });
10431
11377
  }
10432
11378
  return {
10433
11379
  /** Get cached HTML for a route, or undefined if not cached or expired */
10434
11380
  get(path2) {
10435
- const entry = cache.get(path2);
11381
+ const entry = cache2.get(path2);
10436
11382
  if (!entry) return void 0;
10437
11383
  if (!isValid(entry)) {
10438
- cache.delete(path2);
11384
+ cache2.delete(path2);
10439
11385
  return void 0;
10440
11386
  }
10441
11387
  return entry.html;
10442
11388
  },
10443
11389
  /** Check if a route has been prerendered and is still valid */
10444
11390
  has(path2) {
10445
- const entry = cache.get(path2);
11391
+ const entry = cache2.get(path2);
10446
11392
  if (!entry) return false;
10447
11393
  if (!isValid(entry)) {
10448
- cache.delete(path2);
11394
+ cache2.delete(path2);
10449
11395
  return false;
10450
11396
  }
10451
11397
  return true;
10452
11398
  },
10453
11399
  /** Invalidate a cached route */
10454
11400
  invalidate(path2) {
10455
- cache.delete(path2);
11401
+ cache2.delete(path2);
10456
11402
  },
10457
11403
  /** Clear all cached routes */
10458
11404
  clear() {
10459
- cache.clear();
11405
+ cache2.clear();
10460
11406
  },
10461
11407
  /** Get cache statistics */
10462
11408
  stats() {
10463
11409
  if (cacheTTL > 0) {
10464
- for (const [key, entry] of cache) {
11410
+ for (const [key, entry] of cache2) {
10465
11411
  if (!isValid(entry)) {
10466
- cache.delete(key);
11412
+ cache2.delete(key);
10467
11413
  }
10468
11414
  }
10469
11415
  }
10470
11416
  return {
10471
- size: cache.size,
10472
- routes: Array.from(cache.keys())
11417
+ size: cache2.size,
11418
+ routes: Array.from(cache2.keys())
10473
11419
  };
10474
11420
  }
10475
11421
  };
@@ -10478,7 +11424,7 @@ function createSSRCache(config) {
10478
11424
  const maxSize = config?.maxSize ?? 100;
10479
11425
  const defaultTTL = config?.defaultTTL ?? 6e4;
10480
11426
  assertCacheSize("maxSize", maxSize);
10481
- const cache = /* @__PURE__ */ new Map();
11427
+ const cache2 = /* @__PURE__ */ new Map();
10482
11428
  let hits = 0;
10483
11429
  let misses = 0;
10484
11430
  function isValid(entry) {
@@ -10488,13 +11434,13 @@ function createSSRCache(config) {
10488
11434
  return {
10489
11435
  /** Get cached HTML for a key, or undefined if not cached or expired */
10490
11436
  get(key) {
10491
- const entry = cache.get(key);
11437
+ const entry = cache2.get(key);
10492
11438
  if (!entry) {
10493
11439
  misses++;
10494
11440
  return void 0;
10495
11441
  }
10496
11442
  if (!isValid(entry)) {
10497
- cache.delete(key);
11443
+ cache2.delete(key);
10498
11444
  misses++;
10499
11445
  return void 0;
10500
11446
  }
@@ -10503,8 +11449,8 @@ function createSSRCache(config) {
10503
11449
  },
10504
11450
  /** Cache an HTML string with an optional TTL override */
10505
11451
  set(key, html2, ttl) {
10506
- if (!makeRoomFor(cache, key, maxSize, isValid)) return;
10507
- cache.set(key, {
11452
+ if (!makeRoomFor(cache2, key, maxSize, isValid)) return;
11453
+ cache2.set(key, {
10508
11454
  html: html2,
10509
11455
  timestamp: Date.now(),
10510
11456
  ttl: ttl ?? defaultTTL
@@ -10512,27 +11458,27 @@ function createSSRCache(config) {
10512
11458
  },
10513
11459
  /** Check if a key exists in the cache and is still valid */
10514
11460
  has(key) {
10515
- const entry = cache.get(key);
11461
+ const entry = cache2.get(key);
10516
11462
  if (!entry) return false;
10517
11463
  if (!isValid(entry)) {
10518
- cache.delete(key);
11464
+ cache2.delete(key);
10519
11465
  return false;
10520
11466
  }
10521
11467
  return true;
10522
11468
  },
10523
11469
  /** Invalidate a cached entry */
10524
11470
  invalidate(key) {
10525
- cache.delete(key);
11471
+ cache2.delete(key);
10526
11472
  },
10527
11473
  /** Clear all cached entries and reset statistics */
10528
11474
  clear() {
10529
- cache.clear();
11475
+ cache2.clear();
10530
11476
  hits = 0;
10531
11477
  misses = 0;
10532
11478
  },
10533
11479
  /** Get cache statistics including hit/miss counts */
10534
11480
  stats() {
10535
- return { size: cache.size, hits, misses };
11481
+ return { size: cache2.size, hits, misses };
10536
11482
  }
10537
11483
  };
10538
11484
  }
@@ -10611,7 +11557,7 @@ function createBootSequence() {
10611
11557
 
10612
11558
  // src/plugins/versioning.ts
10613
11559
  init_globalSingleton();
10614
- var VERSION = true ? "4.14.0" : "dev";
11560
+ var VERSION = true ? "4.15.0" : "dev";
10615
11561
  var NUM = "(?:0|[1-9]\\d*)";
10616
11562
  var PRE_ID = `(?:${NUM}|\\d*[a-zA-Z-][0-9a-zA-Z-]*)`;
10617
11563
  var BUILD_ID = "[0-9a-zA-Z-]+";
@@ -10796,9 +11742,9 @@ function createMigrationRunner(config) {
10796
11742
  return serialize(async () => {
10797
11743
  const applied = [];
10798
11744
  const errors = [];
10799
- let pending;
11745
+ let pending2;
10800
11746
  try {
10801
- pending = getPending();
11747
+ pending2 = getPending();
10802
11748
  } catch (e) {
10803
11749
  errors.push({
10804
11750
  version: getAppliedVersion() ?? "",
@@ -10806,7 +11752,7 @@ function createMigrationRunner(config) {
10806
11752
  });
10807
11753
  return { applied, errors };
10808
11754
  }
10809
- for (const migration of pending) {
11755
+ for (const migration of pending2) {
10810
11756
  try {
10811
11757
  await migration.up();
10812
11758
  } catch (e) {