@solidjs/signals 0.13.12 → 2.0.0-beta.10

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 (55) hide show
  1. package/README.md +8 -7
  2. package/dist/dev.js +590 -275
  3. package/dist/node.cjs +1549 -1320
  4. package/dist/prod.js +1217 -976
  5. package/dist/types/boundaries.d.ts +124 -3
  6. package/dist/types/core/action.d.ts +34 -0
  7. package/dist/types/core/constants.d.ts +24 -0
  8. package/dist/types/core/context.d.ts +10 -2
  9. package/dist/types/core/core.d.ts +108 -9
  10. package/dist/types/core/dev.d.ts +1 -1
  11. package/dist/types/core/effect.d.ts +3 -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 +1 -0
  15. package/dist/types/core/owner.d.ts +93 -3
  16. package/dist/types/core/scheduler.d.ts +27 -2
  17. package/dist/types/core/types.d.ts +3 -6
  18. package/dist/types/index.d.ts +2 -2
  19. package/dist/types/map.d.ts +32 -3
  20. package/dist/types/signals.d.ts +338 -39
  21. package/dist/types/store/optimistic.d.ts +38 -12
  22. package/dist/types/store/projection.d.ts +55 -15
  23. package/dist/types/store/reconcile.d.ts +22 -0
  24. package/dist/types/store/store.d.ts +72 -15
  25. package/dist/types/store/storePath.d.ts +28 -0
  26. package/dist/types/store/utils.d.ts +78 -7
  27. package/dist/types-cjs/boundaries.d.cts +173 -0
  28. package/dist/types-cjs/core/action.d.cts +35 -0
  29. package/dist/types-cjs/core/async.d.cts +6 -0
  30. package/dist/types-cjs/core/constants.d.cts +49 -0
  31. package/dist/types-cjs/core/context.d.cts +36 -0
  32. package/dist/types-cjs/core/core.d.cts +153 -0
  33. package/dist/types-cjs/core/dev.d.cts +49 -0
  34. package/dist/types-cjs/core/effect.d.cts +31 -0
  35. package/dist/types-cjs/core/error.d.cts +38 -0
  36. package/dist/types-cjs/core/external.d.cts +45 -0
  37. package/dist/types-cjs/core/graph.d.cts +4 -0
  38. package/dist/types-cjs/core/heap.d.cts +14 -0
  39. package/dist/types-cjs/core/index.d.cts +12 -0
  40. package/dist/types-cjs/core/lanes.d.cts +54 -0
  41. package/dist/types-cjs/core/owner.d.cts +116 -0
  42. package/dist/types-cjs/core/scheduler.d.cts +106 -0
  43. package/dist/types-cjs/core/types.d.cts +83 -0
  44. package/dist/types-cjs/index.d.cts +9 -0
  45. package/dist/types-cjs/map.d.cts +53 -0
  46. package/dist/types-cjs/package.json +3 -0
  47. package/dist/types-cjs/signals.d.cts +491 -0
  48. package/dist/types-cjs/store/index.d.cts +9 -0
  49. package/dist/types-cjs/store/optimistic.d.cts +45 -0
  50. package/dist/types-cjs/store/projection.d.cts +66 -0
  51. package/dist/types-cjs/store/reconcile.d.cts +23 -0
  52. package/dist/types-cjs/store/store.d.cts +125 -0
  53. package/dist/types-cjs/store/storePath.d.cts +58 -0
  54. package/dist/types-cjs/store/utils.d.cts +114 -0
  55. package/package.json +32 -24
package/dist/dev.js CHANGED
@@ -35,6 +35,12 @@ 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 CONFIG_OWNED_WRITE = 1 << 0;
39
+ const CONFIG_NO_SNAPSHOT = 1 << 1;
40
+ const CONFIG_TRANSPARENT = 1 << 2;
41
+ const CONFIG_IN_SNAPSHOT_SCOPE = 1 << 3;
42
+ const CONFIG_CHILDREN_FORBIDDEN = 1 << 4;
43
+ const CONFIG_AUTO_DISPOSE = 1 << 5;
38
44
  const STATUS_PENDING = 1 << 0;
39
45
  const STATUS_ERROR = 1 << 1;
40
46
  const STATUS_UNINITIALIZED = 1 << 2;
@@ -240,6 +246,23 @@ let inTrackedQueueCallback = false;
240
246
  let _enforceLoadingBoundary = false;
241
247
  let _hitUnhandledAsync = false;
242
248
  let stashedOptimisticReads = null;
249
+ const transientStoreNodes = new Set();
250
+ function registerTransientStoreNode(node) {
251
+ transientStoreNodes.add(node);
252
+ }
253
+ function sweepTransientStoreNodes() {
254
+ if (transientStoreNodes.size === 0) return;
255
+ for (const node of transientStoreNodes) {
256
+ if (node._subs !== null) {
257
+ transientStoreNodes.delete(node);
258
+ continue;
259
+ }
260
+ if (node._pendingValue !== NOT_PENDING) continue;
261
+ if (node._overrideValue !== undefined && node._overrideValue !== NOT_PENDING) continue;
262
+ transientStoreNodes.delete(node);
263
+ node._unobserved?.();
264
+ }
265
+ }
243
266
  function resetUnhandledAsync() {
244
267
  _hitUnhandledAsync = false;
245
268
  }
@@ -292,6 +315,7 @@ function mergeTransitionState(target, outgoing) {
292
315
  if (!targetReporters) target._asyncReporters.set(source, (targetReporters = new Set()));
293
316
  for (const reporter of reporters) targetReporters.add(reporter);
294
317
  }
318
+ for (const sub of outgoing._gatedSubs) target._gatedSubs.add(sub);
295
319
  }
