sibujs 3.2.2 → 3.3.1

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 (60) hide show
  1. package/dist/browser.cjs +217 -27
  2. package/dist/browser.js +5 -5
  3. package/dist/build.cjs +236 -105
  4. package/dist/build.js +14 -14
  5. package/dist/cdn.global.js +7 -7
  6. package/dist/{chunk-5N74TKLD.js → chunk-37BUKSLH.js} +1 -1
  7. package/dist/{chunk-BGNLPNGV.js → chunk-4UUMSLSL.js} +4 -4
  8. package/dist/{chunk-2UPRY23K.js → chunk-5VGSK6D2.js} +1 -1
  9. package/dist/{chunk-OYLPZO4N.js → chunk-6LTFHJQG.js} +4 -4
  10. package/dist/{chunk-VOCE4NNK.js → chunk-AMIKDMLP.js} +5 -5
  11. package/dist/{chunk-LMLD24FC.js → chunk-COY6PUD2.js} +7 -1
  12. package/dist/{chunk-YFDGQWDA.js → chunk-F7FXQ3QS.js} +1 -1
  13. package/dist/{chunk-V2MTG5FT.js → chunk-IKLYI3RF.js} +33 -16
  14. package/dist/{chunk-HMJFCBRR.js → chunk-L3GAGWCC.js} +10 -1
  15. package/dist/{chunk-X67UYC74.js → chunk-LU2MQXQQ.js} +14 -24
  16. package/dist/{chunk-4JCAUOLN.js → chunk-M5KBNOSJ.js} +22 -12
  17. package/dist/{chunk-FDY42FIU.js → chunk-MHBCEJQO.js} +2 -2
  18. package/dist/{chunk-RLUJL2MV.js → chunk-NHKQKKZU.js} +6 -7
  19. package/dist/{chunk-HXMS4SNP.js → chunk-R3QEDXFS.js} +2 -2
  20. package/dist/{chunk-NPIEEKPT.js → chunk-RYMOSG5B.js} +6 -6
  21. package/dist/{chunk-H6PCHJZQ.js → chunk-SLMFA3ZZ.js} +11 -3
  22. package/dist/{chunk-Z2FWAE4B.js → chunk-TEFZT5PJ.js} +84 -16
  23. package/dist/{chunk-7XDYVJLE.js → chunk-ULLTNDRA.js} +6 -6
  24. package/dist/{chunk-GOUM4JCT.js → chunk-VOVVTOEA.js} +2 -2
  25. package/dist/{chunk-FOI23UJL.js → chunk-WL7BIR6O.js} +1 -1
  26. package/dist/{chunk-JYXOEYI4.js → chunk-WW6DAGGR.js} +5 -5
  27. package/dist/{chunk-C427DVQF.js → chunk-WZG2SZOT.js} +22 -5
  28. package/dist/{chunk-NFYWLRUO.js → chunk-XH2RTYEQ.js} +3 -3
  29. package/dist/{chunk-2C4E3HBM.js → chunk-Z37APKBV.js} +5 -5
  30. package/dist/{chunk-RDRSWYNP.js → chunk-ZUVLC7TM.js} +1 -1
  31. package/dist/data.cjs +168 -24
  32. package/dist/data.js +8 -8
  33. package/dist/devtools.cjs +252 -32
  34. package/dist/devtools.js +7 -7
  35. package/dist/ecosystem.cjs +205 -64
  36. package/dist/ecosystem.js +10 -10
  37. package/dist/extras.cjs +245 -112
  38. package/dist/extras.js +24 -24
  39. package/dist/index.cjs +236 -105
  40. package/dist/index.d.cts +72 -8
  41. package/dist/index.d.ts +72 -8
  42. package/dist/index.js +14 -14
  43. package/dist/motion.cjs +336 -14
  44. package/dist/motion.js +4 -4
  45. package/dist/patterns.cjs +168 -24
  46. package/dist/patterns.js +6 -6
  47. package/dist/performance.cjs +305 -32
  48. package/dist/performance.js +8 -8
  49. package/dist/plugins.cjs +268 -69
  50. package/dist/plugins.js +12 -12
  51. package/dist/{ssr-2QDQ27EV.js → ssr-6D67RAVB.js} +3 -3
  52. package/dist/ssr.cjs +205 -63
  53. package/dist/ssr.js +11 -11
  54. package/dist/testing.cjs +415 -12
  55. package/dist/testing.js +16 -10
  56. package/dist/ui.cjs +248 -36
  57. package/dist/ui.js +9 -9
  58. package/dist/widgets.cjs +176 -26
  59. package/dist/widgets.js +8 -8
  60. package/package.json +1 -1
