@solidjs/signals 2.0.0-beta.10 → 2.0.0-beta.11

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 (80) hide show
  1. package/dist/dev.js +757 -383
  2. package/dist/node.cjs +1839 -1523
  3. package/dist/prod.js +1546 -1219
  4. package/dist/types/boundaries.d.ts +2 -2
  5. package/dist/types/core/constants.d.ts +8 -6
  6. package/dist/types/core/core.d.ts +29 -8
  7. package/dist/types/core/dev.d.ts +1 -1
  8. package/dist/types/core/effect.d.ts +1 -0
  9. package/dist/types/core/graph.d.ts +1 -0
  10. package/dist/types/core/index.d.ts +1 -1
  11. package/dist/types/core/scheduler.d.ts +19 -3
  12. package/dist/types/core/types.d.ts +2 -0
  13. package/dist/types/index.d.ts +1 -1
  14. package/dist/types/signals.d.ts +25 -4
  15. package/dist/types/src/boundaries.d.ts +173 -0
  16. package/dist/types/src/core/action.d.ts +35 -0
  17. package/dist/types/src/core/async.d.ts +6 -0
  18. package/dist/types/src/core/constants.d.ts +51 -0
  19. package/dist/types/src/core/context.d.ts +36 -0
  20. package/dist/types/src/core/core.d.ts +174 -0
  21. package/dist/types/src/core/dev.d.ts +49 -0
  22. package/dist/types/src/core/effect.d.ts +32 -0
  23. package/dist/types/src/core/error.d.ts +38 -0
  24. package/dist/types/src/core/external.d.ts +45 -0
  25. package/dist/types/src/core/graph.d.ts +5 -0
  26. package/dist/types/src/core/heap.d.ts +14 -0
  27. package/dist/types/src/core/index.d.ts +12 -0
  28. package/dist/types/src/core/lanes.d.ts +54 -0
  29. package/dist/types/src/core/owner.d.ts +116 -0
  30. package/dist/types/src/core/scheduler.d.ts +122 -0
  31. package/dist/types/src/core/types.d.ts +85 -0
  32. package/dist/types/src/index.d.ts +9 -0
  33. package/dist/types/src/map.d.ts +53 -0
  34. package/dist/types/src/signals.d.ts +512 -0
  35. package/dist/types/src/store/index.d.ts +9 -0
  36. package/dist/types/src/store/optimistic.d.ts +45 -0
  37. package/dist/types/src/store/projection.d.ts +66 -0
  38. package/dist/types/src/store/reconcile.d.ts +23 -0
  39. package/dist/types/src/store/store.d.ts +125 -0
  40. package/dist/types/src/store/storePath.d.ts +58 -0
  41. package/dist/types/src/store/utils.d.ts +114 -0
  42. package/dist/types-cjs/boundaries.d.cts +2 -2
  43. package/dist/types-cjs/core/constants.d.cts +8 -6
  44. package/dist/types-cjs/core/core.d.cts +29 -8
  45. package/dist/types-cjs/core/dev.d.cts +1 -1
  46. package/dist/types-cjs/core/effect.d.cts +1 -0
  47. package/dist/types-cjs/core/graph.d.cts +1 -0
  48. package/dist/types-cjs/core/index.d.cts +1 -1
  49. package/dist/types-cjs/core/scheduler.d.cts +19 -3
  50. package/dist/types-cjs/core/types.d.cts +2 -0
  51. package/dist/types-cjs/index.d.cts +1 -1
  52. package/dist/types-cjs/signals.d.cts +25 -4
  53. package/dist/types-cjs/src/boundaries.d.cts +173 -0
  54. package/dist/types-cjs/src/core/action.d.cts +35 -0
  55. package/dist/types-cjs/src/core/async.d.cts +6 -0
  56. package/dist/types-cjs/src/core/constants.d.cts +51 -0
  57. package/dist/types-cjs/src/core/context.d.cts +36 -0
  58. package/dist/types-cjs/src/core/core.d.cts +174 -0
  59. package/dist/types-cjs/src/core/dev.d.cts +49 -0
  60. package/dist/types-cjs/src/core/effect.d.cts +32 -0
  61. package/dist/types-cjs/src/core/error.d.cts +38 -0
  62. package/dist/types-cjs/src/core/external.d.cts +45 -0
  63. package/dist/types-cjs/src/core/graph.d.cts +5 -0
  64. package/dist/types-cjs/src/core/heap.d.cts +14 -0
  65. package/dist/types-cjs/src/core/index.d.cts +12 -0
  66. package/dist/types-cjs/src/core/lanes.d.cts +54 -0
  67. package/dist/types-cjs/src/core/owner.d.cts +116 -0
  68. package/dist/types-cjs/src/core/scheduler.d.cts +122 -0
  69. package/dist/types-cjs/src/core/types.d.cts +85 -0
  70. package/dist/types-cjs/src/index.d.cts +9 -0
  71. package/dist/types-cjs/src/map.d.cts +53 -0
  72. package/dist/types-cjs/src/signals.d.cts +512 -0
  73. package/dist/types-cjs/src/store/index.d.cts +9 -0
  74. package/dist/types-cjs/src/store/optimistic.d.cts +45 -0
  75. package/dist/types-cjs/src/store/projection.d.cts +66 -0
  76. package/dist/types-cjs/src/store/reconcile.d.cts +23 -0
  77. package/dist/types-cjs/src/store/store.d.cts +125 -0
  78. package/dist/types-cjs/src/store/storePath.d.cts +58 -0
  79. package/dist/types-cjs/src/store/utils.d.cts +114 -0
  80. package/package.json +4 -4
package/dist/dev.js CHANGED
@@ -35,12 +35,14 @@ const REACTIVE_DISPOSED = 1 << 6;
35
35
  const REACTIVE_OPTIMISTIC_DIRTY = 1 << 7;
36
36
  const REACTIVE_SNAPSHOT_STALE = 1 << 8;
37
37
  const REACTIVE_LAZY = 1 << 9;
38
+ const REACTIVE_MANUAL_WRITE = 1 << 10;
38
39
  const CONFIG_OWNED_WRITE = 1 << 0;
39
40
  const CONFIG_NO_SNAPSHOT = 1 << 1;
40
41
  const CONFIG_TRANSPARENT = 1 << 2;
41
42
  const CONFIG_IN_SNAPSHOT_SCOPE = 1 << 3;
42
43
  const CONFIG_CHILDREN_FORBIDDEN = 1 << 4;
43
44
  const CONFIG_AUTO_DISPOSE = 1 << 5;
45
+ const CONFIG_SYNC = 1 << 6;
44
46
  const STATUS_PENDING = 1 << 0;
45
47
  const STATUS_ERROR = 1 << 1;
46
48
  const STATUS_UNINITIALIZED = 1 << 2;
@@ -53,6 +55,91 @@ const STORE_SNAPSHOT_PROPS = "sp";
53
55
  const SUPPORTS_PROXY = typeof Proxy === "function";
54
56
  const defaultContext = {};
55
57
  const $REFRESH = Symbol("refresh");
58
+ const hooks = {};
59
+ const diagnosticListeners = new Set();
60
+ const diagnosticCaptures = new Set();
61
+ let diagnosticSequence = 0;
62
+ const diagnostics = {
63
+ subscribe(listener) {
64
+ diagnosticListeners.add(listener);
65
+ return () => diagnosticListeners.delete(listener);
66
+ },
67
+ capture() {
68
+ const events = [];
69
+ diagnosticCaptures.add(events);
70
+ return {
71
+ get events() {
72
+ return events;
73
+ },
74
+ clear() {
75
+ events.length = 0;
76
+ },
77
+ stop() {
78
+ diagnosticCaptures.delete(events);
79
+ return [...events];
80
+ }
81
+ };
82
+ }
83
+ };
84
+ const DEV$1 = {
85
+ hooks: hooks,
86
+ diagnostics: diagnostics,
87
+ getChildren: getChildren,
88
+ getSignals: getSignals,
89
+ getParent: getParent,
90
+ getSources: getSources,
91
+ getObservers: getObservers
92
+ };
93
+ function emitDiagnostic(event) {
94
+ const entry = { sequence: ++diagnosticSequence, ...event };
95
+ for (const listener of diagnosticListeners) listener(entry);
96
+ for (const capture of diagnosticCaptures) capture.push(entry);
97
+ return entry;
98
+ }
99
+ function registerGraph(value, owner) {
100
+ value._owner = owner;
101
+ if (owner) {
102
+ if (!owner._signals) owner._signals = [];
103
+ owner._signals.push(value);
104
+ }
105
+ DEV$1.hooks.onGraph?.(value, owner);
106
+ }
107
+ function clearSignals(node) {
108
+ node._signals = undefined;
109
+ }
110
+ function getChildren(owner) {
111
+ const children = [];
112
+ let child = owner._firstChild;
113
+ while (child) {
114
+ children.push(child);
115
+ child = child._nextSibling;
116
+ }
117
+ return children;
118
+ }
119
+ function getSignals(owner) {
120
+ return owner._signals ? [...owner._signals] : [];
121
+ }
122
+ function getParent(owner) {
123
+ return owner._parent;
124
+ }
125
+ function getSources(computation) {
126
+ const sources = [];
127
+ let link = computation._deps;
128
+ while (link) {
129
+ sources.push(link._dep);
130
+ link = link._nextDep;
131
+ }
132
+ return sources;
133
+ }
134
+ function getObservers(node) {
135
+ const observers = [];
136
+ let link = node._subs;
137
+ while (link) {
138
+ observers.push(link._sub);
139
+ link = link._nextSub;
140
+ }
141
+ return observers;
142
+ }
56
143
  function actualInsertIntoHeap(n, heap) {
57
144
  const parentHeight =
58
145
  (n._parent?._root ? n._parent._parentComputed?._height : n._parent?._height) ?? -1;
@@ -70,7 +157,7 @@ function actualInsertIntoHeap(n, heap) {
70
157
  }
71
158
  function insertIntoHeap(n, heap) {
72
159
  let flags = n._flags;
73
- if (flags & (REACTIVE_IN_HEAP | REACTIVE_RECOMPUTING_DEPS)) return;
160
+ if (flags & (REACTIVE_IN_HEAP | REACTIVE_RECOMPUTING_DEPS | REACTIVE_MANUAL_WRITE)) return;
74
161
  if (flags & REACTIVE_CHECK) {
75
162
  n._flags = (flags & -4) | REACTIVE_DIRTY | REACTIVE_IN_HEAP;
76
163
  } else n._flags = flags | REACTIVE_IN_HEAP;
@@ -78,7 +165,11 @@ function insertIntoHeap(n, heap) {
78
165
  }
79
166
  function insertIntoHeapHeight(n, heap) {
80
167
  let flags = n._flags;
81
- if (flags & (REACTIVE_IN_HEAP | REACTIVE_RECOMPUTING_DEPS | REACTIVE_IN_HEAP_HEIGHT)) return;
168
+ if (
169
+ flags &
170
+ (REACTIVE_IN_HEAP | REACTIVE_RECOMPUTING_DEPS | REACTIVE_IN_HEAP_HEIGHT | REACTIVE_MANUAL_WRITE)
171
+ )
172
+ return;
82
173
  n._flags = flags | REACTIVE_IN_HEAP_HEIGHT;
83
174
  actualInsertIntoHeap(n, heap);
84
175
  }
@@ -150,90 +241,76 @@ function adjustHeight(el, heap) {
150
241
  }
151
242
  }
152
243
  }