296
320
  function resolveOptimisticNodes(nodes) {
297
321
  for (let i = 0; i < nodes.length; i++) {
@@ -422,11 +446,15 @@ class GlobalQueue extends Queue {
422
446
  scheduled = dirtyQueue._max >= dirtyQueue._min;
423
447
  reassignPendingTransition(stashedTransition._pendingNodes);
424
448
  activeTransition = null;
425
- if (!stashedTransition._actions.length && stashedTransition._optimisticNodes.length) {
449
+ if (
450
+ !stashedTransition._actions.length &&
451
+ !stashedTransition._asyncReporters.size &&
452
+ stashedTransition._optimisticNodes.length
453
+ ) {
426
454
  stashedOptimisticReads = new Set();
427
455
  for (let i = 0; i < stashedTransition._optimisticNodes.length; i++) {
428
456
  const node = stashedTransition._optimisticNodes[i];
429
- if (node._fn || node._pureWrite) continue;
457
+ if (node._fn || node._config & CONFIG_OWNED_WRITE) continue;
430
458
  stashedOptimisticReads.add(node);
431
459
  queueStashedOptimisticEffects(node);
432
460
  }
@@ -492,7 +520,8 @@ class GlobalQueue extends Queue {
492
520
  _optimisticStores: new Set(),
493
521
  _actions: [],
494
522
  _queueStash: { _queues: [[], []], _children: [] },
495
- _done: false
523
+ _done: false,
524
+ _gatedSubs: new Set()
496
525
  };
497
526
  } else if (transition) {
498
527
  const outgoing = activeTransition;
@@ -531,7 +560,7 @@ function insertSubs(node, optimistic = false) {
531
560
  const sourceLane = node._optimisticLane || currentOptimisticLane;
532
561
  const hasSnapshot = node._snapshotValue !== undefined;
533
562
  for (let s = node._subs; s !== null; s = s._nextSub) {
534
- if (hasSnapshot && s._sub._inSnapshotScope) {
563
+ if (hasSnapshot && s._sub._config & CONFIG_IN_SNAPSHOT_SCOPE) {
535
564
  s._sub._flags |= REACTIVE_SNAPSHOT_STALE;
536
565
  continue;
537
566
  }
@@ -579,6 +608,22 @@ function finalizePureQueue(completingTransition = null, incomplete = false) {
579
608
  resolveOptimisticNodes(
580
609
  completingTransition ? completingTransition._optimisticNodes : globalQueue._optimisticNodes
581
610
  );
611
+ if (completingTransition && completingTransition._gatedSubs.size) {
612
+ for (const sub of completingTransition._gatedSubs) {
613
+ if (sub._flags & REACTIVE_DISPOSED) continue;
614
+ if (sub._type === EFFECT_TRACKED) {
615
+ if (!sub._modified) {
616
+ sub._modified = true;
617
+ sub._queue.enqueue(EFFECT_USER, sub._run);
618
+ }
619
+ continue;
620
+ }
621
+ const queue = sub._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue;
622
+ if (queue._min > sub._height) queue._min = sub._height;
623
+ insertIntoHeap(sub, queue);
624
+ }
625
+ completingTransition._gatedSubs.clear();
626
+ }
582
627
  const optimisticStores = completingTransition
583
628
  ? completingTransition._optimisticStores
584
629
  : globalQueue._optimisticStores;
@@ -589,6 +634,7 @@ function finalizePureQueue(completingTransition = null, incomplete = false) {
589
634
  optimisticStores.clear();
590
635
  schedule();
591
636
  }
637
+ sweepTransientStoreNodes();
592
638
  cleanupCompletedLanes(completingTransition);
593
639
  }
594
640
  }
@@ -778,7 +824,8 @@ function unlinkSubs(link) {
778
824
  dep._subs = nextSub;
779
825
  if (nextSub === null) {
780
826
  dep._unobserved?.();
781
- dep._fn && !dep._preventAutoDisposal && !(dep._flags & REACTIVE_ZOMBIE) && unobserved(dep);
827
+ const c = dep;
828
+ c._fn && c._config & CONFIG_AUTO_DISPOSE && !(c._flags & REACTIVE_ZOMBIE) && unobserved(c);
782
829
  }
783
830
  }
784
831
  return nextDep;
@@ -790,6 +837,7 @@ function unobserved(el) {
790
837
  dep = unlinkSubs(dep);
791
838
  }
792
839
  el._deps = null;
840
+ el._depsTail = null;
793
841
  disposeChildren(el, true);
794
842
  }
795
843
  function link(dep, sub) {
@@ -894,7 +942,7 @@ function runDisposal(node, zombie) {
894
942
  }
895
943
  function childId(owner, consume) {
896
944
  let counter = owner;
897
- while (counter._transparent && counter._parent) counter = counter._parent;
945
+ while (counter._config & CONFIG_TRANSPARENT && counter._parent) counter = counter._parent;
898
946
  if (counter.id != null)
899
947
  return formatId(counter.id, consume ? counter._childCount++ : counter._childCount);
900
948
  throw new Error("Cannot get child id from owner without an id");
@@ -934,7 +982,7 @@ function createOwner(options) {
934
982
  id:
935
983
  options?.id ??
936
984
  (transparent ? parent?.id : parent?.id != null ? getNextChildId(parent) : undefined),
937
- _transparent: transparent || undefined,
985
+ _config: transparent ? CONFIG_TRANSPARENT : 0,
938
986
  _root: true,
939
987
  _parentComputed: parent?._root ? parent._parentComputed : parent,
940
988
  _firstChild: null,
@@ -950,10 +998,16 @@ function createOwner(options) {
950
998
  disposeChildren(owner, self);
951
999
  }
952
1000
  };
953
- if (parent?._childrenForbidden) {
954
- throw new Error(
955
- "Cannot create reactive primitives inside createTrackedEffect or owner-backed onSettled"
956
- );
1001
+ if (parent && parent._config & CONFIG_CHILDREN_FORBIDDEN) {
1002
+ emitDiagnostic({
1003
+ code: "PRIMITIVE_IN_FORBIDDEN_SCOPE",
1004
+ kind: "lifecycle",
1005
+ severity: "error",
1006
+ message: PRIMITIVE_IN_FORBIDDEN_SCOPE_MESSAGE,
1007
+ ownerId: parent.id,
1008
+ ownerName: parent._name
1009
+ });
1010
+ throw new Error(PRIMITIVE_IN_FORBIDDEN_SCOPE_MESSAGE);
957
1011
  }
958
1012
  if (parent) {
959
1013
  const lastChild = parent._firstChild;
@@ -1081,6 +1135,7 @@ function handleAsync(el, result, setter) {
1081
1135
  if (el._inFlight !== result) return;
1082
1136
  if (el._flags & (REACTIVE_DIRTY | REACTIVE_OPTIMISTIC_DIRTY)) return;
1083
1137
  globalQueue.initTransition(resolveTransition(el));
1138
+ const wasUninitialized = !!(el._statusFlags & STATUS_UNINITIALIZED);
1084
1139
  clearStatus(el);
1085
1140
  const lane = resolveLane(el);
1086
1141
  if (lane) lane._pendingAsync.delete(el);
@@ -1094,9 +1149,10 @@ function handleAsync(el, result, setter) {
1094
1149
  }
1095
1150
  el._time = clock;
1096
1151
  } else if (lane) {
1152
+ const isEffect = el._type;
1097
1153
  const prevValue = el._value;
1098
1154
  const equals = el._equals;
1099
- if (!equals || !equals(value, prevValue)) {
1155
+ if ((!isEffect && wasUninitialized) || !equals || !equals(value, prevValue)) {
1100
1156
  el._value = value;
1101
1157
  el._time = clock;
1102
1158
  if (el._latestValueComputed) {
@@ -1278,6 +1334,8 @@ function enableExternalSource(config) {
1278
1334
  }
1279
1335
  GlobalQueue._update = recompute;
1280
1336
  GlobalQueue._dispose = disposeChildren;
1337
+ const PRIMITIVE_IN_FORBIDDEN_SCOPE_MESSAGE =
1338
+ "[PRIMITIVE_IN_FORBIDDEN_SCOPE] Cannot create reactive primitives inside createTrackedEffect or owner-backed onSettled";
1281
1339
  let tracking = false;
1282
1340
  let stale = false;
1283
1341
  let refreshing = false;
@@ -1316,7 +1374,7 @@ function releaseSubtree(owner) {
1316
1374
  }
1317
1375
  if (child._fn) {
1318
1376
  const comp = child;
1319
- comp._inSnapshotScope = false;
1377
+ comp._config &= ~CONFIG_IN_SNAPSHOT_SCOPE;
1320
1378
  if (comp._flags & REACTIVE_SNAPSHOT_STALE) {
1321
1379
  comp._flags &= ~REACTIVE_SNAPSHOT_STALE;
1322
1380
  comp._flags |= REACTIVE_DIRTY;
@@ -1356,9 +1414,10 @@ function recompute(el, create = false) {
1356
1414
  clearSignals(el);
1357
1415
  }
1358
1416
  }
1359
- const isOptimisticDirty = !!(el._flags & REACTIVE_OPTIMISTIC_DIRTY);
1417
+ let isOptimisticDirty = !!(el._flags & REACTIVE_OPTIMISTIC_DIRTY);
1360
1418
  const hasOverride = el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING;
1361
1419
  const wasPending = !!(el._statusFlags & STATUS_PENDING);
1420
+ const wasUninitialized = !!(el._statusFlags & STATUS_UNINITIALIZED);
1362
1421
  const oldcontext = context;
1363
1422
  context = el;
1364
1423
  el._depsTail = null;
@@ -1377,9 +1436,25 @@ function recompute(el, create = false) {
1377
1436
  if (isOptimisticDirty) {
1378
1437
  const lane = resolveLane(el);
1379
1438
  if (lane) currentOptimisticLane = lane;
1439
+ } else if (activeTransition && !create && activeTransition._optimisticNodes.length) {
1440
+ for (let d = el._deps; d; d = d._nextDep) {
1441
+ const dep = d._dep;
1442
+ if (dep._flags & REACTIVE_OPTIMISTIC_DIRTY) {
1443
+ const depLane = resolveLane(dep);
1444
+ if (depLane) {
1445
+ isOptimisticDirty = true;
1446
+ currentOptimisticLane = depLane;
1447
+ el._flags |= REACTIVE_OPTIMISTIC_DIRTY;
1448
+ assignOrMergeLane(el, depLane);
1449
+ break;
1450
+ }
1451
+ }
1452
+ }
1380
1453
  }
1381
1454
  try {
1382
- value = handleAsync(el, el._fn(value));
1455
+ const prevInFlight = el._inFlight;
1456
+ const fnResult = el._fn(value);
1457
+ value = el._inFlight !== prevInFlight ? fnResult : handleAsync(el, fnResult);
1383
1458
  clearStatus(el, create);
1384
1459
  const resolvedLane = resolveLane(el);
1385
1460
  if (resolvedLane) {
@@ -1424,7 +1499,8 @@ function recompute(el, create = false) {
1424
1499
  : el._pendingValue === NOT_PENDING
1425
1500
  ? el._value
1426
1501
  : el._pendingValue;
1427
- const valueChanged = !el._equals || !el._equals(compareValue, value);
1502
+ const valueChanged =
1503
+ (!isEffect && wasUninitialized) || !el._equals || !el._equals(compareValue, value);
1428
1504
  if (valueChanged) {
1429
1505
  const prevVisible = hasOverride ? el._overrideValue : undefined;
1430
1506
  if (create || (isEffect && activeTransition !== el._transition) || isOptimisticDirty) {
@@ -1477,22 +1553,25 @@ function updateIfNecessary(el) {
1477
1553
  }
1478
1554
  el._flags = el._flags & (REACTIVE_SNAPSHOT_STALE | REACTIVE_IN_HEAP | REACTIVE_IN_HEAP_HEIGHT);
1479
1555
  }
1480
- function computed(fn, initialValue, options) {
1556
+ function computed(fn, options) {
1481
1557
  const transparent = options?.transparent ?? false;
1482
1558
  const self = {
1483
1559
  id:
1484
1560
  options?.id ??
1485
1561
  (transparent ? context?.id : context?.id != null ? getNextChildId(context) : undefined),
1486
- _transparent: transparent || undefined,
1562
+ _config:
1563
+ (transparent ? CONFIG_TRANSPARENT : 0) |
1564
+ (options?.ownedWrite ? CONFIG_OWNED_WRITE : 0) |
1565
+ (!context || options?.lazy ? CONFIG_AUTO_DISPOSE : 0) |
1566
+ (snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
1487
1567
  _equals: options?.equals != null ? options.equals : isEqual,
1488
- _pureWrite: !!options?.pureWrite,
1489
1568
  _unobserved: options?.unobserved,
1490
1569
  _disposal: null,
1491
1570
  _queue: context?._queue ?? globalQueue,
1492
1571
  _context: context?._context ?? defaultContext,
1493
1572
  _childCount: 0,
1494
1573
  _fn: fn,
1495
- _value: initialValue,
1574
+ _value: undefined,
1496
1575
  _height: 0,
1497
1576
  _child: null,
1498
1577
  _nextHeap: undefined,
@@ -1516,10 +1595,16 @@ function computed(fn, initialValue, options) {
1516
1595
  self._name = options?.name ?? "computed";
1517
1596
  self._prevHeap = self;
1518
1597
  const parent = context?._root ? context._parentComputed : context;
1519
- if (context?._childrenForbidden) {
1520
- throw new Error(
1521
- "Cannot create reactive primitives inside createTrackedEffect or owner-backed onSettled"
1522
- );
1598
+ if (context && context._config & CONFIG_CHILDREN_FORBIDDEN) {
1599
+ emitDiagnostic({
1600
+ code: "PRIMITIVE_IN_FORBIDDEN_SCOPE",
1601
+ kind: "lifecycle",
1602
+ severity: "error",
1603
+ message: PRIMITIVE_IN_FORBIDDEN_SCOPE_MESSAGE,
1604
+ ownerId: context.id,
1605
+ ownerName: context._name
1606
+ });
1607
+ throw new Error(PRIMITIVE_IN_FORBIDDEN_SCOPE_MESSAGE);
1523
1608
  }
1524
1609
  if (context) {
1525
1610
  const lastChild = context._firstChild;
@@ -1532,9 +1617,8 @@ function computed(fn, initialValue, options) {
1532
1617
  }
1533
1618
  DEV$1.hooks.onOwner?.(self);
1534
1619
  if (parent) self._height = parent._height + 1;
1535
- if (snapshotCaptureActive && ownerInSnapshotScope(context)) self._inSnapshotScope = true;
1536
1620
  if (externalSourceConfig) {
1537
- const bridgeSignal = signal(undefined, { equals: false, pureWrite: true });
1621
+ const bridgeSignal = signal(undefined, { equals: false, ownedWrite: true });
1538
1622
  const source = externalSourceConfig.factory(self._fn, () => {
1539
1623
  setSignal(bridgeSignal, undefined);
1540
1624
  });
@@ -1556,8 +1640,9 @@ function computed(fn, initialValue, options) {
1556
1640
  function signal(v, options, firewall = null) {
1557
1641
  const s = {
1558
1642
  _equals: options?.equals != null ? options.equals : isEqual,
1559
- _pureWrite: !!options?.pureWrite,
1560
- _noSnapshot: !!options?._noSnapshot,
1643
+ _config:
1644
+ (options?.ownedWrite ? CONFIG_OWNED_WRITE : 0) |
1645
+ (options?._noSnapshot ? CONFIG_NO_SNAPSHOT : 0),
1561
1646
  _unobserved: options?.unobserved,
1562
1647
  _value: v,
1563
1648
  _subs: null,
@@ -1574,7 +1659,7 @@ function signal(v, options, firewall = null) {
1574
1659
  firewall && (firewall._child = s);
1575
1660
  if (
1576
1661
  snapshotCaptureActive &&
1577
- !s._noSnapshot &&
1662
+ !(s._config & CONFIG_NO_SNAPSHOT) &&
1578
1663
  !((firewall?._statusFlags ?? 0) & STATUS_PENDING)
1579
1664
  ) {
1580
1665
  s._snapshotValue = v === undefined ? NO_SNAPSHOT : v;
@@ -1587,8 +1672,8 @@ function optimisticSignal(v, options) {
1587
1672
  s._overrideValue = NOT_PENDING;
1588
1673
  return s;
1589
1674
  }
1590
- function optimisticComputed(fn, initialValue, options) {
1591
- const c = computed(fn, initialValue, options);
1675
+ function optimisticComputed(fn, options) {
1676
+ const c = computed(fn, options);
1592
1677
  c._overrideValue = NOT_PENDING;
1593
1678
  return c;
1594
1679
  }
@@ -1668,15 +1753,21 @@ function read(el) {
1668
1753
  }
1669
1754
  let c = context;
1670
1755
  if (c?._root) c = c._parentComputed;
1671
- if (refreshing && el._fn) recompute(el);
1672
- if (el._flags & REACTIVE_LAZY) {
1673
- el._flags &= ~REACTIVE_LAZY;
1674
- recompute(el, true);
1756
+ const computed = el;
1757
+ if (typeof computed._fn === "function") {
1758
+ const comp = el;
1759
+ if (refreshing && !(comp._flags & REACTIVE_DISPOSED)) recompute(comp);
1760
+ if (comp._flags & REACTIVE_LAZY) {
1761
+ comp._flags &= ~REACTIVE_LAZY;
1762
+ recompute(comp, true);
1763
+ } else if (comp._flags & REACTIVE_DISPOSED) {
1764
+ recompute(comp, true);
1765
+ }
1675
1766
  }
1676
1767
  const owner = el._firewall || el;
1677
1768
  if (strictRead && owner._statusFlags & STATUS_PENDING) {
1678
1769
  const message =
1679
- `Reading a pending async value directly in ${strictRead}. ` +
1770
+ `[PENDING_ASYNC_UNTRACKED_READ] Reading a pending async value directly in ${strictRead}. ` +
1680
1771
  `Async values must be read within a tracking scope (JSX, a memo, or an effect's compute function).`;
1681
1772
  emitDiagnostic({
1682
1773
  code: "PENDING_ASYNC_UNTRACKED_READ",
@@ -1691,7 +1782,6 @@ function read(el) {
1691
1782
  throw new Error(message);
1692
1783
  }
1693
1784
  if (c && tracking) {
1694
- if (el._fn && el._flags & REACTIVE_DISPOSED) recompute(el);
1695
1785
  link(el, c);
1696
1786
  if (owner._fn) {
1697
1787
  const isZombie = el._flags & REACTIVE_ZOMBIE;
@@ -1708,9 +1798,9 @@ function read(el) {
1708
1798
  }
1709
1799
  if (owner._statusFlags & STATUS_PENDING) {
1710
1800
  if (c && !(stale && owner._transition && activeTransition !== owner._transition)) {
1711
- if (c?._childrenForbidden) {
1801
+ if (c && c._config & CONFIG_CHILDREN_FORBIDDEN) {
1712
1802
  const message =
1713
- "Reading a pending async value inside createTrackedEffect or onSettled will throw. " +
1803
+ "[PENDING_ASYNC_FORBIDDEN_SCOPE] Reading a pending async value inside createTrackedEffect or onSettled will throw. " +
1714
1804
  "Use createEffect instead which supports async-aware reactivity.";
1715
1805
  emitDiagnostic({
1716
1806
  code: "PENDING_ASYNC_FORBIDDEN_SCOPE",
@@ -1747,7 +1837,7 @@ function read(el) {
1747
1837
  return read(el);
1748
1838
  } else throw el._error;
1749
1839
  }
1750
- if (snapshotCaptureActive && c && c._inSnapshotScope) {
1840
+ if (snapshotCaptureActive && c && c._config & CONFIG_IN_SNAPSHOT_SCOPE) {
1751
1841
  const sv = el._snapshotValue;
1752
1842
  if (sv !== undefined) {
1753
1843
  const snapshot = sv === NO_SNAPSHOT ? undefined : sv;
@@ -1758,7 +1848,7 @@ function read(el) {
1758
1848
  }
1759
1849
  if (strictRead) {
1760
1850
  const message =
1761
- `Reactive value read directly in ${strictRead} will not update. ` +
1851
+ `[STRICT_READ_UNTRACKED] Reactive value read directly in ${strictRead} will not update. ` +
1762
1852
  `Move it into a tracking scope (JSX, a memo, or an effect's compute function).`;
1763
1853
  emitDiagnostic({
1764
1854
  code: "STRICT_READ_UNTRACKED",
@@ -1776,7 +1866,20 @@ function read(el) {
1776
1866
  if (c && stale && shouldReadStashedOptimisticValue(el)) return el._value;
1777
1867
  return el._overrideValue;
1778
1868
  }
1779
- return !c ||
1869
+ if (
1870
+ activeTransition !== null &&
1871
+ currentOptimisticLane !== null &&
1872
+ !latestReadActive &&
1873
+ el._pendingValue !== NOT_PENDING &&
1874
+ owner === el &&
1875
+ !el._fn &&
1876
+ c
1877
+ ) {
1878
+ activeTransition._gatedSubs.add(c);
1879
+ return el._value;
1880
+ }
1881
+ const value =
1882
+ !c ||
1780
1883
  (currentOptimisticLane !== null &&
1781
1884
  (el._overrideValue !== undefined ||
1782
1885
  el._optimisticLane ||
@@ -1784,14 +1887,30 @@ function read(el) {
1784
1887
  !!(owner._statusFlags & STATUS_PENDING))) ||
1785
1888
  el._pendingValue === NOT_PENDING ||
1786
1889
  (stale && el._transition && activeTransition !== el._transition)
1787
- ? el._value
1788
- : el._pendingValue;
1890
+ ? el._value
1891
+ : el._pendingValue;
1892
+ if (
1893
+ !c &&
1894
+ owner === el &&
1895
+ typeof computed._fn === "function" &&
1896
+ el._config & CONFIG_AUTO_DISPOSE &&
1897
+ !(owner._statusFlags & STATUS_PENDING) &&
1898
+ !el._subs
1899
+ ) {
1900
+ unobserved(el);
1901
+ }
1902
+ return value;
1789
1903
  }
1790
1904
  function setSignal(el, v) {
1791
- if (!el._pureWrite && !context?._childrenForbidden && context && el._firewall !== context) {
1905
+ if (
1906
+ !(el._config & CONFIG_OWNED_WRITE) &&
1907
+ !(context && context._config & CONFIG_CHILDREN_FORBIDDEN) &&
1908
+ context &&
1909
+ el._firewall !== context
1910
+ ) {
1792
1911
  const message =
1793
- "Writing to a Signal inside an owned scope (component, computation) is not allowed. " +
1794
- "Move the write outside or set the `pureWrite` option if this is intentional.";
1912
+ "[SIGNAL_WRITE_IN_OWNED_SCOPE] Writing to a Signal inside an owned scope (component, computation) is not allowed. " +
1913
+ "Move the write outside or set the `ownedWrite` option if this is intentional.";
1795
1914
  emitDiagnostic({
1796
1915
  code: "SIGNAL_WRITE_IN_OWNED_SCOPE",
1797
1916
  kind: "write",
@@ -1851,7 +1970,7 @@ function setSignal(el, v) {
1851
1970
  function runWithOwner(owner, fn) {
1852
1971
  if (owner && owner._flags & REACTIVE_DISPOSED) {
1853
1972
  const message =
1854
- "runWithOwner called with a disposed owner. Children created inside will never be disposed.";
1973
+ "[RUN_WITH_DISPOSED_OWNER] runWithOwner called with a disposed owner. Children created inside will never be disposed.";
1855
1974
  emitDiagnostic({
1856
1975
  code: "RUN_WITH_DISPOSED_OWNER",
1857
1976
  kind: "owner",
@@ -1875,7 +1994,7 @@ function runWithOwner(owner, fn) {
1875
1994
  }
1876
1995
  function getPendingSignal(el) {
1877
1996
  if (!el._pendingSignal) {
1878
- el._pendingSignal = optimisticSignal(false, { pureWrite: true });
1997
+ el._pendingSignal = optimisticSignal(false, { ownedWrite: true });
1879
1998
  if (el._parentSource) {
1880
1999
  el._pendingSignal._parentSource = el;
1881
2000
  }
@@ -2018,26 +2137,24 @@ function hasContext(context, owner) {
2018
2137
  function isUndefined(value) {
2019
2138
  return typeof value === "undefined";
2020
2139
  }
2021
- function effect(compute, effect, error, initialValue, options) {
2140
+ function effect(compute, effect, error, options) {
2022
2141
  let initialized = false;
2023
- const node = computed(
2024
- options?.render ? p => staleValues(() => compute(p)) : compute,
2025
- initialValue,
2026
- {
2027
- ...options,
2028
- equals: () => {
2029
- node._modified = !node._error;
2030
- if (initialized) node._queue.enqueue(node._type, runEffect.bind(node));
2031
- return false;
2032
- },
2033
- lazy: true
2034
- }
2035
- );
2036
- node._prevValue = initialValue;
2142
+ const isUser = !!options?.user;
2143
+ const node = computed(isUser ? compute : p => staleValues(() => compute(p)), {
2144
+ ...options,
2145
+ equals: () => {
2146
+ node._modified = !node._error;
2147
+ if (initialized) node._queue.enqueue(node._type, runEffect.bind(node));
2148
+ return false;
2149
+ },
2150
+ lazy: true
2151
+ });
2152
+ node._config &= ~CONFIG_AUTO_DISPOSE;
2153
+ node._prevValue = undefined;
2037
2154
  node._effectFn = effect;
2038
2155
  node._errorFn = error;
2039
2156
  node._cleanup = undefined;
2040
- node._type = options?.render ? EFFECT_RENDER : EFFECT_USER;
2157
+ node._type = isUser ? EFFECT_USER : EFFECT_RENDER;
2041
2158
  node._notifyStatus = (status, error) => {
2042
2159
  const actualStatus = status !== undefined ? status : node._statusFlags;
2043
2160
  const actualError = error !== undefined ? error : node._error;
@@ -2061,28 +2178,32 @@ function effect(compute, effect, error, initialValue, options) {
2061
2178
  node._queue.notify(node, STATUS_PENDING | STATUS_ERROR, actualStatus, actualError);
2062
2179
  if (_hitUnhandledAsync) {
2063
2180
  resetUnhandledAsync();
2064
- const err = new Error("An async value must be rendered inside a Loading boundary.");
2065
- emitDiagnostic({
2066
- code: "ASYNC_OUTSIDE_LOADING_BOUNDARY",
2067
- kind: "async",
2068
- severity: "error",
2069
- message: err.message,
2070
- ownerId: node.id,
2071
- ownerName: node._name
2072
- });
2073
- if (!node._queue.notify(node, STATUS_ERROR, STATUS_ERROR)) throw err;
2181
+ if (!node._queue.notify(node, STATUS_ERROR, STATUS_ERROR)) {
2182
+ const message =
2183
+ "[ASYNC_OUTSIDE_LOADING_BOUNDARY] An async value was read outside a Loading boundary. The root mount will be deferred until all pending async settles.";
2184
+ emitDiagnostic({
2185
+ code: "ASYNC_OUTSIDE_LOADING_BOUNDARY",
2186
+ kind: "async",
2187
+ severity: "warn",
2188
+ message: message,
2189
+ ownerId: node.id,
2190
+ ownerName: node._name
2191
+ });
2192
+ console.warn(message);
2193
+ }
2074
2194
  }
2075
2195
  }
2076
2196
  };
2077
2197
  recompute(node, true);
2078
2198
  !options?.defer &&
2079
- (node._type === EFFECT_USER
2199
+ (node._type === EFFECT_USER || options?.schedule
2080
2200
  ? node._queue.enqueue(node._type, runEffect.bind(node))
2081
2201
  : runEffect.call(node));
2082
2202
  initialized = true;
2083
2203
  cleanup(() => node._cleanup?.());
2084
2204
  if (!node._parent) {
2085
- const message = "Effects created outside a reactive context will never be disposed";
2205
+ const message =
2206
+ "[NO_OWNER_EFFECT] Effects created outside a reactive context will never be disposed";
2086
2207
  emitDiagnostic({
2087
2208
  code: "NO_OWNER_EFFECT",
2088
2209
  kind: "lifecycle",
@@ -2144,11 +2265,10 @@ function trackedEffect(fn, options) {
2144
2265
  }
2145
2266
  node._cleanup = cleanup;
2146
2267
  },
2147
- undefined,
2148
2268
  { ...options, lazy: true }
2149
2269
  );
2150
2270
  node._cleanup = undefined;
2151
- node._childrenForbidden = true;
2271
+ node._config = (node._config & ~CONFIG_AUTO_DISPOSE) | CONFIG_CHILDREN_FORBIDDEN;
2152
2272
  node._modified = true;
2153
2273
  node._type = EFFECT_TRACKED;
2154
2274
  node._notifyStatus = (status, error) => {
@@ -2163,7 +2283,8 @@ function trackedEffect(fn, options) {
2163
2283
  node._queue.enqueue(EFFECT_USER, run);
2164
2284
  cleanup(() => node._cleanup?.());
2165
2285
  if (!node._parent) {
2166
- const message = "Effects created outside a reactive context will never be disposed";
2286
+ const message =
2287
+ "[NO_OWNER_EFFECT] Effects created outside a reactive context will never be disposed";
2167
2288
  emitDiagnostic({
2168
2289
  code: "NO_OWNER_EFFECT",
2169
2290
  kind: "lifecycle",
@@ -2224,7 +2345,8 @@ function onCleanup(fn) {
2224
2345
  {
2225
2346
  const owner = getOwner();
2226
2347
  if (!owner) {
2227
- const message = "onCleanup called outside a reactive context will never be run";
2348
+ const message =
2349
+ "[NO_OWNER_CLEANUP] onCleanup called outside a reactive context will never be run";
2228
2350
  emitDiagnostic({
2229
2351
  code: "NO_OWNER_CLEANUP",
2230
2352
  kind: "lifecycle",
@@ -2232,9 +2354,9 @@ function onCleanup(fn) {
2232
2354
  message: message
2233
2355
  });
2234
2356
  console.warn(message);
2235
- } else if (owner._childrenForbidden) {
2357
+ } else if (owner._config & CONFIG_CHILDREN_FORBIDDEN) {
2236
2358
  const message =
2237
- "Cannot use onCleanup inside createTrackedEffect or onSettled; return a cleanup function instead";
2359
+ "[CLEANUP_IN_FORBIDDEN_SCOPE] Cannot use onCleanup inside createTrackedEffect or onSettled; return a cleanup function instead";
2238
2360
  emitDiagnostic({
2239
2361
  code: "CLEANUP_IN_FORBIDDEN_SCOPE",
2240
2362
  kind: "lifecycle",
@@ -2249,35 +2371,44 @@ function onCleanup(fn) {
2249
2371
  return cleanup(fn);
2250
2372
  }
2251
2373
  function accessor(node) {
2252
- const fn = read.bind(null, node);
2253
- fn.$r = true;
2254
- return fn;
2374
+ return read.bind(null, node);
2255
2375
  }
2256
- function createSignal(first, second, third) {
2376
+ function createSignal(first, second) {
2257
2377
  if (typeof first === "function") {
2258
- const node = computed(first, second, third);
2378
+ const node = computed(first, second);
2379
+ node._config &= ~CONFIG_AUTO_DISPOSE;
2259
2380
  return [accessor(node), setSignal.bind(null, node)];
2260
2381
  }
2261
2382
  const node = signal(first, second);
2262
2383
  registerGraph(node, getOwner());
2263
2384
  return [accessor(node), setSignal.bind(null, node)];
2264
2385
  }
2265
- function createMemo(compute, value, options) {
2266
- let node = computed(compute, value, options);
2267
- return accessor(node);
2386
+ function createMemo(compute, options) {
2387
+ return accessor(computed(compute, options));
2268
2388
  }
2269
- function createEffect(compute, effectFn, value, options) {
2270
- effect(compute, effectFn.effect || effectFn, effectFn.error, value, {
2271
- ...options,
2272
- name: options?.name ?? "effect"
2273
- });
2274
- }
2275
- function createRenderEffect(compute, effectFn, value, options) {
2276
- effect(compute, effectFn, undefined, value, {
2277
- render: true,
2389
+ function createEffect(compute, effectFn, options) {
2390
+ if (effectFn === undefined) {
2391
+ const message =
2392
+ "[MISSING_EFFECT_FN] createEffect requires both a compute function and an effect function. " +
2393
+ "Use `createEffect(() => signal(), value => doWork(value))`. " +
2394
+ "If you want a derived value, use `createMemo`. " +
2395
+ "If you want a one-shot side effect, just call the function directly.";
2396
+ emitDiagnostic({
2397
+ code: "MISSING_EFFECT_FN",
2398
+ kind: "lifecycle",
2399
+ severity: "error",
2400
+ message: message
2401
+ });
2402
+ throw new Error(message);
2403
+ }
2404
+ effect(compute, effectFn.effect || effectFn, effectFn.error, {
2405
+ user: true,
2278
2406
  ...{ ...options, name: options?.name ?? "effect" }
2279
2407
  });
2280
2408
  }
2409
+ function createRenderEffect(compute, effectFn, options) {
2410
+ effect(compute, effectFn, undefined, { ...options, name: options?.name ?? "effect" });
2411
+ }
2281
2412
  function createTrackedEffect(compute, options) {
2282
2413
  trackedEffect(compute, { ...options, name: options?.name ?? "trackedEffect" });
2283
2414
  }
@@ -2301,8 +2432,11 @@ function createReaction(effectFn, options) {
2301
2432
  dispose(node);
2302
2433
  },
2303
2434
  effectFn.error,
2304
- undefined,
2305
- { defer: true, ...(true ? { ...options, name: options?.name ?? "effect" } : options) }
2435
+ {
2436
+ ...(true ? { ...options, name: options?.name ?? "effect" } : options),
2437
+ user: true,
2438
+ defer: true
2439
+ }
2306
2440
  );
2307
2441
  });
2308
2442
  };
@@ -2327,9 +2461,10 @@ function resolve(fn) {
2327
2461
  });
2328
2462
  });
2329
2463
  }
2330
- function createOptimistic(first, second, third) {
2464
+ function createOptimistic(first, second) {
2331
2465
  if (typeof first === "function") {
2332
- const node = optimisticComputed(first, second, third);
2466
+ const node = optimisticComputed(first, second);
2467
+ node._config &= ~CONFIG_AUTO_DISPOSE;
2333
2468
  return [accessor(node), setSignal.bind(null, node)];
2334
2469
  }
2335
2470
  const node = optimisticSignal(first, second);
@@ -2338,7 +2473,7 @@ function createOptimistic(first, second, third) {
2338
2473
  }
2339
2474
  function onSettled(callback) {
2340
2475
  const owner = getOwner();
2341
- owner && !owner._childrenForbidden
2476
+ owner && !(owner._config & CONFIG_CHILDREN_FORBIDDEN)
2342
2477
  ? createTrackedEffect(() => untrack(callback), { name: "onSettled" })
2343
2478
  : globalQueue.enqueue(EFFECT_USER, () => {
2344
2479
  const cleanup = callback();
@@ -2495,7 +2630,7 @@ function reconcile(value, key) {
2495
2630
  applyState(value, state, keyFn);
2496
2631
  };
2497
2632
  }
2498
- function createProjectionInternal(fn, initialValue = {}, options) {
2633
+ function createProjectionInternal(fn, seed, options) {
2499
2634
  let node;
2500
2635
  const wrappedMap = new WeakMap();
2501
2636
  const wrapper = s => {
@@ -2515,31 +2650,39 @@ function createProjectionInternal(fn, initialValue = {}, options) {
2515
2650
  wrappedMap.set(source, wrapped);
2516
2651
  return wrapped;
2517
2652
  };
2518
- const wrappedStore = wrapProjection(initialValue);
2519
- node = computed(() => {
2520
- const owner = getOwner();
2521
- let settled = false;
2522
- let result;
2523
- const draft = new Proxy(
2524
- wrappedStore,
2525
- createWriteTraps(() => !settled || owner._inFlight === result)
2526
- );
2527
- storeSetter(draft, s => {
2528
- result = fn(s);
2529
- settled = true;
2530
- const value = handleAsync(owner, result, value => {
2531
- value !== s &&
2532
- value !== undefined &&
2533
- storeSetter(wrappedStore, reconcile(value, options?.key || "id"));
2534
- });
2535
- value !== s && value !== undefined && reconcile(value, options?.key || "id")(wrappedStore);
2536
- });
2537
- });
2538
- node._preventAutoDisposal = true;
2653
+ const wrappedStore = wrapProjection(seed);
2654
+ node = computed(
2655
+ () => {
2656
+ if (!node) node = getOwner();
2657
+ runProjectionComputed(wrappedStore, fn, options?.key || "id");
2658
+ },
2659
+ options?.name ? { name: options.name } : undefined
2660
+ );
2661
+ node._config &= ~CONFIG_AUTO_DISPOSE;
2539
2662
  return { store: wrappedStore, node: node };
2540
2663
  }
2541
- function createProjection(fn, initialValue = {}, options) {
2542
- return createProjectionInternal(fn, initialValue, options).store;
2664
+ function createProjection(fn, seed, options) {
2665
+ return createProjectionInternal(fn, seed, options).store;
2666
+ }
2667
+ function runProjectionComputed(wrappedStore, fn, key, wrapCommit) {
2668
+ const owner = getOwner();
2669
+ let settled = false;
2670
+ let result;
2671
+ const draft = new Proxy(
2672
+ wrappedStore,
2673
+ createWriteTraps(() => !settled || owner._inFlight === result)
2674
+ );
2675
+ storeSetter(draft, s => {
2676
+ result = fn(s);
2677
+ settled = true;
2678
+ const commit = v => {
2679
+ if (v === s || v === undefined) return;
2680
+ const write = () => storeSetter(wrappedStore, reconcile(v, key));
2681
+ wrapCommit ? wrapCommit(write) : write();
2682
+ };
2683
+ commit(handleAsync(owner, result, commit));
2684
+ });
2685
+ return owner;
2543
2686
  }
2544
2687
  function createWriteTraps(isActive) {
2545
2688
  const traps = {
@@ -2603,6 +2746,7 @@ const STORE_VALUE = "v",
2603
2746
  STORE_OPTIMISTIC_OVERRIDE = "x",
2604
2747
  STORE_NODE = "n",
2605
2748
  STORE_HAS = "h",
2749
+ STORE_CUSTOM_PROTO = "c",
2606
2750
  STORE_WRAP = "w",
2607
2751
  STORE_LOOKUP = "l",
2608
2752
  STORE_FIREWALL = "f",
@@ -2613,6 +2757,7 @@ function createStoreProxy(value, traps = storeTraps, extend) {
2613
2757
  newTarget = [];
2614
2758
  newTarget.v = value;
2615
2759
  } else newTarget = { v: value };
2760
+ newTarget[STORE_CUSTOM_PROTO] = hasCustomPrototype(unwrapStoreValue(value));
2616
2761
  extend && extend(newTarget);
2617
2762
  return (newTarget[$PROXY] = new Proxy(newTarget, traps));
2618
2763
  }
@@ -2638,6 +2783,23 @@ function setWriteOverride(value) {
2638
2783
  function writeOnly(proxy) {
2639
2784
  return writeOverride || !!Writing?.has(proxy);
2640
2785
  }
2786
+ function unwrapStoreValue(value) {
2787
+ return value?.[$TARGET]?.[STORE_VALUE] ?? value;
2788
+ }
2789
+ function hasCustomPrototype(value) {
2790
+ if (Array.isArray(value)) return false;
2791
+ const proto = Object.getPrototypeOf(value);
2792
+ return proto !== null && proto !== Object.prototype;
2793
+ }
2794
+ function hasInheritedAccessor(source, property) {
2795
+ let current = Object.getPrototypeOf(source);
2796
+ while (current && current !== Object.prototype) {
2797
+ const desc = Reflect.getOwnPropertyDescriptor(current, property);
2798
+ if (desc) return !!desc.get;
2799
+ current = Object.getPrototypeOf(current);
2800
+ }
2801
+ return false;
2802
+ }
2641
2803
  function getNodes(target, type) {
2642
2804
  let nodes = target[type];
2643
2805
  if (!nodes) target[type] = nodes = Object.create(null);
@@ -2650,7 +2812,7 @@ function getNode(nodes, property, value, firewall, equals = isEqual, optimistic,
2650
2812
  {
2651
2813
  equals: equals,
2652
2814
  unobserved() {
2653
- delete nodes[property];
2815
+ if (nodes[property] === s) delete nodes[property];
2654
2816
  }
2655
2817
  },
2656
2818
  firewall
@@ -2690,12 +2852,87 @@ function getKeys(source, override, enumerable = true) {
2690
2852
  return Array.from(keys);
2691
2853
  }
2692
2854
  function getPropertyDescriptor(source, override, property) {
2693
- let value = source;
2694
2855
  if (override && property in override) {
2695
- if (value[property] === $DELETED) return void 0;
2696
- if (!(property in value)) value = override;
2856
+ if (override[property] === $DELETED) return void 0;
2857
+ const overrideDesc = Reflect.getOwnPropertyDescriptor(override, property);
2858
+ if (overrideDesc?.get || overrideDesc?.set || !(property in source)) return overrideDesc;
2697
2859
  }
2698
- return Reflect.getOwnPropertyDescriptor(value, property);
2860
+ return Reflect.getOwnPropertyDescriptor(source, property);
2861
+ }
2862
+ function prepareStoreWrite(target, store, property) {
2863
+ if (target[STORE_OPTIMISTIC]) {
2864
+ const firewall = target[STORE_FIREWALL];
2865
+ if (firewall?._transition) {
2866
+ globalQueue.initTransition(firewall._transition);
2867
+ }
2868
+ }
2869
+ const state = target[STORE_VALUE];
2870
+ const base = state[property];
2871
+ if (
2872
+ snapshotCaptureActive &&
2873
+ typeof property !== "symbol" &&
2874
+ !((target[STORE_FIREWALL]?._statusFlags ?? 0) & STATUS_PENDING)
2875
+ ) {
2876
+ if (!target[STORE_SNAPSHOT_PROPS]) {
2877
+ target[STORE_SNAPSHOT_PROPS] = Object.create(null);
2878
+ snapshotSources?.add(target);
2879
+ }
2880
+ if (!(property in target[STORE_SNAPSHOT_PROPS])) {
2881
+ target[STORE_SNAPSHOT_PROPS][property] = base;
2882
+ }
2883
+ }
2884
+ const useOptimistic = target[STORE_OPTIMISTIC] && !projectionWriteActive;
2885
+ const overrideKey = useOptimistic ? STORE_OPTIMISTIC_OVERRIDE : STORE_OVERRIDE;
2886
+ if (useOptimistic) trackOptimisticStore(store);
2887
+ return { base: base, overrideKey: overrideKey, state: state };
2888
+ }
2889
+ function upsertStoreNode(target, nodes, property, prev, snapshotProps) {
2890
+ if (nodes[property]) return nodes[property];
2891
+ const initial = isWrappable(prev) ? wrap(prev, target) : prev;
2892
+ const node = getNode(
2893
+ nodes,
2894
+ property,
2895
+ initial,
2896
+ target[STORE_FIREWALL],
2897
+ isEqual,
2898
+ target[STORE_OPTIMISTIC],
2899
+ snapshotProps
2900
+ );
2901
+ registerTransientStoreNode(node);
2902
+ return node;
2903
+ }
2904
+ function notifyStoreProperty(target, property, mode, value, prev, prevHas) {
2905
+ const skipUpsert = projectionWriteActive || target[STORE_OPTIMISTIC];
2906
+ const newHas = mode !== "delete";
2907
+ const existingHas = target[STORE_HAS]?.[property];
2908
+ if (existingHas) {
2909
+ setSignal(existingHas, newHas);
2910
+ } else if (!skipUpsert && mode !== "invalidate" && prevHas !== newHas) {
2911
+ const hasNode = upsertStoreNode(target, getNodes(target, STORE_HAS), property, prevHas);
2912
+ setSignal(hasNode, newHas);
2913
+ }
2914
+ const nodes = getNodes(target, STORE_NODE);
2915
+ if (mode === "set") {
2916
+ if (nodes[property]) {
2917
+ setSignal(nodes[property], () => (isWrappable(value) ? wrap(value, target) : value));
2918
+ } else if (!skipUpsert) {
2919
+ const node = upsertStoreNode(target, nodes, property, prev, target[STORE_SNAPSHOT_PROPS]);
2920
+ setSignal(node, () => (isWrappable(value) ? wrap(value, target) : value));
2921
+ }
2922
+ } else if (mode === "invalidate") {
2923
+ if (nodes[property]) {
2924
+ setSignal(nodes[property], {});
2925
+ delete nodes[property];
2926
+ }
2927
+ } else {
2928
+ if (nodes[property]) {
2929
+ setSignal(nodes[property], undefined);
2930
+ } else if (!skipUpsert) {
2931
+ const node = upsertStoreNode(target, nodes, property, prev, target[STORE_SNAPSHOT_PROPS]);
2932
+ setSignal(node, undefined);
2933
+ }
2934
+ }
2935
+ nodes[$TRACK] && setSignal(nodes[$TRACK], undefined);
2699
2936
  }
2700
2937
  let Writing = null;
2701
2938
  const storeTraps = {
@@ -2722,6 +2959,12 @@ const storeTraps = {
2722
2959
  if (!tracked) {
2723
2960
  const desc = Object.getOwnPropertyDescriptor(storeValue, property);
2724
2961
  if (desc && desc.get) return desc.get.call(receiver);
2962
+ if (!desc && !overridden && target[STORE_CUSTOM_PROTO]) {
2963
+ const source = unwrapStoreValue(storeValue);
2964
+ if (hasInheritedAccessor(source, property)) {
2965
+ return Reflect.get(storeValue, property, receiver);
2966
+ }
2967
+ }
2725
2968
  }
2726
2969
  if (writeOnly(receiver)) {
2727
2970
  let value =
@@ -2768,7 +3011,7 @@ const storeTraps = {
2768
3011
  }
2769
3012
  if (strictRead && typeof property === "string") {
2770
3013
  const message =
2771
- `Reactive value read directly in ${strictRead} will not update. ` +
3014
+ `[STRICT_READ_UNTRACKED] Reactive value read directly in ${strictRead} will not update. ` +
2772
3015
  `Move it into a tracking scope (JSX, a memo, or an effect's compute function).`;
2773
3016
  emitDiagnostic({
2774
3017
  code: "STRICT_READ_UNTRACKED",
@@ -2790,56 +3033,38 @@ const storeTraps = {
2790
3033
  : target[STORE_OVERRIDE] && property in target[STORE_OVERRIDE]
2791
3034
  ? target[STORE_OVERRIDE][property] !== $DELETED
2792
3035
  : property in target[STORE_VALUE];
2793
- if (!writeOnly(target[$PROXY])) {
2794
- getObserver() &&
2795
- read(
2796
- getNode(
2797
- getNodes(target, STORE_HAS),
2798
- property,
2799
- has,
2800
- target[STORE_FIREWALL],
2801
- isEqual,
2802
- target[STORE_OPTIMISTIC]
2803
- )
2804
- );
3036
+ if (writeOnly(target[$PROXY])) return has;
3037
+ const nodes = getNodes(target, STORE_HAS);
3038
+ if (nodes[property]) return read(nodes[property]);
3039
+ if (getObserver()) {
3040
+ return read(
3041
+ getNode(nodes, property, has, target[STORE_FIREWALL], isEqual, target[STORE_OPTIMISTIC])
3042
+ );
2805
3043
  }
2806
3044
  return has;
2807
3045
  },
2808
3046
  set(target, property, rawValue) {
2809
3047
  const store = target[$PROXY];
2810
3048
  if (writeOnly(store)) {
2811
- if (target[STORE_OPTIMISTIC]) {
2812
- const firewall = target[STORE_FIREWALL];
2813
- if (firewall?._transition) {
2814
- globalQueue.initTransition(firewall._transition);
2815
- }
2816
- }
2817
3049
  untrack(() => {
2818
- const state = target[STORE_VALUE];
2819
- const base = state[property];
2820
- if (
2821
- snapshotCaptureActive &&
2822
- typeof property !== "symbol" &&
2823
- !((target[STORE_FIREWALL]?._statusFlags ?? 0) & STATUS_PENDING)
2824
- ) {
2825
- if (!target[STORE_SNAPSHOT_PROPS]) {
2826
- target[STORE_SNAPSHOT_PROPS] = Object.create(null);
2827
- snapshotSources?.add(target);
2828
- }
2829
- if (!(property in target[STORE_SNAPSHOT_PROPS])) {
2830
- target[STORE_SNAPSHOT_PROPS][property] = base;
2831
- }
2832
- }
2833
- const useOptimistic = target[STORE_OPTIMISTIC] && !projectionWriteActive;
2834
- const overrideKey = useOptimistic ? STORE_OPTIMISTIC_OVERRIDE : STORE_OVERRIDE;
2835
- if (useOptimistic) trackOptimisticStore(store);
3050
+ const {
3051
+ base: base,
3052
+ overrideKey: overrideKey,
3053
+ state: state
3054
+ } = prepareStoreWrite(target, store, property);
2836
3055
  const prev =
2837
3056
  target[STORE_OPTIMISTIC_OVERRIDE] && property in target[STORE_OPTIMISTIC_OVERRIDE]
2838
3057
  ? target[STORE_OPTIMISTIC_OVERRIDE][property]
2839
3058
  : target[STORE_OVERRIDE] && property in target[STORE_OVERRIDE]
2840
3059
  ? target[STORE_OVERRIDE][property]
2841
3060
  : base;
2842
- const value = rawValue?.[$TARGET]?.[STORE_VALUE] ?? rawValue;
3061
+ const prevHas =
3062
+ target[STORE_OPTIMISTIC_OVERRIDE] && property in target[STORE_OPTIMISTIC_OVERRIDE]
3063
+ ? target[STORE_OPTIMISTIC_OVERRIDE][property] !== $DELETED
3064
+ : target[STORE_OVERRIDE] && property in target[STORE_OVERRIDE]
3065
+ ? target[STORE_OVERRIDE][property] !== $DELETED
3066
+ : property in target[STORE_VALUE];
3067
+ const value = unwrapStoreValue(rawValue);
2843
3068
  const isArrayIndexWrite = Array.isArray(state) && property !== "length";
2844
3069
  const nextIndex = isArrayIndexWrite ? parseInt(property) + 1 : 0;
2845
3070
  const len =
@@ -2858,21 +3083,53 @@ const storeTraps = {
2858
3083
  override[property] = value;
2859
3084
  if (nextLength !== undefined) override.length = nextLength;
2860
3085
  }
2861
- const wrappable = isWrappable(value);
2862
- target[STORE_HAS]?.[property] && setSignal(target[STORE_HAS][property], true);
2863
- const nodes = getNodes(target, STORE_NODE);
2864
- nodes[property] &&
2865
- setSignal(nodes[property], () => (wrappable ? wrap(value, target) : value));
2866
- if (Array.isArray(state)) {
2867
- const lengthValue = property === "length" ? value : nextLength;
2868
- lengthValue !== undefined && nodes.length && setSignal(nodes.length, lengthValue);
3086
+ notifyStoreProperty(target, property, "set", value, prev, prevHas);
3087
+ if (Array.isArray(state) && property !== "length" && nextLength !== undefined) {
3088
+ const nodes = getNodes(target, STORE_NODE);
3089
+ if (nodes.length) {
3090
+ setSignal(nodes.length, nextLength);
3091
+ } else if (!projectionWriteActive && !target[STORE_OPTIMISTIC]) {
3092
+ const node = upsertStoreNode(
3093
+ target,
3094
+ nodes,
3095
+ "length",
3096
+ len,
3097
+ target[STORE_SNAPSHOT_PROPS]
3098
+ );
3099
+ setSignal(node, nextLength);
3100
+ }
2869
3101
  }
2870
- nodes[$TRACK] && setSignal(nodes[$TRACK], undefined);
2871
3102
  if (true) DEV$1.hooks.onStoreNodeUpdate?.(target[$PROXY], property, value, prev);
2872
3103
  });
2873
3104
  }
2874
3105
  return true;
2875
3106
  },
3107
+ defineProperty(target, property, descriptor) {
3108
+ const store = target[$PROXY];
3109
+ if (writeOnly(store)) {
3110
+ untrack(() => {
3111
+ const { base: base, overrideKey: overrideKey } = prepareStoreWrite(target, store, property);
3112
+ const normalizedDescriptor =
3113
+ "value" in descriptor
3114
+ ? { ...descriptor, value: unwrapStoreValue(descriptor.value) }
3115
+ : descriptor;
3116
+ Object.defineProperty(
3117
+ target[overrideKey] || (target[overrideKey] = Object.create(null)),
3118
+ property,
3119
+ normalizedDescriptor
3120
+ );
3121
+ notifyStoreProperty(target, property, "invalidate");
3122
+ if (true) {
3123
+ const next =
3124
+ "value" in normalizedDescriptor
3125
+ ? normalizedDescriptor.value
3126
+ : normalizedDescriptor.get?.call(store);
3127
+ DEV$1.hooks.onStoreNodeUpdate?.(target[$PROXY], property, next, base);
3128
+ }
3129
+ });
3130
+ }
3131
+ return true;
3132
+ },
2876
3133
  deleteProperty(target, property) {
2877
3134
  const optDeleted = target[STORE_OPTIMISTIC_OVERRIDE]?.[property] === $DELETED;
2878
3135
  const regDeleted = target[STORE_OVERRIDE]?.[property] === $DELETED;
@@ -2895,10 +3152,7 @@ const storeTraps = {
2895
3152
  } else if (target[overrideKey] && property in target[overrideKey]) {
2896
3153
  delete target[overrideKey][property];
2897
3154
  } else return true;
2898
- if (target[STORE_HAS]?.[property]) setSignal(target[STORE_HAS][property], false);
2899
- const nodes = getNodes(target, STORE_NODE);
2900
- nodes[property] && setSignal(nodes[property], undefined);
2901
- nodes[$TRACK] && setSignal(nodes[$TRACK], undefined);
3155
+ notifyStoreProperty(target, property, "delete", undefined, prev, true);
2902
3156
  });
2903
3157
  }
2904
3158
  return true;
@@ -2920,6 +3174,8 @@ const storeTraps = {
2920
3174
  if (property === $PROXY) return { value: target[$PROXY], writable: true, configurable: true };
2921
3175
  if (target[STORE_OPTIMISTIC_OVERRIDE] && property in target[STORE_OPTIMISTIC_OVERRIDE]) {
2922
3176
  if (target[STORE_OPTIMISTIC_OVERRIDE][property] === $DELETED) return undefined;
3177
+ const optDesc = Reflect.getOwnPropertyDescriptor(target[STORE_OPTIMISTIC_OVERRIDE], property);
3178
+ if (optDesc?.get || optDesc?.set || !(property in target[STORE_VALUE])) return optDesc;
2923
3179
  const baseDesc = getPropertyDescriptor(target[STORE_VALUE], target[STORE_OVERRIDE], property);
2924
3180
  if (baseDesc) {
2925
3181
  return { ...baseDesc, value: target[STORE_OPTIMISTIC_OVERRIDE][property] };
@@ -2969,7 +3225,7 @@ function createStore(first, second, options) {
2969
3225
  function createOptimisticStore(first, second, options) {
2970
3226
  GlobalQueue._clearOptimisticStore ||= clearOptimisticStore;
2971
3227
  const derived = typeof first === "function";
2972
- const initialValue = (derived ? second : first) ?? {};
3228
+ const initialValue = derived ? second : first;
2973
3229
  const fn = derived ? first : undefined;
2974
3230
  const { store: wrappedStore } = createOptimisticProjectionInternal(fn, initialValue, options);
2975
3231
  return [wrappedStore, fn => storeSetter(wrappedStore, fn)];
@@ -3003,7 +3259,7 @@ function clearOptimisticStore(store) {
3003
3259
  }
3004
3260
  delete target[STORE_OPTIMISTIC_OVERRIDE];
3005
3261
  }
3006
- function createOptimisticProjectionInternal(fn, initialValue = {}, options) {
3262
+ function createOptimisticProjectionInternal(fn, initialValue, options) {
3007
3263
  let node;
3008
3264
  const wrappedMap = new WeakMap();
3009
3265
  const wrapper = s => {
@@ -3026,42 +3282,33 @@ function createOptimisticProjectionInternal(fn, initialValue = {}, options) {
3026
3282
  };
3027
3283
  const wrappedStore = wrapProjection(initialValue);
3028
3284
  if (fn) {
3029
- node = computed(() => {
3030
- const owner = getOwner();
3031
- let settled = false;
3032
- let result;
3033
- const draft = new Proxy(
3034
- wrappedStore,
3035
- createWriteTraps(() => !settled || owner._inFlight === result)
3036
- );
3285
+ const wrapCommit = write => {
3037
3286
  setProjectionWriteActive(true);
3038
3287
  try {
3039
- storeSetter(draft, s => {
3040
- result = fn(s);
3041
- settled = true;
3042
- const value = handleAsync(owner, result, value => {
3043
- setProjectionWriteActive(true);
3044
- try {
3045
- value !== s &&
3046
- value !== undefined &&
3047
- storeSetter(wrappedStore, reconcile(value, options?.key || "id"));
3048
- } finally {
3049
- setProjectionWriteActive(false);
3050
- }
3051
- });
3052
- value !== s &&
3053
- value !== undefined &&
3054
- reconcile(value, options?.key || "id")(wrappedStore);
3055
- });
3288
+ write();
3056
3289
  } finally {
3057
3290
  setProjectionWriteActive(false);
3058
3291
  }
3059
- });
3060
- node._preventAutoDisposal = true;
3292
+ };
3293
+ node = computed(
3294
+ () => {
3295
+ setProjectionWriteActive(true);
3296
+ try {
3297
+ runProjectionComputed(wrappedStore, fn, options?.key || "id", wrapCommit);
3298
+ } finally {
3299
+ setProjectionWriteActive(false);
3300
+ }
3301
+ },
3302
+ options?.name ? { name: options.name } : undefined
3303
+ );
3304
+ node._config &= ~CONFIG_AUTO_DISPOSE;
3061
3305
  }
3062
3306
  return { store: wrappedStore, node: node };
3063
3307
  }
3064
3308
  const DELETE = Symbol("STORE_PATH_DELETE");
3309
+ function isPrototypePollutionKey(part) {
3310
+ return part === "__proto__" || part === "constructor" || part === "prototype";
3311
+ }
3065
3312
  function updatePath(current, args, i = 0) {
3066
3313
  let part,
3067
3314
  prev = current;
@@ -3069,6 +3316,7 @@ function updatePath(current, args, i = 0) {
3069
3316
  part = args[i];
3070
3317
  const partType = typeof part;
3071
3318
  const isArray = Array.isArray(current);
3319
+ if (partType === "string" && isPrototypePollutionKey(part)) return;
3072
3320
  if (Array.isArray(part)) {
3073
3321
  for (let j = 0; j < part.length; j++) {
3074
3322
  args[i] = part[j];
@@ -3113,7 +3361,13 @@ function updatePath(current, args, i = 0) {
3113
3361
  ) {
3114
3362
  const target = part !== undefined ? current[part] : current;
3115
3363
  const keys = Object.keys(value);
3116
- for (let i = 0; i < keys.length; i++) target[keys[i]] = value[keys[i]];
3364
+ for (let i = 0; i < keys.length; i++) {
3365
+ const key = keys[i];
3366
+ if (isPrototypePollutionKey(key)) continue;
3367
+ const desc = Object.getOwnPropertyDescriptor(value, key);
3368
+ if (desc.get || desc.set) Object.defineProperty(target, key, desc);
3369
+ else target[key] = desc.value;
3370
+ }
3117
3371
  } else {
3118
3372
  current[part] = value;
3119
3373
  }
@@ -3329,23 +3583,25 @@ function mapArray(list, map, options) {
3329
3583
  }
3330
3584
  }
3331
3585
  : map;
3332
- return createMemo(
3333
- updateKeyedMap.bind({
3334
- _owner: createOwner(),
3335
- _len: 0,
3336
- _list: list,
3337
- _items: [],
3338
- _map: wrappedMap,
3339
- _mappings: [],
3340
- _nodes: [],
3341
- _key: keyFn,
3342
- _rows: keyFn || options?.keyed === false ? [] : undefined,
3343
- _indexes: indexes ? [] : undefined,
3344
- _fallback: options?.fallback
3345
- })
3346
- );
3586
+ const data = {
3587
+ _owner: createOwner(),
3588
+ _len: 0,
3589
+ _list: list,
3590
+ _items: [],
3591
+ _map: wrappedMap,
3592
+ _mappings: [],
3593
+ _nodes: [],
3594
+ _key: keyFn,
3595
+ _rows: keyFn || options?.keyed === false ? [] : undefined,
3596
+ _indexes: indexes ? [] : undefined,
3597
+ _fallback: options?.fallback
3598
+ };
3599
+ const node = computed(updateKeyedMap.bind(data));
3600
+ data._owner._parentComputed = node;
3601
+ node._config &= ~CONFIG_AUTO_DISPOSE;
3602
+ return accessor(node);
3347
3603
  }
3348
- const pureOptions = { pureWrite: true };
3604
+ const pureOptions = { ownedWrite: true };
3349
3605
  function updateKeyedMap() {
3350
3606
  const newItems = this._list() || [],
3351
3607
  newLen = newItems.length;
@@ -3482,17 +3738,21 @@ function repeat(count, map, options) {
3482
3738
  }
3483
3739
  }
3484
3740
  : map;
3485
- return updateRepeat.bind({
3486
- _owner: createOwner(),
3487
- _len: 0,
3488
- _offset: 0,
3489
- _count: count,
3490
- _map: wrappedMap,
3491
- _nodes: [],
3492
- _mappings: [],
3493
- _from: options?.from,
3494
- _fallback: options?.fallback
3495
- });
3741
+ const node = computed(
3742
+ updateRepeat.bind({
3743
+ _owner: createOwner(),
3744
+ _len: 0,
3745
+ _offset: 0,
3746
+ _count: count,
3747
+ _map: wrappedMap,
3748
+ _nodes: [],
3749
+ _mappings: [],
3750
+ _from: options?.from,
3751
+ _fallback: options?.fallback
3752
+ })
3753
+ );
3754
+ node._config &= ~CONFIG_AUTO_DISPOSE;
3755
+ return accessor(node);
3496
3756
  }
3497
3757
  function updateRepeat() {
3498
3758
  const newLen = this._count();
@@ -3549,7 +3809,7 @@ function compare(key, a, b) {
3549
3809
  return key ? key(a) === key(b) : true;
3550
3810
  }
3551
3811
  function boundaryComputed(fn, propagationMask) {
3552
- const node = computed(fn, undefined, { lazy: true });
3812
+ const node = computed(fn, { lazy: true });
3553
3813
  node._notifyStatus = (status, error) => {
3554
3814
  const flags = status !== undefined ? status : node._statusFlags;
3555
3815
  const actualError = error !== undefined ? error : node._error;
@@ -3557,7 +3817,7 @@ function boundaryComputed(fn, propagationMask) {
3557
3817
  node._queue.notify(node, node._propagationMask, flags, actualError);
3558
3818
  };
3559
3819
  node._propagationMask = propagationMask;
3560
- node._preventAutoDisposal = true;
3820
+ node._config &= ~CONFIG_AUTO_DISPOSE;
3561
3821
  recompute(node, true);
3562
3822
  return node;
3563
3823
  }
@@ -3574,12 +3834,16 @@ const ON_INIT = Symbol();
3574
3834
  const RevealControllerContext = createContext(null);
3575
3835
  let _revealUsed = false;
3576
3836
  const FALSE_ACCESSOR = () => false;
3837
+ const SEQUENTIAL_ACCESSOR = () => "sequential";
3577
3838
  function isRevealController(slot) {
3578
3839
  return slot instanceof RevealController;
3579
3840
  }
3580
3841
  function isSlotReady(slot) {
3581
3842
  return isRevealController(slot) ? slot.isReady() : slot._sources.size === 0 && !slot._pending;
3582
3843
  }
3844
+ function isSlotMinimallyReady(slot) {
3845
+ return isRevealController(slot) ? slot.isMinimallyReady() : isSlotReady(slot);
3846
+ }
3583
3847
  function setSlotState(slot, controller, disabled, collapsed) {
3584
3848
  setSignal(slot._disabled, disabled);
3585
3849
  setSignal(slot._collapsed, collapsed);
@@ -3591,16 +3855,17 @@ function setSlotState(slot, controller, disabled, collapsed) {
3591
3855
  slot._revealController = undefined;
3592
3856
  }
3593
3857
  class RevealController {
3594
- _togetherAccessor;
3858
+ _orderAccessor;
3595
3859
  _collapsedAccessor;
3596
3860
  _slots = [];
3597
3861
  _parentController;
3598
- _disabled = signal(false, { pureWrite: true, _noSnapshot: true });
3599
- _collapsed = signal(false, { pureWrite: true, _noSnapshot: true });
3862
+ _disabled = signal(false, { ownedWrite: true, _noSnapshot: true });
3863
+ _collapsed = signal(false, { ownedWrite: true, _noSnapshot: true });
3600
3864
  _ready = true;
3865
+ _minimallyReady = true;
3601
3866
  _evaluating = false;
3602
- constructor(together, collapsed) {
3603
- this._togetherAccessor = together;
3867
+ constructor(order, collapsed) {
3868
+ this._orderAccessor = order;
3604
3869
  this._collapsedAccessor = collapsed;
3605
3870
  }
3606
3871
  _forEachOwnedSlot(fn) {
@@ -3615,12 +3880,37 @@ class RevealController {
3615
3880
  isReady() {
3616
3881
  return this._forEachOwnedSlot(isSlotReady);
3617
3882
  }
3883
+ isMinimallyReady() {
3884
+ const order = untrack(this._orderAccessor);
3885
+ if (order === "together") return this.isReady();
3886
+ if (order === "natural") {
3887
+ let hasSlot = false;
3888
+ let anyReady = false;
3889
+ this._forEachOwnedSlot(slot => {
3890
+ hasSlot = true;
3891
+ if (isSlotMinimallyReady(slot)) {
3892
+ anyReady = true;
3893
+ return false;
3894
+ }
3895
+ });
3896
+ return !hasSlot || anyReady;
3897
+ }
3898
+ let firstReady = true;
3899
+ this._forEachOwnedSlot(slot => {
3900
+ firstReady = isSlotMinimallyReady(slot);
3901
+ return false;
3902
+ });
3903
+ return firstReady;
3904
+ }
3618
3905
  register(slot) {
3619
3906
  if (this._slots.includes(slot)) return;
3620
3907
  this._slots.push(slot);
3621
- const together = !!untrack(this._togetherAccessor);
3622
- setSignal(slot._disabled, true),
3623
- setSignal(slot._collapsed, together ? false : !!untrack(this._collapsedAccessor));
3908
+ const order = untrack(this._orderAccessor);
3909
+ (setSignal(slot._disabled, true),
3910
+ setSignal(
3911
+ slot._collapsed,
3912
+ order === "sequential" ? !!untrack(this._collapsedAccessor) : false
3913
+ ));
3624
3914
  untrack(() => this.evaluate());
3625
3915
  }
3626
3916
  unregister(slot) {
@@ -3632,29 +3922,52 @@ class RevealController {
3632
3922
  if (this._evaluating) return;
3633
3923
  this._evaluating = true;
3634
3924
  const wasReady = this._ready;
3925
+ const wasMinReady = this._minimallyReady;
3635
3926
  try {
3636
3927
  const disabled = disabledOverride ?? read(this._disabled),
3637
- collapseTail = !!untrack(this._collapsedAccessor),
3928
+ order = untrack(this._orderAccessor),
3929
+ collapseTail = order === "sequential" && !!untrack(this._collapsedAccessor),
3638
3930
  collapsed = collapsedOverride ?? collapseTail;
3639
- if (disabled && collapsed)
3640
- this._forEachOwnedSlot(slot => setSlotState(slot, this, true, true));
3641
- else if (!!untrack(this._togetherAccessor)) {
3642
- const ready = this.isReady();
3643
- this._forEachOwnedSlot(slot => setSlotState(slot, this, !ready, false));
3931
+ if (disabled) {
3932
+ this._forEachOwnedSlot(slot => setSlotState(slot, this, true, collapsed));
3933
+ } else if (order === "natural") {
3934
+ this._forEachOwnedSlot(slot => {
3935
+ if (isRevealController(slot)) {
3936
+ setSignal(slot._collapsed, false);
3937
+ setSignal(slot._disabled, false);
3938
+ slot.evaluate(false, false);
3939
+ } else {
3940
+ setSlotState(slot, this, !isSlotReady(slot), false);
3941
+ }
3942
+ });
3943
+ } else if (order === "together") {
3944
+ const minReady = this._forEachOwnedSlot(isSlotMinimallyReady);
3945
+ this._forEachOwnedSlot(slot => setSlotState(slot, this, !minReady, false));
3644
3946
  } else {
3645
3947
  let pendingSeen = false;
3646
3948
  this._forEachOwnedSlot(slot => {
3647
3949
  if (pendingSeen) return setSlotState(slot, this, true, collapseTail);
3648
3950
  if (isSlotReady(slot)) return setSlotState(slot, this, false, false);
3649
3951
  pendingSeen = true;
3650
- setSlotState(slot, this, true, false);
3952
+ if (isRevealController(slot)) {
3953
+ setSignal(slot._collapsed, false);
3954
+ setSignal(slot._disabled, false);
3955
+ slot.evaluate(false, false);
3956
+ } else {
3957
+ setSlotState(slot, this, true, false);
3958
+ }
3651
3959
  });
3652
3960
  }
3653
3961
  } finally {
3654
3962
  this._ready = this.isReady();
3963
+ this._minimallyReady = this.isMinimallyReady();
3655
3964
  this._evaluating = false;
3656
3965
  }
3657
- if (this._parentController && wasReady !== this._ready) this._parentController.evaluate();
3966
+ if (
3967
+ this._parentController &&
3968
+ (wasReady !== this._ready || wasMinReady !== this._minimallyReady)
3969
+ )
3970
+ this._parentController.evaluate();
3658
3971
  }
3659
3972
  }
3660
3973
  class CollectionQueue extends Queue {
@@ -3662,8 +3975,8 @@ class CollectionQueue extends Queue {
3662
3975
  _sources = new Set();
3663
3976
  _tree;
3664
3977
  _pending = true;
3665
- _disabled = signal(false, { pureWrite: true, _noSnapshot: true });
3666
- _collapsed = signal(false, { pureWrite: true, _noSnapshot: true });
3978
+ _disabled = signal(false, { ownedWrite: true, _noSnapshot: true });
3979
+ _collapsed = signal(false, { ownedWrite: true, _noSnapshot: true });
3667
3980
  _revealController;
3668
3981
  _initialized = false;
3669
3982
  _onFn;
@@ -3743,7 +4056,8 @@ class CollectionQueue extends Queue {
3743
4056
  }
3744
4057
  function createCollectionBoundary(type, fn, fallback, onFn) {
3745
4058
  if (!getOwner()) {
3746
- const message = "Boundaries created outside a reactive context will never be disposed.";
4059
+ const message =
4060
+ "[NO_OWNER_BOUNDARY] Boundaries created outside a reactive context will never be disposed.";
3747
4061
  emitDiagnostic({
3748
4062
  code: "NO_OWNER_BOUNDARY",
3749
4063
  kind: "lifecycle",
@@ -3776,15 +4090,16 @@ function createCollectionBoundary(type, fn, fallback, onFn) {
3776
4090
  controller.register(queue);
3777
4091
  cleanup(() => controller.unregister(queue));
3778
4092
  }
3779
- const decision = computed(() => {
3780
- if (!read(queue._disabled)) {
3781
- const resolved = read(tree);
3782
- if (!untrack(() => read(queue._disabled))) return (queue._initialized = true), resolved;
3783
- }
3784
- if (_revealUsed && read(queue._collapsed)) return undefined;
3785
- return fallback(queue);
3786
- });
3787
- return accessor(decision);
4093
+ return accessor(
4094
+ computed(() => {
4095
+ if (!read(queue._disabled)) {
4096
+ const resolved = read(tree);
4097
+ if (!untrack(() => read(queue._disabled))) return ((queue._initialized = true), resolved);
4098
+ }
4099
+ if (_revealUsed && read(queue._collapsed)) return undefined;
4100
+ return fallback(queue);
4101
+ })
4102
+ );
3788
4103
  }
3789
4104
  function createLoadingBoundary(fn, fallback, options) {
3790
4105
  return createCollectionBoundary(STATUS_PENDING, fn, () => fallback(), options?.on);
@@ -3803,14 +4118,14 @@ function createRevealOrder(fn, options) {
3803
4118
  _revealUsed = true;
3804
4119
  const owner = createOwner();
3805
4120
  const parentController = getContext(RevealControllerContext);
3806
- const together = options?.together || FALSE_ACCESSOR,
4121
+ const order = options?.order || SEQUENTIAL_ACCESSOR,
3807
4122
  collapsed = options?.collapsed || FALSE_ACCESSOR;
3808
- const controller = new RevealController(together, collapsed);
4123
+ const controller = new RevealController(order, collapsed);
3809
4124
  setContext(RevealControllerContext, controller, owner);
3810
4125
  return runWithOwner(owner, () => {
3811
4126
  const value = fn();
3812
4127
  computed(() => {
3813
- together();
4128
+ order();
3814
4129
  collapsed();
3815
4130
  controller.evaluate();
3816
4131
  });