@solidjs/signals 2.0.0-beta.14 → 2.0.0-beta.16

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 (87) hide show
  1. package/README.md +2 -3
  2. package/dist/dev.js +966 -550
  3. package/dist/node.cjs +2153 -1821
  4. package/dist/prod.js +1848 -1530
  5. package/dist/types/boundaries.d.ts +3 -3
  6. package/dist/types/core/async.d.ts +1 -0
  7. package/dist/types/core/core.d.ts +27 -15
  8. package/dist/types/core/dev.d.ts +10 -2
  9. package/dist/types/core/effect.d.ts +1 -3
  10. package/dist/types/core/graph.d.ts +1 -1
  11. package/dist/types/core/index.d.ts +2 -2
  12. package/dist/types/core/invariants.d.ts +49 -0
  13. package/dist/types/core/scheduler.d.ts +8 -0
  14. package/dist/types/core/types.d.ts +19 -0
  15. package/dist/types/index.d.ts +1 -1
  16. package/dist/types/signals.d.ts +39 -2
  17. package/dist/types/store/projection.d.ts +4 -4
  18. package/dist/types/store/store.d.ts +29 -1
  19. package/dist/types-cjs/boundaries.d.cts +3 -3
  20. package/dist/types-cjs/core/async.d.cts +1 -0
  21. package/dist/types-cjs/core/core.d.cts +27 -15
  22. package/dist/types-cjs/core/dev.d.cts +10 -2
  23. package/dist/types-cjs/core/effect.d.cts +1 -3
  24. package/dist/types-cjs/core/graph.d.cts +1 -1
  25. package/dist/types-cjs/core/index.d.cts +2 -2
  26. package/dist/types-cjs/core/invariants.d.cts +49 -0
  27. package/dist/types-cjs/core/scheduler.d.cts +8 -0
  28. package/dist/types-cjs/core/types.d.cts +19 -0
  29. package/dist/types-cjs/index.d.cts +1 -1
  30. package/dist/types-cjs/signals.d.cts +39 -2
  31. package/dist/types-cjs/store/projection.d.cts +4 -4
  32. package/dist/types-cjs/store/store.d.cts +29 -1
  33. package/package.json +1 -1
  34. package/dist/types/src/boundaries.d.ts +0 -173
  35. package/dist/types/src/core/action.d.ts +0 -35
  36. package/dist/types/src/core/async.d.ts +0 -6
  37. package/dist/types/src/core/constants.d.ts +0 -51
  38. package/dist/types/src/core/context.d.ts +0 -36
  39. package/dist/types/src/core/core.d.ts +0 -174
  40. package/dist/types/src/core/dev.d.ts +0 -49
  41. package/dist/types/src/core/effect.d.ts +0 -32
  42. package/dist/types/src/core/error.d.ts +0 -38
  43. package/dist/types/src/core/external.d.ts +0 -45
  44. package/dist/types/src/core/graph.d.ts +0 -5
  45. package/dist/types/src/core/heap.d.ts +0 -14
  46. package/dist/types/src/core/index.d.ts +0 -12
  47. package/dist/types/src/core/lanes.d.ts +0 -54
  48. package/dist/types/src/core/owner.d.ts +0 -116
  49. package/dist/types/src/core/scheduler.d.ts +0 -122
  50. package/dist/types/src/core/types.d.ts +0 -85
  51. package/dist/types/src/index.d.ts +0 -9
  52. package/dist/types/src/map.d.ts +0 -53
  53. package/dist/types/src/signals.d.ts +0 -512
  54. package/dist/types/src/store/index.d.ts +0 -9
  55. package/dist/types/src/store/optimistic.d.ts +0 -45
  56. package/dist/types/src/store/projection.d.ts +0 -66
  57. package/dist/types/src/store/reconcile.d.ts +0 -23
  58. package/dist/types/src/store/store.d.ts +0 -125
  59. package/dist/types/src/store/storePath.d.ts +0 -58
  60. package/dist/types/src/store/utils.d.ts +0 -114
  61. package/dist/types-cjs/src/boundaries.d.cts +0 -173
  62. package/dist/types-cjs/src/core/action.d.cts +0 -35
  63. package/dist/types-cjs/src/core/async.d.cts +0 -6
  64. package/dist/types-cjs/src/core/constants.d.cts +0 -51
  65. package/dist/types-cjs/src/core/context.d.cts +0 -36
  66. package/dist/types-cjs/src/core/core.d.cts +0 -174
  67. package/dist/types-cjs/src/core/dev.d.cts +0 -49
  68. package/dist/types-cjs/src/core/effect.d.cts +0 -32
  69. package/dist/types-cjs/src/core/error.d.cts +0 -38
  70. package/dist/types-cjs/src/core/external.d.cts +0 -45
  71. package/dist/types-cjs/src/core/graph.d.cts +0 -5
  72. package/dist/types-cjs/src/core/heap.d.cts +0 -14
  73. package/dist/types-cjs/src/core/index.d.cts +0 -12
  74. package/dist/types-cjs/src/core/lanes.d.cts +0 -54
  75. package/dist/types-cjs/src/core/owner.d.cts +0 -116
  76. package/dist/types-cjs/src/core/scheduler.d.cts +0 -122
  77. package/dist/types-cjs/src/core/types.d.cts +0 -85
  78. package/dist/types-cjs/src/index.d.cts +0 -9
  79. package/dist/types-cjs/src/map.d.cts +0 -53
  80. package/dist/types-cjs/src/signals.d.cts +0 -512
  81. package/dist/types-cjs/src/store/index.d.cts +0 -9
  82. package/dist/types-cjs/src/store/optimistic.d.cts +0 -45
  83. package/dist/types-cjs/src/store/projection.d.cts +0 -66
  84. package/dist/types-cjs/src/store/reconcile.d.cts +0 -23
  85. package/dist/types-cjs/src/store/store.d.cts +0 -125
  86. package/dist/types-cjs/src/store/storePath.d.cts +0 -58
  87. package/dist/types-cjs/src/store/utils.d.cts +0 -114
package/dist/dev.js CHANGED
@@ -140,106 +140,21 @@ function getObservers(node) {
140
140
  }
141
141
  return observers;
142
142
  }