package/dist/extras.cjs CHANGED
@@ -145,7 +145,7 @@ __export(extras_exports, {
145
145
  getPerformanceReport: () => getPerformanceReport,
146
146
  getQueryData: () => getQueryData,
147
147
  getSignalName: () => getSignalName,
148
- getSubscriberCount: () => getSubscriberCount2,
148
+ getSubscriberCount: () => getSubscriberCount3,
149
149
  globalStore: () => globalStore,
150
150
  healthCheck: () => healthCheck,
151
151
  hmrState: () => hmrState,
@@ -317,7 +317,13 @@ module.exports = __toCommonJS(extras_exports);
317
317
 
318
318
  // src/core/dev.ts
319
319
  function isDev() {
320
- return typeof globalThis.__SIBU_DEV__ !== "undefined" ? !!globalThis.__SIBU_DEV__ : typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : typeof process !== "undefined" && process.env?.NODE_ENV !== "production";
320
+ return typeof globalThis.__SIBU_DEV__ !== "undefined" ? !!globalThis.__SIBU_DEV__ : (
321
+ // The bare `__SIBU_DEV__` is a bundler define that only exists in
322
+ // production builds; under the test runner it is always undefined, so
323
+ // this branch is unreachable here.
324
+ /* v8 ignore next 2 */
325
+ typeof __SIBU_DEV__ !== "undefined" ? __SIBU_DEV__ : typeof process !== "undefined" && process.env?.NODE_ENV !== "production"
326
+ );
321
327
  }
322
328
  var _isDev = isDev();
323
329
  function devAssert(condition, message) {
@@ -331,7 +337,7 @@ function devWarn(message) {
331
337
  }
332
338
  }
333
339
 
334
- // src/reactivity/track.ts
340
+ // src/reactivity/track-core.ts
335
341
  var _isDev2 = isDev();
336
342
  var POOL_MAX = 4096;
337
343
  var nodePool = [];
@@ -415,6 +421,7 @@ function unlinkSub(node) {
415
421
  else sub2.depsTail = prev;
416
422
  }
417
423
  var currentSubscriber = null;
424
+ var suspendSavedSub = null;
418
425
  var notifyDepth = 0;
419
426
  var pendingQueue = [];
420
427
  var pendingSet = /* @__PURE__ */ new Set();
@@ -426,7 +433,35 @@ function safeInvoke(sub2) {
426
433
  if (_isDev2) devWarn(`Subscriber threw during notification: ${err instanceof Error ? err.message : String(err)}`);
427
434
  }
428
435
  }
436
+ var suspendDepth = 0;
429
437
  var trackingSuspended = false;
438
+ function suspendTracking() {
439
+ if (suspendDepth === 0) {
440
+ suspendSavedSub = currentSubscriber;
441
+ currentSubscriber = null;
442
+ trackingSuspended = true;
443
+ }
444
+ suspendDepth++;
445
+ }
446
+ function resumeTracking() {
447
+ suspendDepth--;
448
+ if (suspendDepth === 0) {
449
+ currentSubscriber = suspendSavedSub;
450
+ suspendSavedSub = null;
451
+ trackingSuspended = false;
452
+ }
453
+ }
454
+ function isTrackingSuspended() {
455
+ return trackingSuspended;
456
+ }
457
+ function untracked(fn) {
458
+ suspendTracking();
459
+ try {
460
+ return fn();
461
+ } finally {
462
+ resumeTracking();
463
+ }
464
+ }
430
465
  var subscriberEpochCounter = 0;
431
466
  function retrack(effectFn, subscriber) {
432
467
  const prev = currentSubscriber;
@@ -536,6 +571,16 @@ function cleanup(subscriber) {
536
571
  var maxSubscriberRepeats = 50;
537
572
  var maxDrainIterations = 1e6;
538
573
  var drainEpoch = 0;
574
+ function setMaxSubscriberRepeats(n) {
575
+ const prev = maxSubscriberRepeats;
576
+ if (Number.isFinite(n) && n > 0) maxSubscriberRepeats = Math.floor(n);
577
+ return prev;
578
+ }
579
+ function setMaxDrainIterations(n) {
580
+ const prev = maxDrainIterations;
581
+ if (Number.isFinite(n) && n > 0) maxDrainIterations = Math.floor(n);
582
+ return prev;
583
+ }
539
584
  function tickRepeat(sub2) {
540
585
  const s2 = sub2;
541
586
  if (s2._runEpoch !== drainEpoch) {
@@ -706,6 +751,64 @@ function forEachSubscriber(signal2, visit) {
706
751
  }
707
752
  }
708
753
 
754
+ // src/reactivity/track.ts
755
+ var _isDev3 = isDev();
756
+ var _runtimeVersion = typeof __SIBU_VERSION__ !== "undefined" ? __SIBU_VERSION__ : "dev";
757
+ var REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.v1");
758
+ function resolveReactiveApi() {
759
+ const g2 = globalThis;
760
+ const existing = g2[REGISTRY_KEY];
761
+ if (existing) {
762
+ if (_isDev3 && !existing.__dupWarned) {
763
+ existing.__dupWarned = true;
764
+ devWarn(
765
+ `Multiple instances of the reactive runtime detected on this page (active: ${existing.version}, duplicate: ${_runtimeVersion}). Reactivity still works \u2014 all copies share the first one \u2014 but de-duplicate sibujs in your bundler (e.g. Vite optimizeDeps.exclude: ['sibujs'] or resolve.dedupe: ['sibujs']).`
766
+ );
767
+ }
768
+ return existing;
769
+ }
770
+ const local = {
771
+ suspendTracking,
772
+ resumeTracking,
773
+ isTrackingSuspended,
774
+ untracked,
775
+ retrack,
776
+ track,
777
+ reactiveBinding,
778
+ recordDependency,
779
+ cleanup,
780
+ setMaxSubscriberRepeats,
781
+ setMaxDrainIterations,
782
+ drainNotificationQueue,
783
+ queueSignalNotification,
784
+ notifySubscribers,
785
+ getSubscriberCount,
786
+ getSubscriberDeps,
787
+ forEachSubscriber,
788
+ version: _runtimeVersion
789
+ };
790
+ g2[REGISTRY_KEY] = local;
791
+ return local;
792
+ }
793
+ var API = resolveReactiveApi();
794
+ var suspendTracking2 = API.suspendTracking;
795
+ var resumeTracking2 = API.resumeTracking;
796
+ var isTrackingSuspended2 = API.isTrackingSuspended;
797
+ var untracked2 = API.untracked;
798
+ var retrack2 = API.retrack;
799
+ var track2 = API.track;
800
+ var reactiveBinding2 = API.reactiveBinding;
801
+ var recordDependency2 = API.recordDependency;
802
+ var cleanup2 = API.cleanup;
803
+ var setMaxSubscriberRepeats2 = API.setMaxSubscriberRepeats;
804
+ var setMaxDrainIterations2 = API.setMaxDrainIterations;
805
+ var drainNotificationQueue2 = API.drainNotificationQueue;
806
+ var queueSignalNotification2 = API.queueSignalNotification;
807
+ var notifySubscribers2 = API.notifySubscribers;
808
+ var getSubscriberCount2 = API.getSubscriberCount;
809
+ var getSubscriberDeps2 = API.getSubscriberDeps;
810
+ var forEachSubscriber2 = API.forEachSubscriber;
811
+
709
812
  // src/core/signals/derived.ts
710
813
  function derived(getter, options) {
711
814
  devAssert(typeof getter === "function", "derived: argument must be a getter function.");
@@ -728,7 +831,7 @@ function derived(getter, options) {
728
831
  cs._d = false;
729
832
  cs._init = true;
730
833
  };
731
- track(() => {
834
+ track2(() => {
732
835
  let threw = true;
733
836
  try {
734
837
  cs._v = getter();
@@ -747,12 +850,12 @@ function derived(getter, options) {
747
850
  `[SibuJS] Circular dependency detected in derived${debugName ? ` "${debugName}"` : ""}. A derived signal cannot read itself (directly or through a chain).`
748
851
  );
749
852
  }
750
- if (trackingSuspended) {
853
+ if (isTrackingSuspended2()) {
751
854
  if (cs._d) {
752
855
  const prev = cs._v;
753
856
  evaluating = true;
754
857
  try {
755
- retrack(recompute, markDirty);
858
+ retrack2(recompute, markDirty);
756
859
  if (!Object.is(prev, cs._v)) cs.__v++;
757
860
  } finally {
758
861
  evaluating = false;
@@ -760,12 +863,12 @@ function derived(getter, options) {
760
863
  }
761
864
  return cs._v;
762
865
  }
763
- recordDependency(cs);
866
+ recordDependency2(cs);
764
867
  if (cs._d) {
765
868
  const oldValue = cs._v;
766
869
  evaluating = true;
767
870
  try {
768
- retrack(recompute, markDirty);
871
+ retrack2(recompute, markDirty);
769
872
  if (!Object.is(oldValue, cs._v)) cs.__v++;
770
873
  } finally {
771
874
  evaluating = false;
@@ -845,7 +948,7 @@ function drainReruns(ctx) {
845
948
  do {
846
949
  ctx.rerunPending = false;
847
950
  if (ctx.userCleanups.length > 0) flushUserCleanups(ctx);
848
- retrack(ctx.bodyFn, ctx.subscriber);
951
+ retrack2(ctx.bodyFn, ctx.subscriber);
849
952
  } while (ctx.rerunPending && ++reruns <= MAX_RERUNS);
850
953
  if (ctx.rerunPending) {
851
954
  ctx.rerunPending = false;
@@ -874,7 +977,7 @@ function disposeEffect(ctx) {
874
977
  }
875
978
  }
876
979
  try {
877
- cleanup(ctx.subscriber);
980
+ cleanup2(ctx.subscriber);
878
981
  } catch (err) {
879
982
  if (typeof console !== "undefined") {
880
983
  console.warn("[SibuJS effect] dispose threw:", err);
@@ -919,7 +1022,7 @@ function effect(effectFn, options) {
919
1022
  try {
920
1023
  ctx.rerunPending = false;
921
1024
  if (ctx.userCleanups.length > 0) flushUserCleanups(ctx);
922
- retrack(ctx.bodyFn, sub2);
1025
+ retrack2(ctx.bodyFn, sub2);
923
1026
  if (ctx.rerunPending) drainReruns(ctx);
924
1027
  } finally {
925
1028
  ctx.running = false;
@@ -935,7 +1038,7 @@ function effect(effectFn, options) {
935
1038
  ctx.subscriber = sub2;
936
1039
  ctx.running = true;
937
1040
  try {
938
- retrack(ctx.bodyFn, ctx.subscriber);
1041
+ retrack2(ctx.bodyFn, ctx.subscriber);
939
1042
  if (ctx.rerunPending) drainReruns(ctx);
940
1043
  } finally {
941
1044
  ctx.running = false;
@@ -949,7 +1052,7 @@ function effect(effectFn, options) {
949
1052
  // src/reactivity/batch.ts
950
1053
  var batchDepth = 0;
951
1054
  var pendingSignals = /* @__PURE__ */ new Set();
952
- function batch(fn) {
1055
+ function batchImpl(fn) {
953
1056
  batchDepth++;
954
1057
  try {
955
1058
  return fn();
@@ -960,25 +1063,45 @@ function batch(fn) {
960
1063
  }
961
1064
  }
962
1065
  }
963
- function enqueueBatchedSignal(signal2) {
1066
+ function enqueueBatchedSignalImpl(signal2) {
964
1067
  if (batchDepth === 0) return false;
965
1068
  pendingSignals.add(signal2);
966
1069
  return true;
967
1070
  }
1071
+ function isBatchingImpl() {
1072
+ return batchDepth > 0;
1073
+ }
968
1074
  function flushBatch() {
969
1075
  try {
970
1076
  for (const signal2 of pendingSignals) {
971
- queueSignalNotification(signal2);
1077
+ queueSignalNotification2(signal2);
972
1078
  }
973
1079
  } finally {
974
1080
  pendingSignals.clear();
975
1081
  }
976
- drainNotificationQueue();
1082
+ drainNotificationQueue2();
1083
+ }
1084
+ var BATCH_REGISTRY_KEY = /* @__PURE__ */ Symbol.for("sibujs.reactive.batch.v1");
1085
+ function resolveBatchApi() {
1086
+ const g2 = globalThis;
1087
+ const existing = g2[BATCH_REGISTRY_KEY];
1088
+ if (existing) return existing;
1089
+ const local = {
1090
+ batch: batchImpl,
1091
+ enqueueBatchedSignal: enqueueBatchedSignalImpl,
1092
+ isBatching: isBatchingImpl
1093
+ };
1094
+ g2[BATCH_REGISTRY_KEY] = local;
1095
+ return local;
977
1096
  }
1097
+ var API2 = resolveBatchApi();
1098
+ var batch = API2.batch;
1099
+ var enqueueBatchedSignal = API2.enqueueBatchedSignal;
1100
+ var isBatching = API2.isBatching;
978
1101
 
979
1102
  // src/core/signals/signal.ts
980
1103
  var _g2 = globalThis;
981
- var _isDev3 = isDev();
1104
+ var _isDev4 = isDev();
982
1105
  function signal(initial, options) {
983
1106
  const state = {
984
1107
  value: initial,
@@ -989,11 +1112,11 @@ function signal(initial, options) {
989
1112
  __activeNode: null,
990
1113
  __name: void 0
991
1114
  };
992
- const debugName = _isDev3 ? options?.name : void 0;
1115
+ const debugName = _isDev4 ? options?.name : void 0;
993
1116
  const equalsFn = options?.equals;
994
1117
  if (debugName) state.__name = debugName;
995
1118
  function get() {
996
- recordDependency(state);
1119
+ recordDependency2(state);
997
1120
  return state.value;
998
1121
  }
999
1122
  get.__signal = state;
@@ -1006,15 +1129,15 @@ function signal(initial, options) {
1006
1129
  if (equalsFn(prev, newValue)) return;
1007
1130
  state.value = newValue;
1008
1131
  state.__v++;
1009
- if (_isDev3) {
1132
+ if (_isDev4) {
1010
1133
  const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
1011
1134
  if (hook) hook.emit("signal:update", { signal: state, name: debugName, oldValue: prev, newValue });
1012
1135
  }
1013
1136
  if (!enqueueBatchedSignal(state)) {
1014
- notifySubscribers(state);
1137
+ notifySubscribers2(state);
1015
1138
  }
1016
1139
  };
1017
- } else if (_isDev3) {
1140
+ } else if (_isDev4) {
1018
1141
  set = (next) => {
1019
1142
  const prev = state.value;
1020
1143
  const newValue = typeof next === "function" ? next(prev) : next;
@@ -1024,7 +1147,7 @@ function signal(initial, options) {
1024
1147
  const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
1025
1148
  if (hook) hook.emit("signal:update", { signal: state, name: debugName, oldValue: prev, newValue });
1026
1149
  if (!enqueueBatchedSignal(state)) {
1027
- notifySubscribers(state);
1150
+ notifySubscribers2(state);
1028
1151
  }
1029
1152
  };
1030
1153
  } else {
@@ -1035,11 +1158,11 @@ function signal(initial, options) {
1035
1158
  state.value = newValue;
1036
1159
  state.__v++;
1037
1160
  if (!enqueueBatchedSignal(state)) {
1038
- notifySubscribers(state);
1161
+ notifySubscribers2(state);
1039
1162
  }
1040
1163
  };
1041
1164
  }
1042
- if (_isDev3) {
1165
+ if (_isDev4) {
1043
1166
  const hook = _g2.__SIBU_DEVTOOLS_GLOBAL_HOOK__;
1044
1167
  if (hook) hook.emit("signal:create", { signal: state, name: debugName, getter: get, initial });
1045
1168
  }
@@ -2247,7 +2370,9 @@ function sanitizeSrcset(value) {
2247
2370
  }
2248
2371
  return out.join(", ");
2249
2372
  }
2373
+ var CSS_DANGER_GATE = /[(:@\\]/;
2250
2374
  function sanitizeCSSValue(value) {
2375
+ if (!CSS_DANGER_GATE.test(value)) return value;
2251
2376
  const decoded = value.replace(/\\([0-9a-fA-F]{1,6})\s?/g, (_m, hex) => {
2252
2377
  const code2 = Number.parseInt(hex, 16);
2253
2378
  if (!Number.isFinite(code2) || code2 < 0 || code2 > 1114111) return "";
@@ -2293,8 +2418,11 @@ var URL_ATTRIBUTES = /* @__PURE__ */ new Set([
2293
2418
  "ping",
2294
2419
  "data"
2295
2420
  ]);
2296
- function isUrlAttribute(attr) {
2297
- return URL_ATTRIBUTES.has(attr.toLowerCase());
2421
+ function sanitizeAttributeString(attr, value) {
2422
+ const lower = attr.toLowerCase();
2423
+ if (lower === "srcset") return sanitizeSrcset(value);
2424
+ if (URL_ATTRIBUTES.has(lower)) return sanitizeUrl(value);
2425
+ return value;
2298
2426
  }
2299
2427
 
2300
2428
  // src/ui/stream.ts
@@ -2401,7 +2529,7 @@ function resize(target) {
2401
2529
  } };
2402
2530
  }
2403
2531
  const getter = resolveTarget(target);
2404
- const cleanup2 = effect(() => {
2532
+ const cleanup3 = effect(() => {
2405
2533
  const el = getter();
2406
2534
  if (observer) {
2407
2535
  observer.disconnect();
@@ -2420,7 +2548,7 @@ function resize(target) {
2420
2548
  observer.observe(el);
2421
2549
  });
2422
2550
  function dispose2() {
2423
- cleanup2();
2551
+ cleanup3();
2424
2552
  if (observer) {
2425
2553
  observer.disconnect();
2426
2554
  observer = null;
@@ -2704,7 +2832,7 @@ function draggable(element, data2) {
2704
2832
  let onDragStart = null;
2705
2833
  let onDragEnd = null;
2706
2834
  const getter = resolveTarget2(element);
2707
- const cleanup2 = effect(() => {
2835
+ const cleanup3 = effect(() => {
2708
2836
  if (currentEl && onDragStart && onDragEnd) {
2709
2837
  currentEl.removeEventListener("dragstart", onDragStart);
2710
2838
  currentEl.removeEventListener("dragend", onDragEnd);
@@ -2726,7 +2854,7 @@ function draggable(element, data2) {
2726
2854
  el.addEventListener("dragend", onDragEnd);
2727
2855
  });
2728
2856
  function dispose2() {
2729
- cleanup2();
2857
+ cleanup3();
2730
2858
  if (currentEl && onDragStart && onDragEnd) {
2731
2859
  currentEl.removeEventListener("dragstart", onDragStart);
2732
2860
  currentEl.removeEventListener("dragend", onDragEnd);
@@ -2747,7 +2875,7 @@ function dropZone(element, options) {
2747
2875
  let onDragLeave = null;
2748
2876
  let onDrop = null;
2749
2877
  const getter = resolveTarget2(element);
2750
- const cleanup2 = effect(() => {
2878
+ const cleanup3 = effect(() => {
2751
2879
  if (currentEl && onDragOver && onDragEnter && onDragLeave && onDrop) {
2752
2880
  currentEl.removeEventListener("dragover", onDragOver);
2753
2881
  currentEl.removeEventListener("dragenter", onDragEnter);
@@ -2789,7 +2917,7 @@ function dropZone(element, options) {
2789
2917
  el.addEventListener("drop", onDrop);
2790
2918
  });
2791
2919
  function dispose2() {
2792
- cleanup2();
2920
+ cleanup3();
2793
2921
  if (currentEl && onDragOver && onDragEnter && onDragLeave && onDrop) {
2794
2922
  currentEl.removeEventListener("dragover", onDragOver);
2795
2923
  currentEl.removeEventListener("dragenter", onDragEnter);
@@ -2809,11 +2937,11 @@ function title(value) {
2809
2937
  }
2810
2938
  const previousTitle = document.title;
2811
2939
  if (typeof value === "function") {
2812
- const cleanup2 = effect(() => {
2940
+ const cleanup3 = effect(() => {
2813
2941
  document.title = value();
2814
2942
  });
2815
2943
  return () => {
2816
- cleanup2();
2944
+ cleanup3();
2817
2945
  document.title = previousTitle;
2818
2946
  };
2819
2947
  }
@@ -4506,7 +4634,7 @@ function TransitionGroup(options) {
4506
4634
  }
4507
4635
  setElements((prev) => prev.filter((e) => e !== el));
4508
4636
  }
4509
- function track3(newElements) {
4637
+ function track4(newElements) {
4510
4638
  const oldPositions = /* @__PURE__ */ new Map();
4511
4639
  for (const el of elements()) {
4512
4640
  if (typeof el.getBoundingClientRect === "function") {
@@ -4548,7 +4676,7 @@ function TransitionGroup(options) {
4548
4676
  }
4549
4677
  }
4550
4678
  }
4551
- return { add, remove, track: track3 };
4679
+ return { add, remove, track: track4 };
4552
4680
  }
4553
4681
 
4554
4682
  // src/ui/viewTransition.ts
@@ -4852,7 +4980,7 @@ function form(config) {
4852
4980
 
4853
4981
  // src/core/rendering/dispose.ts
4854
4982
  var elementDisposers = /* @__PURE__ */ new WeakMap();
4855
- var _isDev4 = isDev();
4983
+ var _isDev5 = isDev();
4856
4984
  var activeBindingCount = 0;
4857
4985
  function registerDisposer(node, teardown) {
4858
4986
  let disposers = elementDisposers.get(node);
@@ -4861,7 +4989,7 @@ function registerDisposer(node, teardown) {
4861
4989
  elementDisposers.set(node, disposers);
4862
4990
  }
4863
4991
  disposers.push(teardown);
4864
- if (_isDev4) activeBindingCount++;
4992
+ if (_isDev5) activeBindingCount++;
4865
4993
  }
4866
4994
  function dispose(node) {
4867
4995
  const stack = [node];
@@ -4880,12 +5008,12 @@ function dispose(node) {
4880
5008
  if (disposers) {
4881
5009
  const snapshot = disposers.slice();
4882
5010
  elementDisposers.delete(current);
4883
- if (_isDev4) activeBindingCount -= snapshot.length;
5011
+ if (_isDev5) activeBindingCount -= snapshot.length;
4884
5012
  for (const d of snapshot) {
4885
5013
  try {
4886
5014
  d();
4887
5015
  } catch (err) {
4888
- if (_isDev4 && typeof console !== "undefined") {
5016
+ if (_isDev5 && typeof console !== "undefined") {
4889
5017
  console.warn("[SibuJS] Disposer threw during cleanup:", err);
4890
5018
  }
4891
5019
  }
@@ -4896,12 +5024,12 @@ function dispose(node) {
4896
5024
  if (!added || added.length === 0) break;
4897
5025
  const moreSnapshot = added.slice();
4898
5026
  elementDisposers.delete(current);
4899
- if (_isDev4) activeBindingCount -= moreSnapshot.length;
5027
+ if (_isDev5) activeBindingCount -= moreSnapshot.length;
4900
5028
  for (const d of moreSnapshot) {
4901
5029
  try {
4902
5030
  d();
4903
5031
  } catch (err) {
4904
- if (_isDev4 && typeof console !== "undefined") {
5032
+ if (_isDev5 && typeof console !== "undefined") {
4905
5033
  console.warn("[SibuJS] Disposer threw during cleanup:", err);
4906
5034
  }
4907
5035
  }
@@ -5139,7 +5267,7 @@ function aria(element, attrs) {
5139
5267
  const getter = value;
5140
5268
  registerDisposer(
5141
5269
  element,
5142
- track(() => {
5270
+ track2(() => {
5143
5271
  element.setAttribute(ariaKey, String(getter()));
5144
5272
  })
5145
5273
  );
@@ -5412,13 +5540,13 @@ function removeScopedStyle(scopeId) {
5412
5540
  }
5413
5541
 
5414
5542
  // src/reactivity/bindAttribute.ts
5415
- var _isDev5 = isDev();
5543
+ var _isDev6 = isDev();
5416
5544
  function setProp(el, key, val) {
5417
5545
  el[key] = val;
5418
5546
  }
5419
5547
  function bindAttribute(el, attr, getter) {
5420
5548
  if (isEventHandlerAttr(attr)) {
5421
- if (_isDev5)
5549
+ if (_isDev6)
5422
5550
  devWarn(
5423
5551
  `bindAttribute: refusing to bind event-handler attribute "${attr}". Use on:{ ${attr.slice(2)}: fn } instead.`
5424
5552
  );
@@ -5430,7 +5558,7 @@ function bindAttribute(el, attr, getter) {
5430
5558
  try {
5431
5559
  value = getter();
5432
5560
  } catch (err) {
5433
- if (_isDev5)
5561
+ if (_isDev6)
5434
5562
  devWarn(`bindAttribute: getter for "${attr}" threw: ${err instanceof Error ? err.message : String(err)}`);
5435
5563
  return;
5436
5564
  }
@@ -5448,10 +5576,10 @@ function bindAttribute(el, attr, getter) {
5448
5576
  if ((attr === "value" || attr === "checked") && attr in el) {
5449
5577
  setProp(el, attr, attr === "checked" ? Boolean(value) : str);
5450
5578
  } else {
5451
- el.setAttribute(attr, isUrlAttribute(attr) ? sanitizeUrl(str) : str);
5579
+ el.setAttribute(attr, sanitizeAttributeString(attr, str));
5452
5580
  }
5453
5581
  }
5454
- return reactiveBinding(commit);
5582
+ return reactiveBinding2(commit);
5455
5583
  }
5456
5584
 
5457
5585
  // src/ui/reactiveAttr.ts
@@ -5501,7 +5629,7 @@ function bindBoolAttr(el, attr, getter) {
5501
5629
  el.removeAttribute(attr);
5502
5630
  }
5503
5631
  }
5504
- const teardown = track(commit);
5632
+ const teardown = track2(commit);
5505
5633
  return teardown;
5506
5634
  }
5507
5635
  function bindData(el, key, getter) {
@@ -5962,7 +6090,7 @@ function uniqueId(suffix) {
5962
6090
  }
5963
6091
 
5964
6092
  // src/performance/domRecycler.ts
5965
- var _isDev6 = isDev();
6093
+ var _isDev7 = isDev();
5966
6094
  var DOMPool = class {
5967
6095
  constructor(maxSize = 50) {
5968
6096
  this.pools = /* @__PURE__ */ new Map();
@@ -5989,7 +6117,7 @@ var DOMPool = class {
5989
6117
  * is almost certainly a bug.
5990
6118
  */
5991
6119
  release(element) {
5992
- if (_isDev6 && element.isConnected) {
6120
+ if (_isDev7 && element.isConnected) {
5993
6121
  devWarn(
5994
6122
  "DOMPool.release() called on a still-connected element. Detach it from the DOM first (remove() / dispose())."
5995
6123
  );
@@ -6036,11 +6164,13 @@ function getDOMPool() {
6036
6164
  }
6037
6165
  var preloadedResources = /* @__PURE__ */ new Set();
6038
6166
  function preloadResource(url, type = "fetch") {
6039
- if (preloadedResources.has(url)) return;
6040
- preloadedResources.add(url);
6167
+ const safe = sanitizeUrl(url);
6168
+ if (!safe) return;
6169
+ if (preloadedResources.has(safe)) return;
6170
+ preloadedResources.add(safe);
6041
6171
  const link2 = document.createElement("link");
6042
6172
  link2.rel = "preload";
6043
- link2.href = url;
6173
+ link2.href = safe;
6044
6174
  switch (type) {
6045
6175
  case "script":
6046
6176
  link2.setAttribute("as", "script");
@@ -6058,11 +6188,13 @@ function preloadResource(url, type = "fetch") {
6058
6188
  document.head.appendChild(link2);
6059
6189
  }
6060
6190
  function prefetch(url) {
6061
- if (preloadedResources.has(url)) return;
6062
- preloadedResources.add(url);
6191
+ const safe = sanitizeUrl(url);
6192
+ if (!safe) return;
6193
+ if (preloadedResources.has(safe)) return;
6194
+ preloadedResources.add(safe);
6063
6195
  const link2 = document.createElement("link");
6064
6196
  link2.rel = "prefetch";
6065
- link2.href = url;
6197
+ link2.href = safe;
6066
6198
  document.head.appendChild(link2);
6067
6199
  }
6068
6200
  function preloadImage(src) {
@@ -6100,7 +6232,7 @@ function noSideEffect(fn) {
6100
6232
  function sanitizeUrlAttr(name, value) {
6101
6233
  return name === "srcset" ? sanitizeSrcset(value) : sanitizeUrl(value);
6102
6234
  }
6103
- var _isDev7 = isDev();
6235
+ var _isDev8 = isDev();
6104
6236
  var SAFE_ATTR_NAME = /^[A-Za-z_:][-A-Za-z0-9_.:]*$/;
6105
6237
  function isSafeAttrName(name) {
6106
6238
  return SAFE_ATTR_NAME.test(name);
@@ -6120,7 +6252,7 @@ var URL_ATTRS = /* @__PURE__ */ new Set([
6120
6252
  "xlink:href"
6121
6253
  ]);
6122
6254
  function ssrErrorComment(err) {
6123
- if (_isDev7) {
6255
+ if (_isDev8) {
6124
6256
  const msg = escapeHtml(err instanceof Error ? err.message : String(err));
6125
6257
  return `<!--SSR error: ${safeCommentText(msg)}-->`;
6126
6258
  }
@@ -6166,10 +6298,10 @@ function renderToString(element) {
6166
6298
  }
6167
6299
  const tag = element.tagName.toLowerCase();
6168
6300
  if (tag === "script" || tag === "style") {
6169
- return _isDev7 ? `<!--ssr:${tag}-stripped-->` : "";
6301
+ return _isDev8 ? `<!--ssr:${tag}-stripped-->` : "";
6170
6302
  }
6171
6303
  if (!/^[a-z][a-z0-9-]*$/i.test(tag)) {
6172
- return _isDev7 ? "<!--ssr:invalid-tag-->" : "";
6304
+ return _isDev8 ? "<!--ssr:invalid-tag-->" : "";
6173
6305
  }
6174
6306
  let html2 = `<${tag}`;
6175
6307
  for (const attr of Array.from(element.attributes)) {
@@ -6210,7 +6342,7 @@ function hydrate(component, container, options = {}) {
6210
6342
  const first = mismatches[0];
6211
6343
  if (options.onMismatch) {
6212
6344
  options.onMismatch(first);
6213
- } else if (_isDev7) {
6345
+ } else if (_isDev8) {
6214
6346
  console.warn(
6215
6347
  `[SibuJS hydration] ${first.message}
6216
6348
  at ${first.path}
@@ -6405,11 +6537,11 @@ async function* renderToStream(element) {
6405
6537
  }
6406
6538
  const tag = element.tagName.toLowerCase();
6407
6539
  if (tag === "script" || tag === "style") {
6408
- if (_isDev7) yield `<!--ssr:${tag}-stripped-->`;
6540
+ if (_isDev8) yield `<!--ssr:${tag}-stripped-->`;
6409
6541
  return;
6410
6542
  }
6411
6543
  if (!/^[a-z][a-z0-9-]*$/i.test(tag)) {
6412
- if (_isDev7) yield "<!--ssr:invalid-tag-->";
6544
+ if (_isDev8) yield "<!--ssr:invalid-tag-->";
6413
6545
  return;
6414
6546
  }
6415
6547
  let openTag = `<${tag}`;
@@ -6513,7 +6645,7 @@ function hydrateProgressively(container, islands, options) {
6513
6645
  }
6514
6646
  container.setAttribute("data-sibu-hydrated", "progressive");
6515
6647
  return () => {
6516
- for (const cleanup2 of cleanups) cleanup2();
6648
+ for (const cleanup3 of cleanups) cleanup3();
6517
6649
  };
6518
6650
  }
6519
6651
  function resetSSRState() {
@@ -6542,7 +6674,7 @@ function ssrSuspense(props) {
6542
6674
  },
6543
6675
  (err) => {
6544
6676
  if (timer) clearTimeout(timer);
6545
- if (_isDev7) console.warn("[SibuJS SSR] ssrSuspense rejected:", err);
6677
+ if (_isDev8) console.warn("[SibuJS SSR] ssrSuspense rejected:", err);
6546
6678
  return { id, html: fallbackHtml };
6547
6679
  }
6548
6680
  );
@@ -6588,7 +6720,7 @@ function serializeState(state, nonce, options) {
6588
6720
  }
6589
6721
  function deserializeState(validate) {
6590
6722
  if (typeof window === "undefined") return void 0;
6591
- if (_isDev7 && !validate) {
6723
+ if (_isDev8 && !validate) {
6592
6724
  console.warn(
6593
6725
  "[SibuJS SSR] deserializeState() called without a validate guard \u2014 tampered SSR payloads will not be detected."
6594
6726
  );
@@ -6941,11 +7073,14 @@ function lazyChunk(id, loader, registry, fallback) {
6941
7073
  }
6942
7074
  function preloadModule(url) {
6943
7075
  if (typeof document === "undefined") return;
6944
- const existing = document.querySelector(`link[href="${url}"][rel="modulepreload"]`);
7076
+ const safe = sanitizeUrl(url);
7077
+ if (!safe) return;
7078
+ const safeHref = typeof CSS !== "undefined" && typeof CSS.escape === "function" ? CSS.escape(safe) : safe.replace(/["\\]/g, "\\$&");
7079
+ const existing = document.querySelector(`link[rel="modulepreload"][href="${safeHref}"]`);
6945
7080
  if (existing) return;
6946
7081
  const link2 = document.createElement("link");
6947
7082
  link2.rel = "modulepreload";
6948
- link2.href = url;
7083
+ link2.href = safe;
6949
7084
  document.head.appendChild(link2);
6950
7085
  }
6951
7086
  function preloadModules(urls) {
@@ -6989,7 +7124,7 @@ function Head(props) {
6989
7124
  const anchor = document.createComment("sibu-head");
6990
7125
  const managedElements = [];
6991
7126
  const effectCleanups = [];
6992
- const cleanup2 = () => {
7127
+ const cleanup3 = () => {
6993
7128
  for (const el of managedElements) {
6994
7129
  if (el.parentNode) el.parentNode.removeChild(el);
6995
7130
  }
@@ -6998,7 +7133,7 @@ function Head(props) {
6998
7133
  effectCleanups.length = 0;
6999
7134
  };
7000
7135
  const apply = () => {
7001
- cleanup2();
7136
+ cleanup3();
7002
7137
  if (props.title) {
7003
7138
  if (typeof props.title === "function") {
7004
7139
  const cleanupFn = effect(() => {
@@ -7552,7 +7687,7 @@ function isWasmCached(key) {
7552
7687
  }
7553
7688
 
7554
7689
  // src/reactivity/bindChildNode.ts
7555
- var _isDev8 = isDev();
7690
+ var _isDev9 = isDev();
7556
7691
  function bindChildNode(placeholder, getter) {
7557
7692
  let lastNodes = [];
7558
7693
  function commit() {
@@ -7560,7 +7695,7 @@ function bindChildNode(placeholder, getter) {
7560
7695
  try {
7561
7696
  result = getter();
7562
7697
  } catch (err) {
7563
- if (_isDev8) devWarn(`bindChildNode: getter threw: ${err instanceof Error ? err.message : String(err)}`);
7698
+ if (_isDev9) devWarn(`bindChildNode: getter threw: ${err instanceof Error ? err.message : String(err)}`);
7564
7699
  return;
7565
7700
  }
7566
7701
  if (result == null || typeof result === "boolean") {
@@ -7586,7 +7721,7 @@ function bindChildNode(placeholder, getter) {
7586
7721
  if (item == null || typeof item === "boolean") continue;
7587
7722
  const node = item instanceof Node ? item : document.createTextNode(String(item));
7588
7723
  if (seen.has(node)) {
7589
- if (_isDev8)
7724
+ if (_isDev9)
7590
7725
  devWarn("bindChildNode: duplicate node reference in array \u2014 only the first occurrence is rendered.");
7591
7726
  continue;
7592
7727
  }
@@ -7621,18 +7756,15 @@ function bindChildNode(placeholder, getter) {
7621
7756
  }
7622
7757
  lastNodes = newNodes;
7623
7758
  }
7624
- return reactiveBinding(commit);
7759
+ return reactiveBinding2(commit);
7625
7760
  }
7626
7761
 
7627
7762
  // src/core/rendering/tagFactory.ts
7628
7763
  var SVG_NS = "http://www.w3.org/2000/svg";
7629
- var _isDev9 = isDev();
7764
+ var _isDev10 = isDev();
7630
7765
  var BLOCKED_TAGS = /* @__PURE__ */ new Set(["script", "iframe", "object", "embed", "frame", "frameset"]);
7631
- function validateTagName(tag) {
7632
- const lower = tag.toLowerCase();
7633
- if (BLOCKED_TAGS.has(lower)) {
7634
- throw new Error(`tagFactory: refusing to create <${tag}> \u2014 tag is blocked for security reasons.`);
7635
- }
7766
+ function isBlockedTag(tag) {
7767
+ return BLOCKED_TAGS.has(tag.toLowerCase());
7636
7768
  }
7637
7769
  var CLOBBER_RISKY_IDS = /* @__PURE__ */ new Set([
7638
7770
  "config",
@@ -7672,7 +7804,7 @@ function toKebab(prop) {
7672
7804
  }
7673
7805
  function applyStyle(el, style2) {
7674
7806
  if (typeof style2 === "function") {
7675
- const teardown = track(() => {
7807
+ const teardown = track2(() => {
7676
7808
  el.setAttribute("style", style2());
7677
7809
  });
7678
7810
  registerDisposer(el, teardown);
@@ -7688,7 +7820,7 @@ function applyStyle(el, style2) {
7688
7820
  const name = toKebab(prop);
7689
7821
  if (typeof val === "function") {
7690
7822
  const getter = val;
7691
- const teardown = track(() => {
7823
+ const teardown = track2(() => {
7692
7824
  htmlEl.style.setProperty(name, sanitizeCSSValue(String(getter())));
7693
7825
  });
7694
7826
  registerDisposer(el, teardown);
@@ -7703,7 +7835,7 @@ function applyClass(el, cls) {
7703
7835
  return;
7704
7836
  }
7705
7837
  if (typeof cls === "function") {
7706
- const teardown = track(() => {
7838
+ const teardown = track2(() => {
7707
7839
  el.setAttribute("class", cls());
7708
7840
  });
7709
7841
  registerDisposer(el, teardown);
@@ -7730,7 +7862,7 @@ function applyClass(el, cls) {
7730
7862
  }
7731
7863
  el.setAttribute("class", r);
7732
7864
  };
7733
- const teardown = track(update);
7865
+ const teardown = track2(update);
7734
7866
  registerDisposer(el, teardown);
7735
7867
  } else {
7736
7868
  el.setAttribute("class", result);
@@ -7787,8 +7919,11 @@ function appendChildren(el, nodes) {
7787
7919
  }
7788
7920
  }
7789
7921
  var tagFactory = (tag, ns) => {
7922
+ const blocked = isBlockedTag(tag);
7790
7923
  return (first, second) => {
7791
- validateTagName(tag);
7924
+ if (blocked) {
7925
+ throw new Error(`tagFactory: refusing to create <${tag}> \u2014 tag is blocked for security reasons.`);
7926
+ }
7792
7927
  const el = ns ? document.createElementNS(ns, tag) : document.createElement(tag);
7793
7928
  if (first === void 0) return el;
7794
7929
  if (typeof first === "string") {
@@ -7797,7 +7932,7 @@ var tagFactory = (tag, ns) => {
7797
7932
  appendChildren(el, second);
7798
7933
  return el;
7799
7934
  }
7800
- if (_isDev9 && looksLikeClassList(first)) {
7935
+ if (_isDev10 && looksLikeClassList(first)) {
7801
7936
  devWarn(
7802
7937
  `tagFactory: lone string "${first}" looks like a class list but is being rendered as TEXT. For a class, use ${tag}({ class: "${first}" }) \u2014 or ${tag}("${first}", children) to set the class AND add children.`
7803
7938
  );
@@ -7818,7 +7953,7 @@ var tagFactory = (tag, ns) => {
7818
7953
  if (pClass != null) applyClass(el, pClass);
7819
7954
  const pId = props.id;
7820
7955
  if (pId != null) {
7821
- if (_isDev9 && typeof pId === "string" && CLOBBER_RISKY_IDS.has(pId.toLowerCase())) {
7956
+ if (_isDev10 && typeof pId === "string" && CLOBBER_RISKY_IDS.has(pId.toLowerCase())) {
7822
7957
  devWarn(
7823
7958
  `tagFactory: element id="${pId}" matches a common global and may cause DOM clobbering. Avoid setting ids from untrusted input.`
7824
7959
  );
@@ -7833,7 +7968,7 @@ var tagFactory = (tag, ns) => {
7833
7968
  const handler = pOn[ev];
7834
7969
  if (typeof handler === "function") {
7835
7970
  el.addEventListener(ev, handler);
7836
- } else if (_isDev9) {
7971
+ } else if (_isDev10) {
7837
7972
  devWarn(
7838
7973
  `tagFactory: on.${ev} handler is not a function (got ${typeof handler}). Event listener was not attached.`
7839
7974
  );
@@ -7858,7 +7993,6 @@ var tagFactory = (tag, ns) => {
7858
7993
  default: {
7859
7994
  const value = props[key];
7860
7995
  if (value == null) continue;
7861
- const lkey = key.toLowerCase();
7862
7996
  if (isEventHandlerAttr(key)) continue;
7863
7997
  if (typeof value === "function") {
7864
7998
  registerDisposer(el, bindAttribute(el, key, value));
@@ -7871,14 +8005,7 @@ var tagFactory = (tag, ns) => {
7871
8005
  el.removeAttribute(key);
7872
8006
  }
7873
8007
  } else {
7874
- const str = String(value);
7875
- if (lkey === "srcset") {
7876
- el.setAttribute(key, sanitizeSrcset(str));
7877
- } else if (isUrlAttribute(lkey)) {
7878
- el.setAttribute(key, sanitizeUrl(str));
7879
- } else {
7880
- el.setAttribute(key, str);
7881
- }
8008
+ el.setAttribute(key, sanitizeAttributeString(key, String(value)));
7882
8009
  }
7883
8010
  }
7884
8011
  }
@@ -7954,7 +8081,7 @@ var area = tagFactory("area");
7954
8081
  var audio = tagFactory("audio");
7955
8082
  var img = tagFactory("img");
7956
8083
  var map = tagFactory("map");
7957
- var track2 = tagFactory("track");
8084
+ var track3 = tagFactory("track");
7958
8085
  var video = tagFactory("video");
7959
8086
  var embed = tagFactory("embed");
7960
8087
  var iframe = tagFactory("iframe");
@@ -9286,18 +9413,18 @@ function clearPerformanceData() {
9286
9413
  perfMarks.clear();
9287
9414
  }
9288
9415
  var trackedCleanups = /* @__PURE__ */ new Map();
9289
- function trackCleanup(component, cleanup2) {
9416
+ function trackCleanup(component, cleanup3) {
9290
9417
  if (!trackedCleanups.has(component)) {
9291
9418
  trackedCleanups.set(component, []);
9292
9419
  }
9293
- trackedCleanups.get(component)?.push(cleanup2);
9420
+ trackedCleanups.get(component)?.push(cleanup3);
9294
9421
  }
9295
9422
  function runCleanups(component) {
9296
9423
  const cleanups = trackedCleanups.get(component);
9297
9424
  if (cleanups) {
9298
- for (const cleanup2 of cleanups) {
9425
+ for (const cleanup3 of cleanups) {
9299
9426
  try {
9300
- cleanup2();
9427
+ cleanup3();
9301
9428
  } catch (err) {
9302
9429
  if (typeof console !== "undefined") {
9303
9430
  console.warn("[SibuJS debug] cleanup threw:", err);
@@ -10304,13 +10431,13 @@ function startMeasure(profiler) {
10304
10431
  function getSignalName(getter) {
10305
10432
  return getter.__name;
10306
10433
  }
10307
- function getSubscriberCount2(getter) {
10434
+ function getSubscriberCount3(getter) {
10308
10435
  const signal2 = getter.__signal;
10309
10436
  if (!signal2) return 0;
10310
- return getSubscriberCount(signal2);
10437
+ return getSubscriberCount2(signal2);
10311
10438
  }
10312
10439
  function getDependencies(subscriberFn) {
10313
- return getSubscriberDeps(subscriberFn);
10440
+ return getSubscriberDeps2(subscriberFn);
10314
10441
  }
10315
10442
  function inspectSignal(getter) {
10316
10443
  const signal2 = getter.__signal;
@@ -10318,7 +10445,7 @@ function inspectSignal(getter) {
10318
10445
  return {
10319
10446
  name: getter.__name,
10320
10447
  signal: signal2,
10321
- subscriberCount: getSubscriberCount(signal2)
10448
+ subscriberCount: getSubscriberCount2(signal2)
10322
10449
  };
10323
10450
  }
10324
10451
  function walkDependencyGraph(getter, maxDepth = 10, visited = /* @__PURE__ */ new WeakSet()) {
@@ -10328,7 +10455,7 @@ function walkDependencyGraph(getter, maxDepth = 10, visited = /* @__PURE__ */ ne
10328
10455
  }
10329
10456
  visited.add(signal2);
10330
10457
  const downstream = [];
10331
- forEachSubscriber(signal2, (sub2) => {
10458
+ forEachSubscriber2(signal2, (sub2) => {
10332
10459
  const subSig = sub2._sig;
10333
10460
  if (subSig && !visited.has(subSig)) {
10334
10461
  const subName = subSig.__name;
@@ -10341,7 +10468,7 @@ function walkDependencyGraph(getter, maxDepth = 10, visited = /* @__PURE__ */ ne
10341
10468
  });
10342
10469
  return {
10343
10470
  name: getSignalName(getter),
10344
- subscribers: getSubscriberCount(signal2),
10471
+ subscribers: getSubscriberCount2(signal2),
10345
10472
  downstream
10346
10473
  };
10347
10474
  }
@@ -10396,11 +10523,17 @@ function watch(getter, callback) {
10396
10523
  return;
10397
10524
  }
10398
10525
  if (!Object.is(newValue, oldValue)) {
10399
- callback(newValue, oldValue);
10526
+ const prev = oldValue;
10400
10527
  oldValue = newValue;
10528
+ suspendTracking2();
10529
+ try {
10530
+ callback(newValue, prev);
10531
+ } finally {
10532
+ resumeTracking2();
10533
+ }
10401
10534
  }
10402
10535
  };
10403
- const teardown = track(subscriber);
10536
+ const teardown = track2(subscriber);
10404
10537
  return teardown;
10405
10538
  }
10406
10539