sibujs 4.4.0 → 4.6.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 (112) hide show
  1. package/README.md +11 -0
  2. package/dist/browser.cjs +339 -130
  3. package/dist/browser.d.cts +61 -16
  4. package/dist/browser.d.ts +61 -16
  5. package/dist/browser.js +8 -6
  6. package/dist/build.cjs +273 -82
  7. package/dist/build.js +15 -16
  8. package/dist/cdn.dev.global.js +12 -12
  9. package/dist/cdn.full.dev.global.js +11 -11
  10. package/dist/cdn.full.global.js +10 -10
  11. package/dist/cdn.global.js +12 -12
  12. package/dist/{chunk-IXKSNWV5.js → chunk-2INLLLMZ.js} +1 -1
  13. package/dist/chunk-3ISI6ACU.js +44 -0
  14. package/dist/{chunk-VCTAEPSB.js → chunk-47M47FOM.js} +11 -3
  15. package/dist/chunk-5HZXGZ6T.js +24 -0
  16. package/dist/{chunk-KKLW7YWL.js → chunk-5MT6SJ3P.js} +275 -144
  17. package/dist/{chunk-3BTTCZ5J.js → chunk-5Q4R7HCL.js} +42 -4
  18. package/dist/{chunk-ADM46X22.js → chunk-7GQCWFOE.js} +157 -61
  19. package/dist/{chunk-4Z3SPQ67.js → chunk-7NCARGJW.js} +16 -8
  20. package/dist/{chunk-5DXA2J44.js → chunk-7XHATCIH.js} +5 -2
  21. package/dist/{chunk-LQFGQNMV.js → chunk-AIF3Z2T7.js} +302 -39
  22. package/dist/{chunk-UCALUKB5.js → chunk-BAAG6ZTI.js} +98 -29
  23. package/dist/{chunk-NVNJH22U.js → chunk-D33YTSX5.js} +2 -2
  24. package/dist/{chunk-M2F7TZHH.js → chunk-DKGBBKOF.js} +136 -80
  25. package/dist/{chunk-NIOYEGBQ.js → chunk-HURREPU2.js} +27 -13
  26. package/dist/{chunk-HFCOH2GN.js → chunk-HYXDKS4N.js} +153 -110
  27. package/dist/chunk-J6FW5TV6.js +233 -0
  28. package/dist/{chunk-36S2YPP4.js → chunk-JSXPZCET.js} +1 -1
  29. package/dist/chunk-NYNYSPK7.js +318 -0
  30. package/dist/{chunk-HQSEH5F6.js → chunk-ORMZXBKQ.js} +108 -45
  31. package/dist/{chunk-LYVUX7NT.js → chunk-OXUY2A6L.js} +287 -130
  32. package/dist/{chunk-6GSIXTWX.js → chunk-PK6FK2G2.js} +187 -66
  33. package/dist/{chunk-W2EQ7X2L.js → chunk-QE4TTDU3.js} +47 -9
  34. package/dist/{chunk-XLO7SLIX.js → chunk-SXXVZMKZ.js} +262 -70
  35. package/dist/{chunk-R25EFXXC.js → chunk-TUCPL2HB.js} +3 -3
  36. package/dist/{chunk-RR7M3FHM.js → chunk-UZQ6ALFS.js} +3 -3
  37. package/dist/{chunk-PNIRUQ4C.js → chunk-VVWPJ543.js} +6 -8
  38. package/dist/{chunk-7GIHSAWB.js → chunk-XC4MEKGA.js} +3 -3
  39. package/dist/{chunk-SKPTERHP.js → chunk-XRRZKZYX.js} +55 -31
  40. package/dist/{contracts-DBdg9J_a.d.cts → contracts-DRIuclVT.d.cts} +10 -2
  41. package/dist/{contracts-DBdg9J_a.d.ts → contracts-DRIuclVT.d.ts} +10 -2
  42. package/dist/{customElement-CNZxEB9G.d.ts → customElement-MmInOW1U.d.cts} +59 -10
  43. package/dist/{customElement-CNZxEB9G.d.cts → customElement-MmInOW1U.d.ts} +59 -10
  44. package/dist/data.cjs +293 -125
  45. package/dist/data.d.cts +47 -9
  46. package/dist/data.d.ts +47 -9
  47. package/dist/data.js +12 -9
  48. package/dist/devtools.cjs +121 -58
  49. package/dist/devtools.js +7 -8
  50. package/dist/dispose-GEIG2KOF.js +28 -0
  51. package/dist/ecosystem.cjs +391 -112
  52. package/dist/ecosystem.d.cts +31 -7
  53. package/dist/ecosystem.d.ts +31 -7
  54. package/dist/ecosystem.js +12 -12
  55. package/dist/extras.cjs +2250 -879
  56. package/dist/extras.d.cts +10 -9
  57. package/dist/extras.d.ts +10 -9
  58. package/dist/extras.js +39 -28
  59. package/dist/index.cjs +273 -82
  60. package/dist/index.d.cts +44 -154
  61. package/dist/index.d.ts +44 -154
  62. package/dist/index.js +24 -27
  63. package/dist/motion.cjs +137 -42
  64. package/dist/motion.js +5 -5
  65. package/dist/patterns.cjs +397 -48
  66. package/dist/patterns.d.cts +32 -9
  67. package/dist/patterns.d.ts +32 -9
  68. package/dist/patterns.js +8 -8
  69. package/dist/performance.cjs +338 -217
  70. package/dist/performance.d.cts +2 -2
  71. package/dist/performance.d.ts +2 -2
  72. package/dist/performance.js +8 -9
  73. package/dist/plugin-DVgSnTfK.d.cts +112 -0
  74. package/dist/plugin-DVgSnTfK.d.ts +112 -0
  75. package/dist/plugins.cjs +587 -203
  76. package/dist/plugins.d.cts +3 -3
  77. package/dist/plugins.d.ts +3 -3
  78. package/dist/plugins.js +35 -23
  79. package/dist/signal-EotCj4hS.d.cts +110 -0
  80. package/dist/signal-EotCj4hS.d.ts +110 -0
  81. package/dist/{ssr-BiPRdZ6n.d.cts → ssr-Bli9XRW5.d.cts} +5 -0
  82. package/dist/{ssr-BiPRdZ6n.d.ts → ssr-Bli9XRW5.d.ts} +5 -0
  83. package/dist/{ssr-Y7XOEPEN.js → ssr-XOTUASDO.js} +4 -5
  84. package/dist/ssr.cjs +214 -73
  85. package/dist/ssr.d.cts +9 -3
  86. package/dist/ssr.d.ts +9 -3
  87. package/dist/ssr.js +11 -12
  88. package/dist/{startup-BMpaiMhP.d.ts → startup-BLfSeL15.d.cts} +73 -22
  89. package/dist/{startup-BMpaiMhP.d.cts → startup-BLfSeL15.d.ts} +73 -22
  90. package/dist/tagFactory-DFstCLQV.d.cts +117 -0
  91. package/dist/tagFactory-DkaNVUNV.d.ts +117 -0
  92. package/dist/testing.cjs +2481 -2153
  93. package/dist/testing.d.cts +56 -5
  94. package/dist/testing.d.ts +56 -5
  95. package/dist/testing.js +580 -307
  96. package/dist/ui.cjs +798 -328
  97. package/dist/ui.d.cts +40 -7
  98. package/dist/ui.d.ts +40 -7
  99. package/dist/ui.js +151 -56
  100. package/dist/widgets.cjs +319 -285
  101. package/dist/widgets.js +9 -10
  102. package/package.json +2 -2
  103. package/dist/chunk-2WLZ6757.js +0 -149
  104. package/dist/chunk-7NBDXVHS.js +0 -60
  105. package/dist/chunk-CCSJMTRN.js +0 -15
  106. package/dist/chunk-QKRPLZ2V.js +0 -108
  107. package/dist/chunk-WWV3SJ3L.js +0 -131
  108. package/dist/dispose-46BOMMQJ.js +0 -19
  109. package/dist/plugin-D30wlGW5.d.cts +0 -71
  110. package/dist/plugin-D30wlGW5.d.ts +0 -71
  111. package/dist/tagFactory-Bzupt4Pj.d.cts +0 -55
  112. package/dist/tagFactory-Bzupt4Pj.d.ts +0 -55
