@solidjs/signals 0.13.13 → 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 (110) hide show
  1. package/README.md +8 -7
  2. package/dist/dev.js +1230 -598
  3. package/dist/node.cjs +2064 -1555
  4. package/dist/prod.js +1783 -1251
  5. package/dist/types/boundaries.d.ts +126 -5
  6. package/dist/types/core/action.d.ts +34 -0
  7. package/dist/types/core/constants.d.ts +26 -0
  8. package/dist/types/core/context.d.ts +10 -2
  9. package/dist/types/core/core.d.ts +129 -9
  10. package/dist/types/core/dev.d.ts +1 -1
  11. package/dist/types/core/effect.d.ts +4 -2
  12. package/dist/types/core/error.d.ts +24 -0
  13. package/dist/types/core/external.d.ts +19 -0
  14. package/dist/types/core/graph.d.ts +2 -0
  15. package/dist/types/core/index.d.ts +1 -1
  16. package/dist/types/core/owner.d.ts +93 -3
  17. package/dist/types/core/scheduler.d.ts +43 -2
  18. package/dist/types/core/types.d.ts +5 -6
  19. package/dist/types/index.d.ts +3 -3
  20. package/dist/types/map.d.ts +32 -3
  21. package/dist/types/signals.d.ts +362 -42
  22. package/dist/types/src/boundaries.d.ts +173 -0
  23. package/dist/types/src/core/action.d.ts +35 -0
  24. package/dist/types/src/core/async.d.ts +6 -0
  25. package/dist/types/src/core/constants.d.ts +51 -0
  26. package/dist/types/src/core/context.d.ts +36 -0
  27. package/dist/types/src/core/core.d.ts +174 -0
  28. package/dist/types/src/core/dev.d.ts +49 -0
  29. package/dist/types/src/core/effect.d.ts +32 -0
  30. package/dist/types/src/core/error.d.ts +38 -0
  31. package/dist/types/src/core/external.d.ts +45 -0
  32. package/dist/types/src/core/graph.d.ts +5 -0
  33. package/dist/types/src/core/heap.d.ts +14 -0
  34. package/dist/types/src/core/index.d.ts +12 -0
  35. package/dist/types/src/core/lanes.d.ts +54 -0
  36. package/dist/types/src/core/owner.d.ts +116 -0
  37. package/dist/types/src/core/scheduler.d.ts +122 -0
  38. package/dist/types/src/core/types.d.ts +85 -0
  39. package/dist/types/src/index.d.ts +9 -0
  40. package/dist/types/src/map.d.ts +53 -0
  41. package/dist/types/src/signals.d.ts +512 -0
  42. package/dist/types/src/store/index.d.ts +9 -0
  43. package/dist/types/src/store/optimistic.d.ts +45 -0
  44. package/dist/types/src/store/projection.d.ts +66 -0
  45. package/dist/types/src/store/reconcile.d.ts +23 -0
  46. package/dist/types/src/store/store.d.ts +125 -0
  47. package/dist/types/src/store/storePath.d.ts +58 -0
  48. package/dist/types/src/store/utils.d.ts +114 -0
  49. package/dist/types/store/optimistic.d.ts +38 -12
  50. package/dist/types/store/projection.d.ts +55 -15
  51. package/dist/types/store/reconcile.d.ts +22 -0
  52. package/dist/types/store/store.d.ts +72 -15
  53. package/dist/types/store/storePath.d.ts +28 -0
  54. package/dist/types/store/utils.d.ts +78 -7
  55. package/dist/types-cjs/boundaries.d.cts +173 -0
  56. package/dist/types-cjs/core/action.d.cts +35 -0
  57. package/dist/types-cjs/core/async.d.cts +6 -0
  58. package/dist/types-cjs/core/constants.d.cts +51 -0
  59. package/dist/types-cjs/core/context.d.cts +36 -0
  60. package/dist/types-cjs/core/core.d.cts +174 -0
  61. package/dist/types-cjs/core/dev.d.cts +49 -0
  62. package/dist/types-cjs/core/effect.d.cts +32 -0
  63. package/dist/types-cjs/core/error.d.cts +38 -0
  64. package/dist/types-cjs/core/external.d.cts +45 -0
  65. package/dist/types-cjs/core/graph.d.cts +5 -0
  66. package/dist/types-cjs/core/heap.d.cts +14 -0
  67. package/dist/types-cjs/core/index.d.cts +12 -0
  68. package/dist/types-cjs/core/lanes.d.cts +54 -0
  69. package/dist/types-cjs/core/owner.d.cts +116 -0
  70. package/dist/types-cjs/core/scheduler.d.cts +122 -0
  71. package/dist/types-cjs/core/types.d.cts +85 -0
  72. package/dist/types-cjs/index.d.cts +9 -0
  73. package/dist/types-cjs/map.d.cts +53 -0
  74. package/dist/types-cjs/package.json +3 -0
  75. package/dist/types-cjs/signals.d.cts +512 -0
  76. package/dist/types-cjs/src/boundaries.d.cts +173 -0
  77. package/dist/types-cjs/src/core/action.d.cts +35 -0
  78. package/dist/types-cjs/src/core/async.d.cts +6 -0
  79. package/dist/types-cjs/src/core/constants.d.cts +51 -0
  80. package/dist/types-cjs/src/core/context.d.cts +36 -0
  81. package/dist/types-cjs/src/core/core.d.cts +174 -0
  82. package/dist/types-cjs/src/core/dev.d.cts +49 -0
  83. package/dist/types-cjs/src/core/effect.d.cts +32 -0
  84. package/dist/types-cjs/src/core/error.d.cts +38 -0
  85. package/dist/types-cjs/src/core/external.d.cts +45 -0
  86. package/dist/types-cjs/src/core/graph.d.cts +5 -0
  87. package/dist/types-cjs/src/core/heap.d.cts +14 -0
  88. package/dist/types-cjs/src/core/index.d.cts +12 -0
  89. package/dist/types-cjs/src/core/lanes.d.cts +54 -0
  90. package/dist/types-cjs/src/core/owner.d.cts +116 -0
  91. package/dist/types-cjs/src/core/scheduler.d.cts +122 -0
  92. package/dist/types-cjs/src/core/types.d.cts +85 -0
  93. package/dist/types-cjs/src/index.d.cts +9 -0
  94. package/dist/types-cjs/src/map.d.cts +53 -0
  95. package/dist/types-cjs/src/signals.d.cts +512 -0
  96. package/dist/types-cjs/src/store/index.d.cts +9 -0
  97. package/dist/types-cjs/src/store/optimistic.d.cts +45 -0
  98. package/dist/types-cjs/src/store/projection.d.cts +66 -0
  99. package/dist/types-cjs/src/store/reconcile.d.cts +23 -0
  100. package/dist/types-cjs/src/store/store.d.cts +125 -0
  101. package/dist/types-cjs/src/store/storePath.d.cts +58 -0
  102. package/dist/types-cjs/src/store/utils.d.cts +114 -0
  103. package/dist/types-cjs/store/index.d.cts +9 -0
  104. package/dist/types-cjs/store/optimistic.d.cts +45 -0
  105. package/dist/types-cjs/store/projection.d.cts +66 -0
  106. package/dist/types-cjs/store/reconcile.d.cts +23 -0
  107. package/dist/types-cjs/store/store.d.cts +125 -0
  108. package/dist/types-cjs/store/storePath.d.cts +58 -0
  109. package/dist/types-cjs/store/utils.d.cts +114 -0
  110. package/package.json +35 -27
package/dist/dev.js CHANGED
@@ -35,6 +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;
39
+ const CONFIG_OWNED_WRITE = 1 << 0;
40
+ const CONFIG_NO_SNAPSHOT = 1 << 1;
41
+ const CONFIG_TRANSPARENT = 1 << 2;
42
+ const CONFIG_IN_SNAPSHOT_SCOPE = 1 << 3;
43
+ const CONFIG_CHILDREN_FORBIDDEN = 1 << 4;
44
+ const CONFIG_AUTO_DISPOSE = 1 << 5;
45
+ const CONFIG_SYNC = 1 << 6;
38
46
  const STATUS_PENDING = 1 << 0;
39
47
  const STATUS_ERROR = 1 << 1;
40
48
  const STATUS_UNINITIALIZED = 1 << 2;
@@ -47,6 +55,91 @@ const STORE_SNAPSHOT_PROPS = "sp";
47
55
  const SUPPORTS_PROXY = typeof Proxy === "function";
48
56
  const defaultContext = {};
49
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
+ }
50
143
  function actualInsertIntoHeap(n, heap) {
51
144
  const parentHeight =
52
145
  (n._parent?._root ? n._parent._parentComputed?._height : n._parent?._height) ?? -1;
@@ -64,7 +157,7 @@ function actualInsertIntoHeap(n, heap) {
64
157
  }
65
158
  function insertIntoHeap(n, heap) {
66
159
  let flags = n._flags;
67
- if (flags & (REACTIVE_IN_HEAP | REACTIVE_RECOMPUTING_DEPS)) return;
160
+ if (flags & (REACTIVE_IN_HEAP | REACTIVE_RECOMPUTING_DEPS | REACTIVE_MANUAL_WRITE)) return;
68
161
  if (flags & REACTIVE_CHECK) {
69
162
  n._flags = (flags & -4) | REACTIVE_DIRTY | REACTIVE_IN_HEAP;
70
163
  } else n._flags = flags | REACTIVE_IN_HEAP;
@@ -72,7 +165,11 @@ function insertIntoHeap(n, heap) {
72
165
  }
73
166
  function insertIntoHeapHeight(n, heap) {
74
167
  let flags = n._flags;
75
- 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;
76
173
  n._flags = flags | REACTIVE_IN_HEAP_HEIGHT;
77
174
  actualInsertIntoHeap(n, heap);
78
175
  }
@@ -144,90 +241,76 @@ function adjustHeight(el, heap) {
144
241
  }
145
242
  }
146
243
  }
147
- const hooks = {};
148
- const diagnosticListeners = new Set();
149
- const diagnosticCaptures = new Set();
150
- let diagnosticSequence = 0;
151
- const diagnostics = {
152
- subscribe(listener) {
153
- diagnosticListeners.add(listener);
154
- return () => diagnosticListeners.delete(listener);
155
- },
156
- capture() {
157
- const events = [];
158
- diagnosticCaptures.add(events);
159
- return {
160
- get events() {
161
- return events;
162
- },
163
- clear() {
164
- events.length = 0;
165
- },
166
- stop() {
167
- diagnosticCaptures.delete(events);
168
- return [...events];
169
- }
170
- };
171
- }
172
- };
173
- const DEV$1 = {
174
- hooks: hooks,
175
- diagnostics: diagnostics,
176
- getChildren: getChildren,
177
- getSignals: getSignals,
178
- getParent: getParent,
179
- getSources: getSources,
180
- getObservers: getObservers
181
- };
182
- function emitDiagnostic(event) {
183
- const entry = { sequence: ++diagnosticSequence, ...event };
184
- for (const listener of diagnosticListeners) listener(entry);
185
- for (const capture of diagnosticCaptures) capture.push(entry);
186
- return entry;
187
- }
188
- function registerGraph(value, owner) {
189
- value._owner = owner;
190
- if (owner) {
191
- if (!owner._signals) owner._signals = [];
192
- 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);
193
250
  }
194
- 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;
195
265
  }