143
- function actualInsertIntoHeap(n, heap) {
144
- const parentHeight =
145
- (n._parent?._root ? n._parent._parentComputed?._height : n._parent?._height) ?? -1;
146
- if (parentHeight >= n._height) n._height = parentHeight + 1;
147
- const height = n._height;
148
- const heapAtHeight = heap._heap[height];
149
- if (heapAtHeight === undefined) heap._heap[height] = n;
150
- else {
151
- const tail = heapAtHeight._prevHeap;
152
- tail._nextHeap = n;
153
- n._prevHeap = tail;
154
- heapAtHeight._prevHeap = n;
155
- }
156
- if (height > heap._max) heap._max = height;
157
- }
158
- function insertIntoHeap(n, heap) {
159
- let flags = n._flags;
160
- if (flags & (REACTIVE_IN_HEAP | REACTIVE_RECOMPUTING_DEPS | REACTIVE_MANUAL_WRITE)) return;
161
- if (flags & REACTIVE_CHECK) {
162
- n._flags = (flags & -4) | REACTIVE_DIRTY | REACTIVE_IN_HEAP;
163
- } else n._flags = flags | REACTIVE_IN_HEAP;
164
- if (!(flags & REACTIVE_IN_HEAP_HEIGHT)) actualInsertIntoHeap(n, heap);
143
+ function createAsyncReporters() {
144
+ return new Map();
165
145
  }
166
- function insertIntoHeapHeight(n, heap) {
167
- let flags = n._flags;
168
- if (
169
- flags &
170
- (REACTIVE_IN_HEAP | REACTIVE_RECOMPUTING_DEPS | REACTIVE_IN_HEAP_HEIGHT | REACTIVE_MANUAL_WRITE)
171
- )
172
- return;
173
- n._flags = flags | REACTIVE_IN_HEAP_HEIGHT;
174
- actualInsertIntoHeap(n, heap);
146
+ function devCheckActiveOverrides(isRegisteredForRevert) {
147
+ return;
175
148
  }
176
- function deleteFromHeap(n, heap) {
177
- const flags = n._flags;
178
- if (!(flags & (REACTIVE_IN_HEAP | REACTIVE_IN_HEAP_HEIGHT))) return;
179
- n._flags = flags & -25;
180
- const height = n._height;
181
- if (n._prevHeap === n) heap._heap[height] = undefined;
182
- else {
183
- const next = n._nextHeap;
184
- const dhh = heap._heap[height];
185
- const end = next ?? dhh;
186
- if (n === dhh) heap._heap[height] = next;
187
- else n._prevHeap._nextHeap = next;
188
- end._prevHeap = n._prevHeap;
189
- }
190
- n._prevHeap = n;
191
- n._nextHeap = undefined;
192
- }
193
- function markHeap(heap) {
194
- if (heap._marked) return;
195
- heap._marked = true;
196
- for (let i = 0; i <= heap._max; i++) {
197
- for (let el = heap._heap[i]; el !== undefined; el = el._nextHeap) {
198
- if (el._flags & REACTIVE_IN_HEAP) markNode(el);
199
- }
200
- }
201
- }
202
- function markNode(el, newState = REACTIVE_DIRTY) {
203
- const flags = el._flags;
204
- if ((flags & (REACTIVE_CHECK | REACTIVE_DIRTY)) >= newState) return;
205
- el._flags = (flags & -4) | newState;
206
- for (let link = el._subs; link !== null; link = link._nextSub) {
207
- markNode(link._sub, REACTIVE_CHECK);
208
- }
209
- if (el._child !== null) {
210
- for (let child = el._child; child !== null; child = child._nextChild) {
211
- for (let link = child._subs; link !== null; link = link._nextSub) {
212
- markNode(link._sub, REACTIVE_CHECK);
213
- }
214
- }
215
- }
149
+ function devCheckFlushStart() {
150
+ return;
216
151
  }
217
- function runHeap(heap, recompute) {
218
- heap._marked = false;
219
- for (heap._min = 0; heap._min <= heap._max; heap._min++) {
220
- let el = heap._heap[heap._min];
221
- while (el !== undefined) {
222
- if (el._flags & REACTIVE_IN_HEAP) recompute(el);
223
- else adjustHeight(el, heap);
224
- el = heap._heap[heap._min];
225
- }
226
- }
227
- heap._max = 0;
152
+ typeof globalThis !== "undefined" && !!globalThis.process?.env?.COMPANION_CENSUS;
153
+ function devCensusCompanions(isQueuedForCommit) {
154
+ return;
228
155
  }
229
- function adjustHeight(el, heap) {
230
- deleteFromHeap(el, heap);
231
- let newHeight = el._height;
232
- for (let d = el._deps; d; d = d._nextDep) {
233
- const dep1 = d._dep;
234
- const dep = dep1._firewall || dep1;
235
- if (dep._fn && dep._height >= newHeight) newHeight = dep._height + 1;
236
- }
237
- if (el._height !== newHeight) {
238
- el._height = newHeight;
239
- for (let s = el._subs; s !== null; s = s._nextSub) {
240
- insertIntoHeapHeight(s._sub, heap);
241
- }
242
- }
156
+ function devCheckQuiescent(isQueuedForCommit) {
157
+ return;
243
158
  }
244
159
  const signalLanes = new WeakMap();
245
160
  const activeLanes = new Set();
@@ -260,7 +175,6 @@ function getOrCreateLane(signal) {
260
175
  };
261
176
  signalLanes.set(signal, lane);
262
177
  activeLanes.add(lane);
263
- signal._overrideSinceLane = false;
264
178
  return lane;
265
179
  }
266
180
  function findLane(lane) {
@@ -273,8 +187,11 @@ function mergeLanes(lane1, lane2) {
273
187
  if (lane1 === lane2) return lane1;
274
188
  lane2._mergedInto = lane1;
275
189
  for (const node of lane2._pendingAsync) lane1._pendingAsync.add(node);
190
+ lane2._pendingAsync.clear();
276
191
  lane1._effectQueues[0].push(...lane2._effectQueues[0]);
277
192
  lane1._effectQueues[1].push(...lane2._effectQueues[1]);
193
+ lane2._effectQueues[0].length = 0;
194
+ lane2._effectQueues[1].length = 0;
278
195
  return lane1;
279
196
  }
280
197
  function resolveLane(el) {
@@ -318,6 +235,8 @@ const zombieQueue = { _heap: new Array(2e3).fill(undefined), _marked: false, _mi
318
235
  let clock = 0;
319
236
  let activeTransition = null;
320
237
  let scheduled = false;
238
+ let halted = false;
239
+ let haltNotified = false;
321
240
  let syncDepth = 0;
322
241
  let projectionWriteActive = false;
323
242
  let inTrackedQueueCallback = false;
@@ -406,19 +325,24 @@ function mergeTransitionState(target, outgoing) {
406
325
  for (const sub of outgoing._gatedSubs) target._gatedSubs.add(sub);
407
326
  }
408
327
  function resolveOptimisticNodes(nodes) {
409
- for (let i = 0; i < nodes.length; i++) {
328
+ const len = nodes.length;
329
+ for (let i = 0; i < len; i++) {
410
330
  const node = nodes[i];
411
331
  node._optimisticLane = undefined;
412
- if (node._pendingValue !== NOT_PENDING) {
413
- node._value = node._pendingValue;
414
- node._pendingValue = NOT_PENDING;
415
- }
332
+ if (!(node._statusFlags & STATUS_PENDING)) node._statusFlags &= ~STATUS_UNINITIALIZED;
416
333
  const prevOverride = node._overrideValue;
417
334
  node._overrideValue = NOT_PENDING;
418
335
  if (prevOverride !== NOT_PENDING && node._value !== prevOverride) insertSubs(node, true);
419
336
  node._transition = null;
420
337
  }
421
- nodes.length = 0;
338
+ for (let i = 0; i < len; i++) {
339
+ const node = nodes[i];
340
+ if (node._pendingSignal || node._latestValueComputed) snapCompanionsToState(node);
341
+ const owner = node._parentSource;
342
+ if (owner && (owner._pendingSignal === node || owner._latestValueComputed === node))
343
+ snapCompanionsToState(owner);
344
+ }
345
+ nodes.splice(0, len);
422
346
  }
423
347
  function cleanupCompletedLanes(completingTransition) {
424
348
  for (const lane of activeLanes) {
@@ -439,10 +363,41 @@ function cleanupCompletedLanes(completingTransition) {
439
363
  }
440
364
  }
441
365
  function schedule() {
366
+ if (halted) {
367
+ notifyHalted();
368
+ return;
369
+ }
442
370
  if (scheduled) return;
443
371
  scheduled = true;
444
372
  if (!syncDepth && !globalQueue._running && !projectionWriteActive) queueMicrotask(flush);
445
373
  }
374
+ function haltReactivity() {
375
+ if (halted) return;
376
+ halted = true;
377
+ let message = "[REACTIVITY_HALTED] An uncaught error halted the reactive system.";
378
+ {
379
+ message +=
380
+ " No further updates will be processed. Handle errors with createErrorBoundary/<Errored> or treat this as a crash.";
381
+ emitDiagnostic({
382
+ code: "REACTIVITY_HALTED",
383
+ kind: "error",
384
+ severity: "error",
385
+ message: message
386
+ });
387
+ }
388
+ console.error(message);
389
+ }
390
+ function notifyHalted() {
391
+ if (haltNotified) return;
392
+ haltNotified = true;
393
+ console.error(
394
+ "[REACTIVITY_HALTED] Update ignored: the reactive system was halted by an earlier uncaught error."
395
+ );
396
+ }
397
+ function resetErrorHalt() {
398
+ halted = false;
399
+ haltNotified = false;
400
+ }
446
401
  class Queue {
447
402
  _parent = null;
448
403
  _queues = [[], []];
@@ -520,6 +475,7 @@ class GlobalQueue extends Queue {
520
475
  if (this._running) return;
521
476
  this._running = true;
522
477
  try {
478
+ if (true) devCheckFlushStart();
523
479
  runHeap(dirtyQueue, GlobalQueue._update);
524
480
  if (activeTransition) {
525
481
  const isComplete = transitionComplete(activeTransition);
@@ -583,6 +539,24 @@ class GlobalQueue extends Queue {
583
539
  this.run(EFFECT_RENDER);
584
540
  activeLanes.size && runLaneEffects(EFFECT_USER);
585
541
  this.run(EFFECT_USER);
542
+ if (true) {
543
+ devCheckActiveOverrides(n => {
544
+ if (this._optimisticNodes.includes(n)) return true;
545
+ if (activeTransition?._optimisticNodes.includes(n)) return true;
546
+ for (const t of transitions) if (t._optimisticNodes.includes(n)) return true;
547
+ return false;
548
+ });
549
+ devCensusCompanions(n => n === this._pendingNode || this._pendingNodes.includes(n));
550
+ }
551
+ if (
552
+ true &&
553
+ !scheduled &&
554
+ !activeTransition &&
555
+ transitions.size === 0 &&
556
+ activeLanes.size === 0
557
+ ) {
558
+ devCheckQuiescent(n => n === this._pendingNode || this._pendingNodes.includes(n));
559
+ }
586
560
  if (true) DEV$1.hooks.onUpdate?.();
587
561
  } finally {
588
562
  this._running = false;
@@ -614,7 +588,7 @@ class GlobalQueue extends Queue {
614
588
  activeTransition = transition ?? {
615
589
  _time: clock,
616
590
  _pendingNodes: [],
617
- _asyncReporters: new Map(),
591
+ _asyncReporters: createAsyncReporters(),
618
592
  _optimisticNodes: [],
619
593
  _optimisticStores: new Set(),
620
594
  _actions: [],
@@ -710,6 +684,7 @@ function commitPendingNode(n) {
710
684
  n._value = n._pendingValue;
711
685
  n._pendingValue = NOT_PENDING;
712
686
  }
687
+ if (n._pendingSignal || n._latestValueComputed) snapCompanionsToState(n);
713
688
  return;
714
689
  }
715
690
  if (n._pendingValue !== NOT_PENDING) {
@@ -721,6 +696,7 @@ function commitPendingNode(n) {
721
696
  if (!(c._statusFlags & STATUS_PENDING)) c._statusFlags &= ~STATUS_UNINITIALIZED;
722
697
  if (c._pendingFirstChild !== null || c._pendingDisposal !== null)
723
698
  GlobalQueue._dispose(c, false, true);
699
+ if (n._pendingSignal || n._latestValueComputed) snapCompanionsToState(n);
724
700
  }
725
701
  function commitPendingNodes() {
726
702
  if (globalQueue._pendingNode !== null) {
@@ -796,8 +772,11 @@ function flush(fn) {
796
772
  try {
797
773
  return fn();
798
774
  } finally {
799
- flush();
800
- syncDepth--;
775
+ try {
776
+ flush();
777
+ } finally {
778
+ syncDepth--;
779
+ }
801
780
  }
802
781
  }
803
782
  if (globalQueue._running) {
@@ -808,6 +787,7 @@ function flush(fn) {
808
787
  }
809
788
  return;
810
789
  }
790
+ if (halted) return;
811
791
  let count = 0;
812
792
  while (scheduled || activeTransition) {
813
793
  if (++count === 1e5) throw new Error("Potential Infinite Loop Detected.");
@@ -859,8 +839,7 @@ function transitionComplete(transition) {
859
839
  hasActiveOverride(node) &&
860
840
  "_statusFlags" in node &&
861
841
  node._statusFlags & STATUS_PENDING &&
862
- node._error instanceof NotReadyError &&
863
- node._error.source !== node
842
+ node._error instanceof NotReadyError
864
843
  ) {
865
844
  done = false;
866
845
  break;
@@ -886,24 +865,127 @@ function runInTransition(transition, fn) {
886
865
  activeTransition = prevTransition;
887
866
  }
888
867
  }
868
+ function actualInsertIntoHeap(n, heap) {
869
+ const parentHeight =
870
+ (n._parent?._root ? n._parent._parentComputed?._height : n._parent?._height) ?? -1;
871
+ if (parentHeight >= n._height) n._height = parentHeight + 1;
872
+ const height = n._height;
873
+ const heapAtHeight = heap._heap[height];
874
+ if (heapAtHeight === undefined) heap._heap[height] = n;
875
+ else {
876
+ const tail = heapAtHeight._prevHeap;
877
+ tail._nextHeap = n;
878
+ n._prevHeap = tail;
879
+ heapAtHeight._prevHeap = n;
880
+ }
881
+ if (height > heap._max) heap._max = height;
882
+ }
883
+ function insertIntoHeap(n, heap) {
884
+ let flags = n._flags;
885
+ if (flags & (REACTIVE_IN_HEAP | REACTIVE_RECOMPUTING_DEPS | REACTIVE_MANUAL_WRITE)) return;
886
+ if (flags & REACTIVE_CHECK) {
887
+ n._flags = (flags & -4) | REACTIVE_DIRTY | REACTIVE_IN_HEAP;
888
+ } else n._flags = flags | REACTIVE_IN_HEAP;
889
+ if (!(flags & REACTIVE_IN_HEAP_HEIGHT)) actualInsertIntoHeap(n, heap);
890
+ }
891
+ function insertIntoHeapHeight(n, heap) {
892
+ let flags = n._flags;
893
+ if (
894
+ flags &
895
+ (REACTIVE_IN_HEAP | REACTIVE_RECOMPUTING_DEPS | REACTIVE_IN_HEAP_HEIGHT | REACTIVE_MANUAL_WRITE)
896
+ )
897
+ return;
898
+ n._flags = flags | REACTIVE_IN_HEAP_HEIGHT;
899
+ actualInsertIntoHeap(n, heap);
900
+ }
901
+ function deleteFromHeap(n, heap) {
902
+ const flags = n._flags;
903
+ if (!(flags & (REACTIVE_IN_HEAP | REACTIVE_IN_HEAP_HEIGHT))) return;
904
+ n._flags = flags & -25;
905
+ const height = n._height;
906
+ if (n._prevHeap === n) heap._heap[height] = undefined;
907
+ else {
908
+ const next = n._nextHeap;
909
+ const dhh = heap._heap[height];
910
+ const end = next ?? dhh;
911
+ if (n === dhh) heap._heap[height] = next;
912
+ else n._prevHeap._nextHeap = next;
913
+ end._prevHeap = n._prevHeap;
914
+ }
915
+ n._prevHeap = n;
916
+ n._nextHeap = undefined;
917
+ }
918
+ function markHeap(heap) {
919
+ if (heap._marked) return;
920
+ heap._marked = true;
921
+ for (let i = 0; i <= heap._max; i++) {
922
+ for (let el = heap._heap[i]; el !== undefined; el = el._nextHeap) {
923
+ if (el._flags & REACTIVE_IN_HEAP) markNode(el);
924
+ }
925
+ }
926
+ }
927
+ function markNode(el, newState = REACTIVE_DIRTY) {
928
+ const flags = el._flags;
929
+ if ((flags & (REACTIVE_CHECK | REACTIVE_DIRTY)) >= newState) return;
930
+ el._flags = (flags & -4) | newState;
931
+ for (let link = el._subs; link !== null; link = link._nextSub) {
932
+ markNode(link._sub, REACTIVE_CHECK);
933
+ }
934
+ if (el._child !== null) {
935
+ for (let child = el._child; child !== null; child = child._nextChild) {
936
+ for (let link = child._subs; link !== null; link = link._nextSub) {
937
+ markNode(link._sub, REACTIVE_CHECK);
938
+ }
939
+ }
940
+ }
941
+ }
942
+ function runHeap(heap, recompute) {
943
+ heap._marked = false;
944
+ for (heap._min = 0; heap._min <= heap._max; heap._min++) {
945
+ let el = heap._heap[heap._min];
946
+ while (el !== undefined) {
947
+ if (el._flags & REACTIVE_IN_HEAP) recompute(el);
948
+ else adjustHeight(el, heap);
949
+ el = heap._heap[heap._min];
950
+ }
951
+ }
952
+ heap._max = 0;
953
+ }
954
+ function adjustHeight(el, heap) {
955
+ deleteFromHeap(el, heap);
956
+ let newHeight = el._height;
957
+ for (let d = el._deps; d; d = d._nextDep) {
958
+ const dep1 = d._dep;
959
+ const dep = dep1._firewall || dep1;
960
+ if (dep._fn && dep._height >= newHeight) newHeight = dep._height + 1;
961
+ }
962
+ if (el._height !== newHeight) {
963
+ el._height = newHeight;
964
+ for (let s = el._subs; s !== null; s = s._nextSub) {
965
+ insertIntoHeapHeight(s._sub, s._sub._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
966
+ }
967
+ }
968
+ }
889
969
  const PENDING_OWNER = {};
890
970
  function markDisposal(el) {
891
971
  let child = el._firstChild;
892
972
  while (child) {
893
- child._flags |= REACTIVE_ZOMBIE;
894
- if (child._flags & REACTIVE_IN_HEAP) {
895
- deleteFromHeap(child, dirtyQueue);
896
- insertIntoHeap(child, zombieQueue);
973
+ const flags = child._flags;
974
+ child._flags = flags | REACTIVE_ZOMBIE;
975
+ if (flags & (REACTIVE_IN_HEAP | REACTIVE_IN_HEAP_HEIGHT)) {
976
+ deleteFromHeap(child, flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
977
+ if (flags & REACTIVE_IN_HEAP) insertIntoHeap(child, zombieQueue);
978
+ else insertIntoHeapHeight(child, zombieQueue);
897
979
  }
898
980
  markDisposal(child);
899
981
  child = child._nextSibling;
900
982
  }
901
983
  }
902
984
  function dispose(node) {
903
- let toRemove = node._deps || null;
904
- do {
985
+ let toRemove = node._deps;
986
+ while (toRemove !== null) {
905
987
  toRemove = unlinkSubs(toRemove);
906
- } while (toRemove !== null);
988
+ }
907
989
  node._deps = null;
908
990
  node._depsTail = null;
909
991
  disposeChildren(node, true);
@@ -911,7 +993,11 @@ function dispose(node) {
911
993
  function disposeChildren(node, self = false, zombie) {
912
994
  const flags = node._flags;
913
995
  if (flags & REACTIVE_DISPOSED) return;
914
- if (self) node._flags = flags | REACTIVE_DISPOSED;
996
+ if (self) {
997
+ node._flags = flags | REACTIVE_DISPOSED;
998
+ const n = node;
999
+ if (n._pendingSignal || n._latestValueComputed) snapCompanionsToState(n);
1000
+ }
915
1001
  if (self && true) clearSignals(node);
916
1002
  if (self && node._fn) node._inFlight = null;
917
1003
  let child = zombie ? node._pendingFirstChild : node._firstChild;
@@ -951,6 +1037,11 @@ function disposeChildren(node, self = false, zombie) {
951
1037
  node._prevSibling = null;
952
1038
  }
953
1039
  runDisposal(node, zombie);
1040
+ if (self && node._cleanup) {
1041
+ const effectCleanup = node._cleanup;
1042
+ node._cleanup = undefined;
1043
+ effectCleanup();
1044
+ }
954
1045
  }
955
1046
  function runDisposal(node, zombie) {
956
1047
  let disposal = zombie ? node._pendingDisposal : node._disposal;
@@ -1092,42 +1183,49 @@ function unobserved(el) {
1092
1183
  el._depsTail = null;
1093
1184
  disposeChildren(el, true);
1094
1185
  }
1095
- function link(dep, sub) {
1186
+ function link(dep, sub, pendingObserver = false) {
1096
1187
  const prevDep = sub._depsTail;
1097
- if (prevDep !== null && prevDep._dep === dep) return;
1188
+ if (prevDep !== null && prevDep._dep === dep) {
1189
+ prevDep._pendingObserver = pendingObserver;
1190
+ return;
1191
+ }
1098
1192
  let nextDep = null;
1099
1193
  const isRecomputing = sub._flags & REACTIVE_RECOMPUTING_DEPS;
1100
1194
  if (isRecomputing) {
1101
1195
  nextDep = prevDep !== null ? prevDep._nextDep : sub._deps;
1102
1196
  if (nextDep !== null && nextDep._dep === dep) {
1197
+ nextDep._gen = sub._depGen;
1103
1198
  sub._depsTail = nextDep;
1199
+ nextDep._pendingObserver = pendingObserver;
1104
1200
  return;
1105
1201
  }
1106
1202
  }
1107
1203
  const prevSub = dep._subsTail;
1108
- if (prevSub !== null && prevSub._sub === sub && (!isRecomputing || isValidLink(prevSub, sub)))
1204
+ if (
1205
+ prevSub !== null &&
1206
+ prevSub._sub === sub &&
1207
+ (!isRecomputing || prevSub._gen === sub._depGen)
1208
+ ) {
1209
+ prevSub._pendingObserver = pendingObserver;
1109
1210
  return;
1211
+ }
1110
1212
  const newLink =
1111
1213
  (sub._depsTail =
1112
1214
  dep._subsTail =
1113
- { _dep: dep, _sub: sub, _nextDep: nextDep, _prevSub: prevSub, _nextSub: null });
1215
+ {
1216
+ _dep: dep,
1217
+ _sub: sub,
1218
+ _nextDep: nextDep,
1219
+ _prevSub: prevSub,
1220
+ _nextSub: null,
1221
+ _gen: sub._depGen,
1222
+ _pendingObserver: pendingObserver
1223
+ });
1114
1224
  if (prevDep !== null) prevDep._nextDep = newLink;
1115
1225
  else sub._deps = newLink;
1116
1226
  if (prevSub !== null) prevSub._nextSub = newLink;
1117
1227
  else dep._subs = newLink;
1118
1228
  }
1119
- function isValidLink(checkLink, sub) {
1120
- const depsTail = sub._depsTail;
1121
- if (depsTail !== null) {
1122
- let link = sub._deps;
1123
- do {
1124
- if (link === checkLink) return true;
1125
- if (link === depsTail) break;
1126
- link = link._nextDep;
1127
- } while (link !== null);
1128
- }
1129
- return false;
1130
- }
1131
1229
  function addPendingSource(el, source) {
1132
1230
  if (el._pendingSource === source || el._pendingSources?.has(source)) return false;
1133
1231
  if (!el._pendingSource) {
@@ -1177,9 +1275,22 @@ function setPendingError(el, source, error) {
1177
1275
  }
1178
1276
  }
1179
1277
  function forEachDependent(el, fn) {
1180
- for (let s = el._subs; s !== null; s = s._nextSub) fn(s._sub);
1278
+ for (let s = el._subs; s !== null; s = s._nextSub) fn(s._sub, s);
1181
1279
  for (let child = el._child; child !== null; child = child._nextChild) {
1182
- for (let s = child._subs; s !== null; s = s._nextSub) fn(s._sub);
1280
+ for (let s = child._subs; s !== null; s = s._nextSub) fn(s._sub, s);
1281
+ }
1282
+ }
1283
+ function enqueueForRerun(node) {
1284
+ if (node._type === EFFECT_TRACKED) {
1285
+ const tracked = node;
1286
+ if (!tracked._modified) {
1287
+ tracked._modified = true;
1288
+ tracked._queue.enqueue(EFFECT_USER, tracked._run);
1289
+ }
1290
+ } else {
1291
+ const queue = node._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue;
1292
+ if (queue._min > node._height) queue._min = node._height;
1293
+ insertIntoHeap(node, queue);
1183
1294
  }
1184
1295
  }
1185
1296
  function settlePendingSource(el) {
@@ -1198,17 +1309,7 @@ function settlePendingSource(el) {
1198
1309
  setPendingError(node);
1199
1310
  updatePendingSignal(node);
1200
1311
  if (node._blocked) {
1201
- if (node._type === EFFECT_TRACKED) {
1202
- const tracked = node;
1203
- if (!tracked._modified) {
1204
- tracked._modified = true;
1205
- tracked._queue.enqueue(EFFECT_USER, tracked._run);
1206
- }
1207
- } else {
1208
- const queue = node._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue;
1209
- if (queue._min > node._height) queue._min = node._height;
1210
- insertIntoHeap(node, queue);
1211
- }
1312
+ enqueueForRerun(node);
1212
1313
  scheduled = true;
1213
1314
  }
1214
1315
  node._blocked = false;
@@ -1218,23 +1319,26 @@ function settlePendingSource(el) {
1218
1319
  forEachDependent(el, settle);
1219
1320
  if (scheduled) schedule();
1220
1321
  }
1322
+ function isThenable(value) {
1323
+ return value != null && typeof value === "object" && typeof value.then === "function";
1324
+ }
1221
1325
  function handleAsync(el, result, setter) {
1222
1326
  let iterator = false;
1223
- let isThenable = false;
1327
+ let thenable = false;
1224
1328
  if (typeof result === "object" && result !== null) {
1225
1329
  untrack(() => {
1226
1330
  iterator = result[Symbol.asyncIterator];
1227
- isThenable = !iterator && typeof result.then === "function";
1331
+ thenable = !iterator && isThenable(result);
1228
1332
  });
1229
1333
  }
1230
- if (!isThenable && !iterator) {
1334
+ if (!thenable && !iterator) {
1231
1335
  el._inFlight = null;
1232
1336
  return result;
1233
1337
  }
1234
1338
  if (el._config & CONFIG_SYNC) {
1235
1339
  const message =
1236
1340
  `[SYNC_NODE_RECEIVED_ASYNC] A computed/effect created with \`sync: true\` returned ` +
1237
- `${isThenable ? "a Promise" : "an AsyncIterable"}. The value would be stored as-is and ` +
1341
+ `${thenable ? "a Promise" : "an AsyncIterable"}. The value would be stored as-is and ` +
1238
1342
  `never awaited in production; remove \`sync: true\` to use async-aware behavior, or ` +
1239
1343
  `unwrap the value before returning.`;
1240
1344
  emitDiagnostic({
@@ -1264,37 +1368,45 @@ function handleAsync(el, result, setter) {
1264
1368
  clearStatus(el);
1265
1369
  const lane = resolveLane(el);
1266
1370
  if (lane) lane._pendingAsync.delete(el);
1267
- if (setter) setter(value);
1268
- else if (el._overrideValue !== undefined) {
1269
- if (el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING)
1270
- el._pendingValue = value;
1271
- else {
1272
- el._value = value;
1273
- insertSubs(el);
1274
- }
1371
+ if (setter) {
1372
+ setter(value);
1373
+ if (wasUninitialized) clearStatus(el, true);
1374
+ } else if (el._overrideValue !== undefined) {
1375
+ if (el._pendingValue === NOT_PENDING) queuePendingNode(el);
1376
+ el._pendingValue = value;
1377
+ syncCompanions(el, value);
1378
+ if (!hasActiveOverride(el)) insertSubs(el);
1275
1379
  el._time = clock;
1276
1380
  } else if (lane) {
1277
1381
  const isEffect = el._type;
1278
1382
  const prevValue = el._value;
1279
1383
  const equals = el._equals;
1280
- if ((!isEffect && wasUninitialized) || !equals || !equals(value, prevValue)) {
1281
- el._value = value;
1282
- el._time = clock;
1283
- if (el._latestValueComputed) {
1284
- setSignal(el._latestValueComputed, value);
1384
+ try {
1385
+ if ((!isEffect && wasUninitialized) || !equals || !equals(value, prevValue)) {
1386
+ el._value = value;
1387
+ el._time = clock;
1388
+ syncCompanions(el, value);
1389
+ insertSubs(el, true);
1285
1390
  }
1286
- insertSubs(el, true);
1391
+ } catch (e) {
1392
+ notifyStatus(el, STATUS_ERROR, e);
1287
1393
  }
1288
1394
  } else {
1289
- setSignal(el, () => value);
1395
+ try {
1396
+ setSignal(el, () => value);
1397
+ } catch (e) {
1398
+ notifyStatus(el, STATUS_ERROR, e);
1399
+ }
1290
1400
  }
1291
1401
  settlePendingSource(el);
1292
1402
  schedule();
1293
1403
  flush();
1294
1404
  then?.();
1295
1405
  };
1296
- if (isThenable) {
1406
+ if (thenable) {
1297
1407
  let resolved = false,
1408
+ rejected = false,
1409
+ syncError,
1298
1410
  isSync = true;
1299
1411
  result.then(
1300
1412
  v => {
@@ -1304,11 +1416,17 @@ function handleAsync(el, result, setter) {
1304
1416
  } else asyncWrite(v);
1305
1417
  },
1306
1418
  e => {
1307
- if (!isSync) handleError(e);
1419
+ if (isSync) {
1420
+ syncError = e;
1421
+ rejected = true;
1422
+ } else handleError(e);
1308
1423
  }
1309
1424
  );
1310
1425
  isSync = false;
1311
- if (!resolved) {
1426
+ if (rejected) {
1427
+ handleError(syncError);
1428
+ throw syncError;
1429
+ } else if (!resolved) {
1312
1430
  globalQueue.initTransition(resolveTransition(el));
1313
1431
  throw new NotReadyError(context);
1314
1432
  }
@@ -1322,9 +1440,7 @@ function handleAsync(el, result, setter) {
1322
1440
  completed = true;
1323
1441
  try {
1324
1442
  const returned = it.return?.();
1325
- if (returned && typeof returned.then === "function") {
1326
- returned.then(undefined, () => {});
1327
- }
1443
+ if (isThenable(returned)) returned.then(undefined, () => {});
1328
1444
  } catch {}
1329
1445
  });
1330
1446
  const iterate = () => {
@@ -1374,7 +1490,8 @@ function clearStatus(el, clearUninitialized = false) {
1374
1490
  if (el._blocked) el._blocked = false;
1375
1491
  el._statusFlags = clearUninitialized ? 0 : el._statusFlags & STATUS_UNINITIALIZED;
1376
1492
  if (el._error) setPendingError(el);
1377
- if (el._pendingSignal) updatePendingSignal(el);
1493
+ if (el._pendingSignal || el._latestValueComputed) updatePendingSignal(el);
1494
+ if (el._child) updateChildCompanions(el);
1378
1495
  if (el._notifyStatus) el._notifyStatus();
1379
1496
  }
1380
1497
  function notifyStatus(el, status, error, blockStatus, lane) {
@@ -1402,6 +1519,7 @@ function notifyStatus(el, status, error, blockStatus, lane) {
1402
1519
  el._error = error;
1403
1520
  }
1404
1521
  updatePendingSignal(el);
1522
+ if (el._child) updateChildCompanions(el);
1405
1523
  }
1406
1524
  if (lane && !blockStatus) {
1407
1525
  assignOrMergeLane(el, lane);
@@ -1419,7 +1537,7 @@ function notifyStatus(el, status, error, blockStatus, lane) {
1419
1537
  }
1420
1538
  return;
1421
1539
  }
1422
- forEachDependent(el, sub => {
1540
+ forEachDependent(el, (sub, link) => {
1423
1541
  sub._time = clock;
1424
1542
  if (
1425
1543
  (status === STATUS_PENDING &&
@@ -1429,6 +1547,11 @@ function notifyStatus(el, status, error, blockStatus, lane) {
1429
1547
  (status !== STATUS_PENDING &&
1430
1548
  (sub._error !== error || sub._pendingSource || sub._pendingSources))
1431
1549
  ) {
1550
+ if (link._pendingObserver && status !== STATUS_PENDING && !(error instanceof NotReadyError)) {
1551
+ enqueueForRerun(sub);
1552
+ schedule();
1553
+ return;
1554
+ }
1432
1555
  if (!downstreamBlockStatus && !sub._transition) queuePendingNode(sub);
1433
1556
  notifyStatus(sub, status, error, downstreamBlockStatus, downstreamLane);
1434
1557
  }
@@ -1461,15 +1584,19 @@ GlobalQueue._update = recompute;
1461
1584
  GlobalQueue._dispose = disposeChildren;
1462
1585
  const PRIMITIVE_IN_FORBIDDEN_SCOPE_MESSAGE =
1463
1586
  "[PRIMITIVE_IN_FORBIDDEN_SCOPE] Cannot create reactive primitives inside createTrackedEffect or owner-backed onSettled";
1587
+ const REACTIVE_WRITE_IN_OWNED_SCOPE_SIGNAL_MESSAGE =
1588
+ "[REACTIVE_WRITE_IN_OWNED_SCOPE] Writing to reactive state inside an owned scope (component, computation) is not allowed. " +
1589
+ "Move the write outside or set the `ownedWrite` option if this is intentional.";
1590
+ const REACTIVE_WRITE_IN_OWNED_SCOPE_REFRESH_MESSAGE =
1591
+ "[REACTIVE_WRITE_IN_OWNED_SCOPE] Calling refresh() inside an owned scope (component, computation) is not allowed. " +
1592
+ "Move the invalidation outside pure computation.";
1464
1593
  let tracking = false;
1465
1594
  let stale = false;
1466
- let refreshing = false;
1467
1595
  let pendingCheckActive = false;
1468
- let foundPending = false;
1469
1596
  let latestReadActive = false;
1470
1597
  let context = null;
1471
1598
  let currentOptimisticLane = null;
1472
- let pendingCheckSources = null;
1599
+ let pendingProbe = null;
1473
1600
  let snapshotCaptureActive = false;
1474
1601
  let snapshotSources = null;
1475
1602
  function ownerInSnapshotScope(owner) {
@@ -1542,11 +1669,12 @@ function recompute(el, create = false) {
1542
1669
  }
1543
1670
  let isOptimisticDirty = !!(el._flags & REACTIVE_OPTIMISTIC_DIRTY);
1544
1671
  const hasOverride = el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING;
1545
- const wasPending = !!(el._statusFlags & STATUS_PENDING);
1672
+ !!(el._statusFlags & STATUS_PENDING);
1546
1673
  const wasUninitialized = !!(el._statusFlags & STATUS_UNINITIALIZED);
1547
1674
  const oldcontext = context;
1548
1675
  context = el;
1549
1676
  el._depsTail = null;
1677
+ el._depGen++;
1550
1678
  el._flags = REACTIVE_RECOMPUTING_DEPS;
1551
1679
  el._time = clock;
1552
1680
  let value = el._pendingValue === NOT_PENDING ? el._value : el._pendingValue;
@@ -1629,26 +1757,35 @@ function recompute(el, create = false) {
1629
1757
  : el._pendingValue === NOT_PENDING
1630
1758
  ? el._value
1631
1759
  : el._pendingValue;
1632
- const valueChanged =
1633
- (!isEffect && wasUninitialized) || !el._equals || !el._equals(compareValue, value);
1760
+ let valueChanged = false;
1761
+ try {
1762
+ valueChanged =
1763
+ (!isEffect && wasUninitialized) || !el._equals || !el._equals(compareValue, value);
1764
+ } catch (e) {
1765
+ notifyStatus(el, STATUS_ERROR, e);
1766
+ }
1634
1767
  if (isEffect && valueChanged) {
1635
1768
  el._modified = !el._error;
1636
- if (!create) el._queue.enqueue(isEffect, GlobalQueue._runEffect.bind(null, el));
1769
+ if (!create)
1770
+ el._queue.enqueue(isEffect, (el._boundRunEffect ??= GlobalQueue._runEffect.bind(null, el)));
1637
1771
  }
1638
- if (valueChanged) {
1772
+ if (el._error);
1773
+ else if (valueChanged) {
1639
1774
  const prevVisible = hasOverride ? el._overrideValue : undefined;
1640
1775
  if (create || (isEffect && activeTransition !== el._transition) || isOptimisticDirty) {
1641
1776
  el._value = value;
1642
1777
  if (hasOverride && isOptimisticDirty) {
1643
1778
  el._overrideValue = value;
1644
- el._pendingValue = value;
1779
+ el._pendingValue = NOT_PENDING;
1645
1780
  }
1646
- } else el._pendingValue = value;
1647
- if (hasOverride && !isOptimisticDirty && wasPending && !el._overrideSinceLane)
1648
- el._overrideValue = value;
1781
+ } else {
1782
+ el._pendingValue = value;
1783
+ if (activeTransition || el._transition) syncCompanions(el, value);
1784
+ }
1649
1785
  if (!hasOverride || isOptimisticDirty || el._overrideValue !== prevVisible)
1650
1786
  insertSubs(el, isOptimisticDirty || hasOverride);
1651
1787
  } else if (hasOverride) {
1788
+ if (el._pendingValue === NOT_PENDING) queuePendingNode(el);
1652
1789
  el._pendingValue = value;
1653
1790
  } else if (el._height != oldHeight) {
1654
1791
  for (let s = el._subs; s !== null; s = s._nextSub) {
@@ -1664,8 +1801,7 @@ function recompute(el, create = false) {
1664
1801
  !!(el._statusFlags & (STATUS_PENDING | STATUS_UNINITIALIZED));
1665
1802
  needsPendingCommit &&
1666
1803
  (!create || el._statusFlags & STATUS_PENDING) &&
1667
- !el._transition &&
1668
- !(activeTransition && hasOverride) &&
1804
+ (!el._transition || hasOverride) &&
1669
1805
  queuePendingNode(el);
1670
1806
  el._transition &&
1671
1807
  isEffect &&
@@ -1704,6 +1840,7 @@ function computed(fn, options) {
1704
1840
  (options?.ownedWrite ? CONFIG_OWNED_WRITE : 0) |
1705
1841
  (!context || options?.lazy ? CONFIG_AUTO_DISPOSE : 0) |
1706
1842
  (options?.sync ? CONFIG_SYNC : 0) |
1843
+ (options?._noSnapshot ? CONFIG_NO_SNAPSHOT : 0) |
1707
1844
  (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
1708
1845
  _equals: options?.equals != null ? options.equals : isEqual,
1709
1846
  _unobserved: options?.unobserved,
@@ -1719,6 +1856,7 @@ function computed(fn, options) {
1719
1856
  _prevHeap: null,
1720
1857
  _deps: null,
1721
1858
  _depsTail: null,
1859
+ _depGen: 0,
1722
1860
  _subs: null,
1723
1861
  _subsTail: null,
1724
1862
  _parent: context,
@@ -1763,6 +1901,7 @@ function createEffectNode(fn, effectFn, errorFn, type, notifyStatus, options) {
1763
1901
  _prevHeap: null,
1764
1902
  _deps: null,
1765
1903
  _depsTail: null,
1904
+ _depGen: 0,
1766
1905
  _subs: null,
1767
1906
  _subsTail: null,
1768
1907
  _parent: context,
@@ -1782,7 +1921,6 @@ function createEffectNode(fn, effectFn, errorFn, type, notifyStatus, options) {
1782
1921
  _effectFn: effectFn,
1783
1922
  _errorFn: errorFn,
1784
1923
  _cleanup: undefined,
1785
- _cleanupRegistered: false,
1786
1924
  _type: type,
1787
1925
  _notifyStatus: notifyStatus
1788
1926
  };
@@ -1830,7 +1968,7 @@ function setupComputedNode(self, options) {
1830
1968
  }
1831
1969
  !options?.lazy && recompute(self, true);
1832
1970
  if (snapshotCaptureActive && !options?.lazy) {
1833
- if (!(self._statusFlags & STATUS_PENDING)) {
1971
+ if (!(self._statusFlags & STATUS_PENDING) && !(self._config & CONFIG_NO_SNAPSHOT)) {
1834
1972
  self._snapshotValue = self._value === undefined ? NO_SNAPSHOT : self._value;
1835
1973
  snapshotSources.add(self);
1836
1974
  }
@@ -1899,6 +2037,16 @@ function untrack(fn, strictReadLabel) {
1899
2037
  strictRead = prevStrictRead;
1900
2038
  }
1901
2039
  }
2040
+ function prepareComputed(comp, refresh) {
2041
+ if (comp._flags & REACTIVE_LAZY) {
2042
+ comp._flags &= ~REACTIVE_LAZY;
2043
+ recompute(comp, true);
2044
+ } else if (comp._flags & REACTIVE_DISPOSED) {
2045
+ recompute(comp, true);
2046
+ } else if (refresh) {
2047
+ updateIfNecessary(comp);
2048
+ }
2049
+ }
1902
2050
  function read(el) {
1903
2051
  if (latestReadActive) {
1904
2052
  const pendingComputed = getLatestValueComputed(el);
@@ -1912,7 +2060,8 @@ function read(el) {
1912
2060
  try {
1913
2061
  value = read(pendingComputed);
1914
2062
  } catch (e) {
1915
- if (!context && e instanceof NotReadyError) return visibleValue;
2063
+ if (e instanceof NotReadyError && (!context || !(el._statusFlags & STATUS_UNINITIALIZED)))
2064
+ return visibleValue;
1916
2065
  throw e;
1917
2066
  } finally {
1918
2067
  latestReadActive = prevPending;
@@ -1927,59 +2076,25 @@ function read(el) {
1927
2076
  }
1928
2077
  return value;
1929
2078
  }
2079
+ let c = context;
2080
+ if (c?._root) c = c._parentComputed;
2081
+ const computed = el;
2082
+ const firewall = el._firewall;
2083
+ const owner = firewall || el;
1930
2084
  if (pendingCheckActive) {
1931
- const firewall = el._firewall;
1932
- const prevCheck = pendingCheckActive;
1933
2085
  pendingCheckActive = false;
1934
- let c = context;
1935
- if (c?._root) c = c._parentComputed;
1936
- const owner = firewall || el;
1937
- const pendingComputed = el;
1938
- if (typeof pendingComputed._fn === "function") {
1939
- const comp = el;
1940
- if (comp._flags & REACTIVE_LAZY) {
1941
- comp._flags &= ~REACTIVE_LAZY;
1942
- recompute(comp, true);
1943
- } else if (comp._flags & REACTIVE_DISPOSED) {
1944
- recompute(comp, true);
1945
- } else {
1946
- updateIfNecessary(comp);
1947
- }
1948
- }
2086
+ if (typeof computed._fn === "function") prepareComputed(el, true);
1949
2087
  if (c && owner._statusFlags & STATUS_PENDING && owner._statusFlags & STATUS_UNINITIALIZED) {
1950
2088
  if (tracking && el !== c) link(el, c);
1951
- pendingCheckActive = prevCheck;
2089
+ pendingCheckActive = true;
1952
2090
  throw owner._error;
1953
2091
  }
1954
- if (firewall && el._overrideValue !== undefined) {
1955
- if (
1956
- el._overrideValue !== NOT_PENDING &&
1957
- (firewall._inFlight || !!(firewall._statusFlags & STATUS_PENDING))
1958
- ) {
1959
- foundPending = true;
1960
- }
1961
- collectPendingSources(el);
1962
- collectPendingSources(firewall);
1963
- if (c && tracking) link(el, c);
1964
- } else {
1965
- collectPendingSources(el);
1966
- if (firewall) collectPendingSources(firewall);
1967
- }
1968
- pendingCheckActive = prevCheck;
2092
+ collectPendingSources(el);
2093
+ if (firewall) collectPendingSources(firewall);
2094
+ pendingCheckActive = true;
2095
+ } else if (typeof computed._fn === "function") {
2096
+ prepareComputed(el, false);
1969
2097
  }
1970
- let c = context;
1971
- if (c?._root) c = c._parentComputed;
1972
- const computed = el;
1973
- if (typeof computed._fn === "function") {
1974
- const comp = el;
1975
- if (comp._flags & REACTIVE_LAZY) {
1976
- comp._flags &= ~REACTIVE_LAZY;
1977
- recompute(comp, true);
1978
- } else if (comp._flags & REACTIVE_DISPOSED) {
1979
- recompute(comp, true);
1980
- }
1981
- }
1982
- const owner = el._firewall || el;
1983
2098
  if (
1984
2099
  !computed._fn &&
1985
2100
  owner === el &&
@@ -2010,7 +2125,7 @@ function read(el) {
2010
2125
  throw new Error(message);
2011
2126
  }
2012
2127
  if (c && tracking) {
2013
- link(el, c);
2128
+ link(el, c, pendingCheckActive);
2014
2129
  if (owner._fn) {
2015
2130
  const isZombie = el._flags & REACTIVE_ZOMBIE;
2016
2131
  if (owner._height >= (isZombie ? zombieQueue._min : dirtyQueue._min)) {
@@ -2060,7 +2175,7 @@ function read(el) {
2060
2175
  }
2061
2176
  }
2062
2177
  if (el._fn && el._statusFlags & STATUS_ERROR) {
2063
- if (el._time < clock) {
2178
+ if (tracking && !pendingCheckActive && el._time < clock) {
2064
2179
  recompute(el);
2065
2180
  return read(el);
2066
2181
  } else throw el._error;
@@ -2099,7 +2214,7 @@ function read(el) {
2099
2214
  currentOptimisticLane !== null &&
2100
2215
  !latestReadActive &&
2101
2216
  el._pendingValue !== NOT_PENDING &&
2102
- owner === el &&
2217
+ (owner === el || !!(owner._flags & REACTIVE_MANUAL_WRITE)) &&
2103
2218
  !el._fn &&
2104
2219
  c
2105
2220
  ) {
@@ -2111,12 +2226,19 @@ function read(el) {
2111
2226
  (currentOptimisticLane !== null &&
2112
2227
  (el._overrideValue !== undefined ||
2113
2228
  el._optimisticLane ||
2114
- (owner === el && stale) ||
2229
+ (owner === el && stale && c._parentSource !== el) ||
2115
2230
  !!(owner._statusFlags & STATUS_PENDING))) ||
2116
2231
  el._pendingValue === NOT_PENDING ||
2117
2232
  (stale && el._transition && activeTransition !== el._transition)
2118
2233
  ? el._value
2119
2234
  : el._pendingValue;
2235
+ if (
2236
+ pendingCheckActive &&
2237
+ pendingProbe !== null &&
2238
+ el._pendingValue !== NOT_PENDING &&
2239
+ value === el._pendingValue
2240
+ )
2241
+ pendingProbe.freshReads.add(el);
2120
2242
  if (
2121
2243
  !c &&
2122
2244
  owner === el &&
@@ -2136,19 +2258,17 @@ function setSignal(el, v) {
2136
2258
  context &&
2137
2259
  el._firewall !== context
2138
2260
  ) {
2139
- const message =
2140
- "[SIGNAL_WRITE_IN_OWNED_SCOPE] Writing to a Signal inside an owned scope (component, computation) is not allowed. " +
2141
- "Move the write outside or set the `ownedWrite` option if this is intentional.";
2142
2261
  emitDiagnostic({
2143
- code: "SIGNAL_WRITE_IN_OWNED_SCOPE",
2262
+ code: "REACTIVE_WRITE_IN_OWNED_SCOPE",
2144
2263
  kind: "write",
2145
2264
  severity: "error",
2146
- message: message,
2265
+ message: REACTIVE_WRITE_IN_OWNED_SCOPE_SIGNAL_MESSAGE,
2147
2266
  ownerId: context.id,
2148
2267
  ownerName: context._name,
2149
- nodeName: el._name
2268
+ nodeName: el._name,
2269
+ data: { operation: "setSignal" }
2150
2270
  });
2151
- throw new Error(message);
2271
+ throw new Error(REACTIVE_WRITE_IN_OWNED_SCOPE_SIGNAL_MESSAGE);
2152
2272
  }
2153
2273
  if (el._transition && activeTransition !== el._transition)
2154
2274
  globalQueue.initTransition(el._transition);
@@ -2163,22 +2283,18 @@ function setSignal(el, v) {
2163
2283
  : el._pendingValue;
2164
2284
  if (typeof v === "function") v = v(currentValue);
2165
2285
  const valueChanged =
2166
- !el._equals || !el._equals(currentValue, v) || !!(el._statusFlags & STATUS_UNINITIALIZED);
2286
+ !!(el._statusFlags & STATUS_UNINITIALIZED) || !el._equals || !el._equals(currentValue, v);
2167
2287
  if (!valueChanged) {
2168
- if (isOptimistic && hasOverride && el._fn) {
2169
- insertSubs(el, true);
2170
- schedule();
2288
+ if (isOptimistic && hasOverride) {
2289
+ const transition = resolveTransition(el);
2290
+ if (transition && activeTransition !== transition) globalQueue.initTransition(transition);
2171
2291
  }
2172
2292
  return v;
2173
2293
  }
2174
2294
  if (isOptimistic) {
2175
2295
  const firstOverride = el._overrideValue === NOT_PENDING;
2176
2296
  if (!firstOverride) globalQueue.initTransition(resolveTransition(el));
2177
- if (firstOverride) {
2178
- el._pendingValue = el._value;
2179
- globalQueue._optimisticNodes.push(el);
2180
- }
2181
- el._overrideSinceLane = true;
2297
+ if (firstOverride) globalQueue._optimisticNodes.push(el);
2182
2298
  const lane = getOrCreateLane(el);
2183
2299
  el._optimisticLane = lane;
2184
2300
  el._overrideValue = v;
@@ -2186,10 +2302,7 @@ function setSignal(el, v) {
2186
2302
  if (el._pendingValue === NOT_PENDING) queuePendingNode(el);
2187
2303
  el._pendingValue = v;
2188
2304
  }
2189
- if (el._pendingSignal) updatePendingSignal(el);
2190
- if (el._latestValueComputed) {
2191
- setSignal(el._latestValueComputed, v);
2192
- }
2305
+ syncCompanions(el, v);
2193
2306
  el._time = clock;
2194
2307
  insertSubs(el, isOptimistic);
2195
2308
  schedule();
@@ -2197,8 +2310,10 @@ function setSignal(el, v) {
2197
2310
  }
2198
2311
  function suppressComputedRecompute(el) {
2199
2312
  deleteFromHeap(el, el._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
2200
- if (!(el._flags & REACTIVE_MANUAL_WRITE) && el._pendingValue === NOT_PENDING)
2313
+ if (!(el._flags & REACTIVE_MANUAL_WRITE) && el._pendingValue === NOT_PENDING) {
2201
2314
  queuePendingNode(el);
2315
+ schedule();
2316
+ }
2202
2317
  el._flags = (el._flags & -4) | REACTIVE_MANUAL_WRITE;
2203
2318
  }
2204
2319
  function setMemo(el, v) {
@@ -2234,61 +2349,82 @@ function runWithOwner(owner, fn) {
2234
2349
  function getPendingSignal(el) {
2235
2350
  if (!el._pendingSignal) {
2236
2351
  el._pendingSignal = optimisticSignal(false, { ownedWrite: true });
2237
- if (el._parentSource) {
2238
- el._pendingSignal._parentSource = el;
2239
- }
2352
+ el._pendingSignal._parentSource = el;
2240
2353
  if (computePendingState(el)) setSignal(el._pendingSignal, true);
2241
2354
  }
2242
2355
  return el._pendingSignal;
2243
2356
  }
2244
2357
  function collectPendingSources(el) {
2245
- pendingCheckSources?.add(el);
2358
+ if (!pendingProbe) return;
2359
+ pendingProbe.sources.add(el);
2246
2360
  const owner = el._firewall || el;
2247
- if (owner !== el) pendingCheckSources?.add(owner);
2361
+ if (owner !== el) pendingProbe.sources.add(owner);
2248
2362
  }
2249
2363
  function computePendingState(el) {
2250
2364
  const comp = el;
2365
+ if (comp._flags & REACTIVE_DISPOSED) return false;
2251
2366
  const firewall = el._firewall;
2367
+ if ((firewall || comp)._optimisticMask) return false;
2252
2368
  if (el._parentSource) {
2253
- const parent = el._parentSource;
2254
- if (parent._statusFlags & STATUS_PENDING && !(parent._statusFlags & STATUS_UNINITIALIZED))
2255
- return true;
2256
- return el._pendingValue !== NOT_PENDING && !(comp._statusFlags & STATUS_UNINITIALIZED);
2369
+ const parentNode = el._parentSource;
2370
+ if (hasActiveOverride(parentNode)) return false;
2371
+ const parent = parentNode._firewall || parentNode;
2372
+ if (parent._optimisticMask) return false;
2373
+ return !!(
2374
+ parent._statusFlags & STATUS_PENDING && !(parent._statusFlags & STATUS_UNINITIALIZED)
2375
+ );
2257
2376
  }
2377
+ if (hasActiveOverride(el)) return false;
2258
2378
  if (firewall && el._pendingValue !== NOT_PENDING) {
2259
- return !firewall._inFlight && !(firewall._statusFlags & STATUS_PENDING);
2260
- }
2261
- if (el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING) {
2262
- if (comp._statusFlags & STATUS_PENDING && !(comp._statusFlags & STATUS_UNINITIALIZED))
2263
- return true;
2264
- if (el._parentSource) {
2265
- const lane = el._optimisticLane ? findLane(el._optimisticLane) : null;
2266
- return !!(lane && lane._pendingAsync.size > 0);
2267
- }
2268
- return true;
2269
- }
2270
- if (el._overrideValue !== undefined && el._overrideValue === NOT_PENDING && !el._parentSource) {
2271
- return false;
2379
+ return (
2380
+ !!(firewall._flags & REACTIVE_MANUAL_WRITE) ||
2381
+ (!firewall._inFlight && !(firewall._statusFlags & STATUS_PENDING))
2382
+ );
2272
2383
  }
2273
2384
  if (el._pendingValue !== NOT_PENDING && !(comp._statusFlags & STATUS_UNINITIALIZED)) return true;
2274
2385
  return !!(comp._statusFlags & STATUS_PENDING && !(comp._statusFlags & STATUS_UNINITIALIZED));
2275
2386
  }
2387
+ function syncCompanions(el, value) {
2388
+ if (el._pendingSignal) updatePendingSignal(el);
2389
+ if (el._latestValueComputed) setSignal(el._latestValueComputed, value);
2390
+ }
2276
2391
  function updatePendingSignal(el) {
2277
2392
  if (el._pendingSignal) {
2278
- const pending = computePendingState(el);
2279
- const sig = el._pendingSignal;
2280
- setSignal(sig, pending);
2281
- if (!pending && sig._optimisticLane) {
2282
- const sourceLane = resolveLane(el);
2283
- if (sourceLane && sourceLane._pendingAsync.size > 0) {
2284
- const sigLane = findLane(sig._optimisticLane);
2285
- if (sigLane !== sourceLane) {
2286
- mergeLanes(sourceLane, sigLane);
2287
- }
2288
- }
2289
- signalLanes.delete(sig);
2290
- sig._optimisticLane = undefined;
2393
+ setSignal(el._pendingSignal, computePendingState(el));
2394
+ }
2395
+ if (el._latestValueComputed) updatePendingSignal(el._latestValueComputed);
2396
+ }
2397
+ function updateChildCompanions(el) {
2398
+ for (let child = el._child; child !== null; child = child._nextChild) {
2399
+ if (child._pendingSignal || child._latestValueComputed) updatePendingSignal(child);
2400
+ }
2401
+ }
2402
+ function snapCompanionsToState(owner) {
2403
+ const sig = owner._pendingSignal;
2404
+ if (sig && (sig._overrideValue === undefined || sig._overrideValue === NOT_PENDING)) {
2405
+ const pending = computePendingState(owner);
2406
+ if (sig._value !== pending || sig._pendingValue !== NOT_PENDING) {
2407
+ sig._value = pending;
2408
+ sig._pendingValue = NOT_PENDING;
2409
+ sig._time = clock;
2410
+ insertSubs(sig);
2411
+ schedule();
2412
+ }
2413
+ }
2414
+ const shadow = owner._latestValueComputed;
2415
+ if (shadow && !(shadow._flags & REACTIVE_DISPOSED)) {
2416
+ if (
2417
+ (shadow._overrideValue === undefined || shadow._overrideValue === NOT_PENDING) &&
2418
+ shadow._pendingValue === NOT_PENDING &&
2419
+ !Object.is(shadow._value, owner._value) &&
2420
+ !(shadow._flags & (REACTIVE_DIRTY | REACTIVE_CHECK))
2421
+ ) {
2422
+ shadow._flags |= REACTIVE_DIRTY;
2423
+ insertIntoHeap(shadow, shadow._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
2424
+ insertSubs(shadow);
2425
+ schedule();
2291
2426
  }
2427
+ snapCompanionsToState(shadow);
2292
2428
  }
2293
2429
  }
2294
2430
  function getLatestValueComputed(el) {
@@ -2327,18 +2463,16 @@ function latest(fn) {
2327
2463
  }
2328
2464
  function isPending(fn) {
2329
2465
  const prevPendingCheck = pendingCheckActive;
2330
- const prevFoundPending = foundPending;
2331
- const prevPendingCheckSources = pendingCheckSources;
2466
+ const prevProbe = pendingProbe;
2332
2467
  pendingCheckActive = true;
2333
- foundPending = false;
2334
- pendingCheckSources = new Set();
2468
+ const probe = (pendingProbe = { found: false, sources: new Set(), freshReads: new Set() });
2335
2469
  const collectPending = () => {
2336
2470
  pendingCheckActive = false;
2337
2471
  const prevStrictRead = strictRead;
2338
2472
  strictRead = false;
2339
2473
  try {
2340
- pendingCheckSources.forEach(source => {
2341
- if (read(getPendingSignal(source))) foundPending = true;
2474
+ probe.sources.forEach(source => {
2475
+ if (read(getPendingSignal(source)) && !probe.freshReads.has(source)) probe.found = true;
2342
2476
  });
2343
2477
  } finally {
2344
2478
  strictRead = prevStrictRead;
@@ -2348,26 +2482,23 @@ function isPending(fn) {
2348
2482
  try {
2349
2483
  fn();
2350
2484
  collectPending();
2351
- return foundPending;
2485
+ return probe.found;
2352
2486
  } catch (e) {
2353
2487
  collectPending();
2354
2488
  if (e instanceof NotReadyError) {
2355
- if (foundPending && !(e.source?._statusFlags & STATUS_UNINITIALIZED)) return true;
2489
+ if (probe.found && !(e.source?._statusFlags & STATUS_UNINITIALIZED)) return true;
2356
2490
  if (context) throw e;
2357
2491
  }
2358
- return foundPending;
2492
+ return probe.found;
2359
2493
  } finally {
2360
2494
  pendingCheckActive = prevPendingCheck;
2361
- foundPending = prevFoundPending;
2362
- pendingCheckSources = prevPendingCheckSources;
2495
+ pendingProbe = prevProbe;
2363
2496
  }
2364
2497
  }
2365
2498
  function refresh(target) {
2366
- let prevRefreshing = refreshing;
2367
- refreshing = true;
2368
- try {
2369
- const node = target?.[$REFRESH];
2370
- if (true && !node) {
2499
+ const node = target?.[$REFRESH];
2500
+ if (!node) {
2501
+ {
2371
2502
  const message =
2372
2503
  "[INVALID_REFRESH_TARGET] refresh() expects a Solid source accessor or refreshable store. " +
2373
2504
  "Pass the original source target, not a wrapper function or derived property read.";
@@ -2379,18 +2510,32 @@ function refresh(target) {
2379
2510
  });
2380
2511
  throw new Error(message);
2381
2512
  }
2382
- if (node && typeof node._fn === "function" && !(node._flags & REACTIVE_DISPOSED)) {
2383
- recompute(node);
2384
- }
2385
- } finally {
2386
- refreshing = prevRefreshing;
2387
- if (!prevRefreshing) {
2388
- schedule();
2389
- }
2390
2513
  }
2391
- }
2392
- function isRefreshing() {
2393
- return refreshing;
2514
+ if (
2515
+ context &&
2516
+ !((node._config ?? 0) & CONFIG_OWNED_WRITE) &&
2517
+ !(context._config & CONFIG_CHILDREN_FORBIDDEN)
2518
+ ) {
2519
+ emitDiagnostic({
2520
+ code: "REACTIVE_WRITE_IN_OWNED_SCOPE",
2521
+ kind: "write",
2522
+ severity: "error",
2523
+ message: REACTIVE_WRITE_IN_OWNED_SCOPE_REFRESH_MESSAGE,
2524
+ ownerId: context.id,
2525
+ ownerName: context._name,
2526
+ nodeName: node._name,
2527
+ data: { operation: "refresh" }
2528
+ });
2529
+ throw new Error(REACTIVE_WRITE_IN_OWNED_SCOPE_REFRESH_MESSAGE);
2530
+ }
2531
+ if (
2532
+ typeof node._fn === "function" &&
2533
+ !(node._flags & (REACTIVE_DISPOSED | REACTIVE_MANUAL_WRITE))
2534
+ ) {
2535
+ node._flags = (node._flags & ~REACTIVE_CHECK) | REACTIVE_DIRTY;
2536
+ insertIntoHeap(node, node._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
2537
+ schedule();
2538
+ }
2394
2539
  }
2395
2540
  function createContext(defaultValue, description) {
2396
2541
  return { id: Symbol(description), defaultValue: defaultValue };
@@ -2454,50 +2599,67 @@ function notifyEffectStatus(status, error) {
2454
2599
  const actualStatus = status !== undefined ? status : this._statusFlags;
2455
2600
  const actualError = error !== undefined ? error : this._error;
2456
2601
  if (actualStatus & STATUS_ERROR) {
2457
- let err = actualError;
2458
2602
  this._queue.notify(this, STATUS_PENDING, 0);
2459
2603
  if (this._type === EFFECT_USER) {
2460
- try {
2461
- return this._errorFn
2462
- ? this._errorFn(err, () => {
2463
- this._cleanup?.();
2464
- this._cleanup = undefined;
2465
- })
2466
- : console.error(err);
2467
- } catch (e) {
2468
- err = e;
2604
+ if (this._statusFlags & STATUS_ERROR) {
2605
+ this._modified = true;
2606
+ this._queue.enqueue(this._type, (this._boundRunEffect ??= runEffect.bind(null, this)));
2469
2607
  }
2608
+ return;
2609
+ }
2610
+ if (!this._queue.notify(this, STATUS_ERROR, STATUS_ERROR)) {
2611
+ haltReactivity();
2612
+ throw actualError;
2470
2613
  }
2471
- if (!this._queue.notify(this, STATUS_ERROR, STATUS_ERROR)) throw err;
2472
2614
  } else if (this._type === EFFECT_RENDER) {
2473
2615
  this._queue.notify(this, STATUS_PENDING | STATUS_ERROR, actualStatus, actualError);
2474
2616
  if (_hitUnhandledAsync) {
2475
2617
  resetUnhandledAsync();
2476
- if (!this._queue.notify(this, STATUS_ERROR, STATUS_ERROR)) {
2477
- const message =
2478
- "[ASYNC_OUTSIDE_LOADING_BOUNDARY] An async value was read outside a Loading boundary. The root mount will be deferred until all pending async settles.";
2479
- emitDiagnostic({
2480
- code: "ASYNC_OUTSIDE_LOADING_BOUNDARY",
2481
- kind: "async",
2482
- severity: "warn",
2483
- message: message,
2484
- ownerId: this.id,
2485
- ownerName: this._name
2486
- });
2487
- console.warn(message);
2488
- }
2618
+ const message =
2619
+ "[ASYNC_OUTSIDE_LOADING_BOUNDARY] An async value was read outside a Loading boundary. The root mount will be deferred until all pending async settles.";
2620
+ emitDiagnostic({
2621
+ code: "ASYNC_OUTSIDE_LOADING_BOUNDARY",
2622
+ kind: "async",
2623
+ severity: "warn",
2624
+ message: message,
2625
+ ownerId: this.id,
2626
+ ownerName: this._name
2627
+ });
2628
+ console.warn(message);
2489
2629
  }
2490
2630
  }
2491
2631
  }
2492
2632
  function runEffect(node) {
2493
2633
  if (!node._modified || node._flags & REACTIVE_DISPOSED) return;
2634
+ if (node._statusFlags & STATUS_ERROR && node._type === EFFECT_USER) {
2635
+ const err =
2636
+ node._error instanceof StatusError ? (node._error.cause ?? node._error) : node._error;
2637
+ node._prevValue = node._value;
2638
+ node._modified = false;
2639
+ try {
2640
+ node._errorFn
2641
+ ? node._errorFn(err, () => {
2642
+ const prevCleanup = node._cleanup;
2643
+ node._cleanup = undefined;
2644
+ prevCleanup?.();
2645
+ })
2646
+ : console.error(err);
2647
+ } catch (error) {
2648
+ if (!node._queue.notify(node, STATUS_ERROR, STATUS_ERROR)) {
2649
+ haltReactivity();
2650
+ throw error;
2651
+ }
2652
+ }
2653
+ return;
2654
+ }
2494
2655
  let prevStrictRead = false;
2495
2656
  {
2496
2657
  prevStrictRead = setStrictRead("an effect callback");
2497
2658
  }
2498
- node._cleanup?.();
2659
+ const prevCleanup = node._cleanup;
2499
2660
  node._cleanup = undefined;
2500
2661
  try {
2662
+ prevCleanup?.();
2501
2663
  const nextCleanup = node._effectFn(node._value, node._prevValue);
2502
2664
  if (true && nextCleanup !== undefined && typeof nextCleanup !== "function") {
2503
2665
  throw new Error(
@@ -2505,14 +2667,13 @@ function runEffect(node) {
2505
2667
  );
2506
2668
  }
2507
2669
  node._cleanup = nextCleanup;
2508
- if (node._cleanup && !node._cleanupRegistered) {
2509
- node._cleanupRegistered = true;
2510
- runWithOwner(node._parent, () => cleanup(() => node._cleanup?.()));
2511
- }
2512
2670
  } catch (error) {
2513
2671
  node._error = new StatusError(node, error);
2514
2672
  node._statusFlags |= STATUS_ERROR;
2515
- if (!node._queue.notify(node, STATUS_ERROR, STATUS_ERROR)) throw error;
2673
+ if (!node._queue.notify(node, STATUS_ERROR, STATUS_ERROR)) {
2674
+ haltReactivity();
2675
+ throw error;
2676
+ }
2516
2677
  } finally {
2517
2678
  setStrictRead(prevStrictRead);
2518
2679
  node._prevValue = node._value;
@@ -2533,8 +2694,9 @@ function trackedEffect(fn, options) {
2533
2694
  };
2534
2695
  const node = computed(
2535
2696
  () => {
2536
- node._cleanup?.();
2697
+ const prevCleanup = node._cleanup;
2537
2698
  node._cleanup = undefined;
2699
+ prevCleanup?.();
2538
2700
  const cleanup = staleValues(fn);
2539
2701
  if (cleanup !== undefined && typeof cleanup !== "function") {
2540
2702
  throw new Error(
@@ -2554,12 +2716,14 @@ function trackedEffect(fn, options) {
2554
2716
  if (actualStatus & STATUS_ERROR) {
2555
2717
  node._queue.notify(node, STATUS_PENDING, 0);
2556
2718
  const err = error !== undefined ? error : node._error;
2557
- if (!node._queue.notify(node, STATUS_ERROR, STATUS_ERROR)) throw err;
2719
+ if (!node._queue.notify(node, STATUS_ERROR, STATUS_ERROR)) {
2720
+ haltReactivity();
2721
+ throw err;
2722
+ }
2558
2723
  }
2559
2724
  };
2560
2725
  node._run = run;
2561
2726
  node._queue.enqueue(EFFECT_USER, run);
2562
- cleanup(() => node._cleanup?.());
2563
2727
  if (!node._parent) {
2564
2728
  const message =
2565
2729
  "[NO_OWNER_EFFECT] Effects created outside a reactive context will never be disposed";
@@ -2603,13 +2767,12 @@ function action(genFn) {
2603
2767
  } catch (e) {
2604
2768
  return done(undefined, e);
2605
2769
  }
2606
- if (r instanceof Promise)
2607
- return void r.then(run, e => restoreTransition(ctx, () => step(e, true)));
2770
+ if (isThenable(r)) return void r.then(run, e => done(undefined, e));
2608
2771
  run(r);
2609
2772
  };
2610
2773
  const run = r => {
2611
2774
  if (r.done) return done(r.value);
2612
- if (r.value instanceof Promise)
2775
+ if (isThenable(r.value))
2613
2776
  return void r.value.then(
2614
2777
  v => restoreTransition(ctx, () => step(v)),
2615
2778
  e => restoreTransition(ctx, () => step(e, true))
@@ -2729,15 +2892,18 @@ function resolve(fn) {
2729
2892
  }
2730
2893
  return new Promise((res, rej) => {
2731
2894
  createRoot(dispose => {
2732
- computed(() => {
2733
- try {
2734
- res(fn());
2735
- } catch (err) {
2736
- if (err instanceof NotReadyError) throw err;
2895
+ effect(
2896
+ fn,
2897
+ value => {
2898
+ res(value);
2899
+ dispose();
2900
+ },
2901
+ err => {
2737
2902
  rej(err);
2738
- }
2739
- dispose();
2740
- });
2903
+ dispose();
2904
+ },
2905
+ { user: true }
2906
+ );
2741
2907
  });
2742
2908
  });
2743
2909
  }
@@ -2757,27 +2923,110 @@ function onSettled(callback) {
2757
2923
  ? createTrackedEffect(() => untrack(callback), { name: "onSettled" })
2758
2924
  : globalQueue.enqueue(EFFECT_USER, () => {
2759
2925
  const cleanup = callback();
2760
- if (cleanup !== undefined && typeof cleanup !== "function") {
2761
- throw new Error(
2762
- "onSettled callback returned an invalid cleanup value. Return a cleanup function or undefined."
2763
- );
2926
+ if (cleanup !== undefined) {
2927
+ const message =
2928
+ "[SETTLED_CLEANUP_UNOWNED] onSettled returned a cleanup in an unowned scope; a cleanup can only be honored under an owner. Call your setup helper from an owned scope (e.g. the component body) instead of from inside an event handler, tracked effect, or another onSettled.";
2929
+ emitDiagnostic({
2930
+ code: "SETTLED_CLEANUP_UNOWNED",
2931
+ kind: "lifecycle",
2932
+ severity: "error",
2933
+ message: message
2934
+ });
2935
+ throw new Error(message);
2764
2936
  }
2765
- cleanup?.();
2766
2937
  });
2767
2938
  }
2939
+ function nodeKeys(nodes) {
2940
+ const keys = Object.keys(nodes);
2941
+ if (symbolKeyedRecords.has(nodes)) {
2942
+ const syms = Object.getOwnPropertySymbols(nodes);
2943
+ for (let i = 0, len = syms.length; i < len; i++) {
2944
+ if (syms[i] !== $TRACK) keys.push(syms[i]);
2945
+ }
2946
+ }
2947
+ return keys;
2948
+ }
2768
2949
  function unwrap(value) {
2769
- return value?.[$TARGET]?.[STORE_NODE] ?? value;
2950
+ if (value === null || typeof value !== "object") return value;
2951
+ return value[$TARGET]?.[STORE_VALUE] ?? value;
2770
2952
  }
2771
2953
  function getOverrideValue(value, override, key, optOverride) {
2772
2954
  if (optOverride && key in optOverride) return optOverride[key];
2773
2955
  return override && key in override ? override[key] : value[key];
2774
2956
  }
2957
+ function addEnumSymbols(o, syms, keys) {
2958
+ for (let i = 0, len = syms.length; i < len; i++) {
2959
+ if (Object.prototype.propertyIsEnumerable.call(o, syms[i])) keys.add(syms[i]);
2960
+ }
2961
+ }
2775
2962
  function getAllKeys(value, override, next) {
2776
2963
  const keys = getKeys(value, override);
2777
2964
  const nextKeys = Object.keys(next);
2778
- return Array.from(new Set([...keys, ...nextKeys]));
2965
+ const valueSyms = value[$TARGET]
2966
+ ? untrack(() => Object.getOwnPropertySymbols(value))
2967
+ : Object.getOwnPropertySymbols(value);
2968
+ const nextSyms = Object.getOwnPropertySymbols(next);
2969
+ if (valueSyms.length === 0 && nextSyms.length === 0) {
2970
+ if (keys.length === nextKeys.length) {
2971
+ let same = true;
2972
+ for (let i = 0; i < keys.length; i++) {
2973
+ if (keys[i] !== nextKeys[i]) {
2974
+ same = false;
2975
+ break;
2976
+ }
2977
+ }
2978
+ if (same) return keys;
2979
+ }
2980
+ const set = new Set(keys);
2981
+ for (let i = 0; i < nextKeys.length; i++) set.add(nextKeys[i]);
2982
+ return Array.from(set);
2983
+ }
2984
+ const set = new Set(keys);
2985
+ addEnumSymbols(value, valueSyms, set);
2986
+ if (override) {
2987
+ for (const key of Reflect.ownKeys(override)) {
2988
+ override[key] === $DELETED ? set.delete(key) : set.add(key);
2989
+ }
2990
+ }
2991
+ for (let i = 0; i < nextKeys.length; i++) set.add(nextKeys[i]);
2992
+ addEnumSymbols(next, nextSyms, set);
2993
+ return Array.from(set);
2994
+ }
2995
+ function wrapValue(value, target) {
2996
+ return isWrappable(value) ? wrap(value, target) : value;
2997
+ }
2998
+ function itemKey(item, keyFn) {
2999
+ return isWrappable(item) ? keyFn(item) : item;
3000
+ }
3001
+ function keyedMatch(a, b, keyFn) {
3002
+ return a === b || (isWrappable(a) && isWrappable(b) && keyFn(a) === keyFn(b));
3003
+ }
3004
+ function syncArrayNodeMembership(target, next) {
3005
+ let nodes = target[STORE_NODE];
3006
+ if (nodes) {
3007
+ const keys = nodeKeys(nodes);
3008
+ for (let i = 0, len = keys.length; i < len; i++) {
3009
+ const key = keys[i];
3010
+ key in next || setSignal(nodes[key], undefined);
3011
+ }
3012
+ }
3013
+ if ((nodes = target[STORE_HAS])) {
3014
+ const keys = nodeKeys(nodes);
3015
+ for (let i = 0, len = keys.length; i < len; i++) {
3016
+ const key = keys[i];
3017
+ setSignal(nodes[key], key in next);
3018
+ }
3019
+ }
3020
+ }
3021
+ function applyArrayItem(next, previous, target, node, keyFn) {
3022
+ if (isWrappable(next) && isWrappable(previous)) {
3023
+ const wrapped = wrap(previous, target);
3024
+ node && setSignal(node, wrapped);
3025
+ applyState(next, wrapped, keyFn);
3026
+ } else node && setSignal(node, wrapValue(next, target));
2779
3027
  }
2780
3028
  function applyState(next, state, keyFn) {
3029
+ next = unwrap(next);
2781
3030
  const target = state?.[$TARGET];
2782
3031
  if (!target) return;
2783
3032
  if (target[STORE_OVERRIDE] || target[STORE_OPTIMISTIC_OVERRIDE]) {
@@ -2789,30 +3038,28 @@ function applyState(next, state, keyFn) {
2789
3038
  function applyStateFast(next, target, keyFn) {
2790
3039
  const previous = target[STORE_VALUE];
2791
3040
  if (next === previous) return;
3041
+ const arrayNodes = target[STORE_NODE];
2792
3042
  (target[STORE_LOOKUP] || storeLookup).set(next, target[$PROXY]);
2793
3043
  target[STORE_VALUE] = next;
2794
3044
  if (Array.isArray(previous)) {
2795
3045
  let changed = false;
2796
3046
  const prevLength = previous.length;
2797
- if (next.length && prevLength && next[0] && keyFn(next[0]) != null) {
3047
+ if (next.length && prevLength && isWrappable(next[0]) && keyFn(next[0]) != null) {
2798
3048
  let i, j, start, end, newEnd, item, newIndicesNext, keyVal;
2799
3049
  for (
2800
3050
  start = 0, end = Math.min(prevLength, next.length);
2801
- start < end &&
2802
- ((item = previous[start]) === next[start] ||
2803
- (item && next[start] && keyFn(item) === keyFn(next[start])));
3051
+ start < end && keyedMatch((item = previous[start]), next[start], keyFn);
2804
3052
  start++
2805
3053
  ) {
2806
- applyState(next[start], wrap(item, target), keyFn);
3054
+ isWrappable(item) &&
3055
+ isWrappable(next[start]) &&
3056
+ applyState(next[start], wrap(item, target), keyFn);
2807
3057
  }
2808
3058
  const temp = new Array(next.length),
2809
3059
  newIndices = new Map();
2810
3060
  for (
2811
3061
  end = prevLength - 1, newEnd = next.length - 1;
2812
- end >= start &&
2813
- newEnd >= start &&
2814
- ((item = previous[end]) === next[newEnd] ||
2815
- (item && next[newEnd] && keyFn(item) === keyFn(next[newEnd])));
3062
+ end >= start && newEnd >= start && keyedMatch((item = previous[end]), next[newEnd], keyFn);
2816
3063
  end--, newEnd--
2817
3064
  ) {
2818
3065
  temp[newEnd] = item;
@@ -2820,31 +3067,30 @@ function applyStateFast(next, target, keyFn) {
2820
3067
  if (start > newEnd || start > end) {
2821
3068
  for (j = start; j <= newEnd; j++) {
2822
3069
  changed = true;
2823
- target[STORE_NODE][j] && setSignal(target[STORE_NODE][j], wrap(next[j], target));
3070
+ arrayNodes?.[j] && setSignal(arrayNodes[j], wrapValue(next[j], target));
2824
3071
  }
2825
3072
  for (; j < next.length; j++) {
2826
3073
  changed = true;
2827
- const wrapped = wrap(temp[j], target);
2828
- target[STORE_NODE][j] && setSignal(target[STORE_NODE][j], wrapped);
2829
- applyState(next[j], wrapped, keyFn);
3074
+ applyArrayItem(next[j], temp[j], target, arrayNodes?.[j], keyFn);
2830
3075
  }
2831
- changed && target[STORE_NODE][$TRACK] && setSignal(target[STORE_NODE][$TRACK], void 0);
3076
+ syncArrayNodeMembership(target, next);
3077
+ (changed || prevLength !== next.length) && notifySelf(target);
2832
3078
  prevLength !== next.length &&
2833
- target[STORE_NODE].length &&
2834
- setSignal(target[STORE_NODE].length, next.length);
3079
+ arrayNodes?.length &&
3080
+ setSignal(arrayNodes.length, next.length);
2835
3081
  return;
2836
3082
  }
2837
3083
  newIndicesNext = new Array(newEnd + 1);
2838
3084
  for (j = newEnd; j >= start; j--) {
2839
3085
  item = next[j];
2840
- keyVal = item ? keyFn(item) : item;
3086
+ keyVal = itemKey(item, keyFn);
2841
3087
  i = newIndices.get(keyVal);
2842
3088
  newIndicesNext[j] = i === undefined ? -1 : i;
2843
3089
  newIndices.set(keyVal, j);
2844
3090
  }
2845
3091
  for (i = start; i <= end; i++) {
2846
3092
  item = previous[i];
2847
- keyVal = item ? keyFn(item) : item;
3093
+ keyVal = itemKey(item, keyFn);
2848
3094
  j = newIndices.get(keyVal);
2849
3095
  if (j !== undefined && j !== -1) {
2850
3096
  temp[j] = item;
@@ -2854,31 +3100,33 @@ function applyStateFast(next, target, keyFn) {
2854
3100
  }
2855
3101
  for (j = start; j < next.length; j++) {
2856
3102
  if (j in temp) {
2857
- const wrapped = wrap(temp[j], target);
2858
- target[STORE_NODE][j] && setSignal(target[STORE_NODE][j], wrapped);
2859
- applyState(next[j], wrapped, keyFn);
2860
- } else target[STORE_NODE][j] && setSignal(target[STORE_NODE][j], wrap(next[j], target));
3103
+ applyArrayItem(next[j], temp[j], target, arrayNodes?.[j], keyFn);
3104
+ } else arrayNodes?.[j] && setSignal(arrayNodes[j], wrapValue(next[j], target));
2861
3105
  }
2862
3106
  if (start < next.length) changed = true;
2863
3107
  } else if (next.length) {
2864
3108
  for (let i = 0, len = next.length; i < len; i++) {
2865
3109
  const item = previous[i];
2866
- isWrappable(item)
2867
- ? applyState(next[i], wrap(item, target), keyFn)
2868
- : target[STORE_NODE][i] && setSignal(target[STORE_NODE][i], next[i]);
3110
+ if (isWrappable(item) && isWrappable(next[i]))
3111
+ applyState(next[i], wrap(item, target), keyFn);
3112
+ else {
3113
+ if (item !== next[i]) changed = true;
3114
+ arrayNodes?.[i] && setSignal(arrayNodes[i], wrapValue(next[i], target));
3115
+ }
2869
3116
  }
2870
3117
  }
3118
+ syncArrayNodeMembership(target, next);
2871
3119
  if (prevLength !== next.length) {
2872
3120
  changed = true;
2873
- target[STORE_NODE].length && setSignal(target[STORE_NODE].length, next.length);
3121
+ arrayNodes?.length && setSignal(arrayNodes.length, next.length);
2874
3122
  }
2875
- changed && target[STORE_NODE][$TRACK] && setSignal(target[STORE_NODE][$TRACK], void 0);
3123
+ changed && notifySelf(target);
2876
3124
  return;
2877
3125
  }
2878
3126
  let nodes = target[STORE_NODE];
2879
3127
  if (nodes) {
2880
3128
  const tracked = nodes[$TRACK];
2881
- const keys = tracked ? getAllKeys(previous, undefined, next) : Object.keys(nodes);
3129
+ const keys = tracked ? getAllKeys(previous, undefined, next) : nodeKeys(nodes);
2882
3130
  for (let i = 0, len = keys.length; i < len; i++) {
2883
3131
  const key = keys[i];
2884
3132
  const node = nodes[key];
@@ -2889,6 +3137,7 @@ function applyStateFast(next, target, keyFn) {
2889
3137
  !previousValue ||
2890
3138
  !isWrappable(previousValue) ||
2891
3139
  !isWrappable(nextValue) ||
3140
+ Array.isArray(previousValue) !== Array.isArray(nextValue) ||
2892
3141
  (keyFn(previousValue) != null && keyFn(previousValue) !== keyFn(nextValue))
2893
3142
  ) {
2894
3143
  tracked && setSignal(tracked, void 0);
@@ -2897,7 +3146,7 @@ function applyStateFast(next, target, keyFn) {
2897
3146
  }
2898
3147
  }
2899
3148
  if ((nodes = target[STORE_HAS])) {
2900
- const keys = Object.keys(nodes);
3149
+ const keys = nodeKeys(nodes);
2901
3150
  for (let i = 0, len = keys.length; i < len; i++) {
2902
3151
  const key = keys[i];
2903
3152
  setSignal(nodes[key], key in next);
@@ -2915,16 +3164,21 @@ function applyStateSlow(next, target, keyFn) {
2915
3164
  if (Array.isArray(previous)) {
2916
3165
  let changed = false;
2917
3166
  const prevLength = getOverrideValue(previous, override, "length", optOverride);
2918
- if (next.length && prevLength && next[0] && keyFn(next[0]) != null) {
3167
+ if (next.length && prevLength && isWrappable(next[0]) && keyFn(next[0]) != null) {
2919
3168
  let i, j, start, end, newEnd, item, newIndicesNext, keyVal;
2920
3169
  for (
2921
3170
  start = 0, end = Math.min(prevLength, next.length);
2922
3171
  start < end &&
2923
- ((item = getOverrideValue(previous, override, start, optOverride)) === next[start] ||
2924
- (item && next[start] && keyFn(item) === keyFn(next[start])));
3172
+ keyedMatch(
3173
+ (item = getOverrideValue(previous, override, start, optOverride)),
3174
+ next[start],
3175
+ keyFn
3176
+ );
2925
3177
  start++
2926
3178
  ) {
2927
- applyState(next[start], wrap(item, target), keyFn);
3179
+ isWrappable(item) &&
3180
+ isWrappable(next[start]) &&
3181
+ applyState(next[start], wrap(item, target), keyFn);
2928
3182
  }
2929
3183
  const temp = new Array(next.length),
2930
3184
  newIndices = new Map();
@@ -2932,8 +3186,11 @@ function applyStateSlow(next, target, keyFn) {
2932
3186
  end = prevLength - 1, newEnd = next.length - 1;
2933
3187
  end >= start &&
2934
3188
  newEnd >= start &&
2935
- ((item = getOverrideValue(previous, override, end, optOverride)) === next[newEnd] ||
2936
- (item && next[newEnd] && keyFn(item) === keyFn(next[newEnd])));
3189
+ keyedMatch(
3190
+ (item = getOverrideValue(previous, override, end, optOverride)),
3191
+ next[newEnd],
3192
+ keyFn
3193
+ );
2937
3194
  end--, newEnd--
2938
3195
  ) {
2939
3196
  temp[newEnd] = item;
@@ -2941,31 +3198,29 @@ function applyStateSlow(next, target, keyFn) {
2941
3198
  if (start > newEnd || start > end) {
2942
3199
  for (j = start; j <= newEnd; j++) {
2943
3200
  changed = true;
2944
- target[STORE_NODE][j] && setSignal(target[STORE_NODE][j], wrap(next[j], target));
3201
+ nodes?.[j] && setSignal(nodes[j], wrapValue(next[j], target));
2945
3202
  }
2946
3203
  for (; j < next.length; j++) {
2947
3204
  changed = true;
2948
- const wrapped = wrap(temp[j], target);
2949
- target[STORE_NODE][j] && setSignal(target[STORE_NODE][j], wrapped);
2950
- applyState(next[j], wrapped, keyFn);
3205
+ applyArrayItem(next[j], temp[j], target, nodes?.[j], keyFn);
2951
3206
  }
2952
- changed && target[STORE_NODE][$TRACK] && setSignal(target[STORE_NODE][$TRACK], void 0);
2953
- prevLength !== next.length &&
2954
- target[STORE_NODE].length &&
2955
- setSignal(target[STORE_NODE].length, next.length);
3207
+ const nextLength = next.length;
3208
+ syncArrayNodeMembership(target, next);
3209
+ (changed || prevLength !== nextLength) && notifySelf(target);
3210
+ prevLength !== nextLength && nodes?.length && setSignal(nodes.length, nextLength);
2956
3211
  return;
2957
3212
  }
2958
3213
  newIndicesNext = new Array(newEnd + 1);
2959
3214
  for (j = newEnd; j >= start; j--) {
2960
3215
  item = next[j];
2961
- keyVal = item ? keyFn(item) : item;
3216
+ keyVal = itemKey(item, keyFn);
2962
3217
  i = newIndices.get(keyVal);
2963
3218
  newIndicesNext[j] = i === undefined ? -1 : i;
2964
3219
  newIndices.set(keyVal, j);
2965
3220
  }
2966
3221
  for (i = start; i <= end; i++) {
2967
3222
  item = getOverrideValue(previous, override, i, optOverride);
2968
- keyVal = item ? keyFn(item) : item;
3223
+ keyVal = itemKey(item, keyFn);
2969
3224
  j = newIndices.get(keyVal);
2970
3225
  if (j !== undefined && j !== -1) {
2971
3226
  temp[j] = item;
@@ -2975,30 +3230,33 @@ function applyStateSlow(next, target, keyFn) {
2975
3230
  }
2976
3231
  for (j = start; j < next.length; j++) {
2977
3232
  if (j in temp) {
2978
- const wrapped = wrap(temp[j], target);
2979
- target[STORE_NODE][j] && setSignal(target[STORE_NODE][j], wrapped);
2980
- applyState(next[j], wrapped, keyFn);
2981
- } else target[STORE_NODE][j] && setSignal(target[STORE_NODE][j], wrap(next[j], target));
3233
+ applyArrayItem(next[j], temp[j], target, nodes?.[j], keyFn);
3234
+ } else nodes?.[j] && setSignal(nodes[j], wrapValue(next[j], target));
2982
3235
  }
2983
3236
  if (start < next.length) changed = true;
2984
3237
  } else if (next.length) {
2985
3238
  for (let i = 0, len = next.length; i < len; i++) {
2986
3239
  const item = getOverrideValue(previous, override, i, optOverride);
2987
- isWrappable(item)
2988
- ? applyState(next[i], wrap(item, target), keyFn)
2989
- : target[STORE_NODE][i] && setSignal(target[STORE_NODE][i], next[i]);
3240
+ if (isWrappable(item) && isWrappable(next[i]))
3241
+ applyState(next[i], wrap(item, target), keyFn);
3242
+ else {
3243
+ if (item !== next[i]) changed = true;
3244
+ nodes?.[i] && setSignal(nodes[i], wrapValue(next[i], target));
3245
+ }
2990
3246
  }
2991
3247
  }
2992
- if (prevLength !== next.length) {
3248
+ const nextLength = next.length;
3249
+ syncArrayNodeMembership(target, next);
3250
+ if (prevLength !== nextLength) {
2993
3251
  changed = true;
2994
- target[STORE_NODE].length && setSignal(target[STORE_NODE].length, next.length);
3252
+ nodes?.length && setSignal(nodes.length, nextLength);
2995
3253
  }
2996
- changed && target[STORE_NODE][$TRACK] && setSignal(target[STORE_NODE][$TRACK], void 0);
3254
+ changed && notifySelf(target);
2997
3255
  return;
2998
3256
  }
2999
3257
  if (nodes) {
3000
3258
  const tracked = nodes[$TRACK];
3001
- const keys = tracked ? getAllKeys(previous, override, next) : Object.keys(nodes);
3259
+ const keys = tracked ? getAllKeys(previous, override, next) : nodeKeys(nodes);
3002
3260
  for (let i = 0, len = keys.length; i < len; i++) {
3003
3261
  const key = keys[i];
3004
3262
  const node = nodes[key];
@@ -3009,6 +3267,7 @@ function applyStateSlow(next, target, keyFn) {
3009
3267
  !previousValue ||
3010
3268
  !isWrappable(previousValue) ||
3011
3269
  !isWrappable(nextValue) ||
3270
+ Array.isArray(previousValue) !== Array.isArray(nextValue) ||
3012
3271
  (keyFn(previousValue) != null && keyFn(previousValue) !== keyFn(nextValue))
3013
3272
  ) {
3014
3273
  tracked && setSignal(tracked, void 0);
@@ -3017,7 +3276,7 @@ function applyStateSlow(next, target, keyFn) {
3017
3276
  }
3018
3277
  }
3019
3278
  if ((nodes = target[STORE_HAS])) {
3020
- const keys = Object.keys(nodes);
3279
+ const keys = nodeKeys(nodes);
3021
3280
  for (let i = 0, len = keys.length; i < len; i++) {
3022
3281
  const key = keys[i];
3023
3282
  setSignal(nodes[key], key in next);
@@ -3029,7 +3288,7 @@ function reconcile(value, key) {
3029
3288
  if (state == null) throw new Error("Cannot reconcile null or undefined state");
3030
3289
  const keyFn = typeof key === "string" ? item => item[key] : key;
3031
3290
  const eq = keyFn(state);
3032
- if (eq !== undefined && keyFn(value) !== keyFn(state))
3291
+ if (eq !== undefined && keyFn(value) !== eq)
3033
3292
  throw new Error("Cannot reconcile states with different identity");
3034
3293
  applyState(value, state, keyFn);
3035
3294
  };
@@ -3068,13 +3327,13 @@ function createProjectionInternal(fn, seed, options) {
3068
3327
  function createProjection(fn, seed, options) {
3069
3328
  return createProjectionInternal(fn, seed, options).store;
3070
3329
  }
3071
- function runProjectionComputed(wrappedStore, fn, key, wrapCommit) {
3330
+ function runProjectionComputed(wrappedStore, fn, key, wrapCommit, onDraftWrite) {
3072
3331
  const owner = getOwner();
3073
3332
  let settled = false;
3074
3333
  let result;
3075
3334
  const draft = new Proxy(
3076
3335
  wrappedStore,
3077
- createWriteTraps(() => !settled || owner._inFlight === result)
3336
+ createWriteTraps(() => !settled || owner._inFlight === result, onDraftWrite)
3078
3337
  );
3079
3338
  storeSetter(draft, s => {
3080
3339
  result = fn(s);
@@ -3088,7 +3347,7 @@ function runProjectionComputed(wrappedStore, fn, key, wrapCommit) {
3088
3347
  });
3089
3348
  return owner;
3090
3349
  }
3091
- function createWriteTraps(isActive) {
3350
+ function createWriteTraps(isActive, onDraftWrite) {
3092
3351
  const traps = {
3093
3352
  get(_, prop) {
3094
3353
  let value;
@@ -3100,6 +3359,7 @@ function createWriteTraps(isActive) {
3100
3359
  setWriteOverride(false);
3101
3360
  setProjectionWriteActive(false);
3102
3361
  }
3362
+ if (prop === $TARGET) return value;
3103
3363
  return typeof value === "object" && value !== null ? new Proxy(value, traps) : value;
3104
3364
  },
3105
3365
  has(_, prop) {
@@ -3120,6 +3380,7 @@ function createWriteTraps(isActive) {
3120
3380
  setProjectionWriteActive(true);
3121
3381
  try {
3122
3382
  _[prop] = value;
3383
+ onDraftWrite?.();
3123
3384
  } finally {
3124
3385
  setWriteOverride(false);
3125
3386
  setProjectionWriteActive(false);
@@ -3132,6 +3393,7 @@ function createWriteTraps(isActive) {
3132
3393
  setProjectionWriteActive(true);
3133
3394
  try {
3134
3395
  delete _[prop];
3396
+ onDraftWrite?.();
3135
3397
  } finally {
3136
3398
  setWriteOverride(false);
3137
3399
  setProjectionWriteActive(false);
@@ -3154,7 +3416,9 @@ const STORE_VALUE = "v",
3154
3416
  STORE_WRAP = "w",
3155
3417
  STORE_LOOKUP = "l",
3156
3418
  STORE_FIREWALL = "f",
3157
- STORE_OPTIMISTIC = "p";
3419
+ STORE_OPTIMISTIC = "p",
3420
+ STORE_MASKED = "m";
3421
+ const STORE_SELF_PENDING = Symbol("STORE_SELF_PENDING");
3158
3422
  function createStoreProxy(value, traps = storeTraps, extend) {
3159
3423
  let newTarget;
3160
3424
  if (Array.isArray(value)) {
@@ -3172,6 +3436,7 @@ function createStoreProxy(value, traps = storeTraps, extend) {
3172
3436
  return (newTarget[$PROXY] = new Proxy(newTarget, traps));
3173
3437
  }
3174
3438
  const storeLookup = new WeakMap();
3439
+ const symbolKeyedRecords = new WeakSet();
3175
3440
  function wrap(value, target) {
3176
3441
  if (target?.[STORE_WRAP]) return target[STORE_WRAP](value, target);
3177
3442
  let p = value[$PROXY] || storeLookup.get(value);
@@ -3189,27 +3454,49 @@ function setWriteOverride(value) {
3189
3454
  function writeOnly(proxy) {
3190
3455
  return writeOverride || !!Writing?.has(proxy);
3191
3456
  }
3192
- function unwrapStoreValue(value) {
3193
- return value?.[$TARGET]?.[STORE_VALUE] ?? value;
3457
+ function unwrapStoreValue(value, map, lookup) {
3458
+ const target = value?.[$TARGET] || lookup?.get(value)?.[$TARGET];
3459
+ if (!target) return value;
3460
+ const override = target[STORE_OVERRIDE];
3461
+ if (!override) return target[STORE_VALUE];
3462
+ if (!map) map = new Map();
3463
+ if (map.has(value)) return map.get(value);
3464
+ const source = target[STORE_VALUE];
3465
+ const isArray = Array.isArray(source);
3466
+ const result = isArray ? [] : Object.create(Object.getPrototypeOf(source));
3467
+ map.set(value, result);
3468
+ lookup = target[STORE_LOOKUP] ?? storeLookup;
3469
+ for (const key of getKeys(source, override)) {
3470
+ if (isArray && key === "length") continue;
3471
+ const next = key in override ? override[key] : source[key];
3472
+ if (next !== $DELETED) result[key] = unwrapStoreValue(next, map, lookup);
3473
+ }
3474
+ if (isArray) result.length = override.length ?? source.length;
3475
+ return result;
3194
3476
  }
3195
3477
  function isPrototypePollutionKey$1(property) {
3196
3478
  return property === "__proto__" || property === "constructor" || property === "prototype";
3197
3479
  }
3198
- function hasOwnStoreProperty(target, property) {
3199
- const optimisticOverride = target[STORE_OPTIMISTIC_OVERRIDE];
3200
- if (
3201
- optimisticOverride &&
3202
- Object.prototype.hasOwnProperty.call(optimisticOverride, property) &&
3203
- optimisticOverride[property] !== $DELETED
3204
- )
3205
- return true;
3480
+ function ownEnumerableKeys(o) {
3481
+ return Reflect.ownKeys(o).filter(k => Object.prototype.propertyIsEnumerable.call(o, k));
3482
+ }
3483
+ function getOverlayLayer(target, property) {
3484
+ const opt = target[STORE_OPTIMISTIC_OVERRIDE];
3485
+ if (opt && property in opt) return opt;
3206
3486
  const override = target[STORE_OVERRIDE];
3207
- if (
3208
- override &&
3209
- Object.prototype.hasOwnProperty.call(override, property) &&
3210
- override[property] !== $DELETED
3211
- )
3212
- return true;
3487
+ if (override && property in override) return override;
3488
+ return undefined;
3489
+ }
3490
+ function visibleNodeValue(node) {
3491
+ return node._overrideValue !== undefined && node._overrideValue !== NOT_PENDING
3492
+ ? node._overrideValue
3493
+ : node._pendingValue !== NOT_PENDING
3494
+ ? node._pendingValue
3495
+ : node._value;
3496
+ }
3497
+ function hasOwnStoreProperty(target, property) {
3498
+ const layer = getOverlayLayer(target, property);
3499
+ if (layer) return layer[property] !== $DELETED;
3213
3500
  return Object.prototype.hasOwnProperty.call(unwrapStoreValue(target[STORE_VALUE]), property);
3214
3501
  }
3215
3502
  function hasInheritedAccessor(source, property) {
@@ -3233,7 +3520,24 @@ function getNode(nodes, property, value, firewall, equals = isEqual, optimistic,
3233
3520
  {
3234
3521
  equals: equals,
3235
3522
  unobserved() {
3236
- if (nodes[property] === s) delete nodes[property];
3523
+ if (nodes[property] === s) {
3524
+ delete nodes[property];
3525
+ if (
3526
+ typeof property === "symbol" &&
3527
+ property !== $TRACK &&
3528
+ symbolKeyedRecords.has(nodes)
3529
+ ) {
3530
+ const syms = Object.getOwnPropertySymbols(nodes);
3531
+ let hasUserSymbol = false;
3532
+ for (let i = 0, len = syms.length; i < len; i++) {
3533
+ if (syms[i] !== $TRACK) {
3534
+ hasUserSymbol = true;
3535
+ break;
3536
+ }
3537
+ }
3538
+ if (!hasUserSymbol) symbolKeyedRecords.delete(nodes);
3539
+ }
3540
+ }
3237
3541
  }
3238
3542
  },
3239
3543
  firewall
@@ -3246,6 +3550,7 @@ function getNode(nodes, property, value, firewall, equals = isEqual, optimistic,
3246
3550
  s._snapshotValue = sv === undefined ? NO_SNAPSHOT : sv;
3247
3551
  snapshotSources?.add(s);
3248
3552
  }
3553
+ if (typeof property === "symbol" && property !== $TRACK) symbolKeyedRecords.add(nodes);
3249
3554
  return (nodes[property] = s);
3250
3555
  }
3251
3556
  function trackSelf(target, symbol = $TRACK) {
@@ -3261,8 +3566,20 @@ function trackSelf(target, symbol = $TRACK) {
3261
3566
  )
3262
3567
  );
3263
3568
  }
3569
+ function notifySelf(target) {
3570
+ const node = target[STORE_NODE]?.[$TRACK];
3571
+ node &&
3572
+ setSignal(
3573
+ node,
3574
+ target[STORE_OPTIMISTIC] && !projectionWriteActive ? STORE_SELF_PENDING : undefined
3575
+ );
3576
+ }
3264
3577
  function getKeys(source, override, enumerable = true) {
3265
- const baseKeys = untrack(() => (enumerable ? Object.keys(source) : Reflect.ownKeys(source)));
3578
+ const baseKeys = source[$TARGET]
3579
+ ? untrack(() => (enumerable ? Object.keys(source) : Reflect.ownKeys(source)))
3580
+ : enumerable
3581
+ ? Object.keys(source)
3582
+ : Reflect.ownKeys(source);
3266
3583
  if (!override) return baseKeys;
3267
3584
  const keys = new Set(baseKeys);
3268
3585
  const overrides = Reflect.ownKeys(override);
@@ -3276,10 +3593,26 @@ function getPropertyDescriptor(source, override, property) {
3276
3593
  if (override && property in override) {
3277
3594
  if (override[property] === $DELETED) return void 0;
3278
3595
  const overrideDesc = Reflect.getOwnPropertyDescriptor(override, property);
3279
- if (overrideDesc?.get || overrideDesc?.set || !(property in source)) return overrideDesc;
3596
+ if (overrideDesc?.get || overrideDesc?.set) return overrideDesc;
3597
+ const baseDesc = Reflect.getOwnPropertyDescriptor(source, property);
3598
+ if (!baseDesc) return overrideDesc;
3599
+ if (baseDesc.get || baseDesc.set) return baseDesc;
3600
+ baseDesc.value = override[property];
3601
+ return baseDesc;
3280
3602
  }
3281
3603
  return Reflect.getOwnPropertyDescriptor(source, property);
3282
3604
  }
3605
+ function maskStoreTarget(target, on) {
3606
+ const firewall = target[STORE_FIREWALL];
3607
+ if (!firewall) return;
3608
+ if (!!target[STORE_MASKED] === on) return;
3609
+ target[STORE_MASKED] = on;
3610
+ const count = (firewall._optimisticMask = (firewall._optimisticMask || 0) + (on ? 1 : -1));
3611
+ if ((on && count === 1) || (!on && count === 0)) {
3612
+ updatePendingSignal(firewall);
3613
+ updateChildCompanions(firewall);
3614
+ }
3615
+ }
3283
3616
  function prepareStoreWrite(target, store, property) {
3284
3617
  if (target[STORE_OPTIMISTIC]) {
3285
3618
  const firewall = target[STORE_FIREWALL];
@@ -3304,9 +3637,14 @@ function prepareStoreWrite(target, store, property) {
3304
3637
  }
3305
3638
  const useOptimistic = target[STORE_OPTIMISTIC] && !projectionWriteActive;
3306
3639
  const overrideKey = useOptimistic ? STORE_OPTIMISTIC_OVERRIDE : STORE_OVERRIDE;
3307
- if (useOptimistic) trackOptimisticStore(store);
3308
3640
  return { base: base, overrideKey: overrideKey, state: state };
3309
3641
  }
3642
+ function armOptimisticStoreWrite(target, store) {
3643
+ if (target[STORE_OPTIMISTIC] && !projectionWriteActive) {
3644
+ trackOptimisticStore(store);
3645
+ maskStoreTarget(target, true);
3646
+ }
3647
+ }
3310
3648
  function upsertStoreNode(target, nodes, property, prev, snapshotProps) {
3311
3649
  if (nodes[property]) return nodes[property];
3312
3650
  const initial = isWrappable(prev) ? wrap(prev, target) : prev;
@@ -3353,7 +3691,7 @@ function notifyStoreProperty(target, property, mode, value, prev, prevHas) {
3353
3691
  setSignal(node, undefined);
3354
3692
  }
3355
3693
  }
3356
- nodes[$TRACK] && setSignal(nodes[$TRACK], undefined);
3694
+ notifySelf(target);
3357
3695
  }
3358
3696
  let Writing = null;
3359
3697
  const storeTraps = {
@@ -3365,8 +3703,9 @@ const storeTraps = {
3365
3703
  trackSelf(target);
3366
3704
  return receiver;
3367
3705
  }
3706
+ const selfRead = getObserver() === target[STORE_FIREWALL];
3368
3707
  const nodes = getNodes(target, STORE_NODE);
3369
- const tracked = nodes[property];
3708
+ const tracked = selfRead ? undefined : nodes[property];
3370
3709
  const source = target[STORE_VALUE];
3371
3710
  if (
3372
3711
  !tracked &&
@@ -3378,20 +3717,15 @@ const storeTraps = {
3378
3717
  !source[$TARGET] &&
3379
3718
  !(property in source) &&
3380
3719
  getObserver() &&
3720
+ !selfRead &&
3381
3721
  !writeOnly(receiver)
3382
3722
  ) {
3383
3723
  return read(getNode(nodes, property, undefined, target[STORE_FIREWALL]));
3384
3724
  }
3385
- const optOverridden =
3386
- target[STORE_OPTIMISTIC_OVERRIDE] && property in target[STORE_OPTIMISTIC_OVERRIDE];
3387
- const overridden =
3388
- optOverridden || (target[STORE_OVERRIDE] && property in target[STORE_OVERRIDE]);
3725
+ const overlay = getOverlayLayer(target, property);
3726
+ const overridden = !!overlay;
3389
3727
  const proxySource = !!target[STORE_VALUE][$TARGET];
3390
- const storeValue = optOverridden
3391
- ? target[STORE_OPTIMISTIC_OVERRIDE]
3392
- : target[STORE_OVERRIDE] && property in target[STORE_OVERRIDE]
3393
- ? target[STORE_OVERRIDE]
3394
- : target[STORE_VALUE];
3728
+ const storeValue = overlay ?? target[STORE_VALUE];
3395
3729
  if (!tracked) {
3396
3730
  const desc = Object.getOwnPropertyDescriptor(storeValue, property);
3397
3731
  if (desc && desc.get) return desc.get.call(receiver);
@@ -3406,13 +3740,7 @@ const storeTraps = {
3406
3740
  if (isPrototypePollutionKey$1(property) && !hasOwnStoreProperty(target, property))
3407
3741
  return undefined;
3408
3742
  let value =
3409
- tracked && (overridden || !proxySource)
3410
- ? tracked._overrideValue !== undefined && tracked._overrideValue !== NOT_PENDING
3411
- ? tracked._overrideValue
3412
- : tracked._pendingValue !== NOT_PENDING
3413
- ? tracked._pendingValue
3414
- : tracked._value
3415
- : storeValue[property];
3743
+ tracked && (overridden || !proxySource) ? visibleNodeValue(tracked) : storeValue[property];
3416
3744
  value === $DELETED && (value = undefined);
3417
3745
  if (!isWrappable(value)) return value;
3418
3746
  const wrapped = wrap(value, target);
@@ -3426,14 +3754,18 @@ const storeTraps = {
3426
3754
  : storeValue[property];
3427
3755
  value === $DELETED && (value = undefined);
3428
3756
  if (!tracked) {
3429
- if (!overridden && typeof value === "function" && !storeValue.hasOwnProperty(property)) {
3757
+ if (
3758
+ !overridden &&
3759
+ typeof value === "function" &&
3760
+ !Object.prototype.hasOwnProperty.call(storeValue, property)
3761
+ ) {
3430
3762
  let proto;
3431
3763
  return !Array.isArray(target[STORE_VALUE]) &&
3432
3764
  (proto = Object.getPrototypeOf(target[STORE_VALUE])) &&
3433
3765
  proto !== Object.prototype
3434
3766
  ? value.bind(storeValue)
3435
3767
  : value;
3436
- } else if (getObserver()) {
3768
+ } else if (getObserver() && !selfRead) {
3437
3769
  return read(
3438
3770
  getNode(
3439
3771
  nodes,
@@ -3465,13 +3797,9 @@ const storeTraps = {
3465
3797
  },
3466
3798
  has(target, property) {
3467
3799
  if (property === $PROXY || property === $TRACK || property === "__proto__") return true;
3468
- const has =
3469
- target[STORE_OPTIMISTIC_OVERRIDE] && property in target[STORE_OPTIMISTIC_OVERRIDE]
3470
- ? target[STORE_OPTIMISTIC_OVERRIDE][property] !== $DELETED
3471
- : target[STORE_OVERRIDE] && property in target[STORE_OVERRIDE]
3472
- ? target[STORE_OVERRIDE][property] !== $DELETED
3473
- : property in target[STORE_VALUE];
3474
- if (writeOnly(target[$PROXY])) return has;
3800
+ const hasLayer = getOverlayLayer(target, property);
3801
+ const has = hasLayer ? hasLayer[property] !== $DELETED : property in target[STORE_VALUE];
3802
+ if (writeOnly(target[$PROXY]) || getObserver() === target[STORE_FIREWALL]) return has;
3475
3803
  const nodes = getNodes(target, STORE_HAS);
3476
3804
  if (nodes[property]) return read(nodes[property]);
3477
3805
  if (getObserver()) {
@@ -3491,30 +3819,19 @@ const storeTraps = {
3491
3819
  overrideKey: overrideKey,
3492
3820
  state: state
3493
3821
  } = prepareStoreWrite(target, store, property);
3494
- const prev =
3495
- target[STORE_OPTIMISTIC_OVERRIDE] && property in target[STORE_OPTIMISTIC_OVERRIDE]
3496
- ? target[STORE_OPTIMISTIC_OVERRIDE][property]
3497
- : target[STORE_OVERRIDE] && property in target[STORE_OVERRIDE]
3498
- ? target[STORE_OVERRIDE][property]
3499
- : base;
3500
- const prevHas =
3501
- target[STORE_OPTIMISTIC_OVERRIDE] && property in target[STORE_OPTIMISTIC_OVERRIDE]
3502
- ? target[STORE_OPTIMISTIC_OVERRIDE][property] !== $DELETED
3503
- : target[STORE_OVERRIDE] && property in target[STORE_OVERRIDE]
3504
- ? target[STORE_OVERRIDE][property] !== $DELETED
3505
- : property in target[STORE_VALUE];
3822
+ const prevLayer = getOverlayLayer(target, property);
3823
+ const prev = prevLayer ? prevLayer[property] : base;
3824
+ const prevHas = prevLayer
3825
+ ? prevLayer[property] !== $DELETED
3826
+ : property in target[STORE_VALUE];
3506
3827
  const value = unwrapStoreValue(rawValue);
3507
- const isArrayIndexWrite = Array.isArray(state) && property !== "length";
3828
+ const isArrayIndexWrite =
3829
+ Array.isArray(state) && property !== "length" && typeof property !== "symbol";
3508
3830
  const nextIndex = isArrayIndexWrite ? parseInt(property) + 1 : 0;
3509
- const len =
3510
- isArrayIndexWrite &&
3511
- (target[STORE_OPTIMISTIC_OVERRIDE] && "length" in target[STORE_OPTIMISTIC_OVERRIDE]
3512
- ? target[STORE_OPTIMISTIC_OVERRIDE].length
3513
- : target[STORE_OVERRIDE] && "length" in target[STORE_OVERRIDE]
3514
- ? target[STORE_OVERRIDE].length
3515
- : state.length);
3831
+ const len = isArrayIndexWrite && (getOverlayLayer(target, "length") ?? state).length;
3516
3832
  const nextLength = isArrayIndexWrite && nextIndex > len ? nextIndex : undefined;
3517
3833
  if (prev === value && nextLength === undefined) return true;
3834
+ armOptimisticStoreWrite(target, store);
3518
3835
  if (value !== undefined && value === base && nextLength === undefined)
3519
3836
  delete target[overrideKey]?.[property];
3520
3837
  else {
@@ -3523,6 +3840,22 @@ const storeTraps = {
3523
3840
  if (nextLength !== undefined) override.length = nextLength;
3524
3841
  }
3525
3842
  notifyStoreProperty(target, property, "set", value, prev, prevHas);
3843
+ if (
3844
+ Array.isArray(state) &&
3845
+ property === "length" &&
3846
+ typeof value === "number" &&
3847
+ typeof prev === "number" &&
3848
+ value < prev
3849
+ ) {
3850
+ const override = target[overrideKey] || (target[overrideKey] = Object.create(null));
3851
+ for (let i = value; i < prev; i++) {
3852
+ if (override[i] === $DELETED) continue;
3853
+ const prevIndex = i in override ? override[i] : state[i];
3854
+ if (!(i in override) && !(i in state)) continue;
3855
+ override[i] = $DELETED;
3856
+ notifyStoreProperty(target, i, "delete", undefined, prevIndex, true);
3857
+ }
3858
+ }
3526
3859
  if (Array.isArray(state) && property !== "length" && nextLength !== undefined) {
3527
3860
  const nodes = getNodes(target, STORE_NODE);
3528
3861
  if (nodes.length) {
@@ -3549,6 +3882,7 @@ const storeTraps = {
3549
3882
  if (writeOnly(store)) {
3550
3883
  untrack(() => {
3551
3884
  const { base: base, overrideKey: overrideKey } = prepareStoreWrite(target, store, property);
3885
+ armOptimisticStoreWrite(target, store);
3552
3886
  const normalizedDescriptor =
3553
3887
  "value" in descriptor
3554
3888
  ? { ...descriptor, value: unwrapStoreValue(descriptor.value) }
@@ -3578,19 +3912,16 @@ const storeTraps = {
3578
3912
  untrack(() => {
3579
3913
  const useOptimistic = target[STORE_OPTIMISTIC] && !projectionWriteActive;
3580
3914
  const overrideKey = useOptimistic ? STORE_OPTIMISTIC_OVERRIDE : STORE_OVERRIDE;
3581
- if (useOptimistic) trackOptimisticStore(target[$PROXY]);
3582
- const prev =
3583
- target[STORE_OPTIMISTIC_OVERRIDE] && property in target[STORE_OPTIMISTIC_OVERRIDE]
3584
- ? target[STORE_OPTIMISTIC_OVERRIDE][property]
3585
- : target[STORE_OVERRIDE] && property in target[STORE_OVERRIDE]
3586
- ? target[STORE_OVERRIDE][property]
3587
- : target[STORE_VALUE][property];
3915
+ const prevLayer = getOverlayLayer(target, property);
3916
+ const prev = prevLayer ? prevLayer[property] : target[STORE_VALUE][property];
3588
3917
  if (
3589
3918
  property in target[STORE_VALUE] ||
3590
3919
  (target[STORE_OVERRIDE] && property in target[STORE_OVERRIDE])
3591
3920
  ) {
3921
+ armOptimisticStoreWrite(target, target[$PROXY]);
3592
3922
  (target[overrideKey] || (target[overrideKey] = Object.create(null)))[property] = $DELETED;
3593
3923
  } else if (target[overrideKey] && property in target[overrideKey]) {
3924
+ armOptimisticStoreWrite(target, target[$PROXY]);
3594
3925
  delete target[overrideKey][property];
3595
3926
  } else return true;
3596
3927
  notifyStoreProperty(target, property, "delete", undefined, prev, true);
@@ -3599,7 +3930,7 @@ const storeTraps = {
3599
3930
  return true;
3600
3931
  },
3601
3932
  ownKeys(target) {
3602
- trackSelf(target);
3933
+ if (getObserver() !== target[STORE_FIREWALL]) trackSelf(target);
3603
3934
  let keys = getKeys(target[STORE_VALUE], target[STORE_OVERRIDE], false);
3604
3935
  if (target[STORE_OPTIMISTIC_OVERRIDE]) {
3605
3936
  const keySet = new Set(keys);
@@ -3619,7 +3950,13 @@ const storeTraps = {
3619
3950
  if (optDesc?.get || optDesc?.set || !(property in target[STORE_VALUE])) return optDesc;
3620
3951
  const baseDesc = getPropertyDescriptor(target[STORE_VALUE], target[STORE_OVERRIDE], property);
3621
3952
  if (baseDesc) {
3622
- return { ...baseDesc, value: target[STORE_OPTIMISTIC_OVERRIDE][property] };
3953
+ const targetDesc = Reflect.getOwnPropertyDescriptor(target, property);
3954
+ const configurable = !targetDesc || targetDesc.configurable ? true : baseDesc.configurable;
3955
+ return {
3956
+ ...baseDesc,
3957
+ configurable: configurable,
3958
+ value: target[STORE_OPTIMISTIC_OVERRIDE][property]
3959
+ };
3623
3960
  }
3624
3961
  return {
3625
3962
  value: target[STORE_OPTIMISTIC_OVERRIDE][property],
@@ -3628,7 +3965,12 @@ const storeTraps = {
3628
3965
  configurable: true
3629
3966
  };
3630
3967
  }
3631
- return getPropertyDescriptor(target[STORE_VALUE], target[STORE_OVERRIDE], property);
3968
+ const desc = getPropertyDescriptor(target[STORE_VALUE], target[STORE_OVERRIDE], property);
3969
+ if (desc && !desc.configurable) {
3970
+ const targetDesc = Reflect.getOwnPropertyDescriptor(target, property);
3971
+ if (!targetDesc || targetDesc.configurable) return { ...desc, configurable: true };
3972
+ }
3973
+ return desc;
3632
3974
  },
3633
3975
  getPrototypeOf(target) {
3634
3976
  return Object.getPrototypeOf(target[STORE_VALUE]);
@@ -3645,7 +3987,7 @@ function storeSetter(store, fn) {
3645
3987
  for (let i = 0, len = value.length; i < len; i++) store[i] = value[i];
3646
3988
  store.length = value.length;
3647
3989
  } else {
3648
- const keys = new Set([...Object.keys(store), ...Object.keys(value)]);
3990
+ const keys = new Set([...ownEnumerableKeys(store), ...ownEnumerableKeys(value)]);
3649
3991
  keys.forEach(key => {
3650
3992
  if (key in value) store[key] = value[key];
3651
3993
  else delete store[key];
@@ -3664,7 +4006,10 @@ function createStore(first, second, options) {
3664
4006
  return [
3665
4007
  wrappedStore,
3666
4008
  derived
3667
- ? fn => (storeSetter(wrappedStore, fn), suppressComputedRecompute(wrappedStore[$REFRESH]))
4009
+ ? fn => {
4010
+ suppressComputedRecompute(wrappedStore[$REFRESH]);
4011
+ storeSetter(wrappedStore, fn);
4012
+ }
3668
4013
  : fn => storeSetter(wrappedStore, fn)
3669
4014
  ];
3670
4015
  }
@@ -3678,32 +4023,47 @@ function createOptimisticStore(first, second, options) {
3678
4023
  }
3679
4024
  function clearOptimisticStore(store) {
3680
4025
  const target = store[$TARGET];
3681
- if (!target || !target[STORE_OPTIMISTIC_OVERRIDE]) return;
4026
+ if (!target) return;
4027
+ maskStoreTarget(target, false);
4028
+ if (!target[STORE_OPTIMISTIC_OVERRIDE]) return;
4029
+ clearOptimisticOverride(target);
4030
+ }
4031
+ function clearOptimisticOverride(target) {
3682
4032
  const override = target[STORE_OPTIMISTIC_OVERRIDE];
4033
+ if (!override) return;
4034
+ maskStoreTarget(target, false);
3683
4035
  const nodes = target[STORE_NODE];
4036
+ delete target[STORE_OPTIMISTIC_OVERRIDE];
4037
+ const wasProjectionWriteActive = projectionWriteActive;
3684
4038
  setProjectionWriteActive(true);
3685
4039
  try {
3686
4040
  if (nodes) {
3687
4041
  for (const key of Reflect.ownKeys(override)) {
3688
4042
  if (nodes[key]) {
3689
- nodes[key]._optimisticLane = undefined;
3690
- const baseValue =
3691
- target[STORE_OVERRIDE] && key in target[STORE_OVERRIDE]
3692
- ? target[STORE_OVERRIDE][key]
3693
- : target[STORE_VALUE][key];
4043
+ const node = nodes[key];
4044
+ node._optimisticLane = undefined;
4045
+ const layer = getOverlayLayer(target, key);
4046
+ const baseValue = layer ? layer[key] : target[STORE_VALUE][key];
3694
4047
  const value = baseValue === $DELETED ? undefined : baseValue;
3695
- setSignal(nodes[key], isWrappable(value) ? wrap(value, target) : value);
4048
+ const next = isWrappable(value) ? wrap(value, target) : value;
4049
+ const prev = visibleNodeValue(node);
4050
+ node._overrideValue = NOT_PENDING;
4051
+ node._pendingValue = NOT_PENDING;
4052
+ node._value = next;
4053
+ if (!node._equals || !node._equals(prev, next)) {
4054
+ insertSubs(node, true);
4055
+ schedule();
4056
+ }
3696
4057
  }
3697
4058
  }
3698
4059
  if (nodes[$TRACK]) {
3699
4060
  nodes[$TRACK]._optimisticLane = undefined;
3700
- setSignal(nodes[$TRACK], undefined);
4061
+ notifySelf(target);
3701
4062
  }
3702
4063
  }
3703
4064
  } finally {
3704
- setProjectionWriteActive(false);
4065
+ setProjectionWriteActive(wasProjectionWriteActive);
3705
4066
  }
3706
- delete target[STORE_OPTIMISTIC_OVERRIDE];
3707
4067
  }
3708
4068
  function createOptimisticProjectionInternal(fn, initialValue, options) {
3709
4069
  let node;
@@ -3728,19 +4088,31 @@ function createOptimisticProjectionInternal(fn, initialValue, options) {
3728
4088
  };
3729
4089
  const wrappedStore = wrapProjection(initialValue);
3730
4090
  if (fn) {
4091
+ const clearProjectionOverride = () => {
4092
+ const target = wrappedStore[$TARGET];
4093
+ if (target?.[STORE_OPTIMISTIC_OVERRIDE]) clearOptimisticOverride(target);
4094
+ };
3731
4095
  const wrapCommit = write => {
4096
+ const wasProjectionWriteActive = projectionWriteActive;
3732
4097
  setProjectionWriteActive(true);
3733
4098
  try {
3734
4099
  write();
4100
+ clearProjectionOverride();
3735
4101
  } finally {
3736
- setProjectionWriteActive(false);
4102
+ setProjectionWriteActive(wasProjectionWriteActive);
3737
4103
  }
3738
4104
  };
3739
4105
  node = computed(
3740
4106
  () => {
3741
4107
  setProjectionWriteActive(true);
3742
4108
  try {
3743
- runProjectionComputed(wrappedStore, fn, options?.key || "id", wrapCommit);
4109
+ runProjectionComputed(
4110
+ wrappedStore,
4111
+ fn,
4112
+ options?.key || "id",
4113
+ wrapCommit,
4114
+ clearProjectionOverride
4115
+ );
3744
4116
  } finally {
3745
4117
  setProjectionWriteActive(false);
3746
4118
  }
@@ -3806,10 +4178,10 @@ function updatePath(current, args, i = 0) {
3806
4178
  (isWrappable(prev) && isWrappable(value) && !Array.isArray(value))
3807
4179
  ) {
3808
4180
  const target = part !== undefined ? current[part] : current;
3809
- const keys = Object.keys(value);
4181
+ const keys = ownEnumerableKeys(value);
3810
4182
  for (let i = 0; i < keys.length; i++) {
3811
4183
  const key = keys[i];
3812
- if (isPrototypePollutionKey(key)) continue;
4184
+ if (typeof key === "string" && isPrototypePollutionKey(key)) continue;
3813
4185
  const desc = Object.getOwnPropertyDescriptor(value, key);
3814
4186
  if (desc.get || desc.set) Object.defineProperty(target, key, desc);
3815
4187
  else target[key] = desc.value;
@@ -3826,6 +4198,11 @@ const storePath = Object.assign(
3826
4198
  },
3827
4199
  { DELETE: DELETE }
3828
4200
  );
4201
+ function mergedOverlay(target) {
4202
+ const override = target[STORE_OVERRIDE];
4203
+ const opt = target[STORE_OPTIMISTIC_OVERRIDE];
4204
+ return override && opt ? { ...override, ...opt } : (opt ?? override);
4205
+ }
3829
4206
  function snapshotImpl(item, track, map, lookup) {
3830
4207
  let target, isArray, override, result, unwrapped, v;
3831
4208
  if (!isWrappable(item)) return item;
@@ -3833,7 +4210,7 @@ function snapshotImpl(item, track, map, lookup) {
3833
4210
  if (!map) map = new Map();
3834
4211
  if ((target = item[$TARGET] || lookup?.get(item)?.[$TARGET])) {
3835
4212
  if (track) trackSelf(target, $TRACK);
3836
- override = target[STORE_OVERRIDE];
4213
+ override = mergedOverlay(target);
3837
4214
  isArray = Array.isArray(target[STORE_VALUE]);
3838
4215
  map.set(
3839
4216
  item,
@@ -3842,13 +4219,13 @@ function snapshotImpl(item, track, map, lookup) {
3842
4219
  : target[STORE_VALUE]
3843
4220
  );
3844
4221
  item = target[STORE_VALUE];
3845
- lookup = storeLookup;
4222
+ lookup = target[STORE_LOOKUP] ?? storeLookup;
3846
4223
  } else {
3847
4224
  isArray = Array.isArray(item);
3848
4225
  map.set(item, item);
3849
4226
  }
3850
4227
  if (isArray) {
3851
- const len = override?.length || item.length;
4228
+ const len = override?.length ?? item.length;
3852
4229
  for (let i = 0; i < len; i++) {
3853
4230
  v = override && i in override ? override[i] : item[i];
3854
4231
  if (v === $DELETED) continue;
@@ -3858,13 +4235,30 @@ function snapshotImpl(item, track, map, lookup) {
3858
4235
  result[i] = unwrapped;
3859
4236
  }
3860
4237
  }
4238
+ if (result) result.length = len;
4239
+ } else if (!override) {
4240
+ const keys = getKeys(item, undefined);
4241
+ for (let i = 0, l = keys.length; i < l; i++) {
4242
+ const prop = keys[i];
4243
+ const desc = Object.getOwnPropertyDescriptor(item, prop);
4244
+ if (desc.get) continue;
4245
+ v = desc.value;
4246
+ if (track && isWrappable(v)) wrap(v, target);
4247
+ if ((unwrapped = snapshotImpl(v, track, map, lookup)) !== v || result) {
4248
+ if (!result) {
4249
+ result = Object.create(Object.getPrototypeOf(item));
4250
+ Object.assign(result, item);
4251
+ }
4252
+ result[prop] = unwrapped;
4253
+ }
4254
+ }
3861
4255
  } else {
3862
4256
  const keys = getKeys(item, override);
3863
4257
  for (let i = 0, l = keys.length; i < l; i++) {
3864
4258
  let prop = keys[i];
3865
4259
  const desc = getPropertyDescriptor(item, override, prop);
3866
4260
  if (desc.get) continue;
3867
- v = override && prop in override ? override[prop] : item[prop];
4261
+ v = prop in override ? override[prop] : item[prop];
3868
4262
  if (track && isWrappable(v)) wrap(v, target);
3869
4263
  if ((unwrapped = snapshotImpl(v, track, map, lookup)) !== item[prop] || result) {
3870
4264
  if (!result) {
@@ -3947,7 +4341,7 @@ function merge(...sources) {
3947
4341
  keys() {
3948
4342
  const keys = new Set();
3949
4343
  for (let i = 0; i < flattened.length; i++) {
3950
- const sourceKeys = Object.keys(resolveSource(flattened[i]));
4344
+ const sourceKeys = ownEnumerableKeys(resolveSource(flattened[i]));
3951
4345
  for (let j = 0; j < sourceKeys.length; j++) keys.add(sourceKeys[j]);
3952
4346
  }
3953
4347
  return [...keys];
@@ -4001,7 +4395,7 @@ function omit(props, ...keys) {
4001
4395
  return !keys.includes(property) && property in props;
4002
4396
  },
4003
4397
  keys() {
4004
- return Object.keys(props).filter(k => !keys.includes(k));
4398
+ return ownEnumerableKeys(props).filter(k => !keys.includes(k));
4005
4399
  }
4006
4400
  },
4007
4401
  propTraps
@@ -4220,6 +4614,7 @@ function updateRepeat() {
4220
4614
  this._nodes = [];
4221
4615
  this._mappings = [];
4222
4616
  this._len = 0;
4617
+ this._offset = 0;
4223
4618
  }
4224
4619
  if (this._fallback && !this._mappings[0]) {
4225
4620
  this._mappings[0] = runWithOwner((this._nodes[0] = createOwner()), this._fallback);
@@ -4229,12 +4624,24 @@ function updateRepeat() {
4229
4624
  const to = from + newLen;
4230
4625
  const prevTo = this._offset + this._len;
4231
4626
  if (this._len === 0 && this._nodes[0]) this._nodes[0].dispose();
4627
+ if (from >= prevTo || to <= this._offset) {
4628
+ for (let i = 0; i < this._len; i++) this._nodes[i].dispose();
4629
+ this._nodes = new Array(newLen);
4630
+ this._mappings = new Array(newLen);
4631
+ for (let i = 0; i < newLen; i++)
4632
+ this._mappings[i] = runWithOwner((this._nodes[i] = createOwner()), () =>
4633
+ this._map(from + i)
4634
+ );
4635
+ this._offset = from;
4636
+ this._len = newLen;
4637
+ return;
4638
+ }
4232
4639
  for (let i = to; i < prevTo; i++) this._nodes[i - this._offset].dispose();
4233
4640
  if (this._offset < from) {
4234
- let i = this._offset;
4235
- while (i < from && i < this._len) this._nodes[i++].dispose();
4236
- this._nodes.splice(0, from - this._offset);
4237
- this._mappings.splice(0, from - this._offset);
4641
+ const removed = from - this._offset;
4642
+ for (let i = 0; i < removed && i < this._len; i++) this._nodes[i].dispose();
4643
+ this._nodes.splice(0, removed);
4644
+ this._mappings.splice(0, removed);
4238
4645
  } else if (this._offset > from) {
4239
4646
  let i = prevTo - this._offset - 1;
4240
4647
  let difference = this._offset - from;
@@ -4270,7 +4677,13 @@ function boundaryComputed(fn, propagationMask) {
4270
4677
  const flags = status !== undefined ? status : node._statusFlags;
4271
4678
  const actualError = error !== undefined ? error : node._error;
4272
4679
  node._statusFlags &= ~node._propagationMask;
4273
- node._queue.notify(node, node._propagationMask, flags, actualError);
4680
+ node._queue.notify(node, STATUS_PENDING | STATUS_ERROR, flags, actualError);
4681
+ const foreign = flags & ~node._propagationMask & (STATUS_PENDING | STATUS_ERROR);
4682
+ if (foreign) {
4683
+ node._statusFlags &= ~foreign;
4684
+ if (node._error === actualError && !(node._statusFlags & (STATUS_PENDING | STATUS_ERROR)))
4685
+ node._error = undefined;
4686
+ }
4274
4687
  };
4275
4688
  node._propagationMask = propagationMask;
4276
4689
  node._config &= ~CONFIG_AUTO_DISPOSE;
@@ -4462,11 +4875,11 @@ class CollectionQueue extends Queue {
4462
4875
  this._sources.clear();
4463
4876
  }
4464
4877
  }
4465
- if (this._collectionType & STATUS_PENDING && this._initialized)
4466
- return super.notify(node, type, flags, error);
4467
4878
  if (this._collectionType & STATUS_PENDING && flags & STATUS_ERROR) {
4468
4879
  return super.notify(node, STATUS_ERROR, flags, error);
4469
4880
  }
4881
+ if (this._collectionType & STATUS_PENDING && this._initialized)
4882
+ return super.notify(node, type, flags, error);
4470
4883
  if (flags & this._collectionType) {
4471
4884
  this._pending = true;
4472
4885
  const source = error?.source || node._error?.source;
@@ -4553,14 +4966,17 @@ function createCollectionBoundary(type, fn, fallback, onFn) {
4553
4966
  cleanup(() => controller.unregister(queue));
4554
4967
  }
4555
4968
  return accessor(
4556
- computed(() => {
4557
- if (!read(queue._disabled)) {
4558
- const resolved = read(tree);
4559
- if (!untrack(() => read(queue._disabled))) return ((queue._initialized = true), resolved);
4560
- }
4561
- if (_revealUsed && read(queue._collapsed)) return undefined;
4562
- return fallback(queue);
4563
- })
4969
+ computed(
4970
+ () => {
4971
+ if (!read(queue._disabled)) {
4972
+ const resolved = read(tree);
4973
+ if (!untrack(() => read(queue._disabled))) return ((queue._initialized = true), resolved);
4974
+ }
4975
+ if (_revealUsed && read(queue._collapsed)) return undefined;
4976
+ return fallback(queue);
4977
+ },
4978
+ { _noSnapshot: true }
4979
+ )
4564
4980
  );
4565
4981
  }
4566
4982
  function createLoadingBoundary(fn, fallback, options) {
@@ -4694,7 +5110,6 @@ export {
4694
5110
  isDisposed,
4695
5111
  isEqual,
4696
5112
  isPending,
4697
- isRefreshing,
4698
5113
  isWrappable,
4699
5114
  latest,
4700
5115
  mapArray,
@@ -4708,6 +5123,7 @@ export {
4708
5123
  refresh,
4709
5124
  releaseSnapshotScope,
4710
5125
  repeat,
5126
+ resetErrorHalt,
4711
5127
  resolve,
4712
5128
  runWithOwner,
4713
5129
  setContext,