package/dist/ssr.cjs CHANGED
@@ -186,6 +186,23 @@ function reportDrainRunaway(label2, executed, remaining) {
186
186
  );
187
187
  }
188
188
  var activeBindingCount = 0;
189
+ function resolveCapture(capture) {
190
+ let frame = capture;
191
+ while (frame?.closed) frame = frame.forwardTo;
192
+ return frame ?? null;
193
+ }
194
+ var registrationCaptures = [];
195
+ function currentDisposerCapture() {
196
+ return resolveCapture(registrationCaptures[registrationCaptures.length - 1]);
197
+ }
198
+ function beginDisposerCapture(capture) {
199
+ if (capture === null && registrationCaptures.length === 0) return false;
200
+ registrationCaptures.push(resolveCapture(capture));
201
+ return true;
202
+ }
203
+ function endDisposerCapture() {
204
+ registrationCaptures.pop();
205
+ }
189
206
  function registerDisposer(node, teardown) {
190
207
  let disposers = elementDisposers.get(node);
191
208
  if (!disposers) {
@@ -194,6 +211,8 @@ function registerDisposer(node, teardown) {
194
211
  }
195
212
  disposers.push(teardown);
196
213
  if (DEV) activeBindingCount++;
214
+ const capture = resolveCapture(registrationCaptures[registrationCaptures.length - 1]);
215
+ if (capture) capture.entries.push([node, teardown]);
197
216
  }
198
217
  function dispose(node) {
199
218
  const stack = [node];
@@ -207,33 +226,34 @@ function dispose(node) {
207
226
  }
208
227
  }
209
228
  for (let i2 = order.length - 1; i2 >= 0; i2--) {
210
- const current = order[i2];
211
- if (elementDisposers.has(current)) {
212
- let executed = 0;
213
- let runaway = false;
214
- while (!runaway) {
215
- const pending = elementDisposers.get(current);
216
- if (!pending || pending.length === 0) break;
217
- const snapshot = pending.slice();
218
- elementDisposers.delete(current);
219
- if (DEV) activeBindingCount -= snapshot.length;
220
- for (let i3 = 0; i3 < snapshot.length; i3++) {
221
- if (executed >= MAX_DRAIN_TEARDOWNS) {
222
- const rest = snapshot.slice(i3);
223
- const added = elementDisposers.get(current);
224
- elementDisposers.set(current, added ? rest.concat(added) : rest);
225
- if (DEV) activeBindingCount += rest.length;
226
- reportDrainRunaway("dispose", executed, rest.length + (added?.length ?? 0));
227
- runaway = true;
228
- break;
229
- }
230
- executed++;
231
- try {
232
- snapshot[i3]();
233
- } catch (err) {
234
- reportError(err, { phase: "cleanup", name: "disposer" });
235
- }
236
- }
229
+ disposeNodeOwn(order[i2]);
230
+ }
231
+ }
232
+ function disposeNodeOwn(node) {
233
+ if (!elementDisposers.has(node)) return;
234
+ let executed = 0;
235
+ let runaway = false;
236
+ while (!runaway) {
237
+ const pending = elementDisposers.get(node);
238
+ if (!pending || pending.length === 0) break;
239
+ const snapshot = pending.slice();
240
+ elementDisposers.delete(node);
241
+ if (DEV) activeBindingCount -= snapshot.length;
242
+ for (let i2 = 0; i2 < snapshot.length; i2++) {
243
+ if (executed >= MAX_DRAIN_TEARDOWNS) {
244
+ const rest = snapshot.slice(i2);
245
+ const added = elementDisposers.get(node);
246
+ elementDisposers.set(node, added ? rest.concat(added) : rest);
247
+ if (DEV) activeBindingCount += rest.length;
248
+ reportDrainRunaway("dispose", executed, rest.length + (added?.length ?? 0));
249
+ runaway = true;
250
+ break;
251
+ }
252
+ executed++;
253
+ try {
254
+ snapshot[i2]();
255
+ } catch (err) {
256
+ reportError(err, { phase: "cleanup", name: "disposer" });
237
257
  }
238
258
  }
239
259
  }
@@ -938,7 +958,7 @@ function renderToDocument(component, options = {}) {
938
958
  <head>
939
959
  <meta charset="UTF-8" />
940
960
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
941
- ${options.title ? `<title>${escapeHtml(options.title)}</title>` : ""}
961
+ ${options.title != null ? `<title>${escapeHtml(options.title)}</title>` : ""}
942
962
  ${metaTags}
943
963
  ${linkTags}
944
964
  ${options.headExtra || ""}
@@ -1113,16 +1133,32 @@ function ssrSuspense(props) {
1113
1133
  const timeoutPromise = new Promise((_, reject) => {
1114
1134
  timer = setTimeout(() => reject(new Error(`[SibuJS SSR] ssrSuspense timed out after ${timeoutMs}ms`)), timeoutMs);
1115
1135
  });
1116
- const raced = Promise.race([props.content(), timeoutPromise]);
1136
+ let contentPromise;
1137
+ try {
1138
+ contentPromise = Promise.resolve(props.content());
1139
+ } catch (err) {
1140
+ contentPromise = Promise.reject(err);
1141
+ }
1142
+ const toFallback = (err) => {
1143
+ if (DEV) console.warn("[SibuJS SSR] ssrSuspense rejected:", err);
1144
+ return { id, html: fallbackHtml };
1145
+ };
1146
+ const clearTimer = () => {
1147
+ if (timer !== void 0) clearTimeout(timer);
1148
+ };
1149
+ const raced = Promise.race([contentPromise, timeoutPromise]);
1117
1150
  const promise = raced.then(
1118
1151
  (resolvedEl) => {
1119
- if (timer) clearTimeout(timer);
1120
- return { id, html: renderToString(resolvedEl) };
1152
+ clearTimer();
1153
+ try {
1154
+ return { id, html: renderToString(resolvedEl) };
1155
+ } catch (err) {
1156
+ return toFallback(err);
1157
+ }
1121
1158
  },
1122
1159
  (err) => {
1123
- if (timer) clearTimeout(timer);
1124
- if (DEV) console.warn("[SibuJS SSR] ssrSuspense rejected:", err);
1125
- return { id, html: fallbackHtml };
1160
+ clearTimer();
1161
+ return toFallback(err);
1126
1162
  }
1127
1163
  );
1128
1164
  promise.catch(noop);
@@ -1332,8 +1368,18 @@ function untracked(fn) {
1332
1368
  var subscriberEpochCounter = 0;
1333
1369
  function retrack(effectFn, subscriber) {
1334
1370
  const prev = currentSubscriber;
1371
+ let savedDepth = 0;
1372
+ let savedSuspendSub = null;
1373
+ if (trackingSuspended) {
1374
+ savedDepth = suspendDepth;
1375
+ savedSuspendSub = suspendSavedSub;
1376
+ suspendDepth = 0;
1377
+ suspendSavedSub = null;
1378
+ trackingSuspended = false;
1379
+ }
1335
1380
  currentSubscriber = subscriber;
1336
1381
  const sub2 = subscriber;
1382
+ if (sub2._cap === void 0) sub2._cap = currentDisposerCapture();
1337
1383
  const epoch = ++subscriberEpochCounter;
1338
1384
  sub2._epoch = epoch;
1339
1385
  sub2._structDirty = false;
@@ -1346,6 +1392,11 @@ function retrack(effectFn, subscriber) {
1346
1392
  effectFn();
1347
1393
  } finally {
1348
1394
  currentSubscriber = prev;
1395
+ if (savedDepth !== 0) {
1396
+ suspendDepth = savedDepth;
1397
+ suspendSavedSub = savedSuspendSub;
1398
+ trackingSuspended = true;
1399
+ }
1349
1400
  let node = sub2.depsHead ?? null;
1350
1401
  while (node !== null) {
1351
1402
  const next = node.subNext;
@@ -1365,11 +1416,25 @@ function track(effectFn, subscriber) {
1365
1416
  if (!subscriber) return reactiveBinding(effectFn);
1366
1417
  cleanup(subscriber);
1367
1418
  const prev = currentSubscriber;
1419
+ let savedDepth = 0;
1420
+ let savedSuspendSub = null;
1421
+ if (trackingSuspended) {
1422
+ savedDepth = suspendDepth;
1423
+ savedSuspendSub = suspendSavedSub;
1424
+ suspendDepth = 0;
1425
+ suspendSavedSub = null;
1426
+ trackingSuspended = false;
1427
+ }
1368
1428
  currentSubscriber = subscriber;
1369
1429
  try {
1370
1430
  effectFn();
1371
1431
  } finally {
1372
1432
  currentSubscriber = prev;
1433
+ if (savedDepth !== 0) {
1434
+ suspendDepth = savedDepth;
1435
+ suspendSavedSub = savedSuspendSub;
1436
+ trackingSuspended = true;
1437
+ }
1373
1438
  const sub3 = subscriber;
1374
1439
  for (let n = sub3.depsHead ?? null; n !== null; n = n.subNext) {
1375
1440
  const sig = n.sig;
@@ -1506,7 +1571,12 @@ function drainQueue() {
1506
1571
  quarantined.add(sub2);
1507
1572
  continue;
1508
1573
  }
1509
- safeInvoke(sub2);
1574
+ const pushed = beginDisposerCapture(sub2._cap ?? null);
1575
+ try {
1576
+ safeInvoke(sub2);
1577
+ } finally {
1578
+ if (pushed) endDisposerCapture();
1579
+ }
1510
1580
  }
1511
1581
  }
1512
1582
  function drainNotificationQueue() {
@@ -1540,8 +1610,9 @@ function propagateDirty(sub2) {
1540
1610
  if (s2._c) {
1541
1611
  const nSig = s2._sig;
1542
1612
  if (nSig) {
1543
- if (!nSig._d) {
1613
+ if (!nSig._d || nSig._f === true) {
1544
1614
  nSig._d = true;
1615
+ nSig._f = false;
1545
1616
  stack.push(nSig);
1546
1617
  }
1547
1618
  } else {
@@ -1641,7 +1712,7 @@ function forEachSubscriber(signal2, visit) {
1641
1712
  }
1642
1713
 
1643
1714
  // src/reactivity/track.ts
1644
- var _runtimeVersion = true ? "4.4.0" : "dev";
1715
+ var _runtimeVersion = true ? "4.6.0" : "dev";
1645
1716
  var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
1646
1717
  function resolveReactiveApi() {
1647
1718
  const g2 = globalThis;
@@ -2007,7 +2078,7 @@ function Head(props) {
2007
2078
  };
2008
2079
  const apply = () => {
2009
2080
  cleanup3();
2010
- if (props.title) {
2081
+ if (props.title != null) {
2011
2082
  if (typeof props.title === "function") {
2012
2083
  const getter = props.title;
2013
2084
  let lease = null;
@@ -2062,13 +2133,14 @@ function Head(props) {
2062
2133
  return anchor;
2063
2134
  }
2064
2135
  function setStructuredData(data2) {
2065
- const existing = document.head.querySelector('script[type="application/ld+json"][data-sibu]');
2066
- if (existing) existing.remove();
2136
+ const json = escapeScriptJsonLocal(JSON.stringify(data2));
2067
2137
  const script2 = document.createElement("script");
2068
2138
  script2.type = "application/ld+json";
2069
2139
  script2.setAttribute("data-sibu", "true");
2070
- script2.textContent = escapeScriptJsonLocal(JSON.stringify(data2));
2071
- document.head.appendChild(script2);
2140
+ script2.textContent = json;
2141
+ const existing = document.head.querySelector('script[type="application/ld+json"][data-sibu]');
2142
+ if (existing) existing.replaceWith(script2);
2143
+ else document.head.appendChild(script2);
2072
2144
  }
2073
2145
  function setCanonical(url) {
2074
2146
  let link2 = document.head.querySelector('link[rel="canonical"]');
@@ -2225,15 +2297,31 @@ function signal(initial, options) {
2225
2297
  // src/platform/incrementalRegeneration.ts
2226
2298
  function createISR(options) {
2227
2299
  const { revalidateAfter, fetcher, initialData } = options;
2300
+ if (!Number.isFinite(revalidateAfter) || revalidateAfter <= 0) {
2301
+ throw new RangeError(`[SibuJS ISR] revalidateAfter must be a positive finite number, got ${revalidateAfter}`);
2302
+ }
2228
2303
  const [data2, setData] = signal(initialData);
2229
- const [timestamp, setTimestamp] = signal(initialData !== void 0 ? Date.now() : 0);
2304
+ const [stale, setStale] = signal(initialData === void 0);
2230
2305
  const controller = new AbortController();
2231
2306
  let inFlight = false;
2232
2307
  let disposed = false;
2233
- const isStale = () => {
2234
- const ts = timestamp();
2235
- if (ts === 0) return true;
2236
- return Date.now() - ts >= revalidateAfter;
2308
+ let deadline;
2309
+ const clearDeadline = () => {
2310
+ if (deadline !== void 0) {
2311
+ clearTimeout(deadline);
2312
+ deadline = void 0;
2313
+ }
2314
+ };
2315
+ const armDeadline = () => {
2316
+ clearDeadline();
2317
+ deadline = setTimeout(() => {
2318
+ deadline = void 0;
2319
+ if (disposed) return;
2320
+ setStale(true);
2321
+ revalidate().catch((err) => {
2322
+ if (typeof console !== "undefined") console.warn("[SibuJS ISR] revalidate failed", err);
2323
+ });
2324
+ }, revalidateAfter);
2237
2325
  };
2238
2326
  const revalidate = async () => {
2239
2327
  if (disposed || inFlight) return;
@@ -2242,8 +2330,14 @@ function createISR(options) {
2242
2330
  try {
2243
2331
  const result = await fetcher({ signal: controller.signal });
2244
2332
  if (disposed || controller.signal.aborted) return;
2245
- setData(result);
2246
- setTimestamp(Date.now());
2333
+ batch(() => {
2334
+ setData(result);
2335
+ setStale(false);
2336
+ });
2337
+ armDeadline();
2338
+ } catch (err) {
2339
+ if (!disposed && !controller.signal.aborted) armDeadline();
2340
+ throw err;
2247
2341
  } finally {
2248
2342
  inFlight = false;
2249
2343
  }
@@ -2252,19 +2346,16 @@ function createISR(options) {
2252
2346
  revalidate().catch((err) => {
2253
2347
  if (typeof console !== "undefined") console.warn("[SibuJS ISR] initial fetch failed", err);
2254
2348
  });
2349
+ } else {
2350
+ armDeadline();
2255
2351
  }
2256
- const intervalId = setInterval(() => {
2257
- revalidate().catch((err) => {
2258
- if (typeof console !== "undefined") console.warn("[SibuJS ISR] revalidate failed", err);
2259
- });
2260
- }, revalidateAfter);
2261
2352
  const dispose2 = () => {
2262
2353
  if (disposed) return;
2263
2354
  disposed = true;
2264
- clearInterval(intervalId);
2355
+ clearDeadline();
2265
2356
  controller.abort();
2266
2357
  };
2267
- return { data: data2, isStale, revalidate, dispose: dispose2 };
2358
+ return { data: data2, isStale: stale, revalidate, dispose: dispose2 };
2268
2359
  }
2269
2360
 
2270
2361
  // src/platform/routeActions.ts
@@ -2468,6 +2559,14 @@ function setSafeAttribute(el, name, value, options = {}) {
2468
2559
  const html2 = isHtmlElement(el);
2469
2560
  const idlName = html2 ? name.toLowerCase() : name;
2470
2561
  if (typeof value === "boolean") {
2562
+ if (name.length > 5 && name.slice(0, 5).toLowerCase() === "aria-") {
2563
+ const token = value ? "true" : "false";
2564
+ if ((ns ? el.getAttributeNS(ns, localName) : el.getAttribute(name)) !== token) {
2565
+ if (ns) el.setAttributeNS(ns, name, token);
2566
+ else el.setAttribute(name, token);
2567
+ }
2568
+ return true;
2569
+ }
2471
2570
  if (html2 && BOOLEAN_IDL_ATTRS.has(idlName) && idlName in el) {
2472
2571
  setProp(el, idlName, value);
2473
2572
  } else if (value) {
@@ -3166,13 +3265,13 @@ function createSharedScope(initialState) {
3166
3265
  for (const key of Object.keys(initialState)) {
3167
3266
  const [get2, set2] = signal(initialState[key]);
3168
3267
  signals.set(key, { get: get2, set: set2 });
3169
- subscribers.set(key, /* @__PURE__ */ new Set());
3268
+ subscribers.set(key, /* @__PURE__ */ new Map());
3170
3269
  }
3171
3270
  function ensureSignal(key) {
3172
3271
  if (!signals.has(key)) {
3173
3272
  const [get2, set2] = signal(void 0);
3174
3273
  signals.set(key, { get: get2, set: set2 });
3175
- subscribers.set(key, /* @__PURE__ */ new Set());
3274
+ subscribers.set(key, /* @__PURE__ */ new Map());
3176
3275
  }
3177
3276
  }
3178
3277
  function get(key) {
@@ -3183,9 +3282,14 @@ function createSharedScope(initialState) {
3183
3282
  ensureSignal(key);
3184
3283
  signals.get(key)?.set(value);
3185
3284
  const subs = subscribers.get(key);
3186
- if (subs) {
3187
- for (const cb of subs) {
3188
- cb(value);
3285
+ if (subs && subs.size > 0) {
3286
+ for (const subscription of Array.from(subs.values())) {
3287
+ if (!subscription.active) continue;
3288
+ try {
3289
+ subscription.callback(value);
3290
+ } catch (err) {
3291
+ reportError(err, { phase: "event", name: `sharedScope(${String(key)})` });
3292
+ }
3189
3293
  }
3190
3294
  }
3191
3295
  }
@@ -3196,9 +3300,17 @@ function createSharedScope(initialState) {
3196
3300
  return () => {
3197
3301
  };
3198
3302
  }
3199
- subs.add(callback);
3303
+ const cb = callback;
3304
+ let subscription = subs.get(cb);
3305
+ if (!subscription) {
3306
+ subscription = { callback: cb, active: true };
3307
+ subs.set(cb, subscription);
3308
+ }
3309
+ const own = subscription;
3200
3310
  return () => {
3201
- subs.delete(callback);
3311
+ if (subs.get(cb) !== own) return;
3312
+ own.active = false;
3313
+ subs.delete(cb);
3202
3314
  };
3203
3315
  }
3204
3316
  return { get, set, subscribe };
@@ -3329,6 +3441,11 @@ function serviceWorker(scriptUrl, options) {
3329
3441
  }
3330
3442
 
3331
3443
  // src/platform/worker.ts
3444
+ function toError(err) {
3445
+ if (err instanceof Error) return err;
3446
+ if (err !== null && typeof err === "object" && "name" in err && "message" in err) return err;
3447
+ return new Error(String(err));
3448
+ }
3332
3449
  function worker(workerFn2) {
3333
3450
  const [result, setResult] = signal(null);
3334
3451
  const [error, setError] = signal(null);
@@ -3351,8 +3468,11 @@ function worker(workerFn2) {
3351
3468
  worker2 = new Worker(blobUrl);
3352
3469
  worker2.addEventListener("message", (e) => {
3353
3470
  revokeBlobUrl();
3354
- setResult(e.data);
3355
- setLoading(false);
3471
+ batch(() => {
3472
+ setResult(e.data);
3473
+ setError(null);
3474
+ setLoading(false);
3475
+ });
3356
3476
  });
3357
3477
  worker2.addEventListener("error", (e) => {
3358
3478
  revokeBlobUrl();
@@ -3369,10 +3489,17 @@ function worker(workerFn2) {
3369
3489
  }
3370
3490
  function post(data2) {
3371
3491
  if (!worker2) return;
3372
- setLoading(true);
3373
- setError(null);
3374
- setResult(null);
3375
- worker2.postMessage(data2);
3492
+ try {
3493
+ worker2.postMessage(data2);
3494
+ } catch (err) {
3495
+ setError(toError(err));
3496
+ return;
3497
+ }
3498
+ batch(() => {
3499
+ setLoading(true);
3500
+ setError(null);
3501
+ setResult(null);
3502
+ });
3376
3503
  }
3377
3504
  function terminate() {
3378
3505
  if (!worker2) return;
@@ -3436,9 +3563,14 @@ function workerFn(fn) {
3436
3563
  reject(new Error("Worker is not available"));
3437
3564
  return;
3438
3565
  }
3439
- setLoading(true);
3566
+ try {
3567
+ worker2.postMessage(args);
3568
+ } catch (err) {
3569
+ reject(toError(err));
3570
+ return;
3571
+ }
3440
3572
  queue.push({ resolve, reject });
3441
- worker2.postMessage(args);
3573
+ setLoading(true);
3442
3574
  });
3443
3575
  }
3444
3576
  function terminate() {
@@ -3468,7 +3600,11 @@ function createWorkerPool(workerFn2, poolSize) {
3468
3600
  }
3469
3601
  };
3470
3602
  function dispatchNext(idx) {
3471
- if (!alive || inflight[idx] || queues[idx].length === 0) return;
3603
+ while (alive && !inflight[idx] && queues[idx].length > 0) {
3604
+ dispatchOne(idx);
3605
+ }
3606
+ }
3607
+ function dispatchOne(idx) {
3472
3608
  const w = workers[idx];
3473
3609
  const slot2 = queues[idx].shift();
3474
3610
  const onMsg = (e) => {
@@ -3493,10 +3629,15 @@ function createWorkerPool(workerFn2, poolSize) {
3493
3629
  slot2.reject(new Error(e.message || "Worker error"));
3494
3630
  dispatchNext(idx);
3495
3631
  };
3632
+ try {
3633
+ w.postMessage(slot2.data);
3634
+ } catch (err) {
3635
+ slot2.reject(toError(err));
3636
+ return;
3637
+ }
3496
3638
  inflight[idx] = { ...slot2, onMsg, onErr };
3497
3639
  w.addEventListener("message", onMsg);
3498
3640
  w.addEventListener("error", onErr);
3499
- w.postMessage(slot2.data);
3500
3641
  }
3501
3642
  try {
3502
3643
  if (typeof Worker === "undefined") {
package/dist/ssr.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- export { H as HydrateOptions, a as HydrationMismatch, T as TrustedHTML, c as collectStream, d as deserializeState, e as escapeScriptJson, h as hydrate, b as hydrateIslands, f as hydrateProgressively, i as isDangerousMetaRefresh, g as island, r as renderToDocument, j as renderToReadableStream, k as renderToStream, l as renderToString, m as renderToSuspenseStream, n as resetSSRState, s as serializeState, o as ssrSuspense, p as suspenseSwapScript, t as trustHTML } from './ssr-BiPRdZ6n.cjs';
1
+ export { H as HydrateOptions, a as HydrationMismatch, T as TrustedHTML, c as collectStream, d as deserializeState, e as escapeScriptJson, h as hydrate, b as hydrateIslands, f as hydrateProgressively, i as isDangerousMetaRefresh, g as island, r as renderToDocument, j as renderToReadableStream, k as renderToStream, l as renderToString, m as renderToSuspenseStream, n as resetSSRState, s as serializeState, o as ssrSuspense, p as suspenseSwapScript, t as trustHTML } from './ssr-Bli9XRW5.cjs';
2
2
 
3
3
  interface HeadProps {
4
4
  title?: string | (() => string);
@@ -482,8 +482,14 @@ interface ISROptions<T> {
482
482
  }
483
483
  /**
484
484
  * Creates an Incremental Static Regeneration (ISR) resource.
485
- * Data is fetched initially, then automatically revalidated after the
486
- * specified interval using setInterval.
485
+ * Data is fetched initially, then automatically revalidated once it goes stale.
486
+ *
487
+ * `isStale()` is a reactive signal: it flips to `true` when `revalidateAfter`
488
+ * elapses since the last successful fetch (effects re-run at that moment), stays
489
+ * `true` while a revalidation is pending or after one fails, and returns to
490
+ * `false` when a revalidation succeeds.
491
+ *
492
+ * @throws RangeError when `revalidateAfter` is not a positive finite number.
487
493
  */
488
494
  declare function createISR<T>(options: ISROptions<T>): {
489
495
  data: () => T | undefined;
package/dist/ssr.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { H as HydrateOptions, a as HydrationMismatch, T as TrustedHTML, c as collectStream, d as deserializeState, e as escapeScriptJson, h as hydrate, b as hydrateIslands, f as hydrateProgressively, i as isDangerousMetaRefresh, g as island, r as renderToDocument, j as renderToReadableStream, k as renderToStream, l as renderToString, m as renderToSuspenseStream, n as resetSSRState, s as serializeState, o as ssrSuspense, p as suspenseSwapScript, t as trustHTML } from './ssr-BiPRdZ6n.js';
1
+ export { H as HydrateOptions, a as HydrationMismatch, T as TrustedHTML, c as collectStream, d as deserializeState, e as escapeScriptJson, h as hydrate, b as hydrateIslands, f as hydrateProgressively, i as isDangerousMetaRefresh, g as island, r as renderToDocument, j as renderToReadableStream, k as renderToStream, l as renderToString, m as renderToSuspenseStream, n as resetSSRState, s as serializeState, o as ssrSuspense, p as suspenseSwapScript, t as trustHTML } from './ssr-Bli9XRW5.js';
2
2
 
3
3
  interface HeadProps {
4
4
  title?: string | (() => string);
@@ -482,8 +482,14 @@ interface ISROptions<T> {
482
482
  }
483
483
  /**
484
484
  * Creates an Incremental Static Regeneration (ISR) resource.
485
- * Data is fetched initially, then automatically revalidated after the
486
- * specified interval using setInterval.
485
+ * Data is fetched initially, then automatically revalidated once it goes stale.
486
+ *
487
+ * `isStale()` is a reactive signal: it flips to `true` when `revalidateAfter`
488
+ * elapses since the last successful fetch (effects re-run at that moment), stays
489
+ * `true` while a revalidation is pending or after one fails, and returns to
490
+ * `false` when a revalidation succeeds.
491
+ *
492
+ * @throws RangeError when `revalidateAfter` is not a positive finite number.
487
493
  */
488
494
  declare function createISR<T>(options: ISROptions<T>): {
489
495
  data: () => T | undefined;
package/dist/ssr.js CHANGED
@@ -23,9 +23,9 @@ import {
23
23
  wasm,
24
24
  worker,
25
25
  workerFn
26
- } from "./chunk-HQSEH5F6.js";
26
+ } from "./chunk-ORMZXBKQ.js";
27
27
  import "./chunk-52XFPGSN.js";
28
- import "./chunk-36S2YPP4.js";
28
+ import "./chunk-JSXPZCET.js";
29
29
  import {
30
30
  collectStream,
31
31
  deserializeState,
@@ -45,17 +45,16 @@ import {
45
45
  ssrSuspense,
46
46
  suspenseSwapScript,
47
47
  trustHTML
48
- } from "./chunk-NIOYEGBQ.js";
49
- import "./chunk-PNIRUQ4C.js";
50
- import "./chunk-VCTAEPSB.js";
51
- import "./chunk-IXKSNWV5.js";
48
+ } from "./chunk-HURREPU2.js";
49
+ import "./chunk-VVWPJ543.js";
50
+ import "./chunk-47M47FOM.js";
51
+ import "./chunk-2INLLLMZ.js";
52
52
  import "./chunk-7ZHH77QA.js";
53
- import "./chunk-7GIHSAWB.js";
54
- import "./chunk-5DXA2J44.js";
55
- import "./chunk-QKRPLZ2V.js";
56
- import "./chunk-NVNJH22U.js";
57
- import "./chunk-3BTTCZ5J.js";
58
- import "./chunk-2WLZ6757.js";
53
+ import "./chunk-XC4MEKGA.js";
54
+ import "./chunk-7XHATCIH.js";
55
+ import "./chunk-D33YTSX5.js";
56
+ import "./chunk-5Q4R7HCL.js";
57
+ import "./chunk-NYNYSPK7.js";
59
58
  export {
60
59
  Head,
61
60
  clearWasmCache,