153
- const hooks = {};
154
- const diagnosticListeners = new Set();
155
- const diagnosticCaptures = new Set();
156
- let diagnosticSequence = 0;
157
- const diagnostics = {
158
- subscribe(listener) {
159
- diagnosticListeners.add(listener);
160
- return () => diagnosticListeners.delete(listener);
161
- },
162
- capture() {
163
- const events = [];
164
- diagnosticCaptures.add(events);
165
- return {
166
- get events() {
167
- return events;
168
- },
169
- clear() {
170
- events.length = 0;
171
- },
172
- stop() {
173
- diagnosticCaptures.delete(events);
174
- return [...events];
175
- }
176
- };
177
- }
178
- };
179
- const DEV$1 = {
180
- hooks: hooks,
181
- diagnostics: diagnostics,
182
- getChildren: getChildren,
183
- getSignals: getSignals,
184
- getParent: getParent,
185
- getSources: getSources,
186
- getObservers: getObservers
187
- };
188
- function emitDiagnostic(event) {
189
- const entry = { sequence: ++diagnosticSequence, ...event };
190
- for (const listener of diagnosticListeners) listener(entry);
191
- for (const capture of diagnosticCaptures) capture.push(entry);
192
- return entry;
193
- }
194
- function registerGraph(value, owner) {
195
- value._owner = owner;
196
- if (owner) {
197
- if (!owner._signals) owner._signals = [];
198
- owner._signals.push(value);
244
+ const signalLanes = new WeakMap();
245
+ const activeLanes = new Set();
246
+ function getOrCreateLane(signal) {
247
+ let lane = signalLanes.get(signal);
248
+ if (lane) {
249
+ return findLane(lane);
199
250
  }
200
- DEV$1.hooks.onGraph?.(value, owner);
251
+ const parentSource = signal._parentSource;
252
+ const parentLane = parentSource?._optimisticLane ? findLane(parentSource._optimisticLane) : null;
253
+ lane = {
254
+ _source: signal,
255
+ _pendingAsync: new Set(),
256
+ _effectQueues: [[], []],
257
+ _mergedInto: null,
258
+ _transition: activeTransition,
259
+ _parentLane: parentLane
260
+ };
261
+ signalLanes.set(signal, lane);
262
+ activeLanes.add(lane);
263
+ signal._overrideSinceLane = false;
264
+ return lane;
201
265
  }
202
- function clearSignals(node) {
203
- node._signals = undefined;
266
+ function findLane(lane) {
267
+ while (lane._mergedInto) lane = lane._mergedInto;
268
+ return lane;
204
269
  }
205
- function getChildren(owner) {
206
- const children = [];
207
- let child = owner._firstChild;
208
- while (child) {
209
- children.push(child);
210
- child = child._nextSibling;
211
- }
212
- return children;
270
+ function mergeLanes(lane1, lane2) {
271
+ lane1 = findLane(lane1);
272
+ lane2 = findLane(lane2);
273
+ if (lane1 === lane2) return lane1;
274
+ lane2._mergedInto = lane1;
275
+ for (const node of lane2._pendingAsync) lane1._pendingAsync.add(node);
276
+ lane1._effectQueues[0].push(...lane2._effectQueues[0]);
277
+ lane1._effectQueues[1].push(...lane2._effectQueues[1]);
278
+ return lane1;
213
279
  }
214
- function getSignals(owner) {
215
- return owner._signals ? [...owner._signals] : [];
280
+ function resolveLane(el) {
281
+ const lane = el._optimisticLane;
282
+ if (!lane) return undefined;
283
+ const root = findLane(lane);
284
+ if (activeLanes.has(root)) return root;
285
+ el._optimisticLane = undefined;
286
+ return undefined;
216
287
  }
217
- function getParent(owner) {
218
- return owner._parent;
288
+ function resolveTransition(el) {
289
+ return resolveLane(el)?._transition ?? el._transition;
219
290
  }
220
- function getSources(computation) {
221
- const sources = [];
222
- let link = computation._deps;
223
- while (link) {
224
- sources.push(link._dep);
225
- link = link._nextDep;
226
- }
227
- return sources;
291
+ function hasActiveOverride(el) {
292
+ return !!(el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING);
228
293
  }
229
- function getObservers(node) {
230
- const observers = [];
231
- let link = node._subs;
232
- while (link) {
233
- observers.push(link._sub);
234
- link = link._nextSub;
294
+ function assignOrMergeLane(el, sourceLane) {
295
+ const sourceRoot = findLane(sourceLane);
296
+ const existing = el._optimisticLane;
297
+ if (existing) {
298
+ if (existing._mergedInto) {
299
+ el._optimisticLane = sourceLane;
300
+ return;
301
+ }
302
+ const existingRoot = findLane(existing);
303
+ if (activeLanes.has(existingRoot)) {
304
+ if (existingRoot !== sourceRoot && !hasActiveOverride(el)) {
305
+ if (sourceRoot._parentLane && findLane(sourceRoot._parentLane) === existingRoot) {
306
+ el._optimisticLane = sourceLane;
307
+ } else if (existingRoot._parentLane && findLane(existingRoot._parentLane) === sourceRoot);
308
+ else mergeLanes(sourceRoot, existingRoot);
309
+ }
310
+ return;
311
+ }
235
312
  }
236
- return observers;
313
+ el._optimisticLane = sourceLane;
237
314
  }
238
315
  const transitions = new Set();
239
316
  const dirtyQueue = { _heap: new Array(2e3).fill(undefined), _marked: false, _min: 0, _max: 0 };
@@ -241,6 +318,7 @@ const zombieQueue = { _heap: new Array(2e3).fill(undefined), _marked: false, _mi
241
318
  let clock = 0;
242
319
  let activeTransition = null;
243
320
  let scheduled = false;
321
+ let syncDepth = 0;
244
322
  let projectionWriteActive = false;
245
323
  let inTrackedQueueCallback = false;
246
324
  let _enforceLoadingBoundary = false;
@@ -250,6 +328,16 @@ const transientStoreNodes = new Set();
250
328
  function registerTransientStoreNode(node) {
251
329
  transientStoreNodes.add(node);
252
330
  }
331
+ function canUseSimpleSyncFlush(queue) {
332
+ return (
333
+ transitions.size === 0 &&
334
+ activeLanes.size === 0 &&
335
+ queue._children.length === 0 &&
336
+ queue._optimisticNodes.length === 0 &&
337
+ queue._optimisticStores.size === 0 &&
338
+ transientStoreNodes.size === 0
339
+ );
340
+ }
253
341
  function sweepTransientStoreNodes() {
254
342
  if (transientStoreNodes.size === 0) return;
255
343
  for (const node of transientStoreNodes) {
@@ -353,7 +441,7 @@ function cleanupCompletedLanes(completingTransition) {
353
441
  function schedule() {
354
442
  if (scheduled) return;
355
443
  scheduled = true;
356
- if (!globalQueue._running && !projectionWriteActive) queueMicrotask(flush);
444
+ if (!syncDepth && !globalQueue._running && !projectionWriteActive) queueMicrotask(flush);
357
445
  }
358
446
  class Queue {
359
447
  _parent = null;
@@ -420,11 +508,13 @@ class Queue {
420
508
  }
421
509
  class GlobalQueue extends Queue {
422
510
  _running = false;
511
+ _pendingNode = null;
423
512
  _pendingNodes = [];
424
513
  _optimisticNodes = [];
425
514
  _optimisticStores = new Set();
426
515
  static _update;
427
516
  static _dispose;
517
+ static _runEffect;
428
518
  static _clearOptimisticStore = null;
429
519
  flush() {
430
520
  if (this._running) return;
@@ -436,6 +526,7 @@ class GlobalQueue extends Queue {
436
526
  if (!isComplete) {
437
527
  const stashedTransition = activeTransition;
438
528
  runHeap(zombieQueue, GlobalQueue._update);
529
+ this._pendingNode = null;
439
530
  this._pendingNodes = [];
440
531
  this._optimisticNodes = [];
441
532
  this._optimisticStores = new Set();
@@ -475,14 +566,22 @@ class GlobalQueue extends Queue {
475
566
  reassignPendingTransition(this._pendingNodes);
476
567
  finalizePureQueue(completingTransition);
477
568
  } else {
478
- if (transitions.size) runHeap(zombieQueue, GlobalQueue._update);
479
- finalizePureQueue();
569
+ if (canUseSimpleSyncFlush(this)) {
570
+ commitPendingNodes();
571
+ if (dirtyQueue._max >= dirtyQueue._min) {
572
+ runHeap(dirtyQueue, GlobalQueue._update);
573
+ commitPendingNodes();
574
+ }
575
+ } else {
576
+ if (transitions.size) runHeap(zombieQueue, GlobalQueue._update);
577
+ finalizePureQueue();
578
+ }
480
579
  }
481
580
  clock++;
482
581
  scheduled = dirtyQueue._max >= dirtyQueue._min;
483
- runLaneEffects(EFFECT_RENDER);
582
+ activeLanes.size && runLaneEffects(EFFECT_RENDER);
484
583
  this.run(EFFECT_RENDER);
485
- runLaneEffects(EFFECT_USER);
584
+ activeLanes.size && runLaneEffects(EFFECT_USER);
486
585
  this.run(EFFECT_USER);
487
586
  if (true) DEV$1.hooks.onUpdate?.();
488
587
  } finally {
@@ -531,6 +630,11 @@ class GlobalQueue extends Queue {
531
630
  }
532
631
  transitions.add(activeTransition);
533
632
  activeTransition._time = clock;
633
+ if (this._pendingNode !== null) {
634
+ this._pendingNode._transition = activeTransition;
635
+ activeTransition._pendingNodes.push(this._pendingNode);
636
+ this._pendingNode = null;
637
+ }
534
638
  if (this._pendingNodes !== activeTransition._pendingNodes) {
535
639
  for (let i = 0; i < this._pendingNodes.length; i++) {
536
640
  const node = this._pendingNodes[i];
@@ -556,6 +660,21 @@ class GlobalQueue extends Queue {
556
660
  }
557
661
  }
558
662
  }
663
+ function queuePendingNode(node) {
664
+ if (activeTransition) {
665
+ globalQueue._pendingNodes.push(node);
666
+ return;
667
+ }
668
+ if (globalQueue._pendingNode === null && globalQueue._pendingNodes.length === 0) {
669
+ globalQueue._pendingNode = node;
670
+ return;
671
+ }
672
+ if (globalQueue._pendingNode !== null) {
673
+ globalQueue._pendingNodes.push(globalQueue._pendingNode);
674
+ globalQueue._pendingNode = null;
675
+ }
676
+ globalQueue._pendingNodes.push(node);
677
+ }
559
678
  function insertSubs(node, optimistic = false) {
560
679
  const sourceLane = node._optimisticLane || currentOptimisticLane;
561
680
  const hasSnapshot = node._snapshotValue !== undefined;
@@ -584,27 +703,44 @@ function insertSubs(node, optimistic = false) {
584
703
  insertIntoHeap(s._sub, queue);
585
704
  }
586
705
  }
587
- function commitPendingNodes() {
588
- const pendingNodes = globalQueue._pendingNodes;
589
- for (let i = 0; i < pendingNodes.length; i++) {
590
- const n = pendingNodes[i];
706
+ function commitPendingNode(n) {
707
+ const c = n;
708
+ if (!c._fn) {
591
709
  if (n._pendingValue !== NOT_PENDING) {
592
710
  n._value = n._pendingValue;
593
711
  n._pendingValue = NOT_PENDING;
594
- if (n._type && n._type !== EFFECT_TRACKED) n._modified = true;
595
712
  }
596
- if (!(n._statusFlags & STATUS_PENDING)) n._statusFlags &= ~STATUS_UNINITIALIZED;
597
- if (n._fn) GlobalQueue._dispose(n, false, true);
713
+ return;
714
+ }
715
+ if (n._pendingValue !== NOT_PENDING) {
716
+ n._value = n._pendingValue;
717
+ n._pendingValue = NOT_PENDING;
718
+ if (n._type && n._type !== EFFECT_TRACKED) n._modified = true;
719
+ }
720
+ c._flags &= ~REACTIVE_MANUAL_WRITE;
721
+ if (!(c._statusFlags & STATUS_PENDING)) c._statusFlags &= ~STATUS_UNINITIALIZED;
722
+ if (c._pendingFirstChild !== null || c._pendingDisposal !== null)
723
+ GlobalQueue._dispose(c, false, true);
724
+ }
725
+ function commitPendingNodes() {
726
+ if (globalQueue._pendingNode !== null) {
727
+ commitPendingNode(globalQueue._pendingNode);
728
+ globalQueue._pendingNode = null;
729
+ }
730
+ const pendingNodes = globalQueue._pendingNodes;
731
+ for (let i = 0; i < pendingNodes.length; i++) {
732
+ commitPendingNode(pendingNodes[i]);
598
733
  }
599
734
  pendingNodes.length = 0;
600
735
  }
601
736
  function finalizePureQueue(completingTransition = null, incomplete = false) {
602
737
  const resolvePending = !incomplete;
603
738
  if (resolvePending) commitPendingNodes();
604
- if (!incomplete) checkBoundaryChildren(globalQueue);
605
- if (dirtyQueue._max >= dirtyQueue._min) runHeap(dirtyQueue, GlobalQueue._update);
739
+ if (!incomplete && globalQueue._children.length) checkBoundaryChildren(globalQueue);
740
+ const ranHeap = dirtyQueue._max >= dirtyQueue._min;
741
+ if (ranHeap) runHeap(dirtyQueue, GlobalQueue._update);
606
742
  if (resolvePending) {
607
- commitPendingNodes();
743
+ if (ranHeap) commitPendingNodes();
608
744
  resolveOptimisticNodes(
609
745
  completingTransition ? completingTransition._optimisticNodes : globalQueue._optimisticNodes
610
746
  );
@@ -654,7 +790,16 @@ function reassignPendingTransition(pendingNodes) {
654
790
  }
655
791
  }
656
792
  const globalQueue = new GlobalQueue();
657
- function flush() {
793
+ function flush(fn) {
794
+ if (fn) {
795
+ syncDepth++;
796
+ try {
797
+ return fn();
798
+ } finally {
799
+ flush();
800
+ syncDepth--;
801
+ }
802
+ }
658
803
  if (globalQueue._running) {
659
804
  if (inTrackedQueueCallback) {
660
805
  throw new Error(
@@ -741,141 +886,6 @@ function runInTransition(transition, fn) {
741
886
  activeTransition = prevTransition;
742
887
  }
743
888
  }
744
- const signalLanes = new WeakMap();
745
- const activeLanes = new Set();
746
- function getOrCreateLane(signal) {
747
- let lane = signalLanes.get(signal);
748
- if (lane) {
749
- return findLane(lane);
750
- }
751
- const parentSource = signal._parentSource;
752
- const parentLane = parentSource?._optimisticLane ? findLane(parentSource._optimisticLane) : null;
753
- lane = {
754
- _source: signal,
755
- _pendingAsync: new Set(),
756
- _effectQueues: [[], []],
757
- _mergedInto: null,
758
- _transition: activeTransition,
759
- _parentLane: parentLane
760
- };
761
- signalLanes.set(signal, lane);
762
- activeLanes.add(lane);
763
- signal._overrideSinceLane = false;
764
- return lane;
765
- }
766
- function findLane(lane) {
767
- while (lane._mergedInto) lane = lane._mergedInto;
768
- return lane;
769
- }
770
- function mergeLanes(lane1, lane2) {
771
- lane1 = findLane(lane1);
772
- lane2 = findLane(lane2);
773
- if (lane1 === lane2) return lane1;
774
- lane2._mergedInto = lane1;
775
- for (const node of lane2._pendingAsync) lane1._pendingAsync.add(node);
776
- lane1._effectQueues[0].push(...lane2._effectQueues[0]);
777
- lane1._effectQueues[1].push(...lane2._effectQueues[1]);
778
- return lane1;
779
- }
780
- function resolveLane(el) {
781
- const lane = el._optimisticLane;
782
- if (!lane) return undefined;
783
- const root = findLane(lane);
784
- if (activeLanes.has(root)) return root;
785
- el._optimisticLane = undefined;
786
- return undefined;
787
- }
788
- function resolveTransition(el) {
789
- return resolveLane(el)?._transition ?? el._transition;
790
- }
791
- function hasActiveOverride(el) {
792
- return !!(el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING);
793
- }
794
- function assignOrMergeLane(el, sourceLane) {
795
- const sourceRoot = findLane(sourceLane);
796
- const existing = el._optimisticLane;
797
- if (existing) {
798
- if (existing._mergedInto) {
799
- el._optimisticLane = sourceLane;
800
- return;
801
- }
802
- const existingRoot = findLane(existing);
803
- if (activeLanes.has(existingRoot)) {
804
- if (existingRoot !== sourceRoot && !hasActiveOverride(el)) {
805
- if (sourceRoot._parentLane && findLane(sourceRoot._parentLane) === existingRoot) {
806
- el._optimisticLane = sourceLane;
807
- } else if (existingRoot._parentLane && findLane(existingRoot._parentLane) === sourceRoot);
808
- else mergeLanes(sourceRoot, existingRoot);
809
- }
810
- return;
811
- }
812
- }
813
- el._optimisticLane = sourceLane;
814
- }
815
- function unlinkSubs(link) {
816
- const dep = link._dep;
817
- const nextDep = link._nextDep;
818
- const nextSub = link._nextSub;
819
- const prevSub = link._prevSub;
820
- if (nextSub !== null) nextSub._prevSub = prevSub;
821
- else dep._subsTail = prevSub;
822
- if (prevSub !== null) prevSub._nextSub = nextSub;
823
- else {
824
- dep._subs = nextSub;
825
- if (nextSub === null) {
826
- dep._unobserved?.();
827
- const c = dep;
828
- c._fn && c._config & CONFIG_AUTO_DISPOSE && !(c._flags & REACTIVE_ZOMBIE) && unobserved(c);
829
- }
830
- }
831
- return nextDep;
832
- }
833
- function unobserved(el) {
834
- deleteFromHeap(el, el._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
835
- let dep = el._deps;
836
- while (dep !== null) {
837
- dep = unlinkSubs(dep);
838
- }
839
- el._deps = null;
840
- el._depsTail = null;
841
- disposeChildren(el, true);
842
- }
843
- function link(dep, sub) {
844
- const prevDep = sub._depsTail;
845
- if (prevDep !== null && prevDep._dep === dep) return;
846
- let nextDep = null;
847
- const isRecomputing = sub._flags & REACTIVE_RECOMPUTING_DEPS;
848
- if (isRecomputing) {
849
- nextDep = prevDep !== null ? prevDep._nextDep : sub._deps;
850
- if (nextDep !== null && nextDep._dep === dep) {
851
- sub._depsTail = nextDep;
852
- return;
853
- }
854
- }
855
- const prevSub = dep._subsTail;
856
- if (prevSub !== null && prevSub._sub === sub && (!isRecomputing || isValidLink(prevSub, sub)))
857
- return;
858
- const newLink =
859
- (sub._depsTail =
860
- dep._subsTail =
861
- { _dep: dep, _sub: sub, _nextDep: nextDep, _prevSub: prevSub, _nextSub: null });
862
- if (prevDep !== null) prevDep._nextDep = newLink;
863
- else sub._deps = newLink;
864
- if (prevSub !== null) prevSub._nextSub = newLink;
865
- else dep._subs = newLink;
866
- }
867
- function isValidLink(checkLink, sub) {
868
- const depsTail = sub._depsTail;
869
- if (depsTail !== null) {
870
- let link = sub._deps;
871
- do {
872
- if (link === checkLink) return true;
873
- if (link === depsTail) break;
874
- link = link._nextDep;
875
- } while (link !== null);
876
- }
877
- return false;
878
- }
879
889
  const PENDING_OWNER = {};
880
890
  function markDisposal(el) {
881
891
  let child = el._firstChild;
@@ -899,8 +909,9 @@ function dispose(node) {
899
909
  disposeChildren(node, true);
900
910
  }
901
911
  function disposeChildren(node, self = false, zombie) {
902
- if (node._flags & REACTIVE_DISPOSED) return;
903
- if (self) node._flags = REACTIVE_DISPOSED;
912
+ const flags = node._flags;
913
+ if (flags & REACTIVE_DISPOSED) return;
914
+ if (self) node._flags = flags | REACTIVE_DISPOSED;
904
915
  if (self && true) clearSignals(node);
905
916
  if (self && node._fn) node._inFlight = null;
906
917
  let child = zombie ? node._pendingFirstChild : node._firstChild;
@@ -925,6 +936,20 @@ function disposeChildren(node, self = false, zombie) {
925
936
  node._firstChild = null;
926
937
  node._childCount = 0;
927
938
  }
939
+ if (
940
+ self &&
941
+ !zombie &&
942
+ !(flags & REACTIVE_ZOMBIE) &&
943
+ node._parent !== null &&
944
+ !(node._parent._flags & REACTIVE_DISPOSED)
945
+ ) {
946
+ const prev = node._prevSibling;
947
+ const next = node._nextSibling;
948
+ if (prev !== null) prev._nextSibling = next;
949
+ else node._parent._firstChild = next;
950
+ if (next !== null) next._prevSibling = prev;
951
+ node._prevSibling = null;
952
+ }
928
953
  runDisposal(node, zombie);
929
954
  }
930
955
  function runDisposal(node, zombie) {
@@ -975,6 +1000,9 @@ function cleanup(fn) {
975
1000
  function isDisposed(node) {
976
1001
  return !!(node._flags & (REACTIVE_DISPOSED | REACTIVE_ZOMBIE));
977
1002
  }
1003
+ function disposeRootSelf(self = true) {
1004
+ disposeChildren(this, self);
1005
+ }
978
1006
  function createOwner(options) {
979
1007
  const parent = context;
980
1008
  const transparent = options?.transparent ?? false;
@@ -987,6 +1015,7 @@ function createOwner(options) {
987
1015
  _parentComputed: parent?._root ? parent._parentComputed : parent,
988
1016
  _firstChild: null,
989
1017
  _nextSibling: null,
1018
+ _prevSibling: null,
990
1019
  _disposal: null,
991
1020
  _queue: parent?._queue ?? globalQueue,
992
1021
  _context: parent?._context || defaultContext,
@@ -994,9 +1023,7 @@ function createOwner(options) {
994
1023
  _pendingDisposal: null,
995
1024
  _pendingFirstChild: null,
996
1025
  _parent: parent,
997
- dispose(self = true) {
998
- disposeChildren(owner, self);
999
- }
1026
+ dispose: disposeRootSelf
1000
1027
  };
1001
1028
  if (parent && parent._config & CONFIG_CHILDREN_FORBIDDEN) {
1002
1029
  emitDiagnostic({
@@ -1015,15 +1042,91 @@ function createOwner(options) {
1015
1042
  parent._firstChild = owner;
1016
1043
  } else {
1017
1044
  owner._nextSibling = lastChild;
1045
+ lastChild._prevSibling = owner;
1018
1046
  parent._firstChild = owner;
1019
1047
  }
1020
1048
  }
1021
1049
  DEV$1.hooks.onOwner?.(owner);
1022
1050
  return owner;
1023
1051
  }
1024
- function createRoot(init, options) {
1025
- const owner = createOwner(options);
1026
- return runWithOwner(owner, () => init(owner.dispose));
1052
+ function createRoot(init, options) {
1053
+ const owner = createOwner(options);
1054
+ return runWithOwner(owner, () => init(() => owner.dispose()));
1055
+ }
1056
+ function unlinkSubs(link) {
1057
+ const dep = link._dep;
1058
+ const nextDep = link._nextDep;
1059
+ const nextSub = link._nextSub;
1060
+ const prevSub = link._prevSub;
1061
+ if (nextSub !== null) nextSub._prevSub = prevSub;
1062
+ else dep._subsTail = prevSub;
1063
+ if (prevSub !== null) prevSub._nextSub = nextSub;
1064
+ else {
1065
+ dep._subs = nextSub;
1066
+ if (nextSub === null) {
1067
+ dep._unobserved?.();
1068
+ const c = dep;
1069
+ c._fn && c._config & CONFIG_AUTO_DISPOSE && !(c._flags & REACTIVE_ZOMBIE) && unobserved(c);
1070
+ }
1071
+ }
1072
+ return nextDep;
1073
+ }
1074
+ function trimStaleDeps(el) {
1075
+ const depsTail = el._depsTail;
1076
+ let toRemove = depsTail !== null ? depsTail._nextDep : el._deps;
1077
+ if (toRemove !== null) {
1078
+ do {
1079
+ toRemove = unlinkSubs(toRemove);
1080
+ } while (toRemove !== null);
1081
+ if (depsTail !== null) depsTail._nextDep = null;
1082
+ else el._deps = null;
1083
+ }
1084
+ }
1085
+ function unobserved(el) {
1086
+ deleteFromHeap(el, el._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
1087
+ let dep = el._deps;
1088
+ while (dep !== null) {
1089
+ dep = unlinkSubs(dep);
1090
+ }
1091
+ el._deps = null;
1092
+ el._depsTail = null;
1093
+ disposeChildren(el, true);
1094
+ }
1095
+ function link(dep, sub) {
1096
+ const prevDep = sub._depsTail;
1097
+ if (prevDep !== null && prevDep._dep === dep) return;
1098
+ let nextDep = null;
1099
+ const isRecomputing = sub._flags & REACTIVE_RECOMPUTING_DEPS;
1100
+ if (isRecomputing) {
1101
+ nextDep = prevDep !== null ? prevDep._nextDep : sub._deps;
1102
+ if (nextDep !== null && nextDep._dep === dep) {
1103
+ sub._depsTail = nextDep;
1104
+ return;
1105
+ }
1106
+ }
1107
+ const prevSub = dep._subsTail;
1108
+ if (prevSub !== null && prevSub._sub === sub && (!isRecomputing || isValidLink(prevSub, sub)))
1109
+ return;
1110
+ const newLink =
1111
+ (sub._depsTail =
1112
+ dep._subsTail =
1113
+ { _dep: dep, _sub: sub, _nextDep: nextDep, _prevSub: prevSub, _nextSub: null });
1114
+ if (prevDep !== null) prevDep._nextDep = newLink;
1115
+ else sub._deps = newLink;
1116
+ if (prevSub !== null) prevSub._nextSub = newLink;
1117
+ else dep._subs = newLink;
1118
+ }
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;
1027
1130
  }
1028
1131
  function addPendingSource(el, source) {
1029
1132
  if (el._pendingSource === source || el._pendingSources?.has(source)) return false;
@@ -1116,13 +1219,34 @@ function settlePendingSource(el) {
1116
1219
  if (scheduled) schedule();
1117
1220
  }
1118
1221
  function handleAsync(el, result, setter) {
1119
- const isObject = typeof result === "object" && result !== null;
1120
- const iterator = isObject && untrack(() => result[Symbol.asyncIterator]);
1121
- const isThenable = !iterator && isObject && untrack(() => typeof result.then === "function");
1222
+ let iterator = false;
1223
+ let isThenable = false;
1224
+ if (typeof result === "object" && result !== null) {
1225
+ untrack(() => {
1226
+ iterator = result[Symbol.asyncIterator];
1227
+ isThenable = !iterator && typeof result.then === "function";
1228
+ });
1229
+ }
1122
1230
  if (!isThenable && !iterator) {
1123
1231
  el._inFlight = null;
1124
1232
  return result;
1125
1233
  }
1234
+ if (el._config & CONFIG_SYNC) {
1235
+ const message =
1236
+ `[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 ` +
1238
+ `never awaited in production; remove \`sync: true\` to use async-aware behavior, or ` +
1239
+ `unwrap the value before returning.`;
1240
+ emitDiagnostic({
1241
+ code: "SYNC_NODE_RECEIVED_ASYNC",
1242
+ kind: "lifecycle",
1243
+ severity: "error",
1244
+ message: message,
1245
+ ownerId: el.id,
1246
+ ownerName: el._name
1247
+ });
1248
+ throw new Error(message);
1249
+ }
1126
1250
  el._inFlight = result;
1127
1251
  let syncValue;
1128
1252
  const handleError = error => {
@@ -1136,6 +1260,7 @@ function handleAsync(el, result, setter) {
1136
1260
  if (el._flags & (REACTIVE_DIRTY | REACTIVE_OPTIMISTIC_DIRTY)) return;
1137
1261
  globalQueue.initTransition(resolveTransition(el));
1138
1262
  const wasUninitialized = !!(el._statusFlags & STATUS_UNINITIALIZED);
1263
+ trimStaleDeps(el);
1139
1264
  clearStatus(el);
1140
1265
  const lane = resolveLane(el);
1141
1266
  if (lane) lane._pendingAsync.delete(el);
@@ -1245,12 +1370,12 @@ function handleAsync(el, result, setter) {
1245
1370
  return syncValue;
1246
1371
  }
1247
1372
  function clearStatus(el, clearUninitialized = false) {
1248
- clearPendingSources(el);
1249
- el._blocked = false;
1373
+ if (el._pendingSource || el._pendingSources) clearPendingSources(el);
1374
+ if (el._blocked) el._blocked = false;
1250
1375
  el._statusFlags = clearUninitialized ? 0 : el._statusFlags & STATUS_UNINITIALIZED;
1251
- setPendingError(el);
1252
- updatePendingSignal(el);
1253
- el._notifyStatus?.();
1376
+ if (el._error) setPendingError(el);
1377
+ if (el._pendingSignal) updatePendingSignal(el);
1378
+ if (el._notifyStatus) el._notifyStatus();
1254
1379
  }
1255
1380
  function notifyStatus(el, status, error, blockStatus, lane) {
1256
1381
  if (
@@ -1304,7 +1429,7 @@ function notifyStatus(el, status, error, blockStatus, lane) {
1304
1429
  (status !== STATUS_PENDING &&
1305
1430
  (sub._error !== error || sub._pendingSource || sub._pendingSources))
1306
1431
  ) {
1307
- if (!downstreamBlockStatus && !sub._transition) globalQueue._pendingNodes.push(sub);
1432
+ if (!downstreamBlockStatus && !sub._transition) queuePendingNode(sub);
1308
1433
  notifyStatus(sub, status, error, downstreamBlockStatus, downstreamLane);
1309
1434
  }
1310
1435
  });
@@ -1404,7 +1529,7 @@ function recompute(el, create = false) {
1404
1529
  deleteFromHeap(el, el._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
1405
1530
  el._inFlight = null;
1406
1531
  if (el._transition || isEffect === EFFECT_TRACKED) disposeChildren(el);
1407
- else {
1532
+ else if (el._firstChild !== null || el._disposal !== null) {
1408
1533
  markDisposal(el);
1409
1534
  el._pendingDisposal = el._disposal;
1410
1535
  el._pendingFirstChild = el._firstChild;
@@ -1412,7 +1537,7 @@ function recompute(el, create = false) {
1412
1537
  el._firstChild = null;
1413
1538
  el._childCount = 0;
1414
1539
  clearSignals(el);
1415
- }
1540
+ } else clearSignals(el);
1416
1541
  }
1417
1542
  let isOptimisticDirty = !!(el._flags & REACTIVE_OPTIMISTIC_DIRTY);
1418
1543
  const hasOverride = el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING;
@@ -1451,15 +1576,26 @@ function recompute(el, create = false) {
1451
1576
  }
1452
1577
  }
1453
1578
  }
1579
+ const isStaleEffect = isEffect && isEffect !== EFFECT_USER;
1580
+ const prevStale = stale;
1581
+ if (isStaleEffect) stale = true;
1454
1582
  try {
1455
- const prevInFlight = el._inFlight;
1456
- const fnResult = el._fn(value);
1457
- value = el._inFlight !== prevInFlight ? fnResult : handleAsync(el, fnResult);
1583
+ if (!true && el._config & CONFIG_SYNC);
1584
+ else {
1585
+ const prevInFlight = el._inFlight;
1586
+ const fnResult = el._fn(value);
1587
+ const isAsyncResult = typeof fnResult === "object" && fnResult !== null;
1588
+ const inFlightChanged = el._inFlight !== prevInFlight;
1589
+ value = inFlightChanged || !isAsyncResult ? fnResult : handleAsync(el, fnResult);
1590
+ if (!inFlightChanged && !isAsyncResult) el._inFlight = null;
1591
+ }
1458
1592
  clearStatus(el, create);
1459
- const resolvedLane = resolveLane(el);
1460
- if (resolvedLane) {
1461
- resolvedLane._pendingAsync.delete(el);
1462
- updatePendingSignal(resolvedLane._source);
1593
+ if (el._optimisticLane) {
1594
+ const resolvedLane = resolveLane(el);
1595
+ if (resolvedLane) {
1596
+ resolvedLane._pendingAsync.delete(el);
1597
+ updatePendingSignal(resolvedLane._source);
1598
+ }
1463
1599
  }
1464
1600
  } catch (e) {
1465
1601
  if (e instanceof NotReadyError && currentOptimisticLane) {
@@ -1481,19 +1617,12 @@ function recompute(el, create = false) {
1481
1617
  } finally {
1482
1618
  tracking = prevTracking;
1483
1619
  strictRead = prevStrictRead;
1620
+ if (isStaleEffect) stale = prevStale;
1484
1621
  el._flags = REACTIVE_NONE | (create ? el._flags & REACTIVE_SNAPSHOT_STALE : 0);
1485
1622
  context = oldcontext;
1486
1623
  }
1487
1624
  if (!el._error) {
1488
- const depsTail = el._depsTail;
1489
- let toRemove = depsTail !== null ? depsTail._nextDep : el._deps;
1490
- if (toRemove !== null) {
1491
- do {
1492
- toRemove = unlinkSubs(toRemove);
1493
- } while (toRemove !== null);
1494
- if (depsTail !== null) depsTail._nextDep = null;
1495
- else el._deps = null;
1496
- }
1625
+ trimStaleDeps(el);
1497
1626
  const compareValue = hasOverride
1498
1627
  ? el._overrideValue
1499
1628
  : el._pendingValue === NOT_PENDING
@@ -1501,6 +1630,10 @@ function recompute(el, create = false) {
1501
1630
  : el._pendingValue;
1502
1631
  const valueChanged =
1503
1632
  (!isEffect && wasUninitialized) || !el._equals || !el._equals(compareValue, value);
1633
+ if (isEffect && valueChanged) {
1634
+ el._modified = !el._error;
1635
+ if (!create) el._queue.enqueue(isEffect, GlobalQueue._runEffect.bind(null, el));
1636
+ }
1504
1637
  if (valueChanged) {
1505
1638
  const prevVisible = hasOverride ? el._overrideValue : undefined;
1506
1639
  if (create || (isEffect && activeTransition !== el._transition) || isOptimisticDirty) {
@@ -1523,10 +1656,16 @@ function recompute(el, create = false) {
1523
1656
  }
1524
1657
  }
1525
1658
  currentOptimisticLane = prevLane;
1526
- (!create || el._statusFlags & STATUS_PENDING) &&
1659
+ const needsPendingCommit =
1660
+ el._pendingValue !== NOT_PENDING ||
1661
+ el._pendingFirstChild !== null ||
1662
+ el._pendingDisposal !== null ||
1663
+ !!(el._statusFlags & (STATUS_PENDING | STATUS_UNINITIALIZED));
1664
+ needsPendingCommit &&
1665
+ (!create || el._statusFlags & STATUS_PENDING) &&
1527
1666
  !el._transition &&
1528
1667
  !(activeTransition && hasOverride) &&
1529
- globalQueue._pendingNodes.push(el);
1668
+ queuePendingNode(el);
1530
1669
  el._transition &&
1531
1670
  isEffect &&
1532
1671
  activeTransition !== el._transition &&
@@ -1563,6 +1702,7 @@ function computed(fn, options) {
1563
1702
  (transparent ? CONFIG_TRANSPARENT : 0) |
1564
1703
  (options?.ownedWrite ? CONFIG_OWNED_WRITE : 0) |
1565
1704
  (!context || options?.lazy ? CONFIG_AUTO_DISPOSE : 0) |
1705
+ (options?.sync ? CONFIG_SYNC : 0) |
1566
1706
  (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
1567
1707
  _equals: options?.equals != null ? options.equals : isEqual,
1568
1708
  _unobserved: options?.unobserved,
@@ -1582,6 +1722,7 @@ function computed(fn, options) {
1582
1722
  _subsTail: null,
1583
1723
  _parent: context,
1584
1724
  _nextSibling: null,
1725
+ _prevSibling: null,
1585
1726
  _firstChild: null,
1586
1727
  _flags: options?.lazy ? REACTIVE_LAZY : REACTIVE_NONE,
1587
1728
  _statusFlags: STATUS_UNINITIALIZED,
@@ -1593,6 +1734,63 @@ function computed(fn, options) {
1593
1734
  _transition: null
1594
1735
  };
1595
1736
  self._name = options?.name ?? "computed";
1737
+ setupComputedNode(self, options);
1738
+ return self;
1739
+ }
1740
+ function createEffectNode(fn, effectFn, errorFn, type, notifyStatus, options) {
1741
+ const transparent = options?.transparent ?? false;
1742
+ const self = {
1743
+ id:
1744
+ options?.id ??
1745
+ (transparent ? context?.id : context?.id != null ? getNextChildId(context) : undefined),
1746
+ _config:
1747
+ (transparent ? CONFIG_TRANSPARENT : 0) |
1748
+ (options?.ownedWrite ? CONFIG_OWNED_WRITE : 0) |
1749
+ (options?.sync ? CONFIG_SYNC : 0) |
1750
+ (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
1751
+ _equals: false,
1752
+ _unobserved: options?.unobserved,
1753
+ _disposal: null,
1754
+ _queue: context?._queue ?? globalQueue,
1755
+ _context: context?._context ?? defaultContext,
1756
+ _childCount: 0,
1757
+ _fn: fn,
1758
+ _value: undefined,
1759
+ _height: 0,
1760
+ _child: null,
1761
+ _nextHeap: undefined,
1762
+ _prevHeap: null,
1763
+ _deps: null,
1764
+ _depsTail: null,
1765
+ _subs: null,
1766
+ _subsTail: null,
1767
+ _parent: context,
1768
+ _nextSibling: null,
1769
+ _prevSibling: null,
1770
+ _firstChild: null,
1771
+ _flags: REACTIVE_LAZY,
1772
+ _statusFlags: STATUS_UNINITIALIZED,
1773
+ _time: clock,
1774
+ _pendingValue: NOT_PENDING,
1775
+ _pendingDisposal: null,
1776
+ _pendingFirstChild: null,
1777
+ _inFlight: null,
1778
+ _transition: null,
1779
+ _modified: false,
1780
+ _prevValue: undefined,
1781
+ _effectFn: effectFn,
1782
+ _errorFn: errorFn,
1783
+ _cleanup: undefined,
1784
+ _cleanupRegistered: false,
1785
+ _type: type,
1786
+ _notifyStatus: notifyStatus
1787
+ };
1788
+ self._name = options?.name ?? "effect";
1789
+ setupComputedNode(self, lazyOptions);
1790
+ return self;
1791
+ }
1792
+ const lazyOptions = { lazy: true };
1793
+ function setupComputedNode(self, options) {
1596
1794
  self._prevHeap = self;
1597
1795
  const parent = context?._root ? context._parentComputed : context;
1598
1796
  if (context && context._config & CONFIG_CHILDREN_FORBIDDEN) {
@@ -1612,6 +1810,7 @@ function computed(fn, options) {
1612
1810
  context._firstChild = self;
1613
1811
  } else {
1614
1812
  self._nextSibling = lastChild;
1813
+ lastChild._prevSibling = self;
1615
1814
  context._firstChild = self;
1616
1815
  }
1617
1816
  }
@@ -1635,7 +1834,6 @@ function computed(fn, options) {
1635
1834
  snapshotSources.add(self);
1636
1835
  }
1637
1836
  }
1638
- return self;
1639
1837
  }
1640
1838
  function signal(v, options, firewall = null) {
1641
1839
  const s = {
@@ -1756,7 +1954,6 @@ function read(el) {
1756
1954
  const computed = el;
1757
1955
  if (typeof computed._fn === "function") {
1758
1956
  const comp = el;
1759
- if (refreshing && !(comp._flags & REACTIVE_DISPOSED)) recompute(comp);
1760
1957
  if (comp._flags & REACTIVE_LAZY) {
1761
1958
  comp._flags &= ~REACTIVE_LAZY;
1762
1959
  recompute(comp, true);
@@ -1765,6 +1962,19 @@ function read(el) {
1765
1962
  }
1766
1963
  }
1767
1964
  const owner = el._firewall || el;
1965
+ if (
1966
+ !computed._fn &&
1967
+ owner === el &&
1968
+ el._overrideValue === undefined &&
1969
+ el._snapshotValue === undefined &&
1970
+ activeTransition === null &&
1971
+ currentOptimisticLane === null &&
1972
+ !snapshotCaptureActive &&
1973
+ !strictRead
1974
+ ) {
1975
+ if (c && tracking) link(el, c);
1976
+ return !c || el._pendingValue === NOT_PENDING ? el._value : el._pendingValue;
1977
+ }
1768
1978
  if (strictRead && owner._statusFlags & STATUS_PENDING) {
1769
1979
  const message =
1770
1980
  `[PENDING_ASYNC_UNTRACKED_READ] Reading a pending async value directly in ${strictRead}. ` +
@@ -1955,10 +2165,10 @@ function setSignal(el, v) {
1955
2165
  el._optimisticLane = lane;
1956
2166
  el._overrideValue = v;
1957
2167
  } else {
1958
- if (el._pendingValue === NOT_PENDING) globalQueue._pendingNodes.push(el);
2168
+ if (el._pendingValue === NOT_PENDING) queuePendingNode(el);
1959
2169
  el._pendingValue = v;
1960
2170
  }
1961
- updatePendingSignal(el);
2171
+ if (el._pendingSignal) updatePendingSignal(el);
1962
2172
  if (el._latestValueComputed) {
1963
2173
  setSignal(el._latestValueComputed, v);
1964
2174
  }
@@ -1967,6 +2177,17 @@ function setSignal(el, v) {
1967
2177
  schedule();
1968
2178
  return v;
1969
2179
  }
2180
+ function suppressComputedRecompute(el) {
2181
+ deleteFromHeap(el, el._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
2182
+ if (!(el._flags & REACTIVE_MANUAL_WRITE) && el._pendingValue === NOT_PENDING)
2183
+ queuePendingNode(el);
2184
+ el._flags = (el._flags & -4) | REACTIVE_MANUAL_WRITE;
2185
+ }
2186
+ function setMemo(el, v) {
2187
+ const result = setSignal(el, v);
2188
+ suppressComputedRecompute(el);
2189
+ return result;
2190
+ }
1970
2191
  function runWithOwner(owner, fn) {
1971
2192
  if (owner && owner._flags & REACTIVE_DISPOSED) {
1972
2193
  const message =
@@ -2090,15 +2311,26 @@ function isPending(fn) {
2090
2311
  foundPending = prevFoundPending;
2091
2312
  }
2092
2313
  }
2093
- function refresh(fn) {
2314
+ function refresh(target) {
2094
2315
  let prevRefreshing = refreshing;
2095
2316
  refreshing = true;
2096
2317
  try {
2097
- if (typeof fn !== "function") {
2098
- recompute(fn[$REFRESH]);
2099
- return fn;
2318
+ const node = target?.[$REFRESH];
2319
+ if (true && !node) {
2320
+ const message =
2321
+ "[INVALID_REFRESH_TARGET] refresh() expects a Solid source accessor or refreshable store. " +
2322
+ "Pass the original source target, not a wrapper function or derived property read.";
2323
+ emitDiagnostic({
2324
+ code: "INVALID_REFRESH_TARGET",
2325
+ kind: "write",
2326
+ severity: "error",
2327
+ message: message
2328
+ });
2329
+ throw new Error(message);
2330
+ }
2331
+ if (node && typeof node._fn === "function" && !(node._flags & REACTIVE_DISPOSED)) {
2332
+ recompute(node);
2100
2333
  }
2101
- return untrack(fn);
2102
2334
  } finally {
2103
2335
  refreshing = prevRefreshing;
2104
2336
  if (!prevRefreshing) {
@@ -2138,69 +2370,20 @@ function isUndefined(value) {
2138
2370
  return typeof value === "undefined";
2139
2371
  }
2140
2372
  function effect(compute, effect, error, options) {
2141
- let initialized = false;
2142
2373
  const isUser = !!options?.user;
2143
- const node = computed(isUser ? compute : p => staleValues(() => compute(p)), {
2144
- ...options,
2145
- equals: () => {
2146
- node._modified = !node._error;
2147
- if (initialized) node._queue.enqueue(node._type, runEffect.bind(node));
2148
- return false;
2149
- },
2150
- lazy: true
2151
- });
2152
- node._config &= ~CONFIG_AUTO_DISPOSE;
2153
- node._prevValue = undefined;
2154
- node._effectFn = effect;
2155
- node._errorFn = error;
2156
- node._cleanup = undefined;
2157
- node._type = isUser ? EFFECT_USER : EFFECT_RENDER;
2158
- node._notifyStatus = (status, error) => {
2159
- const actualStatus = status !== undefined ? status : node._statusFlags;
2160
- const actualError = error !== undefined ? error : node._error;
2161
- if (actualStatus & STATUS_ERROR) {
2162
- let err = actualError;
2163
- node._queue.notify(node, STATUS_PENDING, 0);
2164
- if (node._type === EFFECT_USER) {
2165
- try {
2166
- return node._errorFn
2167
- ? node._errorFn(err, () => {
2168
- node._cleanup?.();
2169
- node._cleanup = undefined;
2170
- })
2171
- : console.error(err);
2172
- } catch (e) {
2173
- err = e;
2174
- }
2175
- }
2176
- if (!node._queue.notify(node, STATUS_ERROR, STATUS_ERROR)) throw err;
2177
- } else if (node._type === EFFECT_RENDER) {
2178
- node._queue.notify(node, STATUS_PENDING | STATUS_ERROR, actualStatus, actualError);
2179
- if (_hitUnhandledAsync) {
2180
- resetUnhandledAsync();
2181
- if (!node._queue.notify(node, STATUS_ERROR, STATUS_ERROR)) {
2182
- const message =
2183
- "[ASYNC_OUTSIDE_LOADING_BOUNDARY] An async value was read outside a Loading boundary. The root mount will be deferred until all pending async settles.";
2184
- emitDiagnostic({
2185
- code: "ASYNC_OUTSIDE_LOADING_BOUNDARY",
2186
- kind: "async",
2187
- severity: "warn",
2188
- message: message,
2189
- ownerId: node.id,
2190
- ownerName: node._name
2191
- });
2192
- console.warn(message);
2193
- }
2194
- }
2195
- }
2196
- };
2374
+ const node = createEffectNode(
2375
+ compute,
2376
+ effect,
2377
+ error,
2378
+ isUser ? EFFECT_USER : EFFECT_RENDER,
2379
+ notifyEffectStatus,
2380
+ options
2381
+ );
2197
2382
  recompute(node, true);
2198
2383
  !options?.defer &&
2199
2384
  (node._type === EFFECT_USER || options?.schedule
2200
- ? node._queue.enqueue(node._type, runEffect.bind(node))
2201
- : runEffect.call(node));
2202
- initialized = true;
2203
- cleanup(() => node._cleanup?.());
2385
+ ? node._queue.enqueue(node._type, runEffect.bind(null, node))
2386
+ : runEffect(node));
2204
2387
  if (!node._parent) {
2205
2388
  const message =
2206
2389
  "[NO_OWNER_EFFECT] Effects created outside a reactive context will never be disposed";
@@ -2216,32 +2399,76 @@ function effect(compute, effect, error, options) {
2216
2399
  console.warn(message);
2217
2400
  }
2218
2401
  }
2219
- function runEffect() {
2220
- if (!this._modified || this._flags & REACTIVE_DISPOSED) return;
2402
+ function notifyEffectStatus(status, error) {
2403
+ const actualStatus = status !== undefined ? status : this._statusFlags;
2404
+ const actualError = error !== undefined ? error : this._error;
2405
+ if (actualStatus & STATUS_ERROR) {
2406
+ let err = actualError;
2407
+ this._queue.notify(this, STATUS_PENDING, 0);
2408
+ if (this._type === EFFECT_USER) {
2409
+ try {
2410
+ return this._errorFn
2411
+ ? this._errorFn(err, () => {
2412
+ this._cleanup?.();
2413
+ this._cleanup = undefined;
2414
+ })
2415
+ : console.error(err);
2416
+ } catch (e) {
2417
+ err = e;
2418
+ }
2419
+ }
2420
+ if (!this._queue.notify(this, STATUS_ERROR, STATUS_ERROR)) throw err;
2421
+ } else if (this._type === EFFECT_RENDER) {
2422
+ this._queue.notify(this, STATUS_PENDING | STATUS_ERROR, actualStatus, actualError);
2423
+ if (_hitUnhandledAsync) {
2424
+ resetUnhandledAsync();
2425
+ if (!this._queue.notify(this, STATUS_ERROR, STATUS_ERROR)) {
2426
+ const message =
2427
+ "[ASYNC_OUTSIDE_LOADING_BOUNDARY] An async value was read outside a Loading boundary. The root mount will be deferred until all pending async settles.";
2428
+ emitDiagnostic({
2429
+ code: "ASYNC_OUTSIDE_LOADING_BOUNDARY",
2430
+ kind: "async",
2431
+ severity: "warn",
2432
+ message: message,
2433
+ ownerId: this.id,
2434
+ ownerName: this._name
2435
+ });
2436
+ console.warn(message);
2437
+ }
2438
+ }
2439
+ }
2440
+ }
2441
+ function runEffect(node) {
2442
+ if (!node._modified || node._flags & REACTIVE_DISPOSED) return;
2221
2443
  let prevStrictRead = false;
2222
2444
  {
2223
2445
  prevStrictRead = setStrictRead("an effect callback");
2224
2446
  }
2225
- this._cleanup?.();
2226
- this._cleanup = undefined;
2447
+ node._cleanup?.();
2448
+ node._cleanup = undefined;
2227
2449
  try {
2228
- const cleanup = this._effectFn(this._value, this._prevValue);
2229
- if (true && cleanup !== undefined && typeof cleanup !== "function") {
2450
+ const nextCleanup = node._effectFn(node._value, node._prevValue);
2451
+ if (true && nextCleanup !== undefined && typeof nextCleanup !== "function") {
2230
2452
  throw new Error(
2231
- `${this._name || "effect"} callback returned an invalid cleanup value. Return a cleanup function or undefined.`
2453
+ `${node._name || "effect"} callback returned an invalid cleanup value. Return a cleanup function or undefined.`
2232
2454
  );
2233
2455
  }
2234
- this._cleanup = cleanup;
2456
+ node._cleanup = nextCleanup;
2457
+ if (node._cleanup && !node._cleanupRegistered) {
2458
+ node._cleanupRegistered = true;
2459
+ runWithOwner(node._parent, () => cleanup(() => node._cleanup?.()));
2460
+ }
2235
2461
  } catch (error) {
2236
- this._error = new StatusError(this, error);
2237
- this._statusFlags |= STATUS_ERROR;
2238
- if (!this._queue.notify(this, STATUS_ERROR, STATUS_ERROR)) throw error;
2462
+ node._error = new StatusError(node, error);
2463
+ node._statusFlags |= STATUS_ERROR;
2464
+ if (!node._queue.notify(node, STATUS_ERROR, STATUS_ERROR)) throw error;
2239
2465
  } finally {
2240
2466
  setStrictRead(prevStrictRead);
2241
- this._prevValue = this._value;
2242
- this._modified = false;
2467
+ node._prevValue = node._value;
2468
+ node._modified = false;
2243
2469
  }
2244
2470
  }
2471
+ GlobalQueue._runEffect = runEffect;
2245
2472
  function trackedEffect(fn, options) {
2246
2473
  const run = () => {
2247
2474
  if (!node._modified || node._flags & REACTIVE_DISPOSED) return;
@@ -2371,13 +2598,15 @@ function onCleanup(fn) {
2371
2598
  return cleanup(fn);
2372
2599
  }
2373
2600
  function accessor(node) {
2374
- return read.bind(null, node);
2601
+ const fn = read.bind(null, node);
2602
+ fn[$REFRESH] = node;
2603
+ return fn;
2375
2604
  }
2376
2605
  function createSignal(first, second) {
2377
2606
  if (typeof first === "function") {
2378
2607
  const node = computed(first, second);
2379
2608
  node._config &= ~CONFIG_AUTO_DISPOSE;
2380
- return [accessor(node), setSignal.bind(null, node)];
2609
+ return [accessor(node), setMemo.bind(null, node)];
2381
2610
  }
2382
2611
  const node = signal(first, second);
2383
2612
  registerGraph(node, getOwner());
@@ -2488,7 +2717,7 @@ function onSettled(callback) {
2488
2717
  function unwrap(value) {
2489
2718
  return value?.[$TARGET]?.[STORE_NODE] ?? value;
2490
2719
  }
2491
- function getOverrideValue(value, override, nodes, key, optOverride) {
2720
+ function getOverrideValue(value, override, key, optOverride) {
2492
2721
  if (optOverride && key in optOverride) return optOverride[key];
2493
2722
  return override && key in override ? override[key] : value[key];
2494
2723
  }
@@ -2500,23 +2729,147 @@ function getAllKeys(value, override, next) {
2500
2729
  function applyState(next, state, keyFn) {
2501
2730
  const target = state?.[$TARGET];
2502
2731
  if (!target) return;
2732
+ if (target[STORE_OVERRIDE] || target[STORE_OPTIMISTIC_OVERRIDE]) {
2733
+ applyStateSlow(next, target, keyFn);
2734
+ } else {
2735
+ applyStateFast(next, target, keyFn);
2736
+ }
2737
+ }
2738
+ function applyStateFast(next, target, keyFn) {
2739
+ const previous = target[STORE_VALUE];
2740
+ if (next === previous) return;
2741
+ (target[STORE_LOOKUP] || storeLookup).set(next, target[$PROXY]);
2742
+ target[STORE_VALUE] = next;
2743
+ if (Array.isArray(previous)) {
2744
+ let changed = false;
2745
+ const prevLength = previous.length;
2746
+ if (next.length && prevLength && next[0] && keyFn(next[0]) != null) {
2747
+ let i, j, start, end, newEnd, item, newIndicesNext, keyVal;
2748
+ for (
2749
+ start = 0, end = Math.min(prevLength, next.length);
2750
+ start < end &&
2751
+ ((item = previous[start]) === next[start] ||
2752
+ (item && next[start] && keyFn(item) === keyFn(next[start])));
2753
+ start++
2754
+ ) {
2755
+ applyState(next[start], wrap(item, target), keyFn);
2756
+ }
2757
+ const temp = new Array(next.length),
2758
+ newIndices = new Map();
2759
+ for (
2760
+ end = prevLength - 1, newEnd = next.length - 1;
2761
+ end >= start &&
2762
+ newEnd >= start &&
2763
+ ((item = previous[end]) === next[newEnd] ||
2764
+ (item && next[newEnd] && keyFn(item) === keyFn(next[newEnd])));
2765
+ end--, newEnd--
2766
+ ) {
2767
+ temp[newEnd] = item;
2768
+ }
2769
+ if (start > newEnd || start > end) {
2770
+ for (j = start; j <= newEnd; j++) {
2771
+ changed = true;
2772
+ target[STORE_NODE][j] && setSignal(target[STORE_NODE][j], wrap(next[j], target));
2773
+ }
2774
+ for (; j < next.length; j++) {
2775
+ changed = true;
2776
+ const wrapped = wrap(temp[j], target);
2777
+ target[STORE_NODE][j] && setSignal(target[STORE_NODE][j], wrapped);
2778
+ applyState(next[j], wrapped, keyFn);
2779
+ }
2780
+ changed && target[STORE_NODE][$TRACK] && setSignal(target[STORE_NODE][$TRACK], void 0);
2781
+ prevLength !== next.length &&
2782
+ target[STORE_NODE].length &&
2783
+ setSignal(target[STORE_NODE].length, next.length);
2784
+ return;
2785
+ }
2786
+ newIndicesNext = new Array(newEnd + 1);
2787
+ for (j = newEnd; j >= start; j--) {
2788
+ item = next[j];
2789
+ keyVal = item ? keyFn(item) : item;
2790
+ i = newIndices.get(keyVal);
2791
+ newIndicesNext[j] = i === undefined ? -1 : i;
2792
+ newIndices.set(keyVal, j);
2793
+ }
2794
+ for (i = start; i <= end; i++) {
2795
+ item = previous[i];
2796
+ keyVal = item ? keyFn(item) : item;
2797
+ j = newIndices.get(keyVal);
2798
+ if (j !== undefined && j !== -1) {
2799
+ temp[j] = item;
2800
+ j = newIndicesNext[j];
2801
+ newIndices.set(keyVal, j);
2802
+ }
2803
+ }
2804
+ for (j = start; j < next.length; j++) {
2805
+ if (j in temp) {
2806
+ const wrapped = wrap(temp[j], target);
2807
+ target[STORE_NODE][j] && setSignal(target[STORE_NODE][j], wrapped);
2808
+ applyState(next[j], wrapped, keyFn);
2809
+ } else target[STORE_NODE][j] && setSignal(target[STORE_NODE][j], wrap(next[j], target));
2810
+ }
2811
+ if (start < next.length) changed = true;
2812
+ } else if (next.length) {
2813
+ for (let i = 0, len = next.length; i < len; i++) {
2814
+ const item = previous[i];
2815
+ isWrappable(item)
2816
+ ? applyState(next[i], wrap(item, target), keyFn)
2817
+ : target[STORE_NODE][i] && setSignal(target[STORE_NODE][i], next[i]);
2818
+ }
2819
+ }
2820
+ if (prevLength !== next.length) {
2821
+ changed = true;
2822
+ target[STORE_NODE].length && setSignal(target[STORE_NODE].length, next.length);
2823
+ }
2824
+ changed && target[STORE_NODE][$TRACK] && setSignal(target[STORE_NODE][$TRACK], void 0);
2825
+ return;
2826
+ }
2827
+ let nodes = target[STORE_NODE];
2828
+ if (nodes) {
2829
+ const tracked = nodes[$TRACK];
2830
+ const keys = tracked ? getAllKeys(previous, undefined, next) : Object.keys(nodes);
2831
+ for (let i = 0, len = keys.length; i < len; i++) {
2832
+ const key = keys[i];
2833
+ const node = nodes[key];
2834
+ const previousValue = unwrap(previous[key]);
2835
+ let nextValue = unwrap(next[key]);
2836
+ if (previousValue === nextValue) continue;
2837
+ if (
2838
+ !previousValue ||
2839
+ !isWrappable(previousValue) ||
2840
+ !isWrappable(nextValue) ||
2841
+ (keyFn(previousValue) != null && keyFn(previousValue) !== keyFn(nextValue))
2842
+ ) {
2843
+ tracked && setSignal(tracked, void 0);
2844
+ node && setSignal(node, isWrappable(nextValue) ? wrap(nextValue, target) : nextValue);
2845
+ } else applyState(nextValue, wrap(previousValue, target), keyFn);
2846
+ }
2847
+ }
2848
+ if ((nodes = target[STORE_HAS])) {
2849
+ const keys = Object.keys(nodes);
2850
+ for (let i = 0, len = keys.length; i < len; i++) {
2851
+ const key = keys[i];
2852
+ setSignal(nodes[key], key in next);
2853
+ }
2854
+ }
2855
+ }
2856
+ function applyStateSlow(next, target, keyFn) {
2503
2857
  const previous = target[STORE_VALUE];
2504
2858
  const override = target[STORE_OVERRIDE];
2505
2859
  const optOverride = target[STORE_OPTIMISTIC_OVERRIDE];
2506
2860
  let nodes = target[STORE_NODE];
2507
- if (next === previous && !override && !optOverride) return;
2508
2861
  (target[STORE_LOOKUP] || storeLookup).set(next, target[$PROXY]);
2509
2862
  target[STORE_VALUE] = next;
2510
2863
  target[STORE_OVERRIDE] = undefined;
2511
2864
  if (Array.isArray(previous)) {
2512
2865
  let changed = false;
2513
- const prevLength = getOverrideValue(previous, override, nodes, "length", optOverride);
2866
+ const prevLength = getOverrideValue(previous, override, "length", optOverride);
2514
2867
  if (next.length && prevLength && next[0] && keyFn(next[0]) != null) {
2515
2868
  let i, j, start, end, newEnd, item, newIndicesNext, keyVal;
2516
2869
  for (
2517
2870
  start = 0, end = Math.min(prevLength, next.length);
2518
2871
  start < end &&
2519
- ((item = getOverrideValue(previous, override, nodes, start, optOverride)) === next[start] ||
2872
+ ((item = getOverrideValue(previous, override, start, optOverride)) === next[start] ||
2520
2873
  (item && next[start] && keyFn(item) === keyFn(next[start])));
2521
2874
  start++
2522
2875
  ) {
@@ -2528,7 +2881,7 @@ function applyState(next, state, keyFn) {
2528
2881
  end = prevLength - 1, newEnd = next.length - 1;
2529
2882
  end >= start &&
2530
2883
  newEnd >= start &&
2531
- ((item = getOverrideValue(previous, override, nodes, end, optOverride)) === next[newEnd] ||
2884
+ ((item = getOverrideValue(previous, override, end, optOverride)) === next[newEnd] ||
2532
2885
  (item && next[newEnd] && keyFn(item) === keyFn(next[newEnd])));
2533
2886
  end--, newEnd--
2534
2887
  ) {
@@ -2560,7 +2913,7 @@ function applyState(next, state, keyFn) {
2560
2913
  newIndices.set(keyVal, j);
2561
2914
  }
2562
2915
  for (i = start; i <= end; i++) {
2563
- item = getOverrideValue(previous, override, nodes, i, optOverride);
2916
+ item = getOverrideValue(previous, override, i, optOverride);
2564
2917
  keyVal = item ? keyFn(item) : item;
2565
2918
  j = newIndices.get(keyVal);
2566
2919
  if (j !== undefined && j !== -1) {
@@ -2579,7 +2932,7 @@ function applyState(next, state, keyFn) {
2579
2932
  if (start < next.length) changed = true;
2580
2933
  } else if (next.length) {
2581
2934
  for (let i = 0, len = next.length; i < len; i++) {
2582
- const item = getOverrideValue(previous, override, nodes, i, optOverride);
2935
+ const item = getOverrideValue(previous, override, i, optOverride);
2583
2936
  isWrappable(item)
2584
2937
  ? applyState(next[i], wrap(item, target), keyFn)
2585
2938
  : target[STORE_NODE][i] && setSignal(target[STORE_NODE][i], next[i]);
@@ -2598,7 +2951,7 @@ function applyState(next, state, keyFn) {
2598
2951
  for (let i = 0, len = keys.length; i < len; i++) {
2599
2952
  const key = keys[i];
2600
2953
  const node = nodes[key];
2601
- const previousValue = unwrap(getOverrideValue(previous, override, nodes, key, optOverride));
2954
+ const previousValue = unwrap(getOverrideValue(previous, override, key, optOverride));
2602
2955
  let nextValue = unwrap(next[key]);
2603
2956
  if (previousValue === nextValue) continue;
2604
2957
  if (
@@ -2756,8 +3109,14 @@ function createStoreProxy(value, traps = storeTraps, extend) {
2756
3109
  if (Array.isArray(value)) {
2757
3110
  newTarget = [];
2758
3111
  newTarget.v = value;
2759
- } else newTarget = { v: value };
2760
- newTarget[STORE_CUSTOM_PROTO] = hasCustomPrototype(unwrapStoreValue(value));
3112
+ } else {
3113
+ newTarget = { v: value };
3114
+ const unwrapped = value?.[$TARGET]?.[STORE_VALUE] ?? value;
3115
+ const proto = Object.getPrototypeOf(unwrapped);
3116
+ if (proto !== null && proto !== Object.prototype) {
3117
+ newTarget[STORE_CUSTOM_PROTO] = true;
3118
+ }
3119
+ }
2761
3120
  extend && extend(newTarget);
2762
3121
  return (newTarget[$PROXY] = new Proxy(newTarget, traps));
2763
3122
  }
@@ -2769,12 +3128,8 @@ function wrap(value, target) {
2769
3128
  return p;
2770
3129
  }
2771
3130
  function isWrappable(obj) {
2772
- return (
2773
- obj != null &&
2774
- typeof obj === "object" &&
2775
- !Object.isFrozen(obj) &&
2776
- !(typeof Node !== "undefined" && obj instanceof Node)
2777
- );
3131
+ if (obj == null || typeof obj !== "object" || Object.isFrozen(obj)) return false;
3132
+ return typeof Node === "undefined" || !(obj instanceof Node);
2778
3133
  }
2779
3134
  let writeOverride = false;
2780
3135
  function setWriteOverride(value) {
@@ -2786,11 +3141,6 @@ function writeOnly(proxy) {
2786
3141
  function unwrapStoreValue(value) {
2787
3142
  return value?.[$TARGET]?.[STORE_VALUE] ?? value;
2788
3143
  }
2789
- function hasCustomPrototype(value) {
2790
- if (Array.isArray(value)) return false;
2791
- const proto = Object.getPrototypeOf(value);
2792
- return proto !== null && proto !== Object.prototype;
2793
- }
2794
3144
  function hasInheritedAccessor(source, property) {
2795
3145
  let current = Object.getPrototypeOf(source);
2796
3146
  while (current && current !== Object.prototype) {
@@ -2946,6 +3296,21 @@ const storeTraps = {
2946
3296
  }
2947
3297
  const nodes = getNodes(target, STORE_NODE);
2948
3298
  const tracked = nodes[property];
3299
+ const source = target[STORE_VALUE];
3300
+ if (
3301
+ !tracked &&
3302
+ !target[STORE_OVERRIDE] &&
3303
+ !target[STORE_OPTIMISTIC_OVERRIDE] &&
3304
+ !target[STORE_CUSTOM_PROTO] &&
3305
+ !target[STORE_OPTIMISTIC] &&
3306
+ !target[STORE_SNAPSHOT_PROPS] &&
3307
+ !source[$TARGET] &&
3308
+ !(property in source) &&
3309
+ getObserver() &&
3310
+ !writeOnly(receiver)
3311
+ ) {
3312
+ return read(getNode(nodes, property, undefined, target[STORE_FIREWALL]));
3313
+ }
2949
3314
  const optOverridden =
2950
3315
  target[STORE_OPTIMISTIC_OVERRIDE] && property in target[STORE_OPTIMISTIC_OVERRIDE];
2951
3316
  const overridden =
@@ -3220,7 +3585,12 @@ function createStore(first, second, options) {
3220
3585
  const derived = typeof first === "function",
3221
3586
  wrappedStore = derived ? createProjectionInternal(first, second, options).store : wrap(first);
3222
3587
  registerGraph(wrappedStore, getOwner());
3223
- return [wrappedStore, fn => storeSetter(wrappedStore, fn)];
3588
+ return [
3589
+ wrappedStore,
3590
+ derived
3591
+ ? fn => (storeSetter(wrappedStore, fn), suppressComputedRecompute(wrappedStore[$REFRESH]))
3592
+ : fn => storeSetter(wrappedStore, fn)
3593
+ ];
3224
3594
  }
3225
3595
  function createOptimisticStore(first, second, options) {
3226
3596
  GlobalQueue._clearOptimisticStore ||= clearOptimisticStore;
@@ -3478,8 +3848,9 @@ function merge(...sources) {
3478
3848
  const s = sources[i];
3479
3849
  proxy = proxy || (!!s && $PROXY in s);
3480
3850
  const childSources = !!s && s[$SOURCES];
3481
- if (childSources) flattened.push(...childSources);
3482
- else flattened.push(typeof s === "function" ? ((proxy = true), createMemo(s)) : s);
3851
+ if (childSources) {
3852
+ for (let i = 0; i < childSources.length; i++) flattened.push(childSources[i]);
3853
+ } else flattened.push(typeof s === "function" ? ((proxy = true), createMemo(s)) : s);
3483
3854
  }
3484
3855
  if (SUPPORTS_PROXY && proxy) {
3485
3856
  return new Proxy(
@@ -3498,10 +3869,12 @@ function merge(...sources) {
3498
3869
  return false;
3499
3870
  },
3500
3871
  keys() {
3501
- const keys = [];
3502
- for (let i = 0; i < flattened.length; i++)
3503
- keys.push(...Object.keys(resolveSource(flattened[i])));
3504
- return [...new Set(keys)];
3872
+ const keys = new Set();
3873
+ for (let i = 0; i < flattened.length; i++) {
3874
+ const sourceKeys = Object.keys(resolveSource(flattened[i]));
3875
+ for (let j = 0; j < sourceKeys.length; j++) keys.add(sourceKeys[j]);
3876
+ }
3877
+ return [...keys];
3505
3878
  }
3506
3879
  },
3507
3880
  propTraps
@@ -3542,26 +3915,27 @@ function merge(...sources) {
3542
3915
  return target;
3543
3916
  }
3544
3917
  function omit(props, ...keys) {
3545
- const blocked = new Set(keys);
3546
3918
  if (SUPPORTS_PROXY && $PROXY in props) {
3547
3919
  return new Proxy(
3548
3920
  {
3549
3921
  get(property) {
3550
- return blocked.has(property) ? undefined : props[property];
3922
+ return keys.includes(property) ? undefined : props[property];
3551
3923
  },
3552
3924
  has(property) {
3553
- return !blocked.has(property) && property in props;
3925
+ return !keys.includes(property) && property in props;
3554
3926
  },
3555
3927
  keys() {
3556
- return Object.keys(props).filter(k => !blocked.has(k));
3928
+ return Object.keys(props).filter(k => !keys.includes(k));
3557
3929
  }
3558
3930
  },
3559
3931
  propTraps
3560
3932
  );
3561
3933
  }
3562
3934
  const result = {};
3563
- for (const propName of Object.getOwnPropertyNames(props)) {
3564
- if (!blocked.has(propName)) {
3935
+ const propNames = Object.getOwnPropertyNames(props);
3936
+ const blocked = keys.length > 4 && propNames.length > keys.length ? new Set(keys) : undefined;
3937
+ for (const propName of propNames) {
3938
+ if (blocked ? !blocked.has(propName) : !keys.includes(propName)) {
3565
3939
  const desc = Object.getOwnPropertyDescriptor(props, propName);
3566
3940
  !desc.get && !desc.set && desc.enumerable && desc.writable && desc.configurable
3567
3941
  ? (result[propName] = desc.value)