@solidjs/signals 0.13.6 → 0.13.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/dev.js CHANGED
@@ -655,6 +655,209 @@ function assignOrMergeLane(el, sourceLane) {
655
655
  }
656
656
  el._optimisticLane = sourceLane;
657
657
  }
658
+ function unlinkSubs(link) {
659
+ const dep = link._dep;
660
+ const nextDep = link._nextDep;
661
+ const nextSub = link._nextSub;
662
+ const prevSub = link._prevSub;
663
+ if (nextSub !== null) nextSub._prevSub = prevSub;
664
+ else dep._subsTail = prevSub;
665
+ if (prevSub !== null) prevSub._nextSub = nextSub;
666
+ else {
667
+ dep._subs = nextSub;
668
+ if (nextSub === null) {
669
+ dep._unobserved?.();
670
+ dep._fn && !dep._preventAutoDisposal && !(dep._flags & REACTIVE_ZOMBIE) && unobserved(dep);
671
+ }
672
+ }
673
+ return nextDep;
674
+ }
675
+ function unobserved(el) {
676
+ deleteFromHeap(el, el._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
677
+ let dep = el._deps;
678
+ while (dep !== null) {
679
+ dep = unlinkSubs(dep);
680
+ }
681
+ el._deps = null;
682
+ disposeChildren(el, true);
683
+ }
684
+ function link(dep, sub) {
685
+ const prevDep = sub._depsTail;
686
+ if (prevDep !== null && prevDep._dep === dep) return;
687
+ let nextDep = null;
688
+ const isRecomputing = sub._flags & REACTIVE_RECOMPUTING_DEPS;
689
+ if (isRecomputing) {
690
+ nextDep = prevDep !== null ? prevDep._nextDep : sub._deps;
691
+ if (nextDep !== null && nextDep._dep === dep) {
692
+ sub._depsTail = nextDep;
693
+ return;
694
+ }
695
+ }
696
+ const prevSub = dep._subsTail;
697
+ if (prevSub !== null && prevSub._sub === sub && (!isRecomputing || isValidLink(prevSub, sub)))
698
+ return;
699
+ const newLink =
700
+ (sub._depsTail =
701
+ dep._subsTail =
702
+ { _dep: dep, _sub: sub, _nextDep: nextDep, _prevSub: prevSub, _nextSub: null });
703
+ if (prevDep !== null) prevDep._nextDep = newLink;
704
+ else sub._deps = newLink;
705
+ if (prevSub !== null) prevSub._nextSub = newLink;
706
+ else dep._subs = newLink;
707
+ }
708
+ function isValidLink(checkLink, sub) {
709
+ const depsTail = sub._depsTail;
710
+ if (depsTail !== null) {
711
+ let link = sub._deps;
712
+ do {
713
+ if (link === checkLink) return true;
714
+ if (link === depsTail) break;
715
+ link = link._nextDep;
716
+ } while (link !== null);
717
+ }
718
+ return false;
719
+ }
720
+ const PENDING_OWNER = {};
721
+ function markDisposal(el) {
722
+ let child = el._firstChild;
723
+ while (child) {
724
+ child._flags |= REACTIVE_ZOMBIE;
725
+ if (child._flags & REACTIVE_IN_HEAP) {
726
+ deleteFromHeap(child, dirtyQueue);
727
+ insertIntoHeap(child, zombieQueue);
728
+ }
729
+ markDisposal(child);
730
+ child = child._nextSibling;
731
+ }
732
+ }
733
+ function dispose(node) {
734
+ let toRemove = node._deps || null;
735
+ do {
736
+ toRemove = unlinkSubs(toRemove);
737
+ } while (toRemove !== null);
738
+ node._deps = null;
739
+ node._depsTail = null;
740
+ disposeChildren(node, true);
741
+ }
742
+ function disposeChildren(node, self = false, zombie) {
743
+ if (node._flags & REACTIVE_DISPOSED) return;
744
+ if (self) node._flags = REACTIVE_DISPOSED;
745
+ if (self && node._fn) node._inFlight = null;
746
+ let child = zombie ? node._pendingFirstChild : node._firstChild;
747
+ while (child) {
748
+ const nextChild = child._nextSibling;
749
+ if (child._deps) {
750
+ const n = child;
751
+ deleteFromHeap(n, n._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
752
+ let toRemove = n._deps;
753
+ do {
754
+ toRemove = unlinkSubs(toRemove);
755
+ } while (toRemove !== null);
756
+ n._deps = null;
757
+ n._depsTail = null;
758
+ }
759
+ disposeChildren(child, true);
760
+ child = nextChild;
761
+ }
762
+ if (zombie) {
763
+ node._pendingFirstChild = null;
764
+ } else {
765
+ node._firstChild = null;
766
+ node._childCount = 0;
767
+ }
768
+ runDisposal(node, zombie);
769
+ }
770
+ function runDisposal(node, zombie) {
771
+ let disposal = zombie ? node._pendingDisposal : node._disposal;
772
+ if (!disposal) return;
773
+ if (Array.isArray(disposal)) {
774
+ for (let i = 0; i < disposal.length; i++) {
775
+ const callable = disposal[i];
776
+ callable.call(callable);
777
+ }
778
+ } else {
779
+ disposal.call(disposal);
780
+ }
781
+ zombie ? (node._pendingDisposal = null) : (node._disposal = null);
782
+ }
783
+ function childId(owner, consume) {
784
+ let counter = owner;
785
+ while (counter._transparent && counter._parent) counter = counter._parent;
786
+ if (counter.id != null)
787
+ return formatId(counter.id, consume ? counter._childCount++ : counter._childCount);
788
+ throw new Error("Cannot get child id from owner without an id");
789
+ }
790
+ function getNextChildId(owner) {
791
+ return childId(owner, true);
792
+ }
793
+ function peekNextChildId(owner) {
794
+ return childId(owner, false);
795
+ }
796
+ function formatId(prefix, id) {
797
+ const num = id.toString(36),
798
+ len = num.length - 1;
799
+ return prefix + (len ? String.fromCharCode(64 + len) : "") + num;
800
+ }
801
+ function getObserver() {
802
+ if (pendingCheckActive || latestReadActive) return PENDING_OWNER;
803
+ return tracking ? context : null;
804
+ }
805
+ function getOwner() {
806
+ return context;
807
+ }
808
+ function cleanup(fn) {
809
+ if (!context) return fn;
810
+ if (!context._disposal) context._disposal = fn;
811
+ else if (Array.isArray(context._disposal)) context._disposal.push(fn);
812
+ else context._disposal = [context._disposal, fn];
813
+ return fn;
814
+ }
815
+ function isDisposed(node) {
816
+ return !!(node._flags & (REACTIVE_DISPOSED | REACTIVE_ZOMBIE));
817
+ }
818
+ function createOwner(options) {
819
+ const parent = context;
820
+ const transparent = options?.transparent ?? false;
821
+ const owner = {
822
+ id:
823
+ options?.id ??
824
+ (transparent ? parent?.id : parent?.id != null ? getNextChildId(parent) : undefined),
825
+ _transparent: transparent || undefined,
826
+ _root: true,
827
+ _parentComputed: parent?._root ? parent._parentComputed : parent,
828
+ _firstChild: null,
829
+ _nextSibling: null,
830
+ _disposal: null,
831
+ _queue: parent?._queue ?? globalQueue,
832
+ _context: parent?._context || defaultContext,
833
+ _childCount: 0,
834
+ _pendingDisposal: null,
835
+ _pendingFirstChild: null,
836
+ _parent: parent,
837
+ dispose(self = true) {
838
+ disposeChildren(owner, self);
839
+ }
840
+ };
841
+ if (parent?._childrenForbidden) {
842
+ throw new Error(
843
+ "Cannot create reactive primitives inside createTrackedEffect or owner-backed onSettled"
844
+ );
845
+ }
846
+ if (parent) {
847
+ const lastChild = parent._firstChild;
848
+ if (lastChild === null) {
849
+ parent._firstChild = owner;
850
+ } else {
851
+ owner._nextSibling = lastChild;
852
+ parent._firstChild = owner;
853
+ }
854
+ }
855
+ return owner;
856
+ }
857
+ function createRoot(init, options) {
858
+ const owner = createOwner(options);
859
+ return runWithOwner(owner, () => init(owner.dispose));
860
+ }
658
861
  function addPendingSource(el, source) {
659
862
  if (el._pendingSource === source || el._pendingSources?.has(source)) return false;
660
863
  if (!el._pendingSource) {
@@ -819,6 +1022,17 @@ function handleAsync(el, result, setter) {
819
1022
  if (iterator) {
820
1023
  const it = result[Symbol.asyncIterator]();
821
1024
  let hadSyncValue = false;
1025
+ let completed = false;
1026
+ cleanup(() => {
1027
+ if (completed) return;
1028
+ completed = true;
1029
+ try {
1030
+ const returned = it.return?.();
1031
+ if (returned && typeof returned.then === "function") {
1032
+ returned.then(undefined, () => {});
1033
+ }
1034
+ } catch {}
1035
+ });
822
1036
  const iterate = () => {
823
1037
  let syncResult,
824
1038
  resolved = false,
@@ -828,14 +1042,21 @@ function handleAsync(el, result, setter) {
828
1042
  if (isSync) {
829
1043
  syncResult = r;
830
1044
  resolved = true;
1045
+ if (r.done) completed = true;
1046
+ } else if (el._inFlight !== result) {
1047
+ return;
831
1048
  } else if (!r.done) asyncWrite(r.value, iterate);
832
1049
  else {
1050
+ completed = true;
833
1051
  schedule();
834
1052
  flush();
835
1053
  }
836
1054
  },
837
1055
  e => {
838
- if (!isSync) handleError(e);
1056
+ if (!isSync && el._inFlight === result) {
1057
+ completed = true;
1058
+ handleError(e);
1059
+ }
839
1060
  }
840
1061
  );
841
1062
  isSync = false;
@@ -942,208 +1163,6 @@ function enableExternalSource(config) {
942
1163
  externalSourceConfig = { factory: factory, untrack: untrackFn };
943
1164
  }
944
1165
  }
945
- const PENDING_OWNER = {};
946
- function markDisposal(el) {
947
- let child = el._firstChild;
948
- while (child) {
949
- child._flags |= REACTIVE_ZOMBIE;
950
- if (child._flags & REACTIVE_IN_HEAP) {
951
- deleteFromHeap(child, dirtyQueue);
952
- insertIntoHeap(child, zombieQueue);
953
- }
954
- markDisposal(child);
955
- child = child._nextSibling;
956
- }
957
- }
958
- function dispose(node) {
959
- let toRemove = node._deps || null;
960
- do {
961
- toRemove = unlinkSubs(toRemove);
962
- } while (toRemove !== null);
963
- node._deps = null;
964
- node._depsTail = null;
965
- disposeChildren(node, true);
966
- }
967
- function disposeChildren(node, self = false, zombie) {
968
- if (node._flags & REACTIVE_DISPOSED) return;
969
- if (self) node._flags = REACTIVE_DISPOSED;
970
- let child = zombie ? node._pendingFirstChild : node._firstChild;
971
- while (child) {
972
- const nextChild = child._nextSibling;
973
- if (child._deps) {
974
- const n = child;
975
- deleteFromHeap(n, n._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
976
- let toRemove = n._deps;
977
- do {
978
- toRemove = unlinkSubs(toRemove);
979
- } while (toRemove !== null);
980
- n._deps = null;
981
- n._depsTail = null;
982
- }
983
- disposeChildren(child, true);
984
- child = nextChild;
985
- }
986
- if (zombie) {
987
- node._pendingFirstChild = null;
988
- } else {
989
- node._firstChild = null;
990
- node._childCount = 0;
991
- }
992
- runDisposal(node, zombie);
993
- }
994
- function runDisposal(node, zombie) {
995
- let disposal = zombie ? node._pendingDisposal : node._disposal;
996
- if (!disposal) return;
997
- if (Array.isArray(disposal)) {
998
- for (let i = 0; i < disposal.length; i++) {
999
- const callable = disposal[i];
1000
- callable.call(callable);
1001
- }
1002
- } else {
1003
- disposal.call(disposal);
1004
- }
1005
- zombie ? (node._pendingDisposal = null) : (node._disposal = null);
1006
- }
1007
- function childId(owner, consume) {
1008
- let counter = owner;
1009
- while (counter._transparent && counter._parent) counter = counter._parent;
1010
- if (counter.id != null)
1011
- return formatId(counter.id, consume ? counter._childCount++ : counter._childCount);
1012
- throw new Error("Cannot get child id from owner without an id");
1013
- }
1014
- function getNextChildId(owner) {
1015
- return childId(owner, true);
1016
- }
1017
- function peekNextChildId(owner) {
1018
- return childId(owner, false);
1019
- }
1020
- function formatId(prefix, id) {
1021
- const num = id.toString(36),
1022
- len = num.length - 1;
1023
- return prefix + (len ? String.fromCharCode(64 + len) : "") + num;
1024
- }
1025
- function getObserver() {
1026
- if (pendingCheckActive || latestReadActive) return PENDING_OWNER;
1027
- return tracking ? context : null;
1028
- }
1029
- function getOwner() {
1030
- return context;
1031
- }
1032
- function cleanup(fn) {
1033
- if (!context) return fn;
1034
- if (!context._disposal) context._disposal = fn;
1035
- else if (Array.isArray(context._disposal)) context._disposal.push(fn);
1036
- else context._disposal = [context._disposal, fn];
1037
- return fn;
1038
- }
1039
- function isDisposed(node) {
1040
- return !!(node._flags & (REACTIVE_DISPOSED | REACTIVE_ZOMBIE));
1041
- }
1042
- function createOwner(options) {
1043
- const parent = context;
1044
- const transparent = options?.transparent ?? false;
1045
- const owner = {
1046
- id:
1047
- options?.id ??
1048
- (transparent ? parent?.id : parent?.id != null ? getNextChildId(parent) : undefined),
1049
- _transparent: transparent || undefined,
1050
- _root: true,
1051
- _parentComputed: parent?._root ? parent._parentComputed : parent,
1052
- _firstChild: null,
1053
- _nextSibling: null,
1054
- _disposal: null,
1055
- _queue: parent?._queue ?? globalQueue,
1056
- _context: parent?._context || defaultContext,
1057
- _childCount: 0,
1058
- _pendingDisposal: null,
1059
- _pendingFirstChild: null,
1060
- _parent: parent,
1061
- dispose(self = true) {
1062
- disposeChildren(owner, self);
1063
- }
1064
- };
1065
- if (parent?._childrenForbidden) {
1066
- throw new Error(
1067
- "Cannot create reactive primitives inside createTrackedEffect or owner-backed onSettled"
1068
- );
1069
- }
1070
- if (parent) {
1071
- const lastChild = parent._firstChild;
1072
- if (lastChild === null) {
1073
- parent._firstChild = owner;
1074
- } else {
1075
- owner._nextSibling = lastChild;
1076
- parent._firstChild = owner;
1077
- }
1078
- }
1079
- return owner;
1080
- }
1081
- function createRoot(init, options) {
1082
- const owner = createOwner(options);
1083
- return runWithOwner(owner, () => init(owner.dispose));
1084
- }
1085
- function unlinkSubs(link) {
1086
- const dep = link._dep;
1087
- const nextDep = link._nextDep;
1088
- const nextSub = link._nextSub;
1089
- const prevSub = link._prevSub;
1090
- if (nextSub !== null) nextSub._prevSub = prevSub;
1091
- else dep._subsTail = prevSub;
1092
- if (prevSub !== null) prevSub._nextSub = nextSub;
1093
- else {
1094
- dep._subs = nextSub;
1095
- if (nextSub === null) {
1096
- dep._unobserved?.();
1097
- dep._fn && !dep._preventAutoDisposal && !(dep._flags & REACTIVE_ZOMBIE) && unobserved(dep);
1098
- }
1099
- }
1100
- return nextDep;
1101
- }
1102
- function unobserved(el) {
1103
- deleteFromHeap(el, el._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
1104
- let dep = el._deps;
1105
- while (dep !== null) {
1106
- dep = unlinkSubs(dep);
1107
- }
1108
- el._deps = null;
1109
- disposeChildren(el, true);
1110
- }
1111
- function link(dep, sub) {
1112
- const prevDep = sub._depsTail;
1113
- if (prevDep !== null && prevDep._dep === dep) return;
1114
- let nextDep = null;
1115
- const isRecomputing = sub._flags & REACTIVE_RECOMPUTING_DEPS;
1116
- if (isRecomputing) {
1117
- nextDep = prevDep !== null ? prevDep._nextDep : sub._deps;
1118
- if (nextDep !== null && nextDep._dep === dep) {
1119
- sub._depsTail = nextDep;
1120
- return;
1121
- }
1122
- }
1123
- const prevSub = dep._subsTail;
1124
- if (prevSub !== null && prevSub._sub === sub && (!isRecomputing || isValidLink(prevSub, sub)))
1125
- return;
1126
- const newLink =
1127
- (sub._depsTail =
1128
- dep._subsTail =
1129
- { _dep: dep, _sub: sub, _nextDep: nextDep, _prevSub: prevSub, _nextSub: null });
1130
- if (prevDep !== null) prevDep._nextDep = newLink;
1131
- else sub._deps = newLink;
1132
- if (prevSub !== null) prevSub._nextSub = newLink;
1133
- else dep._subs = newLink;
1134
- }
1135
- function isValidLink(checkLink, sub) {
1136
- const depsTail = sub._depsTail;
1137
- if (depsTail !== null) {
1138
- let link = sub._deps;
1139
- do {
1140
- if (link === checkLink) return true;
1141
- if (link === depsTail) break;
1142
- link = link._nextDep;
1143
- } while (link !== null);
1144
- }
1145
- return false;
1146
- }
1147
1166
  GlobalQueue._update = recompute;
1148
1167
  GlobalQueue._dispose = disposeChildren;
1149
1168
  let tracking = false;
@@ -1212,6 +1231,7 @@ function recompute(el, create = false) {
1212
1231
  if (el._transition && (!isEffect || activeTransition) && activeTransition !== el._transition)
1213
1232
  globalQueue.initTransition(el._transition);
1214
1233
  deleteFromHeap(el, el._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
1234
+ el._inFlight = null;
1215
1235
  if (el._transition || isEffect === EFFECT_TRACKED) disposeChildren(el);
1216
1236
  else {
1217
1237
  markDisposal(el);
@@ -1516,6 +1536,11 @@ function read(el) {
1516
1536
  ) {
1517
1537
  foundPending = true;
1518
1538
  }
1539
+ let c = context;
1540
+ if (c?._root) c = c._parentComputed;
1541
+ if (c && tracking) link(el, c);
1542
+ read(getPendingSignal(el));
1543
+ read(getPendingSignal(firewall));
1519
1544
  } else {
1520
1545
  if (read(getPendingSignal(el))) foundPending = true;
1521
1546
  if (firewall && read(getPendingSignal(firewall))) foundPending = true;
@@ -1890,7 +1915,13 @@ function runEffect() {
1890
1915
  this._cleanup?.();
1891
1916
  this._cleanup = undefined;
1892
1917
  try {
1893
- this._cleanup = this._effectFn(this._value, this._prevValue);
1918
+ const cleanup = this._effectFn(this._value, this._prevValue);
1919
+ if (true && cleanup !== undefined && typeof cleanup !== "function") {
1920
+ throw new Error(
1921
+ `${this._name || "effect"} callback returned an invalid cleanup value. Return a cleanup function or undefined.`
1922
+ );
1923
+ }
1924
+ this._cleanup = cleanup;
1894
1925
  } catch (error) {
1895
1926
  this._error = new StatusError(this, error);
1896
1927
  this._statusFlags |= STATUS_ERROR;
@@ -1916,7 +1947,13 @@ function trackedEffect(fn, options) {
1916
1947
  () => {
1917
1948
  node._cleanup?.();
1918
1949
  node._cleanup = undefined;
1919
- node._cleanup = staleValues(fn) || undefined;
1950
+ const cleanup = staleValues(fn);
1951
+ if (cleanup !== undefined && typeof cleanup !== "function") {
1952
+ throw new Error(
1953
+ `${node._name || "trackedEffect"} callback returned an invalid cleanup value. Return a cleanup function or undefined.`
1954
+ );
1955
+ }
1956
+ node._cleanup = cleanup;
1920
1957
  },
1921
1958
  undefined,
1922
1959
  { ...options, lazy: true }
@@ -2036,7 +2073,13 @@ function createReaction(effectFn, options) {
2036
2073
  () => (tracking(), getOwner()),
2037
2074
  node => {
2038
2075
  cl?.();
2039
- cl = (effectFn.effect || effectFn)?.();
2076
+ const cleanup = (effectFn.effect || effectFn)?.();
2077
+ if (true && cleanup !== undefined && typeof cleanup !== "function") {
2078
+ throw new Error(
2079
+ "Reaction callback returned an invalid cleanup value. Return a cleanup function or undefined."
2080
+ );
2081
+ }
2082
+ cl = cleanup;
2040
2083
  dispose(node);
2041
2084
  },
2042
2085
  effectFn.error,
@@ -2076,9 +2119,14 @@ function createOptimistic(first, second, third) {
2076
2119
  function onSettled(callback) {
2077
2120
  const owner = getOwner();
2078
2121
  owner && !owner._childrenForbidden
2079
- ? createTrackedEffect(() => untrack(callback))
2122
+ ? createTrackedEffect(() => untrack(callback), { name: "onSettled" })
2080
2123
  : globalQueue.enqueue(EFFECT_USER, () => {
2081
2124
  const cleanup = callback();
2125
+ if (cleanup !== undefined && typeof cleanup !== "function") {
2126
+ throw new Error(
2127
+ "onSettled callback returned an invalid cleanup value. Return a cleanup function or undefined."
2128
+ );
2129
+ }
2082
2130
  cleanup?.();
2083
2131
  });
2084
2132
  }
@@ -2287,6 +2335,18 @@ function createWriteTraps(isActive) {
2287
2335
  }
2288
2336
  return typeof value === "object" && value !== null ? new Proxy(value, traps) : value;
2289
2337
  },
2338
+ has(_, prop) {
2339
+ let value;
2340
+ setWriteOverride(true);
2341
+ setProjectionWriteActive(true);
2342
+ try {
2343
+ value = prop in _;
2344
+ } finally {
2345
+ setWriteOverride(false);
2346
+ setProjectionWriteActive(false);
2347
+ }
2348
+ return value;
2349
+ },
2290
2350
  set(_, prop, value) {
2291
2351
  if (isActive && !isActive()) return true;
2292
2352
  setWriteOverride(true);
@@ -2344,7 +2404,12 @@ function wrap(value, target) {
2344
2404
  return p;
2345
2405
  }
2346
2406
  function isWrappable(obj) {
2347
- return obj != null && typeof obj === "object" && !Object.isFrozen(obj);
2407
+ return (
2408
+ obj != null &&
2409
+ typeof obj === "object" &&
2410
+ !Object.isFrozen(obj) &&
2411
+ !(typeof Node !== "undefined" && obj instanceof Node)
2412
+ );
2348
2413
  }
2349
2414
  let writeOverride = false;
2350
2415
  function setWriteOverride(value) {
@@ -2496,17 +2561,19 @@ const storeTraps = {
2496
2561
  : target[STORE_OVERRIDE] && property in target[STORE_OVERRIDE]
2497
2562
  ? target[STORE_OVERRIDE][property] !== $DELETED
2498
2563
  : property in target[STORE_VALUE];
2499
- getObserver() &&
2500
- read(
2501
- getNode(
2502
- getNodes(target, STORE_HAS),
2503
- property,
2504
- has,
2505
- target[STORE_FIREWALL],
2506
- isEqual,
2507
- target[STORE_OPTIMISTIC]
2508
- )
2509
- );
2564
+ if (!writeOnly(target[$PROXY])) {
2565
+ getObserver() &&
2566
+ read(
2567
+ getNode(
2568
+ getNodes(target, STORE_HAS),
2569
+ property,
2570
+ has,
2571
+ target[STORE_FIREWALL],
2572
+ isEqual,
2573
+ target[STORE_OPTIMISTIC]
2574
+ )
2575
+ );
2576
+ }
2510
2577
  return has;
2511
2578
  },
2512
2579
  set(target, property, rawValue) {
@@ -2544,25 +2611,32 @@ const storeTraps = {
2544
2611
  ? target[STORE_OVERRIDE][property]
2545
2612
  : base;
2546
2613
  const value = rawValue?.[$TARGET]?.[STORE_VALUE] ?? rawValue;
2547
- if (prev === value) return true;
2614
+ const isArrayIndexWrite = Array.isArray(state) && property !== "length";
2615
+ const nextIndex = isArrayIndexWrite ? parseInt(property) + 1 : 0;
2548
2616
  const len =
2549
- target[STORE_OPTIMISTIC_OVERRIDE]?.length ||
2550
- target[STORE_OVERRIDE]?.length ||
2551
- state.length;
2552
- if (value !== undefined && value === base) delete target[overrideKey][property];
2553
- else (target[overrideKey] || (target[overrideKey] = Object.create(null)))[property] = value;
2617
+ isArrayIndexWrite &&
2618
+ (target[STORE_OPTIMISTIC_OVERRIDE] && "length" in target[STORE_OPTIMISTIC_OVERRIDE]
2619
+ ? target[STORE_OPTIMISTIC_OVERRIDE].length
2620
+ : target[STORE_OVERRIDE] && "length" in target[STORE_OVERRIDE]
2621
+ ? target[STORE_OVERRIDE].length
2622
+ : state.length);
2623
+ const nextLength = isArrayIndexWrite && nextIndex > len ? nextIndex : undefined;
2624
+ if (prev === value && nextLength === undefined) return true;
2625
+ if (value !== undefined && value === base && nextLength === undefined)
2626
+ delete target[overrideKey]?.[property];
2627
+ else {
2628
+ const override = target[overrideKey] || (target[overrideKey] = Object.create(null));
2629
+ override[property] = value;
2630
+ if (nextLength !== undefined) override.length = nextLength;
2631
+ }
2554
2632
  const wrappable = isWrappable(value);
2555
2633
  target[STORE_HAS]?.[property] && setSignal(target[STORE_HAS][property], true);
2556
2634
  const nodes = getNodes(target, STORE_NODE);
2557
2635
  nodes[property] &&
2558
2636
  setSignal(nodes[property], () => (wrappable ? wrap(value, target) : value));
2559
2637
  if (Array.isArray(state)) {
2560
- if (property === "length") {
2561
- nodes.length && setSignal(nodes.length, value);
2562
- } else {
2563
- const index = parseInt(property) + 1;
2564
- if (index > len) nodes.length && setSignal(nodes.length, index);
2565
- }
2638
+ const lengthValue = property === "length" ? value : nextLength;
2639
+ lengthValue !== undefined && nodes.length && setSignal(nodes.length, lengthValue);
2566
2640
  }
2567
2641
  nodes[$TRACK] && setSignal(nodes[$TRACK], undefined);
2568
2642
  });
@@ -3316,8 +3390,9 @@ class CollectionQueue extends Queue {
3316
3390
  checkSources() {
3317
3391
  for (const source of this._sources) {
3318
3392
  if (
3319
- !(source._statusFlags & this._collectionType) &&
3320
- !(this._collectionType & STATUS_ERROR && source._statusFlags & STATUS_PENDING)
3393
+ source._flags & REACTIVE_DISPOSED ||
3394
+ (!(source._statusFlags & this._collectionType) &&
3395
+ !(this._collectionType & STATUS_ERROR && source._statusFlags & STATUS_PENDING))
3321
3396
  )
3322
3397
  this._sources.delete(source);
3323
3398
  }