196
- function clearSignals(node) {
197
- node._signals = undefined;
266
+ function findLane(lane) {
267
+ while (lane._mergedInto) lane = lane._mergedInto;
268
+ return lane;
198
269
  }
199
- function getChildren(owner) {
200
- const children = [];
201
- let child = owner._firstChild;
202
- while (child) {
203
- children.push(child);
204
- child = child._nextSibling;
205
- }
206
- 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;
207
279
  }
208
- function getSignals(owner) {
209
- 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;
210
287
  }
211
- function getParent(owner) {
212
- return owner._parent;
288
+ function resolveTransition(el) {
289
+ return resolveLane(el)?._transition ?? el._transition;
213
290
  }
214
- function getSources(computation) {
215
- const sources = [];
216
- let link = computation._deps;
217
- while (link) {
218
- sources.push(link._dep);
219
- link = link._nextDep;
220
- }
221
- return sources;
291
+ function hasActiveOverride(el) {
292
+ return !!(el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING);
222
293
  }
223
- function getObservers(node) {
224
- const observers = [];
225
- let link = node._subs;
226
- while (link) {
227
- observers.push(link._sub);
228
- 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
+ }
229
312
  }
230
- return observers;
313
+ el._optimisticLane = sourceLane;
231
314
  }
232
315
  const transitions = new Set();
233
316
  const dirtyQueue = { _heap: new Array(2e3).fill(undefined), _marked: false, _min: 0, _max: 0 };
@@ -235,11 +318,39 @@ const zombieQueue = { _heap: new Array(2e3).fill(undefined), _marked: false, _mi
235
318
  let clock = 0;
236
319
  let activeTransition = null;
237
320
  let scheduled = false;
321
+ let syncDepth = 0;
238
322
  let projectionWriteActive = false;
239
323
  let inTrackedQueueCallback = false;
240
324
  let _enforceLoadingBoundary = false;
241
325
  let _hitUnhandledAsync = false;
242
326
  let stashedOptimisticReads = null;
327
+ const transientStoreNodes = new Set();
328
+ function registerTransientStoreNode(node) {
329
+ transientStoreNodes.add(node);
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
+ }
341
+ function sweepTransientStoreNodes() {
342
+ if (transientStoreNodes.size === 0) return;
343
+ for (const node of transientStoreNodes) {
344
+ if (node._subs !== null) {
345
+ transientStoreNodes.delete(node);
346
+ continue;
347
+ }
348
+ if (node._pendingValue !== NOT_PENDING) continue;
349
+ if (node._overrideValue !== undefined && node._overrideValue !== NOT_PENDING) continue;
350
+ transientStoreNodes.delete(node);
351
+ node._unobserved?.();
352
+ }
353
+ }
243
354
  function resetUnhandledAsync() {
244
355
  _hitUnhandledAsync = false;
245
356
  }
@@ -292,6 +403,7 @@ function mergeTransitionState(target, outgoing) {
292
403
  if (!targetReporters) target._asyncReporters.set(source, (targetReporters = new Set()));
293
404
  for (const reporter of reporters) targetReporters.add(reporter);
294
405
  }
406
+ for (const sub of outgoing._gatedSubs) target._gatedSubs.add(sub);
295
407
  }
296
408
  function resolveOptimisticNodes(nodes) {
297
409
  for (let i = 0; i < nodes.length; i++) {
@@ -329,7 +441,7 @@ function cleanupCompletedLanes(completingTransition) {
329
441
  function schedule() {
330
442
  if (scheduled) return;
331
443
  scheduled = true;
332
- if (!globalQueue._running && !projectionWriteActive) queueMicrotask(flush);
444
+ if (!syncDepth && !globalQueue._running && !projectionWriteActive) queueMicrotask(flush);
333
445
  }
334
446
  class Queue {
335
447
  _parent = null;
@@ -396,11 +508,13 @@ class Queue {
396
508
  }
397
509
  class GlobalQueue extends Queue {
398
510
  _running = false;
511
+ _pendingNode = null;
399
512
  _pendingNodes = [];
400
513
  _optimisticNodes = [];
401
514
  _optimisticStores = new Set();
402
515
  static _update;
403
516
  static _dispose;
517
+ static _runEffect;
404
518
  static _clearOptimisticStore = null;
405
519
  flush() {
406
520
  if (this._running) return;
@@ -412,6 +526,7 @@ class GlobalQueue extends Queue {
412
526
  if (!isComplete) {
413
527
  const stashedTransition = activeTransition;
414
528
  runHeap(zombieQueue, GlobalQueue._update);
529
+ this._pendingNode = null;
415
530
  this._pendingNodes = [];
416
531
  this._optimisticNodes = [];
417
532
  this._optimisticStores = new Set();
@@ -422,11 +537,15 @@ class GlobalQueue extends Queue {
422
537
  scheduled = dirtyQueue._max >= dirtyQueue._min;
423
538
  reassignPendingTransition(stashedTransition._pendingNodes);
424
539
  activeTransition = null;
425
- if (!stashedTransition._actions.length && stashedTransition._optimisticNodes.length) {
540
+ if (
541
+ !stashedTransition._actions.length &&
542
+ !stashedTransition._asyncReporters.size &&
543
+ stashedTransition._optimisticNodes.length
544
+ ) {
426
545
  stashedOptimisticReads = new Set();
427
546
  for (let i = 0; i < stashedTransition._optimisticNodes.length; i++) {
428
547
  const node = stashedTransition._optimisticNodes[i];
429
- if (node._fn || node._pureWrite) continue;
548
+ if (node._fn || node._config & CONFIG_OWNED_WRITE) continue;
430
549
  stashedOptimisticReads.add(node);
431
550
  queueStashedOptimisticEffects(node);
432
551
  }
@@ -447,14 +566,22 @@ class GlobalQueue extends Queue {
447
566
  reassignPendingTransition(this._pendingNodes);
448
567
  finalizePureQueue(completingTransition);
449
568
  } else {
450
- if (transitions.size) runHeap(zombieQueue, GlobalQueue._update);
451
- 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
+ }
452
579
  }
453
580
  clock++;
454
581
  scheduled = dirtyQueue._max >= dirtyQueue._min;
455
- runLaneEffects(EFFECT_RENDER);
582
+ activeLanes.size && runLaneEffects(EFFECT_RENDER);
456
583
  this.run(EFFECT_RENDER);
457
- runLaneEffects(EFFECT_USER);
584
+ activeLanes.size && runLaneEffects(EFFECT_USER);
458
585
  this.run(EFFECT_USER);
459
586
  if (true) DEV$1.hooks.onUpdate?.();
460
587
  } finally {
@@ -492,7 +619,8 @@ class GlobalQueue extends Queue {
492
619
  _optimisticStores: new Set(),
493
620
  _actions: [],
494
621
  _queueStash: { _queues: [[], []], _children: [] },
495
- _done: false
622
+ _done: false,
623
+ _gatedSubs: new Set()
496
624
  };
497
625
  } else if (transition) {
498
626
  const outgoing = activeTransition;
@@ -502,6 +630,11 @@ class GlobalQueue extends Queue {
502
630
  }
503
631
  transitions.add(activeTransition);
504
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
+ }
505
638
  if (this._pendingNodes !== activeTransition._pendingNodes) {
506
639
  for (let i = 0; i < this._pendingNodes.length; i++) {
507
640
  const node = this._pendingNodes[i];
@@ -527,11 +660,26 @@ class GlobalQueue extends Queue {
527
660
  }
528
661
  }
529
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
+ }
530
678
  function insertSubs(node, optimistic = false) {
531
679
  const sourceLane = node._optimisticLane || currentOptimisticLane;
532
680
  const hasSnapshot = node._snapshotValue !== undefined;
533
681
  for (let s = node._subs; s !== null; s = s._nextSub) {
534
- if (hasSnapshot && s._sub._inSnapshotScope) {
682
+ if (hasSnapshot && s._sub._config & CONFIG_IN_SNAPSHOT_SCOPE) {
535
683
  s._sub._flags |= REACTIVE_SNAPSHOT_STALE;
536
684
  continue;
537
685
  }
@@ -555,30 +703,63 @@ function insertSubs(node, optimistic = false) {
555
703
  insertIntoHeap(s._sub, queue);
556
704
  }
557
705
  }
558
- function commitPendingNodes() {
559
- const pendingNodes = globalQueue._pendingNodes;
560
- for (let i = 0; i < pendingNodes.length; i++) {
561
- const n = pendingNodes[i];
706
+ function commitPendingNode(n) {
707
+ const c = n;
708
+ if (!c._fn) {
562
709
  if (n._pendingValue !== NOT_PENDING) {
563
710
  n._value = n._pendingValue;
564
711
  n._pendingValue = NOT_PENDING;
565
- if (n._type && n._type !== EFFECT_TRACKED) n._modified = true;
566
712
  }
567
- if (!(n._statusFlags & STATUS_PENDING)) n._statusFlags &= ~STATUS_UNINITIALIZED;
568
- 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]);
569
733
  }
570
734
  pendingNodes.length = 0;
571
735
  }
572
736
  function finalizePureQueue(completingTransition = null, incomplete = false) {
573
737
  const resolvePending = !incomplete;
574
738
  if (resolvePending) commitPendingNodes();
575
- if (!incomplete) checkBoundaryChildren(globalQueue);
576
- 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);
577
742
  if (resolvePending) {
578
- commitPendingNodes();
743
+ if (ranHeap) commitPendingNodes();
579
744
  resolveOptimisticNodes(
580
745
  completingTransition ? completingTransition._optimisticNodes : globalQueue._optimisticNodes
581
746
  );
747
+ if (completingTransition && completingTransition._gatedSubs.size) {
748
+ for (const sub of completingTransition._gatedSubs) {
749
+ if (sub._flags & REACTIVE_DISPOSED) continue;
750
+ if (sub._type === EFFECT_TRACKED) {
751
+ if (!sub._modified) {
752
+ sub._modified = true;
753
+ sub._queue.enqueue(EFFECT_USER, sub._run);
754
+ }
755
+ continue;
756
+ }
757
+ const queue = sub._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue;
758
+ if (queue._min > sub._height) queue._min = sub._height;
759
+ insertIntoHeap(sub, queue);
760
+ }
761
+ completingTransition._gatedSubs.clear();
762
+ }
582
763
  const optimisticStores = completingTransition
583
764
  ? completingTransition._optimisticStores
584
765
  : globalQueue._optimisticStores;
@@ -589,6 +770,7 @@ function finalizePureQueue(completingTransition = null, incomplete = false) {
589
770
  optimisticStores.clear();
590
771
  schedule();
591
772
  }
773
+ sweepTransientStoreNodes();
592
774
  cleanupCompletedLanes(completingTransition);
593
775
  }
594
776
  }
@@ -608,7 +790,16 @@ function reassignPendingTransition(pendingNodes) {
608
790
  }
609
791
  }
610
792
  const globalQueue = new GlobalQueue();
611
- function flush() {
793
+ function flush(fn) {
794
+ if (fn) {
795
+ syncDepth++;
796
+ try {
797
+ return fn();
798
+ } finally {
799
+ flush();
800
+ syncDepth--;
801
+ }
802
+ }
612
803
  if (globalQueue._running) {
613
804
  if (inTrackedQueueCallback) {
614
805
  throw new Error(
@@ -673,160 +864,27 @@ function transitionComplete(transition) {
673
864
  ) {
674
865
  done = false;
675
866
  break;
676
- }
677
- }
678
- }
679
- done && (transition._done = true);
680
- return done;
681
- }
682
- function currentTransition(transition) {
683
- while (transition._done && typeof transition._done === "object") transition = transition._done;
684
- return transition;
685
- }
686
- function setActiveTransition(transition) {
687
- activeTransition = transition;
688
- }
689
- function runInTransition(transition, fn) {
690
- const prevTransition = activeTransition;
691
- try {
692
- activeTransition = currentTransition(transition);
693
- return fn();
694
- } finally {
695
- activeTransition = prevTransition;
696
- }
697
- }
698
- const signalLanes = new WeakMap();
699
- const activeLanes = new Set();
700
- function getOrCreateLane(signal) {
701
- let lane = signalLanes.get(signal);
702
- if (lane) {
703
- return findLane(lane);
704
- }
705
- const parentSource = signal._parentSource;
706
- const parentLane = parentSource?._optimisticLane ? findLane(parentSource._optimisticLane) : null;
707
- lane = {
708
- _source: signal,
709
- _pendingAsync: new Set(),
710
- _effectQueues: [[], []],
711
- _mergedInto: null,
712
- _transition: activeTransition,
713
- _parentLane: parentLane
714
- };
715
- signalLanes.set(signal, lane);
716
- activeLanes.add(lane);
717
- signal._overrideSinceLane = false;
718
- return lane;
719
- }
720
- function findLane(lane) {
721
- while (lane._mergedInto) lane = lane._mergedInto;
722
- return lane;
723
- }
724
- function mergeLanes(lane1, lane2) {
725
- lane1 = findLane(lane1);
726
- lane2 = findLane(lane2);
727
- if (lane1 === lane2) return lane1;
728
- lane2._mergedInto = lane1;
729
- for (const node of lane2._pendingAsync) lane1._pendingAsync.add(node);
730
- lane1._effectQueues[0].push(...lane2._effectQueues[0]);
731
- lane1._effectQueues[1].push(...lane2._effectQueues[1]);
732
- return lane1;
733
- }
734
- function resolveLane(el) {
735
- const lane = el._optimisticLane;
736
- if (!lane) return undefined;
737
- const root = findLane(lane);
738
- if (activeLanes.has(root)) return root;
739
- el._optimisticLane = undefined;
740
- return undefined;
741
- }
742
- function resolveTransition(el) {
743
- return resolveLane(el)?._transition ?? el._transition;
744
- }
745
- function hasActiveOverride(el) {
746
- return !!(el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING);
747
- }
748
- function assignOrMergeLane(el, sourceLane) {
749
- const sourceRoot = findLane(sourceLane);
750
- const existing = el._optimisticLane;
751
- if (existing) {
752
- if (existing._mergedInto) {
753
- el._optimisticLane = sourceLane;
754
- return;
755
- }
756
- const existingRoot = findLane(existing);
757
- if (activeLanes.has(existingRoot)) {
758
- if (existingRoot !== sourceRoot && !hasActiveOverride(el)) {
759
- if (sourceRoot._parentLane && findLane(sourceRoot._parentLane) === existingRoot) {
760
- el._optimisticLane = sourceLane;
761
- } else if (existingRoot._parentLane && findLane(existingRoot._parentLane) === sourceRoot);
762
- else mergeLanes(sourceRoot, existingRoot);
763
- }
764
- return;
765
- }
766
- }
767
- el._optimisticLane = sourceLane;
768
- }
769
- function unlinkSubs(link) {
770
- const dep = link._dep;
771
- const nextDep = link._nextDep;
772
- const nextSub = link._nextSub;
773
- const prevSub = link._prevSub;
774
- if (nextSub !== null) nextSub._prevSub = prevSub;
775
- else dep._subsTail = prevSub;
776
- if (prevSub !== null) prevSub._nextSub = nextSub;
777
- else {
778
- dep._subs = nextSub;
779
- if (nextSub === null) {
780
- dep._unobserved?.();
781
- dep._fn && !dep._preventAutoDisposal && !(dep._flags & REACTIVE_ZOMBIE) && unobserved(dep);
867
+ }
782
868
  }
783
869
  }
784
- return nextDep;
870
+ done && (transition._done = true);
871
+ return done;
785
872
  }
786
- function unobserved(el) {
787
- deleteFromHeap(el, el._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
788
- let dep = el._deps;
789
- while (dep !== null) {
790
- dep = unlinkSubs(dep);
791
- }
792
- el._deps = null;
793
- disposeChildren(el, true);
873
+ function currentTransition(transition) {
874
+ while (transition._done && typeof transition._done === "object") transition = transition._done;
875
+ return transition;
794
876
  }
795
- function link(dep, sub) {
796
- const prevDep = sub._depsTail;
797
- if (prevDep !== null && prevDep._dep === dep) return;
798
- let nextDep = null;
799
- const isRecomputing = sub._flags & REACTIVE_RECOMPUTING_DEPS;
800
- if (isRecomputing) {
801
- nextDep = prevDep !== null ? prevDep._nextDep : sub._deps;
802
- if (nextDep !== null && nextDep._dep === dep) {
803
- sub._depsTail = nextDep;
804
- return;
805
- }
806
- }
807
- const prevSub = dep._subsTail;
808
- if (prevSub !== null && prevSub._sub === sub && (!isRecomputing || isValidLink(prevSub, sub)))
809
- return;
810
- const newLink =
811
- (sub._depsTail =
812
- dep._subsTail =
813
- { _dep: dep, _sub: sub, _nextDep: nextDep, _prevSub: prevSub, _nextSub: null });
814
- if (prevDep !== null) prevDep._nextDep = newLink;
815
- else sub._deps = newLink;
816
- if (prevSub !== null) prevSub._nextSub = newLink;
817
- else dep._subs = newLink;
877
+ function setActiveTransition(transition) {
878
+ activeTransition = transition;
818
879
  }
819
- function isValidLink(checkLink, sub) {
820
- const depsTail = sub._depsTail;
821
- if (depsTail !== null) {
822
- let link = sub._deps;
823
- do {
824
- if (link === checkLink) return true;
825
- if (link === depsTail) break;
826
- link = link._nextDep;
827
- } while (link !== null);
880
+ function runInTransition(transition, fn) {
881
+ const prevTransition = activeTransition;
882
+ try {
883
+ activeTransition = currentTransition(transition);
884
+ return fn();
885
+ } finally {
886
+ activeTransition = prevTransition;
828
887
  }
829
- return false;
830
888
  }
831
889
  const PENDING_OWNER = {};
832
890
  function markDisposal(el) {
@@ -851,8 +909,9 @@ function dispose(node) {
851
909
  disposeChildren(node, true);
852
910
  }
853
911
  function disposeChildren(node, self = false, zombie) {
854
- if (node._flags & REACTIVE_DISPOSED) return;
855
- 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;
856
915
  if (self && true) clearSignals(node);
857
916
  if (self && node._fn) node._inFlight = null;
858
917
  let child = zombie ? node._pendingFirstChild : node._firstChild;
@@ -877,6 +936,20 @@ function disposeChildren(node, self = false, zombie) {
877
936
  node._firstChild = null;
878
937
  node._childCount = 0;
879
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
+ }
880
953
  runDisposal(node, zombie);
881
954
  }
882
955
  function runDisposal(node, zombie) {
@@ -894,7 +967,7 @@ function runDisposal(node, zombie) {
894
967
  }
895
968
  function childId(owner, consume) {
896
969
  let counter = owner;
897
- while (counter._transparent && counter._parent) counter = counter._parent;
970
+ while (counter._config & CONFIG_TRANSPARENT && counter._parent) counter = counter._parent;
898
971
  if (counter.id != null)
899
972
  return formatId(counter.id, consume ? counter._childCount++ : counter._childCount);
900
973
  throw new Error("Cannot get child id from owner without an id");
@@ -927,6 +1000,9 @@ function cleanup(fn) {
927
1000
  function isDisposed(node) {
928
1001
  return !!(node._flags & (REACTIVE_DISPOSED | REACTIVE_ZOMBIE));
929
1002
  }
1003
+ function disposeRootSelf(self = true) {
1004
+ disposeChildren(this, self);
1005
+ }
930
1006
  function createOwner(options) {
931
1007
  const parent = context;
932
1008
  const transparent = options?.transparent ?? false;
@@ -934,11 +1010,12 @@ function createOwner(options) {
934
1010
  id:
935
1011
  options?.id ??
936
1012
  (transparent ? parent?.id : parent?.id != null ? getNextChildId(parent) : undefined),
937
- _transparent: transparent || undefined,
1013
+ _config: transparent ? CONFIG_TRANSPARENT : 0,
938
1014
  _root: true,
939
1015
  _parentComputed: parent?._root ? parent._parentComputed : parent,
940
1016
  _firstChild: null,
941
1017
  _nextSibling: null,
1018
+ _prevSibling: null,
942
1019
  _disposal: null,
943
1020
  _queue: parent?._queue ?? globalQueue,
944
1021
  _context: parent?._context || defaultContext,
@@ -946,14 +1023,18 @@ function createOwner(options) {
946
1023
  _pendingDisposal: null,
947
1024
  _pendingFirstChild: null,
948
1025
  _parent: parent,
949
- dispose(self = true) {
950
- disposeChildren(owner, self);
951
- }
1026
+ dispose: disposeRootSelf
952
1027
  };
953
- if (parent?._childrenForbidden) {
954
- throw new Error(
955
- "Cannot create reactive primitives inside createTrackedEffect or owner-backed onSettled"
956
- );
1028
+ if (parent && parent._config & CONFIG_CHILDREN_FORBIDDEN) {
1029
+ emitDiagnostic({
1030
+ code: "PRIMITIVE_IN_FORBIDDEN_SCOPE",
1031
+ kind: "lifecycle",
1032
+ severity: "error",
1033
+ message: PRIMITIVE_IN_FORBIDDEN_SCOPE_MESSAGE,
1034
+ ownerId: parent.id,
1035
+ ownerName: parent._name
1036
+ });
1037
+ throw new Error(PRIMITIVE_IN_FORBIDDEN_SCOPE_MESSAGE);
957
1038
  }
958
1039
  if (parent) {
959
1040
  const lastChild = parent._firstChild;
@@ -961,6 +1042,7 @@ function createOwner(options) {
961
1042
  parent._firstChild = owner;
962
1043
  } else {
963
1044
  owner._nextSibling = lastChild;
1045
+ lastChild._prevSibling = owner;
964
1046
  parent._firstChild = owner;
965
1047
  }
966
1048
  }
@@ -969,7 +1051,82 @@ function createOwner(options) {
969
1051
  }
970
1052
  function createRoot(init, options) {
971
1053
  const owner = createOwner(options);
972
- return runWithOwner(owner, () => init(owner.dispose));
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;
973
1130
  }
974
1131
  function addPendingSource(el, source) {
975
1132
  if (el._pendingSource === source || el._pendingSources?.has(source)) return false;
@@ -1062,13 +1219,34 @@ function settlePendingSource(el) {
1062
1219
  if (scheduled) schedule();
1063
1220
  }
1064
1221
  function handleAsync(el, result, setter) {
1065
- const isObject = typeof result === "object" && result !== null;
1066
- const iterator = isObject && untrack(() => result[Symbol.asyncIterator]);
1067
- 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
+ }
1068
1230
  if (!isThenable && !iterator) {
1069
1231
  el._inFlight = null;
1070
1232
  return result;
1071
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
+ }
1072
1250
  el._inFlight = result;
1073
1251
  let syncValue;
1074
1252
  const handleError = error => {
@@ -1082,6 +1260,7 @@ function handleAsync(el, result, setter) {
1082
1260
  if (el._flags & (REACTIVE_DIRTY | REACTIVE_OPTIMISTIC_DIRTY)) return;
1083
1261
  globalQueue.initTransition(resolveTransition(el));
1084
1262
  const wasUninitialized = !!(el._statusFlags & STATUS_UNINITIALIZED);
1263
+ trimStaleDeps(el);
1085
1264
  clearStatus(el);
1086
1265
  const lane = resolveLane(el);
1087
1266
  if (lane) lane._pendingAsync.delete(el);
@@ -1191,12 +1370,12 @@ function handleAsync(el, result, setter) {
1191
1370
  return syncValue;
1192
1371
  }
1193
1372
  function clearStatus(el, clearUninitialized = false) {
1194
- clearPendingSources(el);
1195
- el._blocked = false;
1373
+ if (el._pendingSource || el._pendingSources) clearPendingSources(el);
1374
+ if (el._blocked) el._blocked = false;
1196
1375
  el._statusFlags = clearUninitialized ? 0 : el._statusFlags & STATUS_UNINITIALIZED;
1197
- setPendingError(el);
1198
- updatePendingSignal(el);
1199
- el._notifyStatus?.();
1376
+ if (el._error) setPendingError(el);
1377
+ if (el._pendingSignal) updatePendingSignal(el);
1378
+ if (el._notifyStatus) el._notifyStatus();
1200
1379
  }
1201
1380
  function notifyStatus(el, status, error, blockStatus, lane) {
1202
1381
  if (
@@ -1250,7 +1429,7 @@ function notifyStatus(el, status, error, blockStatus, lane) {
1250
1429
  (status !== STATUS_PENDING &&
1251
1430
  (sub._error !== error || sub._pendingSource || sub._pendingSources))
1252
1431
  ) {
1253
- if (!downstreamBlockStatus && !sub._transition) globalQueue._pendingNodes.push(sub);
1432
+ if (!downstreamBlockStatus && !sub._transition) queuePendingNode(sub);
1254
1433
  notifyStatus(sub, status, error, downstreamBlockStatus, downstreamLane);
1255
1434
  }
1256
1435
  });
@@ -1280,6 +1459,8 @@ function enableExternalSource(config) {
1280
1459
  }
1281
1460
  GlobalQueue._update = recompute;
1282
1461
  GlobalQueue._dispose = disposeChildren;
1462
+ const PRIMITIVE_IN_FORBIDDEN_SCOPE_MESSAGE =
1463
+ "[PRIMITIVE_IN_FORBIDDEN_SCOPE] Cannot create reactive primitives inside createTrackedEffect or owner-backed onSettled";
1283
1464
  let tracking = false;
1284
1465
  let stale = false;
1285
1466
  let refreshing = false;
@@ -1318,7 +1499,7 @@ function releaseSubtree(owner) {
1318
1499
  }
1319
1500
  if (child._fn) {
1320
1501
  const comp = child;
1321
- comp._inSnapshotScope = false;
1502
+ comp._config &= ~CONFIG_IN_SNAPSHOT_SCOPE;
1322
1503
  if (comp._flags & REACTIVE_SNAPSHOT_STALE) {
1323
1504
  comp._flags &= ~REACTIVE_SNAPSHOT_STALE;
1324
1505
  comp._flags |= REACTIVE_DIRTY;
@@ -1348,7 +1529,7 @@ function recompute(el, create = false) {
1348
1529
  deleteFromHeap(el, el._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
1349
1530
  el._inFlight = null;
1350
1531
  if (el._transition || isEffect === EFFECT_TRACKED) disposeChildren(el);
1351
- else {
1532
+ else if (el._firstChild !== null || el._disposal !== null) {
1352
1533
  markDisposal(el);
1353
1534
  el._pendingDisposal = el._disposal;
1354
1535
  el._pendingFirstChild = el._firstChild;
@@ -1356,9 +1537,9 @@ function recompute(el, create = false) {
1356
1537
  el._firstChild = null;
1357
1538
  el._childCount = 0;
1358
1539
  clearSignals(el);
1359
- }
1540
+ } else clearSignals(el);
1360
1541
  }
1361
- const isOptimisticDirty = !!(el._flags & REACTIVE_OPTIMISTIC_DIRTY);
1542
+ let isOptimisticDirty = !!(el._flags & REACTIVE_OPTIMISTIC_DIRTY);
1362
1543
  const hasOverride = el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING;
1363
1544
  const wasPending = !!(el._statusFlags & STATUS_PENDING);
1364
1545
  const wasUninitialized = !!(el._statusFlags & STATUS_UNINITIALIZED);
@@ -1380,14 +1561,41 @@ function recompute(el, create = false) {
1380
1561
  if (isOptimisticDirty) {
1381
1562
  const lane = resolveLane(el);
1382
1563
  if (lane) currentOptimisticLane = lane;
1564
+ } else if (activeTransition && !create && activeTransition._optimisticNodes.length) {
1565
+ for (let d = el._deps; d; d = d._nextDep) {
1566
+ const dep = d._dep;
1567
+ if (dep._flags & REACTIVE_OPTIMISTIC_DIRTY) {
1568
+ const depLane = resolveLane(dep);
1569
+ if (depLane) {
1570
+ isOptimisticDirty = true;
1571
+ currentOptimisticLane = depLane;
1572
+ el._flags |= REACTIVE_OPTIMISTIC_DIRTY;
1573
+ assignOrMergeLane(el, depLane);
1574
+ break;
1575
+ }
1576
+ }
1577
+ }
1383
1578
  }
1579
+ const isStaleEffect = isEffect && isEffect !== EFFECT_USER;
1580
+ const prevStale = stale;
1581
+ if (isStaleEffect) stale = true;
1384
1582
  try {
1385
- value = handleAsync(el, el._fn(value));
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
+ }
1386
1592
  clearStatus(el, create);
1387
- const resolvedLane = resolveLane(el);
1388
- if (resolvedLane) {
1389
- resolvedLane._pendingAsync.delete(el);
1390
- 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
+ }
1391
1599
  }
1392
1600
  } catch (e) {
1393
1601
  if (e instanceof NotReadyError && currentOptimisticLane) {
@@ -1409,19 +1617,12 @@ function recompute(el, create = false) {
1409
1617
  } finally {
1410
1618
  tracking = prevTracking;
1411
1619
  strictRead = prevStrictRead;
1620
+ if (isStaleEffect) stale = prevStale;
1412
1621
  el._flags = REACTIVE_NONE | (create ? el._flags & REACTIVE_SNAPSHOT_STALE : 0);
1413
1622
  context = oldcontext;
1414
1623
  }
1415
1624
  if (!el._error) {
1416
- const depsTail = el._depsTail;
1417
- let toRemove = depsTail !== null ? depsTail._nextDep : el._deps;
1418
- if (toRemove !== null) {
1419
- do {
1420
- toRemove = unlinkSubs(toRemove);
1421
- } while (toRemove !== null);
1422
- if (depsTail !== null) depsTail._nextDep = null;
1423
- else el._deps = null;
1424
- }
1625
+ trimStaleDeps(el);
1425
1626
  const compareValue = hasOverride
1426
1627
  ? el._overrideValue
1427
1628
  : el._pendingValue === NOT_PENDING
@@ -1429,6 +1630,10 @@ function recompute(el, create = false) {
1429
1630
  : el._pendingValue;
1430
1631
  const valueChanged =
1431
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
+ }
1432
1637
  if (valueChanged) {
1433
1638
  const prevVisible = hasOverride ? el._overrideValue : undefined;
1434
1639
  if (create || (isEffect && activeTransition !== el._transition) || isOptimisticDirty) {
@@ -1451,10 +1656,16 @@ function recompute(el, create = false) {
1451
1656
  }
1452
1657
  }
1453
1658
  currentOptimisticLane = prevLane;
1454
- (!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) &&
1455
1666
  !el._transition &&
1456
1667
  !(activeTransition && hasOverride) &&
1457
- globalQueue._pendingNodes.push(el);
1668
+ queuePendingNode(el);
1458
1669
  el._transition &&
1459
1670
  isEffect &&
1460
1671
  activeTransition !== el._transition &&
@@ -1481,22 +1692,26 @@ function updateIfNecessary(el) {
1481
1692
  }
1482
1693
  el._flags = el._flags & (REACTIVE_SNAPSHOT_STALE | REACTIVE_IN_HEAP | REACTIVE_IN_HEAP_HEIGHT);
1483
1694
  }
1484
- function computed(fn, initialValue, options) {
1695
+ function computed(fn, options) {
1485
1696
  const transparent = options?.transparent ?? false;
1486
1697
  const self = {
1487
1698
  id:
1488
1699
  options?.id ??
1489
1700
  (transparent ? context?.id : context?.id != null ? getNextChildId(context) : undefined),
1490
- _transparent: transparent || undefined,
1701
+ _config:
1702
+ (transparent ? CONFIG_TRANSPARENT : 0) |
1703
+ (options?.ownedWrite ? CONFIG_OWNED_WRITE : 0) |
1704
+ (!context || options?.lazy ? CONFIG_AUTO_DISPOSE : 0) |
1705
+ (options?.sync ? CONFIG_SYNC : 0) |
1706
+ (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
1491
1707
  _equals: options?.equals != null ? options.equals : isEqual,
1492
- _pureWrite: !!options?.pureWrite,
1493
1708
  _unobserved: options?.unobserved,
1494
1709
  _disposal: null,
1495
1710
  _queue: context?._queue ?? globalQueue,
1496
1711
  _context: context?._context ?? defaultContext,
1497
1712
  _childCount: 0,
1498
1713
  _fn: fn,
1499
- _value: initialValue,
1714
+ _value: undefined,
1500
1715
  _height: 0,
1501
1716
  _child: null,
1502
1717
  _nextHeap: undefined,
@@ -1507,6 +1722,7 @@ function computed(fn, initialValue, options) {
1507
1722
  _subsTail: null,
1508
1723
  _parent: context,
1509
1724
  _nextSibling: null,
1725
+ _prevSibling: null,
1510
1726
  _firstChild: null,
1511
1727
  _flags: options?.lazy ? REACTIVE_LAZY : REACTIVE_NONE,
1512
1728
  _statusFlags: STATUS_UNINITIALIZED,
@@ -1518,12 +1734,75 @@ function computed(fn, initialValue, options) {
1518
1734
  _transition: null
1519
1735
  };
1520
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) {
1521
1794
  self._prevHeap = self;
1522
1795
  const parent = context?._root ? context._parentComputed : context;
1523
- if (context?._childrenForbidden) {
1524
- throw new Error(
1525
- "Cannot create reactive primitives inside createTrackedEffect or owner-backed onSettled"
1526
- );
1796
+ if (context && context._config & CONFIG_CHILDREN_FORBIDDEN) {
1797
+ emitDiagnostic({
1798
+ code: "PRIMITIVE_IN_FORBIDDEN_SCOPE",
1799
+ kind: "lifecycle",
1800
+ severity: "error",
1801
+ message: PRIMITIVE_IN_FORBIDDEN_SCOPE_MESSAGE,
1802
+ ownerId: context.id,
1803
+ ownerName: context._name
1804
+ });
1805
+ throw new Error(PRIMITIVE_IN_FORBIDDEN_SCOPE_MESSAGE);
1527
1806
  }
1528
1807
  if (context) {
1529
1808
  const lastChild = context._firstChild;
@@ -1531,14 +1810,14 @@ function computed(fn, initialValue, options) {
1531
1810
  context._firstChild = self;
1532
1811
  } else {
1533
1812
  self._nextSibling = lastChild;
1813
+ lastChild._prevSibling = self;
1534
1814
  context._firstChild = self;
1535
1815
  }
1536
1816
  }
1537
1817
  DEV$1.hooks.onOwner?.(self);
1538
1818
  if (parent) self._height = parent._height + 1;
1539
- if (snapshotCaptureActive && ownerInSnapshotScope(context)) self._inSnapshotScope = true;
1540
1819
  if (externalSourceConfig) {
1541
- const bridgeSignal = signal(undefined, { equals: false, pureWrite: true });
1820
+ const bridgeSignal = signal(undefined, { equals: false, ownedWrite: true });
1542
1821
  const source = externalSourceConfig.factory(self._fn, () => {
1543
1822
  setSignal(bridgeSignal, undefined);
1544
1823
  });
@@ -1555,13 +1834,13 @@ function computed(fn, initialValue, options) {
1555
1834
  snapshotSources.add(self);
1556
1835
  }
1557
1836
  }
1558
- return self;
1559
1837
  }
1560
1838
  function signal(v, options, firewall = null) {
1561
1839
  const s = {
1562
1840
  _equals: options?.equals != null ? options.equals : isEqual,
1563
- _pureWrite: !!options?.pureWrite,
1564
- _noSnapshot: !!options?._noSnapshot,
1841
+ _config:
1842
+ (options?.ownedWrite ? CONFIG_OWNED_WRITE : 0) |
1843
+ (options?._noSnapshot ? CONFIG_NO_SNAPSHOT : 0),
1565
1844
  _unobserved: options?.unobserved,
1566
1845
  _value: v,
1567
1846
  _subs: null,
@@ -1578,7 +1857,7 @@ function signal(v, options, firewall = null) {
1578
1857
  firewall && (firewall._child = s);
1579
1858
  if (
1580
1859
  snapshotCaptureActive &&
1581
- !s._noSnapshot &&
1860
+ !(s._config & CONFIG_NO_SNAPSHOT) &&
1582
1861
  !((firewall?._statusFlags ?? 0) & STATUS_PENDING)
1583
1862
  ) {
1584
1863
  s._snapshotValue = v === undefined ? NO_SNAPSHOT : v;
@@ -1591,8 +1870,8 @@ function optimisticSignal(v, options) {
1591
1870
  s._overrideValue = NOT_PENDING;
1592
1871
  return s;
1593
1872
  }
1594
- function optimisticComputed(fn, initialValue, options) {
1595
- const c = computed(fn, initialValue, options);
1873
+ function optimisticComputed(fn, options) {
1874
+ const c = computed(fn, options);
1596
1875
  c._overrideValue = NOT_PENDING;
1597
1876
  return c;
1598
1877
  }
@@ -1672,15 +1951,33 @@ function read(el) {
1672
1951
  }
1673
1952
  let c = context;
1674
1953
  if (c?._root) c = c._parentComputed;
1675
- if (refreshing && el._fn) recompute(el);
1676
- if (el._flags & REACTIVE_LAZY) {
1677
- el._flags &= ~REACTIVE_LAZY;
1678
- recompute(el, true);
1954
+ const computed = el;
1955
+ if (typeof computed._fn === "function") {
1956
+ const comp = el;
1957
+ if (comp._flags & REACTIVE_LAZY) {
1958
+ comp._flags &= ~REACTIVE_LAZY;
1959
+ recompute(comp, true);
1960
+ } else if (comp._flags & REACTIVE_DISPOSED) {
1961
+ recompute(comp, true);
1962
+ }
1679
1963
  }
1680
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
+ }
1681
1978
  if (strictRead && owner._statusFlags & STATUS_PENDING) {
1682
1979
  const message =
1683
- `Reading a pending async value directly in ${strictRead}. ` +
1980
+ `[PENDING_ASYNC_UNTRACKED_READ] Reading a pending async value directly in ${strictRead}. ` +
1684
1981
  `Async values must be read within a tracking scope (JSX, a memo, or an effect's compute function).`;
1685
1982
  emitDiagnostic({
1686
1983
  code: "PENDING_ASYNC_UNTRACKED_READ",
@@ -1695,7 +1992,6 @@ function read(el) {
1695
1992
  throw new Error(message);
1696
1993
  }
1697
1994
  if (c && tracking) {
1698
- if (el._fn && el._flags & REACTIVE_DISPOSED) recompute(el);
1699
1995
  link(el, c);
1700
1996
  if (owner._fn) {
1701
1997
  const isZombie = el._flags & REACTIVE_ZOMBIE;
@@ -1712,9 +2008,9 @@ function read(el) {
1712
2008
  }
1713
2009
  if (owner._statusFlags & STATUS_PENDING) {
1714
2010
  if (c && !(stale && owner._transition && activeTransition !== owner._transition)) {
1715
- if (c?._childrenForbidden) {
2011
+ if (c && c._config & CONFIG_CHILDREN_FORBIDDEN) {
1716
2012
  const message =
1717
- "Reading a pending async value inside createTrackedEffect or onSettled will throw. " +
2013
+ "[PENDING_ASYNC_FORBIDDEN_SCOPE] Reading a pending async value inside createTrackedEffect or onSettled will throw. " +
1718
2014
  "Use createEffect instead which supports async-aware reactivity.";
1719
2015
  emitDiagnostic({
1720
2016
  code: "PENDING_ASYNC_FORBIDDEN_SCOPE",
@@ -1751,7 +2047,7 @@ function read(el) {
1751
2047
  return read(el);
1752
2048
  } else throw el._error;
1753
2049
  }
1754
- if (snapshotCaptureActive && c && c._inSnapshotScope) {
2050
+ if (snapshotCaptureActive && c && c._config & CONFIG_IN_SNAPSHOT_SCOPE) {
1755
2051
  const sv = el._snapshotValue;
1756
2052
  if (sv !== undefined) {
1757
2053
  const snapshot = sv === NO_SNAPSHOT ? undefined : sv;
@@ -1762,7 +2058,7 @@ function read(el) {
1762
2058
  }
1763
2059
  if (strictRead) {
1764
2060
  const message =
1765
- `Reactive value read directly in ${strictRead} will not update. ` +
2061
+ `[STRICT_READ_UNTRACKED] Reactive value read directly in ${strictRead} will not update. ` +
1766
2062
  `Move it into a tracking scope (JSX, a memo, or an effect's compute function).`;
1767
2063
  emitDiagnostic({
1768
2064
  code: "STRICT_READ_UNTRACKED",
@@ -1780,7 +2076,20 @@ function read(el) {
1780
2076
  if (c && stale && shouldReadStashedOptimisticValue(el)) return el._value;
1781
2077
  return el._overrideValue;
1782
2078
  }
1783
- return !c ||
2079
+ if (
2080
+ activeTransition !== null &&
2081
+ currentOptimisticLane !== null &&
2082
+ !latestReadActive &&
2083
+ el._pendingValue !== NOT_PENDING &&
2084
+ owner === el &&
2085
+ !el._fn &&
2086
+ c
2087
+ ) {
2088
+ activeTransition._gatedSubs.add(c);
2089
+ return el._value;
2090
+ }
2091
+ const value =
2092
+ !c ||
1784
2093
  (currentOptimisticLane !== null &&
1785
2094
  (el._overrideValue !== undefined ||
1786
2095
  el._optimisticLane ||
@@ -1788,14 +2097,30 @@ function read(el) {
1788
2097
  !!(owner._statusFlags & STATUS_PENDING))) ||
1789
2098
  el._pendingValue === NOT_PENDING ||
1790
2099
  (stale && el._transition && activeTransition !== el._transition)
1791
- ? el._value
1792
- : el._pendingValue;
2100
+ ? el._value
2101
+ : el._pendingValue;
2102
+ if (
2103
+ !c &&
2104
+ owner === el &&
2105
+ typeof computed._fn === "function" &&
2106
+ el._config & CONFIG_AUTO_DISPOSE &&
2107
+ !(owner._statusFlags & STATUS_PENDING) &&
2108
+ !el._subs
2109
+ ) {
2110
+ unobserved(el);
2111
+ }
2112
+ return value;
1793
2113
  }
1794
2114
  function setSignal(el, v) {
1795
- if (!el._pureWrite && !context?._childrenForbidden && context && el._firewall !== context) {
2115
+ if (
2116
+ !(el._config & CONFIG_OWNED_WRITE) &&
2117
+ !(context && context._config & CONFIG_CHILDREN_FORBIDDEN) &&
2118
+ context &&
2119
+ el._firewall !== context
2120
+ ) {
1796
2121
  const message =
1797
- "Writing to a Signal inside an owned scope (component, computation) is not allowed. " +
1798
- "Move the write outside or set the `pureWrite` option if this is intentional.";
2122
+ "[SIGNAL_WRITE_IN_OWNED_SCOPE] Writing to a Signal inside an owned scope (component, computation) is not allowed. " +
2123
+ "Move the write outside or set the `ownedWrite` option if this is intentional.";
1799
2124
  emitDiagnostic({
1800
2125
  code: "SIGNAL_WRITE_IN_OWNED_SCOPE",
1801
2126
  kind: "write",
@@ -1840,10 +2165,10 @@ function setSignal(el, v) {
1840
2165
  el._optimisticLane = lane;
1841
2166
  el._overrideValue = v;
1842
2167
  } else {
1843
- if (el._pendingValue === NOT_PENDING) globalQueue._pendingNodes.push(el);
2168
+ if (el._pendingValue === NOT_PENDING) queuePendingNode(el);
1844
2169
  el._pendingValue = v;
1845
2170
  }
1846
- updatePendingSignal(el);
2171
+ if (el._pendingSignal) updatePendingSignal(el);
1847
2172
  if (el._latestValueComputed) {
1848
2173
  setSignal(el._latestValueComputed, v);
1849
2174
  }
@@ -1852,10 +2177,21 @@ function setSignal(el, v) {
1852
2177
  schedule();
1853
2178
  return v;
1854
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
+ }
1855
2191
  function runWithOwner(owner, fn) {
1856
2192
  if (owner && owner._flags & REACTIVE_DISPOSED) {
1857
2193
  const message =
1858
- "runWithOwner called with a disposed owner. Children created inside will never be disposed.";
2194
+ "[RUN_WITH_DISPOSED_OWNER] runWithOwner called with a disposed owner. Children created inside will never be disposed.";
1859
2195
  emitDiagnostic({
1860
2196
  code: "RUN_WITH_DISPOSED_OWNER",
1861
2197
  kind: "owner",
@@ -1879,7 +2215,7 @@ function runWithOwner(owner, fn) {
1879
2215
  }
1880
2216
  function getPendingSignal(el) {
1881
2217
  if (!el._pendingSignal) {
1882
- el._pendingSignal = optimisticSignal(false, { pureWrite: true });
2218
+ el._pendingSignal = optimisticSignal(false, { ownedWrite: true });
1883
2219
  if (el._parentSource) {
1884
2220
  el._pendingSignal._parentSource = el;
1885
2221
  }
@@ -1975,15 +2311,26 @@ function isPending(fn) {
1975
2311
  foundPending = prevFoundPending;
1976
2312
  }
1977
2313
  }
1978
- function refresh(fn) {
2314
+ function refresh(target) {
1979
2315
  let prevRefreshing = refreshing;
1980
2316
  refreshing = true;
1981
2317
  try {
1982
- if (typeof fn !== "function") {
1983
- recompute(fn[$REFRESH]);
1984
- 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);
1985
2333
  }
1986
- return untrack(fn);
1987
2334
  } finally {
1988
2335
  refreshing = prevRefreshing;
1989
2336
  if (!prevRefreshing) {
@@ -2022,71 +2369,24 @@ function hasContext(context, owner) {
2022
2369
  function isUndefined(value) {
2023
2370
  return typeof value === "undefined";
2024
2371
  }
2025
- function effect(compute, effect, error, initialValue, options) {
2026
- let initialized = false;
2027
- const node = computed(
2028
- options?.render ? p => staleValues(() => compute(p)) : compute,
2029
- initialValue,
2030
- {
2031
- ...options,
2032
- equals: () => {
2033
- node._modified = !node._error;
2034
- if (initialized) node._queue.enqueue(node._type, runEffect.bind(node));
2035
- return false;
2036
- },
2037
- lazy: true
2038
- }
2372
+ function effect(compute, effect, error, options) {
2373
+ const isUser = !!options?.user;
2374
+ const node = createEffectNode(
2375
+ compute,
2376
+ effect,
2377
+ error,
2378
+ isUser ? EFFECT_USER : EFFECT_RENDER,
2379
+ notifyEffectStatus,
2380
+ options
2039
2381
  );
2040
- node._prevValue = initialValue;
2041
- node._effectFn = effect;
2042
- node._errorFn = error;
2043
- node._cleanup = undefined;
2044
- node._type = options?.render ? EFFECT_RENDER : EFFECT_USER;
2045
- node._notifyStatus = (status, error) => {
2046
- const actualStatus = status !== undefined ? status : node._statusFlags;
2047
- const actualError = error !== undefined ? error : node._error;
2048
- if (actualStatus & STATUS_ERROR) {
2049
- let err = actualError;
2050
- node._queue.notify(node, STATUS_PENDING, 0);
2051
- if (node._type === EFFECT_USER) {
2052
- try {
2053
- return node._errorFn
2054
- ? node._errorFn(err, () => {
2055
- node._cleanup?.();
2056
- node._cleanup = undefined;
2057
- })
2058
- : console.error(err);
2059
- } catch (e) {
2060
- err = e;
2061
- }
2062
- }
2063
- if (!node._queue.notify(node, STATUS_ERROR, STATUS_ERROR)) throw err;
2064
- } else if (node._type === EFFECT_RENDER) {
2065
- node._queue.notify(node, STATUS_PENDING | STATUS_ERROR, actualStatus, actualError);
2066
- if (_hitUnhandledAsync) {
2067
- resetUnhandledAsync();
2068
- const err = new Error("An async value must be rendered inside a Loading boundary.");
2069
- emitDiagnostic({
2070
- code: "ASYNC_OUTSIDE_LOADING_BOUNDARY",
2071
- kind: "async",
2072
- severity: "error",
2073
- message: err.message,
2074
- ownerId: node.id,
2075
- ownerName: node._name
2076
- });
2077
- if (!node._queue.notify(node, STATUS_ERROR, STATUS_ERROR)) throw err;
2078
- }
2079
- }
2080
- };
2081
2382
  recompute(node, true);
2082
2383
  !options?.defer &&
2083
- (node._type === EFFECT_USER
2084
- ? node._queue.enqueue(node._type, runEffect.bind(node))
2085
- : runEffect.call(node));
2086
- initialized = true;
2087
- cleanup(() => node._cleanup?.());
2384
+ (node._type === EFFECT_USER || options?.schedule
2385
+ ? node._queue.enqueue(node._type, runEffect.bind(null, node))
2386
+ : runEffect(node));
2088
2387
  if (!node._parent) {
2089
- const message = "Effects created outside a reactive context will never be disposed";
2388
+ const message =
2389
+ "[NO_OWNER_EFFECT] Effects created outside a reactive context will never be disposed";
2090
2390
  emitDiagnostic({
2091
2391
  code: "NO_OWNER_EFFECT",
2092
2392
  kind: "lifecycle",
@@ -2099,32 +2399,76 @@ function effect(compute, effect, error, initialValue, options) {
2099
2399
  console.warn(message);
2100
2400
  }
2101
2401
  }
2102
- function runEffect() {
2103
- 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;
2104
2443
  let prevStrictRead = false;
2105
2444
  {
2106
2445
  prevStrictRead = setStrictRead("an effect callback");
2107
2446
  }
2108
- this._cleanup?.();
2109
- this._cleanup = undefined;
2447
+ node._cleanup?.();
2448
+ node._cleanup = undefined;
2110
2449
  try {
2111
- const cleanup = this._effectFn(this._value, this._prevValue);
2112
- if (true && cleanup !== undefined && typeof cleanup !== "function") {
2450
+ const nextCleanup = node._effectFn(node._value, node._prevValue);
2451
+ if (true && nextCleanup !== undefined && typeof nextCleanup !== "function") {
2113
2452
  throw new Error(
2114
- `${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.`
2115
2454
  );
2116
2455
  }
2117
- 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
+ }
2118
2461
  } catch (error) {
2119
- this._error = new StatusError(this, error);
2120
- this._statusFlags |= STATUS_ERROR;
2121
- 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;
2122
2465
  } finally {
2123
2466
  setStrictRead(prevStrictRead);
2124
- this._prevValue = this._value;
2125
- this._modified = false;
2467
+ node._prevValue = node._value;
2468
+ node._modified = false;
2126
2469
  }
2127
2470
  }
2471
+ GlobalQueue._runEffect = runEffect;
2128
2472
  function trackedEffect(fn, options) {
2129
2473
  const run = () => {
2130
2474
  if (!node._modified || node._flags & REACTIVE_DISPOSED) return;
@@ -2148,11 +2492,10 @@ function trackedEffect(fn, options) {
2148
2492
  }
2149
2493
  node._cleanup = cleanup;
2150
2494
  },
2151
- undefined,
2152
2495
  { ...options, lazy: true }
2153
2496
  );
2154
2497
  node._cleanup = undefined;
2155
- node._childrenForbidden = true;
2498
+ node._config = (node._config & ~CONFIG_AUTO_DISPOSE) | CONFIG_CHILDREN_FORBIDDEN;
2156
2499
  node._modified = true;
2157
2500
  node._type = EFFECT_TRACKED;
2158
2501
  node._notifyStatus = (status, error) => {
@@ -2167,7 +2510,8 @@ function trackedEffect(fn, options) {
2167
2510
  node._queue.enqueue(EFFECT_USER, run);
2168
2511
  cleanup(() => node._cleanup?.());
2169
2512
  if (!node._parent) {
2170
- const message = "Effects created outside a reactive context will never be disposed";
2513
+ const message =
2514
+ "[NO_OWNER_EFFECT] Effects created outside a reactive context will never be disposed";
2171
2515
  emitDiagnostic({
2172
2516
  code: "NO_OWNER_EFFECT",
2173
2517
  kind: "lifecycle",
@@ -2228,7 +2572,8 @@ function onCleanup(fn) {
2228
2572
  {
2229
2573
  const owner = getOwner();
2230
2574
  if (!owner) {
2231
- const message = "onCleanup called outside a reactive context will never be run";
2575
+ const message =
2576
+ "[NO_OWNER_CLEANUP] onCleanup called outside a reactive context will never be run";
2232
2577
  emitDiagnostic({
2233
2578
  code: "NO_OWNER_CLEANUP",
2234
2579
  kind: "lifecycle",
@@ -2236,9 +2581,9 @@ function onCleanup(fn) {
2236
2581
  message: message
2237
2582
  });
2238
2583
  console.warn(message);
2239
- } else if (owner._childrenForbidden) {
2584
+ } else if (owner._config & CONFIG_CHILDREN_FORBIDDEN) {
2240
2585
  const message =
2241
- "Cannot use onCleanup inside createTrackedEffect or onSettled; return a cleanup function instead";
2586
+ "[CLEANUP_IN_FORBIDDEN_SCOPE] Cannot use onCleanup inside createTrackedEffect or onSettled; return a cleanup function instead";
2242
2587
  emitDiagnostic({
2243
2588
  code: "CLEANUP_IN_FORBIDDEN_SCOPE",
2244
2589
  kind: "lifecycle",
@@ -2254,34 +2599,45 @@ function onCleanup(fn) {
2254
2599
  }
2255
2600
  function accessor(node) {
2256
2601
  const fn = read.bind(null, node);
2257
- fn.$r = true;
2602
+ fn[$REFRESH] = node;
2258
2603
  return fn;
2259
2604
  }
2260
- function createSignal(first, second, third) {
2605
+ function createSignal(first, second) {
2261
2606
  if (typeof first === "function") {
2262
- const node = computed(first, second, third);
2263
- return [accessor(node), setSignal.bind(null, node)];
2607
+ const node = computed(first, second);
2608
+ node._config &= ~CONFIG_AUTO_DISPOSE;
2609
+ return [accessor(node), setMemo.bind(null, node)];
2264
2610
  }
2265
2611
  const node = signal(first, second);
2266
2612
  registerGraph(node, getOwner());
2267
2613
  return [accessor(node), setSignal.bind(null, node)];
2268
2614
  }
2269
- function createMemo(compute, value, options) {
2270
- let node = computed(compute, value, options);
2271
- return accessor(node);
2272
- }
2273
- function createEffect(compute, effectFn, value, options) {
2274
- effect(compute, effectFn.effect || effectFn, effectFn.error, value, {
2275
- ...options,
2276
- name: options?.name ?? "effect"
2277
- });
2615
+ function createMemo(compute, options) {
2616
+ return accessor(computed(compute, options));
2278
2617
  }
2279
- function createRenderEffect(compute, effectFn, value, options) {
2280
- effect(compute, effectFn, undefined, value, {
2281
- render: true,
2618
+ function createEffect(compute, effectFn, options) {
2619
+ if (effectFn === undefined) {
2620
+ const message =
2621
+ "[MISSING_EFFECT_FN] createEffect requires both a compute function and an effect function. " +
2622
+ "Use `createEffect(() => signal(), value => doWork(value))`. " +
2623
+ "If you want a derived value, use `createMemo`. " +
2624
+ "If you want a one-shot side effect, just call the function directly.";
2625
+ emitDiagnostic({
2626
+ code: "MISSING_EFFECT_FN",
2627
+ kind: "lifecycle",
2628
+ severity: "error",
2629
+ message: message
2630
+ });
2631
+ throw new Error(message);
2632
+ }
2633
+ effect(compute, effectFn.effect || effectFn, effectFn.error, {
2634
+ user: true,
2282
2635
  ...{ ...options, name: options?.name ?? "effect" }
2283
2636
  });
2284
2637
  }
2638
+ function createRenderEffect(compute, effectFn, options) {
2639
+ effect(compute, effectFn, undefined, { ...options, name: options?.name ?? "effect" });
2640
+ }
2285
2641
  function createTrackedEffect(compute, options) {
2286
2642
  trackedEffect(compute, { ...options, name: options?.name ?? "trackedEffect" });
2287
2643
  }
@@ -2305,8 +2661,11 @@ function createReaction(effectFn, options) {
2305
2661
  dispose(node);
2306
2662
  },
2307
2663
  effectFn.error,
2308
- undefined,
2309
- { defer: true, ...(true ? { ...options, name: options?.name ?? "effect" } : options) }
2664
+ {
2665
+ ...(true ? { ...options, name: options?.name ?? "effect" } : options),
2666
+ user: true,
2667
+ defer: true
2668
+ }
2310
2669
  );
2311
2670
  });
2312
2671
  };
@@ -2331,9 +2690,10 @@ function resolve(fn) {
2331
2690
  });
2332
2691
  });
2333
2692
  }
2334
- function createOptimistic(first, second, third) {
2693
+ function createOptimistic(first, second) {
2335
2694
  if (typeof first === "function") {
2336
- const node = optimisticComputed(first, second, third);
2695
+ const node = optimisticComputed(first, second);
2696
+ node._config &= ~CONFIG_AUTO_DISPOSE;
2337
2697
  return [accessor(node), setSignal.bind(null, node)];
2338
2698
  }
2339
2699
  const node = optimisticSignal(first, second);
@@ -2342,7 +2702,7 @@ function createOptimistic(first, second, third) {
2342
2702
  }
2343
2703
  function onSettled(callback) {
2344
2704
  const owner = getOwner();
2345
- owner && !owner._childrenForbidden
2705
+ owner && !(owner._config & CONFIG_CHILDREN_FORBIDDEN)
2346
2706
  ? createTrackedEffect(() => untrack(callback), { name: "onSettled" })
2347
2707
  : globalQueue.enqueue(EFFECT_USER, () => {
2348
2708
  const cleanup = callback();
@@ -2357,7 +2717,7 @@ function onSettled(callback) {
2357
2717
  function unwrap(value) {
2358
2718
  return value?.[$TARGET]?.[STORE_NODE] ?? value;
2359
2719
  }
2360
- function getOverrideValue(value, override, nodes, key, optOverride) {
2720
+ function getOverrideValue(value, override, key, optOverride) {
2361
2721
  if (optOverride && key in optOverride) return optOverride[key];
2362
2722
  return override && key in override ? override[key] : value[key];
2363
2723
  }
@@ -2369,23 +2729,147 @@ function getAllKeys(value, override, next) {
2369
2729
  function applyState(next, state, keyFn) {
2370
2730
  const target = state?.[$TARGET];
2371
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) {
2372
2857
  const previous = target[STORE_VALUE];
2373
2858
  const override = target[STORE_OVERRIDE];
2374
2859
  const optOverride = target[STORE_OPTIMISTIC_OVERRIDE];
2375
2860
  let nodes = target[STORE_NODE];
2376
- if (next === previous && !override && !optOverride) return;
2377
2861
  (target[STORE_LOOKUP] || storeLookup).set(next, target[$PROXY]);
2378
2862
  target[STORE_VALUE] = next;
2379
2863
  target[STORE_OVERRIDE] = undefined;
2380
2864
  if (Array.isArray(previous)) {
2381
2865
  let changed = false;
2382
- const prevLength = getOverrideValue(previous, override, nodes, "length", optOverride);
2866
+ const prevLength = getOverrideValue(previous, override, "length", optOverride);
2383
2867
  if (next.length && prevLength && next[0] && keyFn(next[0]) != null) {
2384
2868
  let i, j, start, end, newEnd, item, newIndicesNext, keyVal;
2385
2869
  for (
2386
2870
  start = 0, end = Math.min(prevLength, next.length);
2387
2871
  start < end &&
2388
- ((item = getOverrideValue(previous, override, nodes, start, optOverride)) === next[start] ||
2872
+ ((item = getOverrideValue(previous, override, start, optOverride)) === next[start] ||
2389
2873
  (item && next[start] && keyFn(item) === keyFn(next[start])));
2390
2874
  start++
2391
2875
  ) {
@@ -2397,7 +2881,7 @@ function applyState(next, state, keyFn) {
2397
2881
  end = prevLength - 1, newEnd = next.length - 1;
2398
2882
  end >= start &&
2399
2883
  newEnd >= start &&
2400
- ((item = getOverrideValue(previous, override, nodes, end, optOverride)) === next[newEnd] ||
2884
+ ((item = getOverrideValue(previous, override, end, optOverride)) === next[newEnd] ||
2401
2885
  (item && next[newEnd] && keyFn(item) === keyFn(next[newEnd])));
2402
2886
  end--, newEnd--
2403
2887
  ) {
@@ -2429,7 +2913,7 @@ function applyState(next, state, keyFn) {
2429
2913
  newIndices.set(keyVal, j);
2430
2914
  }
2431
2915
  for (i = start; i <= end; i++) {
2432
- item = getOverrideValue(previous, override, nodes, i, optOverride);
2916
+ item = getOverrideValue(previous, override, i, optOverride);
2433
2917
  keyVal = item ? keyFn(item) : item;
2434
2918
  j = newIndices.get(keyVal);
2435
2919
  if (j !== undefined && j !== -1) {
@@ -2448,7 +2932,7 @@ function applyState(next, state, keyFn) {
2448
2932
  if (start < next.length) changed = true;
2449
2933
  } else if (next.length) {
2450
2934
  for (let i = 0, len = next.length; i < len; i++) {
2451
- const item = getOverrideValue(previous, override, nodes, i, optOverride);
2935
+ const item = getOverrideValue(previous, override, i, optOverride);
2452
2936
  isWrappable(item)
2453
2937
  ? applyState(next[i], wrap(item, target), keyFn)
2454
2938
  : target[STORE_NODE][i] && setSignal(target[STORE_NODE][i], next[i]);
@@ -2467,7 +2951,7 @@ function applyState(next, state, keyFn) {
2467
2951
  for (let i = 0, len = keys.length; i < len; i++) {
2468
2952
  const key = keys[i];
2469
2953
  const node = nodes[key];
2470
- const previousValue = unwrap(getOverrideValue(previous, override, nodes, key, optOverride));
2954
+ const previousValue = unwrap(getOverrideValue(previous, override, key, optOverride));
2471
2955
  let nextValue = unwrap(next[key]);
2472
2956
  if (previousValue === nextValue) continue;
2473
2957
  if (
@@ -2499,7 +2983,7 @@ function reconcile(value, key) {
2499
2983
  applyState(value, state, keyFn);
2500
2984
  };
2501
2985
  }
2502
- function createProjectionInternal(fn, initialValue = {}, options) {
2986
+ function createProjectionInternal(fn, seed, options) {
2503
2987
  let node;
2504
2988
  const wrappedMap = new WeakMap();
2505
2989
  const wrapper = s => {
@@ -2519,31 +3003,39 @@ function createProjectionInternal(fn, initialValue = {}, options) {
2519
3003
  wrappedMap.set(source, wrapped);
2520
3004
  return wrapped;
2521
3005
  };
2522
- const wrappedStore = wrapProjection(initialValue);
2523
- node = computed(() => {
2524
- const owner = getOwner();
2525
- let settled = false;
2526
- let result;
2527
- const draft = new Proxy(
2528
- wrappedStore,
2529
- createWriteTraps(() => !settled || owner._inFlight === result)
2530
- );
2531
- storeSetter(draft, s => {
2532
- result = fn(s);
2533
- settled = true;
2534
- const value = handleAsync(owner, result, value => {
2535
- value !== s &&
2536
- value !== undefined &&
2537
- storeSetter(wrappedStore, reconcile(value, options?.key || "id"));
2538
- });
2539
- value !== s && value !== undefined && reconcile(value, options?.key || "id")(wrappedStore);
2540
- });
2541
- });
2542
- node._preventAutoDisposal = true;
3006
+ const wrappedStore = wrapProjection(seed);
3007
+ node = computed(
3008
+ () => {
3009
+ if (!node) node = getOwner();
3010
+ runProjectionComputed(wrappedStore, fn, options?.key || "id");
3011
+ },
3012
+ options?.name ? { name: options.name } : undefined
3013
+ );
3014
+ node._config &= ~CONFIG_AUTO_DISPOSE;
2543
3015
  return { store: wrappedStore, node: node };
2544
3016
  }
2545
- function createProjection(fn, initialValue = {}, options) {
2546
- return createProjectionInternal(fn, initialValue, options).store;
3017
+ function createProjection(fn, seed, options) {
3018
+ return createProjectionInternal(fn, seed, options).store;
3019
+ }
3020
+ function runProjectionComputed(wrappedStore, fn, key, wrapCommit) {
3021
+ const owner = getOwner();
3022
+ let settled = false;
3023
+ let result;
3024
+ const draft = new Proxy(
3025
+ wrappedStore,
3026
+ createWriteTraps(() => !settled || owner._inFlight === result)
3027
+ );
3028
+ storeSetter(draft, s => {
3029
+ result = fn(s);
3030
+ settled = true;
3031
+ const commit = v => {
3032
+ if (v === s || v === undefined) return;
3033
+ const write = () => storeSetter(wrappedStore, reconcile(v, key));
3034
+ wrapCommit ? wrapCommit(write) : write();
3035
+ };
3036
+ commit(handleAsync(owner, result, commit));
3037
+ });
3038
+ return owner;
2547
3039
  }
2548
3040
  function createWriteTraps(isActive) {
2549
3041
  const traps = {
@@ -2607,6 +3099,7 @@ const STORE_VALUE = "v",
2607
3099
  STORE_OPTIMISTIC_OVERRIDE = "x",
2608
3100
  STORE_NODE = "n",
2609
3101
  STORE_HAS = "h",
3102
+ STORE_CUSTOM_PROTO = "c",
2610
3103
  STORE_WRAP = "w",
2611
3104
  STORE_LOOKUP = "l",
2612
3105
  STORE_FIREWALL = "f",
@@ -2616,7 +3109,14 @@ function createStoreProxy(value, traps = storeTraps, extend) {
2616
3109
  if (Array.isArray(value)) {
2617
3110
  newTarget = [];
2618
3111
  newTarget.v = value;
2619
- } else newTarget = { v: 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
+ }
2620
3120
  extend && extend(newTarget);
2621
3121
  return (newTarget[$PROXY] = new Proxy(newTarget, traps));
2622
3122
  }
@@ -2628,12 +3128,8 @@ function wrap(value, target) {
2628
3128
  return p;
2629
3129
  }
2630
3130
  function isWrappable(obj) {
2631
- return (
2632
- obj != null &&
2633
- typeof obj === "object" &&
2634
- !Object.isFrozen(obj) &&
2635
- !(typeof Node !== "undefined" && obj instanceof Node)
2636
- );
3131
+ if (obj == null || typeof obj !== "object" || Object.isFrozen(obj)) return false;
3132
+ return typeof Node === "undefined" || !(obj instanceof Node);
2637
3133
  }
2638
3134
  let writeOverride = false;
2639
3135
  function setWriteOverride(value) {
@@ -2642,6 +3138,18 @@ function setWriteOverride(value) {
2642
3138
  function writeOnly(proxy) {
2643
3139
  return writeOverride || !!Writing?.has(proxy);
2644
3140
  }
3141
+ function unwrapStoreValue(value) {
3142
+ return value?.[$TARGET]?.[STORE_VALUE] ?? value;
3143
+ }
3144
+ function hasInheritedAccessor(source, property) {
3145
+ let current = Object.getPrototypeOf(source);
3146
+ while (current && current !== Object.prototype) {
3147
+ const desc = Reflect.getOwnPropertyDescriptor(current, property);
3148
+ if (desc) return !!desc.get;
3149
+ current = Object.getPrototypeOf(current);
3150
+ }
3151
+ return false;
3152
+ }
2645
3153
  function getNodes(target, type) {
2646
3154
  let nodes = target[type];
2647
3155
  if (!nodes) target[type] = nodes = Object.create(null);
@@ -2654,7 +3162,7 @@ function getNode(nodes, property, value, firewall, equals = isEqual, optimistic,
2654
3162
  {
2655
3163
  equals: equals,
2656
3164
  unobserved() {
2657
- delete nodes[property];
3165
+ if (nodes[property] === s) delete nodes[property];
2658
3166
  }
2659
3167
  },
2660
3168
  firewall
@@ -2728,19 +3236,51 @@ function prepareStoreWrite(target, store, property) {
2728
3236
  if (useOptimistic) trackOptimisticStore(store);
2729
3237
  return { base: base, overrideKey: overrideKey, state: state };
2730
3238
  }
2731
- function notifyStoreProperty(target, property, mode, value) {
2732
- if (target[STORE_HAS]?.[property]) setSignal(target[STORE_HAS][property], mode !== "delete");
3239
+ function upsertStoreNode(target, nodes, property, prev, snapshotProps) {
3240
+ if (nodes[property]) return nodes[property];
3241
+ const initial = isWrappable(prev) ? wrap(prev, target) : prev;
3242
+ const node = getNode(
3243
+ nodes,
3244
+ property,
3245
+ initial,
3246
+ target[STORE_FIREWALL],
3247
+ isEqual,
3248
+ target[STORE_OPTIMISTIC],
3249
+ snapshotProps
3250
+ );
3251
+ registerTransientStoreNode(node);
3252
+ return node;
3253
+ }
3254
+ function notifyStoreProperty(target, property, mode, value, prev, prevHas) {
3255
+ const skipUpsert = projectionWriteActive || target[STORE_OPTIMISTIC];
3256
+ const newHas = mode !== "delete";
3257
+ const existingHas = target[STORE_HAS]?.[property];
3258
+ if (existingHas) {
3259
+ setSignal(existingHas, newHas);
3260
+ } else if (!skipUpsert && mode !== "invalidate" && prevHas !== newHas) {
3261
+ const hasNode = upsertStoreNode(target, getNodes(target, STORE_HAS), property, prevHas);
3262
+ setSignal(hasNode, newHas);
3263
+ }
2733
3264
  const nodes = getNodes(target, STORE_NODE);
2734
3265
  if (mode === "set") {
2735
- nodes[property] &&
3266
+ if (nodes[property]) {
2736
3267
  setSignal(nodes[property], () => (isWrappable(value) ? wrap(value, target) : value));
3268
+ } else if (!skipUpsert) {
3269
+ const node = upsertStoreNode(target, nodes, property, prev, target[STORE_SNAPSHOT_PROPS]);
3270
+ setSignal(node, () => (isWrappable(value) ? wrap(value, target) : value));
3271
+ }
2737
3272
  } else if (mode === "invalidate") {
2738
3273
  if (nodes[property]) {
2739
3274
  setSignal(nodes[property], {});
2740
3275
  delete nodes[property];
2741
3276
  }
2742
3277
  } else {
2743
- nodes[property] && setSignal(nodes[property], undefined);
3278
+ if (nodes[property]) {
3279
+ setSignal(nodes[property], undefined);
3280
+ } else if (!skipUpsert) {
3281
+ const node = upsertStoreNode(target, nodes, property, prev, target[STORE_SNAPSHOT_PROPS]);
3282
+ setSignal(node, undefined);
3283
+ }
2744
3284
  }
2745
3285
  nodes[$TRACK] && setSignal(nodes[$TRACK], undefined);
2746
3286
  }
@@ -2756,6 +3296,21 @@ const storeTraps = {
2756
3296
  }
2757
3297
  const nodes = getNodes(target, STORE_NODE);
2758
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
+ }
2759
3314
  const optOverridden =
2760
3315
  target[STORE_OPTIMISTIC_OVERRIDE] && property in target[STORE_OPTIMISTIC_OVERRIDE];
2761
3316
  const overridden =
@@ -2769,6 +3324,12 @@ const storeTraps = {
2769
3324
  if (!tracked) {
2770
3325
  const desc = Object.getOwnPropertyDescriptor(storeValue, property);
2771
3326
  if (desc && desc.get) return desc.get.call(receiver);
3327
+ if (!desc && !overridden && target[STORE_CUSTOM_PROTO]) {
3328
+ const source = unwrapStoreValue(storeValue);
3329
+ if (hasInheritedAccessor(source, property)) {
3330
+ return Reflect.get(storeValue, property, receiver);
3331
+ }
3332
+ }
2772
3333
  }
2773
3334
  if (writeOnly(receiver)) {
2774
3335
  let value =
@@ -2815,7 +3376,7 @@ const storeTraps = {
2815
3376
  }
2816
3377
  if (strictRead && typeof property === "string") {
2817
3378
  const message =
2818
- `Reactive value read directly in ${strictRead} will not update. ` +
3379
+ `[STRICT_READ_UNTRACKED] Reactive value read directly in ${strictRead} will not update. ` +
2819
3380
  `Move it into a tracking scope (JSX, a memo, or an effect's compute function).`;
2820
3381
  emitDiagnostic({
2821
3382
  code: "STRICT_READ_UNTRACKED",
@@ -2837,18 +3398,13 @@ const storeTraps = {
2837
3398
  : target[STORE_OVERRIDE] && property in target[STORE_OVERRIDE]
2838
3399
  ? target[STORE_OVERRIDE][property] !== $DELETED
2839
3400
  : property in target[STORE_VALUE];
2840
- if (!writeOnly(target[$PROXY])) {
2841
- getObserver() &&
2842
- read(
2843
- getNode(
2844
- getNodes(target, STORE_HAS),
2845
- property,
2846
- has,
2847
- target[STORE_FIREWALL],
2848
- isEqual,
2849
- target[STORE_OPTIMISTIC]
2850
- )
2851
- );
3401
+ if (writeOnly(target[$PROXY])) return has;
3402
+ const nodes = getNodes(target, STORE_HAS);
3403
+ if (nodes[property]) return read(nodes[property]);
3404
+ if (getObserver()) {
3405
+ return read(
3406
+ getNode(nodes, property, has, target[STORE_FIREWALL], isEqual, target[STORE_OPTIMISTIC])
3407
+ );
2852
3408
  }
2853
3409
  return has;
2854
3410
  },
@@ -2867,7 +3423,13 @@ const storeTraps = {
2867
3423
  : target[STORE_OVERRIDE] && property in target[STORE_OVERRIDE]
2868
3424
  ? target[STORE_OVERRIDE][property]
2869
3425
  : base;
2870
- const value = rawValue?.[$TARGET]?.[STORE_VALUE] ?? rawValue;
3426
+ const prevHas =
3427
+ target[STORE_OPTIMISTIC_OVERRIDE] && property in target[STORE_OPTIMISTIC_OVERRIDE]
3428
+ ? target[STORE_OPTIMISTIC_OVERRIDE][property] !== $DELETED
3429
+ : target[STORE_OVERRIDE] && property in target[STORE_OVERRIDE]
3430
+ ? target[STORE_OVERRIDE][property] !== $DELETED
3431
+ : property in target[STORE_VALUE];
3432
+ const value = unwrapStoreValue(rawValue);
2871
3433
  const isArrayIndexWrite = Array.isArray(state) && property !== "length";
2872
3434
  const nextIndex = isArrayIndexWrite ? parseInt(property) + 1 : 0;
2873
3435
  const len =
@@ -2886,11 +3448,21 @@ const storeTraps = {
2886
3448
  override[property] = value;
2887
3449
  if (nextLength !== undefined) override.length = nextLength;
2888
3450
  }
2889
- notifyStoreProperty(target, property, "set", value);
2890
- if (Array.isArray(state)) {
3451
+ notifyStoreProperty(target, property, "set", value, prev, prevHas);
3452
+ if (Array.isArray(state) && property !== "length" && nextLength !== undefined) {
2891
3453
  const nodes = getNodes(target, STORE_NODE);
2892
- const lengthValue = property === "length" ? value : nextLength;
2893
- lengthValue !== undefined && nodes.length && setSignal(nodes.length, lengthValue);
3454
+ if (nodes.length) {
3455
+ setSignal(nodes.length, nextLength);
3456
+ } else if (!projectionWriteActive && !target[STORE_OPTIMISTIC]) {
3457
+ const node = upsertStoreNode(
3458
+ target,
3459
+ nodes,
3460
+ "length",
3461
+ len,
3462
+ target[STORE_SNAPSHOT_PROPS]
3463
+ );
3464
+ setSignal(node, nextLength);
3465
+ }
2894
3466
  }
2895
3467
  if (true) DEV$1.hooks.onStoreNodeUpdate?.(target[$PROXY], property, value, prev);
2896
3468
  });
@@ -2904,10 +3476,7 @@ const storeTraps = {
2904
3476
  const { base: base, overrideKey: overrideKey } = prepareStoreWrite(target, store, property);
2905
3477
  const normalizedDescriptor =
2906
3478
  "value" in descriptor
2907
- ? {
2908
- ...descriptor,
2909
- value: descriptor.value?.[$TARGET]?.[STORE_VALUE] ?? descriptor.value
2910
- }
3479
+ ? { ...descriptor, value: unwrapStoreValue(descriptor.value) }
2911
3480
  : descriptor;
2912
3481
  Object.defineProperty(
2913
3482
  target[overrideKey] || (target[overrideKey] = Object.create(null)),
@@ -2948,7 +3517,7 @@ const storeTraps = {
2948
3517
  } else if (target[overrideKey] && property in target[overrideKey]) {
2949
3518
  delete target[overrideKey][property];
2950
3519
  } else return true;
2951
- notifyStoreProperty(target, property, "delete");
3520
+ notifyStoreProperty(target, property, "delete", undefined, prev, true);
2952
3521
  });
2953
3522
  }
2954
3523
  return true;
@@ -3016,12 +3585,17 @@ function createStore(first, second, options) {
3016
3585
  const derived = typeof first === "function",
3017
3586
  wrappedStore = derived ? createProjectionInternal(first, second, options).store : wrap(first);
3018
3587
  registerGraph(wrappedStore, getOwner());
3019
- 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
+ ];
3020
3594
  }
3021
3595
  function createOptimisticStore(first, second, options) {
3022
3596
  GlobalQueue._clearOptimisticStore ||= clearOptimisticStore;
3023
3597
  const derived = typeof first === "function";
3024
- const initialValue = (derived ? second : first) ?? {};
3598
+ const initialValue = derived ? second : first;
3025
3599
  const fn = derived ? first : undefined;
3026
3600
  const { store: wrappedStore } = createOptimisticProjectionInternal(fn, initialValue, options);
3027
3601
  return [wrappedStore, fn => storeSetter(wrappedStore, fn)];
@@ -3055,7 +3629,7 @@ function clearOptimisticStore(store) {
3055
3629
  }
3056
3630
  delete target[STORE_OPTIMISTIC_OVERRIDE];
3057
3631
  }
3058
- function createOptimisticProjectionInternal(fn, initialValue = {}, options) {
3632
+ function createOptimisticProjectionInternal(fn, initialValue, options) {
3059
3633
  let node;
3060
3634
  const wrappedMap = new WeakMap();
3061
3635
  const wrapper = s => {
@@ -3078,42 +3652,33 @@ function createOptimisticProjectionInternal(fn, initialValue = {}, options) {
3078
3652
  };
3079
3653
  const wrappedStore = wrapProjection(initialValue);
3080
3654
  if (fn) {
3081
- node = computed(() => {
3082
- const owner = getOwner();
3083
- let settled = false;
3084
- let result;
3085
- const draft = new Proxy(
3086
- wrappedStore,
3087
- createWriteTraps(() => !settled || owner._inFlight === result)
3088
- );
3655
+ const wrapCommit = write => {
3089
3656
  setProjectionWriteActive(true);
3090
3657
  try {
3091
- storeSetter(draft, s => {
3092
- result = fn(s);
3093
- settled = true;
3094
- const value = handleAsync(owner, result, value => {
3095
- setProjectionWriteActive(true);
3096
- try {
3097
- value !== s &&
3098
- value !== undefined &&
3099
- storeSetter(wrappedStore, reconcile(value, options?.key || "id"));
3100
- } finally {
3101
- setProjectionWriteActive(false);
3102
- }
3103
- });
3104
- value !== s &&
3105
- value !== undefined &&
3106
- reconcile(value, options?.key || "id")(wrappedStore);
3107
- });
3658
+ write();
3108
3659
  } finally {
3109
3660
  setProjectionWriteActive(false);
3110
3661
  }
3111
- });
3112
- node._preventAutoDisposal = true;
3662
+ };
3663
+ node = computed(
3664
+ () => {
3665
+ setProjectionWriteActive(true);
3666
+ try {
3667
+ runProjectionComputed(wrappedStore, fn, options?.key || "id", wrapCommit);
3668
+ } finally {
3669
+ setProjectionWriteActive(false);
3670
+ }
3671
+ },
3672
+ options?.name ? { name: options.name } : undefined
3673
+ );
3674
+ node._config &= ~CONFIG_AUTO_DISPOSE;
3113
3675
  }
3114
3676
  return { store: wrappedStore, node: node };
3115
3677
  }
3116
3678
  const DELETE = Symbol("STORE_PATH_DELETE");
3679
+ function isPrototypePollutionKey(part) {
3680
+ return part === "__proto__" || part === "constructor" || part === "prototype";
3681
+ }
3117
3682
  function updatePath(current, args, i = 0) {
3118
3683
  let part,
3119
3684
  prev = current;
@@ -3121,6 +3686,7 @@ function updatePath(current, args, i = 0) {
3121
3686
  part = args[i];
3122
3687
  const partType = typeof part;
3123
3688
  const isArray = Array.isArray(current);
3689
+ if (partType === "string" && isPrototypePollutionKey(part)) return;
3124
3690
  if (Array.isArray(part)) {
3125
3691
  for (let j = 0; j < part.length; j++) {
3126
3692
  args[i] = part[j];
@@ -3167,6 +3733,7 @@ function updatePath(current, args, i = 0) {
3167
3733
  const keys = Object.keys(value);
3168
3734
  for (let i = 0; i < keys.length; i++) {
3169
3735
  const key = keys[i];
3736
+ if (isPrototypePollutionKey(key)) continue;
3170
3737
  const desc = Object.getOwnPropertyDescriptor(value, key);
3171
3738
  if (desc.get || desc.set) Object.defineProperty(target, key, desc);
3172
3739
  else target[key] = desc.value;
@@ -3281,8 +3848,9 @@ function merge(...sources) {
3281
3848
  const s = sources[i];
3282
3849
  proxy = proxy || (!!s && $PROXY in s);
3283
3850
  const childSources = !!s && s[$SOURCES];
3284
- if (childSources) flattened.push(...childSources);
3285
- 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);
3286
3854
  }
3287
3855
  if (SUPPORTS_PROXY && proxy) {
3288
3856
  return new Proxy(
@@ -3301,10 +3869,12 @@ function merge(...sources) {
3301
3869
  return false;
3302
3870
  },
3303
3871
  keys() {
3304
- const keys = [];
3305
- for (let i = 0; i < flattened.length; i++)
3306
- keys.push(...Object.keys(resolveSource(flattened[i])));
3307
- 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];
3308
3878
  }
3309
3879
  },
3310
3880
  propTraps
@@ -3345,26 +3915,27 @@ function merge(...sources) {
3345
3915
  return target;
3346
3916
  }
3347
3917
  function omit(props, ...keys) {
3348
- const blocked = new Set(keys);
3349
3918
  if (SUPPORTS_PROXY && $PROXY in props) {
3350
3919
  return new Proxy(
3351
3920
  {
3352
3921
  get(property) {
3353
- return blocked.has(property) ? undefined : props[property];
3922
+ return keys.includes(property) ? undefined : props[property];
3354
3923
  },
3355
3924
  has(property) {
3356
- return !blocked.has(property) && property in props;
3925
+ return !keys.includes(property) && property in props;
3357
3926
  },
3358
3927
  keys() {
3359
- return Object.keys(props).filter(k => !blocked.has(k));
3928
+ return Object.keys(props).filter(k => !keys.includes(k));
3360
3929
  }
3361
3930
  },
3362
3931
  propTraps
3363
3932
  );
3364
3933
  }
3365
3934
  const result = {};
3366
- for (const propName of Object.getOwnPropertyNames(props)) {
3367
- 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)) {
3368
3939
  const desc = Object.getOwnPropertyDescriptor(props, propName);
3369
3940
  !desc.get && !desc.set && desc.enumerable && desc.writable && desc.configurable
3370
3941
  ? (result[propName] = desc.value)
@@ -3386,23 +3957,25 @@ function mapArray(list, map, options) {
3386
3957
  }
3387
3958
  }
3388
3959
  : map;
3389
- return createMemo(
3390
- updateKeyedMap.bind({
3391
- _owner: createOwner(),
3392
- _len: 0,
3393
- _list: list,
3394
- _items: [],
3395
- _map: wrappedMap,
3396
- _mappings: [],
3397
- _nodes: [],
3398
- _key: keyFn,
3399
- _rows: keyFn || options?.keyed === false ? [] : undefined,
3400
- _indexes: indexes ? [] : undefined,
3401
- _fallback: options?.fallback
3402
- })
3403
- );
3960
+ const data = {
3961
+ _owner: createOwner(),
3962
+ _len: 0,
3963
+ _list: list,
3964
+ _items: [],
3965
+ _map: wrappedMap,
3966
+ _mappings: [],
3967
+ _nodes: [],
3968
+ _key: keyFn,
3969
+ _rows: keyFn || options?.keyed === false ? [] : undefined,
3970
+ _indexes: indexes ? [] : undefined,
3971
+ _fallback: options?.fallback
3972
+ };
3973
+ const node = computed(updateKeyedMap.bind(data));
3974
+ data._owner._parentComputed = node;
3975
+ node._config &= ~CONFIG_AUTO_DISPOSE;
3976
+ return accessor(node);
3404
3977
  }
3405
- const pureOptions = { pureWrite: true };
3978
+ const pureOptions = { ownedWrite: true };
3406
3979
  function updateKeyedMap() {
3407
3980
  const newItems = this._list() || [],
3408
3981
  newLen = newItems.length;
@@ -3539,17 +4112,21 @@ function repeat(count, map, options) {
3539
4112
  }
3540
4113
  }
3541
4114
  : map;
3542
- return updateRepeat.bind({
3543
- _owner: createOwner(),
3544
- _len: 0,
3545
- _offset: 0,
3546
- _count: count,
3547
- _map: wrappedMap,
3548
- _nodes: [],
3549
- _mappings: [],
3550
- _from: options?.from,
3551
- _fallback: options?.fallback
3552
- });
4115
+ const node = computed(
4116
+ updateRepeat.bind({
4117
+ _owner: createOwner(),
4118
+ _len: 0,
4119
+ _offset: 0,
4120
+ _count: count,
4121
+ _map: wrappedMap,
4122
+ _nodes: [],
4123
+ _mappings: [],
4124
+ _from: options?.from,
4125
+ _fallback: options?.fallback
4126
+ })
4127
+ );
4128
+ node._config &= ~CONFIG_AUTO_DISPOSE;
4129
+ return accessor(node);
3553
4130
  }
3554
4131
  function updateRepeat() {
3555
4132
  const newLen = this._count();
@@ -3606,7 +4183,7 @@ function compare(key, a, b) {
3606
4183
  return key ? key(a) === key(b) : true;
3607
4184
  }
3608
4185
  function boundaryComputed(fn, propagationMask) {
3609
- const node = computed(fn, undefined, { lazy: true });
4186
+ const node = computed(fn, { lazy: true });
3610
4187
  node._notifyStatus = (status, error) => {
3611
4188
  const flags = status !== undefined ? status : node._statusFlags;
3612
4189
  const actualError = error !== undefined ? error : node._error;
@@ -3614,7 +4191,7 @@ function boundaryComputed(fn, propagationMask) {
3614
4191
  node._queue.notify(node, node._propagationMask, flags, actualError);
3615
4192
  };
3616
4193
  node._propagationMask = propagationMask;
3617
- node._preventAutoDisposal = true;
4194
+ node._config &= ~CONFIG_AUTO_DISPOSE;
3618
4195
  recompute(node, true);
3619
4196
  return node;
3620
4197
  }
@@ -3631,12 +4208,16 @@ const ON_INIT = Symbol();
3631
4208
  const RevealControllerContext = createContext(null);
3632
4209
  let _revealUsed = false;
3633
4210
  const FALSE_ACCESSOR = () => false;
4211
+ const SEQUENTIAL_ACCESSOR = () => "sequential";
3634
4212
  function isRevealController(slot) {
3635
4213
  return slot instanceof RevealController;
3636
4214
  }
3637
4215
  function isSlotReady(slot) {
3638
4216
  return isRevealController(slot) ? slot.isReady() : slot._sources.size === 0 && !slot._pending;
3639
4217
  }
4218
+ function isSlotMinimallyReady(slot) {
4219
+ return isRevealController(slot) ? slot.isMinimallyReady() : isSlotReady(slot);
4220
+ }
3640
4221
  function setSlotState(slot, controller, disabled, collapsed) {
3641
4222
  setSignal(slot._disabled, disabled);
3642
4223
  setSignal(slot._collapsed, collapsed);
@@ -3648,16 +4229,17 @@ function setSlotState(slot, controller, disabled, collapsed) {
3648
4229
  slot._revealController = undefined;
3649
4230
  }
3650
4231
  class RevealController {
3651
- _togetherAccessor;
4232
+ _orderAccessor;
3652
4233
  _collapsedAccessor;
3653
4234
  _slots = [];
3654
4235
  _parentController;
3655
- _disabled = signal(false, { pureWrite: true, _noSnapshot: true });
3656
- _collapsed = signal(false, { pureWrite: true, _noSnapshot: true });
4236
+ _disabled = signal(false, { ownedWrite: true, _noSnapshot: true });
4237
+ _collapsed = signal(false, { ownedWrite: true, _noSnapshot: true });
3657
4238
  _ready = true;
4239
+ _minimallyReady = true;
3658
4240
  _evaluating = false;
3659
- constructor(together, collapsed) {
3660
- this._togetherAccessor = together;
4241
+ constructor(order, collapsed) {
4242
+ this._orderAccessor = order;
3661
4243
  this._collapsedAccessor = collapsed;
3662
4244
  }
3663
4245
  _forEachOwnedSlot(fn) {
@@ -3672,12 +4254,37 @@ class RevealController {
3672
4254
  isReady() {
3673
4255
  return this._forEachOwnedSlot(isSlotReady);
3674
4256
  }
4257
+ isMinimallyReady() {
4258
+ const order = untrack(this._orderAccessor);
4259
+ if (order === "together") return this.isReady();
4260
+ if (order === "natural") {
4261
+ let hasSlot = false;
4262
+ let anyReady = false;
4263
+ this._forEachOwnedSlot(slot => {
4264
+ hasSlot = true;
4265
+ if (isSlotMinimallyReady(slot)) {
4266
+ anyReady = true;
4267
+ return false;
4268
+ }
4269
+ });
4270
+ return !hasSlot || anyReady;
4271
+ }
4272
+ let firstReady = true;
4273
+ this._forEachOwnedSlot(slot => {
4274
+ firstReady = isSlotMinimallyReady(slot);
4275
+ return false;
4276
+ });
4277
+ return firstReady;
4278
+ }
3675
4279
  register(slot) {
3676
4280
  if (this._slots.includes(slot)) return;
3677
4281
  this._slots.push(slot);
3678
- const together = !!untrack(this._togetherAccessor);
3679
- setSignal(slot._disabled, true),
3680
- setSignal(slot._collapsed, together ? false : !!untrack(this._collapsedAccessor));
4282
+ const order = untrack(this._orderAccessor);
4283
+ (setSignal(slot._disabled, true),
4284
+ setSignal(
4285
+ slot._collapsed,
4286
+ order === "sequential" ? !!untrack(this._collapsedAccessor) : false
4287
+ ));
3681
4288
  untrack(() => this.evaluate());
3682
4289
  }
3683
4290
  unregister(slot) {
@@ -3689,29 +4296,52 @@ class RevealController {
3689
4296
  if (this._evaluating) return;
3690
4297
  this._evaluating = true;
3691
4298
  const wasReady = this._ready;
4299
+ const wasMinReady = this._minimallyReady;
3692
4300
  try {
3693
4301
  const disabled = disabledOverride ?? read(this._disabled),
3694
- collapseTail = !!untrack(this._collapsedAccessor),
4302
+ order = untrack(this._orderAccessor),
4303
+ collapseTail = order === "sequential" && !!untrack(this._collapsedAccessor),
3695
4304
  collapsed = collapsedOverride ?? collapseTail;
3696
- if (disabled && collapsed)
3697
- this._forEachOwnedSlot(slot => setSlotState(slot, this, true, true));
3698
- else if (!!untrack(this._togetherAccessor)) {
3699
- const ready = this.isReady();
3700
- this._forEachOwnedSlot(slot => setSlotState(slot, this, !ready, false));
4305
+ if (disabled) {
4306
+ this._forEachOwnedSlot(slot => setSlotState(slot, this, true, collapsed));
4307
+ } else if (order === "natural") {
4308
+ this._forEachOwnedSlot(slot => {
4309
+ if (isRevealController(slot)) {
4310
+ setSignal(slot._collapsed, false);
4311
+ setSignal(slot._disabled, false);
4312
+ slot.evaluate(false, false);
4313
+ } else {
4314
+ setSlotState(slot, this, !isSlotReady(slot), false);
4315
+ }
4316
+ });
4317
+ } else if (order === "together") {
4318
+ const minReady = this._forEachOwnedSlot(isSlotMinimallyReady);
4319
+ this._forEachOwnedSlot(slot => setSlotState(slot, this, !minReady, false));
3701
4320
  } else {
3702
4321
  let pendingSeen = false;
3703
4322
  this._forEachOwnedSlot(slot => {
3704
4323
  if (pendingSeen) return setSlotState(slot, this, true, collapseTail);
3705
4324
  if (isSlotReady(slot)) return setSlotState(slot, this, false, false);
3706
4325
  pendingSeen = true;
3707
- setSlotState(slot, this, true, false);
4326
+ if (isRevealController(slot)) {
4327
+ setSignal(slot._collapsed, false);
4328
+ setSignal(slot._disabled, false);
4329
+ slot.evaluate(false, false);
4330
+ } else {
4331
+ setSlotState(slot, this, true, false);
4332
+ }
3708
4333
  });
3709
4334
  }
3710
4335
  } finally {
3711
4336
  this._ready = this.isReady();
4337
+ this._minimallyReady = this.isMinimallyReady();
3712
4338
  this._evaluating = false;
3713
4339
  }
3714
- if (this._parentController && wasReady !== this._ready) this._parentController.evaluate();
4340
+ if (
4341
+ this._parentController &&
4342
+ (wasReady !== this._ready || wasMinReady !== this._minimallyReady)
4343
+ )
4344
+ this._parentController.evaluate();
3715
4345
  }
3716
4346
  }
3717
4347
  class CollectionQueue extends Queue {
@@ -3719,8 +4349,8 @@ class CollectionQueue extends Queue {
3719
4349
  _sources = new Set();
3720
4350
  _tree;
3721
4351
  _pending = true;
3722
- _disabled = signal(false, { pureWrite: true, _noSnapshot: true });
3723
- _collapsed = signal(false, { pureWrite: true, _noSnapshot: true });
4352
+ _disabled = signal(false, { ownedWrite: true, _noSnapshot: true });
4353
+ _collapsed = signal(false, { ownedWrite: true, _noSnapshot: true });
3724
4354
  _revealController;
3725
4355
  _initialized = false;
3726
4356
  _onFn;
@@ -3800,7 +4430,8 @@ class CollectionQueue extends Queue {
3800
4430
  }
3801
4431
  function createCollectionBoundary(type, fn, fallback, onFn) {
3802
4432
  if (!getOwner()) {
3803
- const message = "Boundaries created outside a reactive context will never be disposed.";
4433
+ const message =
4434
+ "[NO_OWNER_BOUNDARY] Boundaries created outside a reactive context will never be disposed.";
3804
4435
  emitDiagnostic({
3805
4436
  code: "NO_OWNER_BOUNDARY",
3806
4437
  kind: "lifecycle",
@@ -3833,15 +4464,16 @@ function createCollectionBoundary(type, fn, fallback, onFn) {
3833
4464
  controller.register(queue);
3834
4465
  cleanup(() => controller.unregister(queue));
3835
4466
  }
3836
- const decision = computed(() => {
3837
- if (!read(queue._disabled)) {
3838
- const resolved = read(tree);
3839
- if (!untrack(() => read(queue._disabled))) return (queue._initialized = true), resolved;
3840
- }
3841
- if (_revealUsed && read(queue._collapsed)) return undefined;
3842
- return fallback(queue);
3843
- });
3844
- return accessor(decision);
4467
+ return accessor(
4468
+ computed(() => {
4469
+ if (!read(queue._disabled)) {
4470
+ const resolved = read(tree);
4471
+ if (!untrack(() => read(queue._disabled))) return ((queue._initialized = true), resolved);
4472
+ }
4473
+ if (_revealUsed && read(queue._collapsed)) return undefined;
4474
+ return fallback(queue);
4475
+ })
4476
+ );
3845
4477
  }
3846
4478
  function createLoadingBoundary(fn, fallback, options) {
3847
4479
  return createCollectionBoundary(STATUS_PENDING, fn, () => fallback(), options?.on);
@@ -3860,14 +4492,14 @@ function createRevealOrder(fn, options) {
3860
4492
  _revealUsed = true;
3861
4493
  const owner = createOwner();
3862
4494
  const parentController = getContext(RevealControllerContext);
3863
- const together = options?.together || FALSE_ACCESSOR,
4495
+ const order = options?.order || SEQUENTIAL_ACCESSOR,
3864
4496
  collapsed = options?.collapsed || FALSE_ACCESSOR;
3865
- const controller = new RevealController(together, collapsed);
4497
+ const controller = new RevealController(order, collapsed);
3866
4498
  setContext(RevealControllerContext, controller, owner);
3867
4499
  return runWithOwner(owner, () => {
3868
4500
  const value = fn();
3869
4501
  computed(() => {
3870
- together();
4502
+ order();
3871
4503
  collapsed();
3872
4504
  controller.evaluate();
3873
4505
  });