@solidjs/signals 0.13.12 → 2.0.0-beta.7

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 (39) hide show
  1. package/README.md +8 -7
  2. package/dist/dev.js +188 -102
  3. package/dist/node.cjs +501 -446
  4. package/dist/prod.js +368 -305
  5. package/dist/types/core/graph.d.ts +1 -0
  6. package/dist/types/core/types.d.ts +2 -2
  7. package/dist/types/signals.d.ts +15 -21
  8. package/dist/types/store/optimistic.d.ts +2 -2
  9. package/dist/types/store/projection.d.ts +4 -4
  10. package/dist/types/store/store.d.ts +2 -2
  11. package/dist/types-cjs/boundaries.d.cts +52 -0
  12. package/dist/types-cjs/core/action.d.cts +1 -0
  13. package/dist/types-cjs/core/async.d.cts +6 -0
  14. package/dist/types-cjs/core/constants.d.cts +25 -0
  15. package/dist/types-cjs/core/context.d.cts +28 -0
  16. package/dist/types-cjs/core/core.d.cts +54 -0
  17. package/dist/types-cjs/core/dev.d.cts +49 -0
  18. package/dist/types-cjs/core/effect.d.cts +30 -0
  19. package/dist/types-cjs/core/error.d.cts +14 -0
  20. package/dist/types-cjs/core/external.d.cts +26 -0
  21. package/dist/types-cjs/core/graph.d.cts +4 -0
  22. package/dist/types-cjs/core/heap.d.cts +14 -0
  23. package/dist/types-cjs/core/index.d.cts +12 -0
  24. package/dist/types-cjs/core/lanes.d.cts +54 -0
  25. package/dist/types-cjs/core/owner.d.cts +26 -0
  26. package/dist/types-cjs/core/scheduler.d.cts +81 -0
  27. package/dist/types-cjs/core/types.d.cts +86 -0
  28. package/dist/types-cjs/index.d.cts +9 -0
  29. package/dist/types-cjs/map.d.cts +24 -0
  30. package/dist/types-cjs/package.json +3 -0
  31. package/dist/types-cjs/signals.d.cts +186 -0
  32. package/dist/types-cjs/store/index.d.cts +9 -0
  33. package/dist/types-cjs/store/optimistic.d.cts +19 -0
  34. package/dist/types-cjs/store/projection.d.cts +26 -0
  35. package/dist/types-cjs/store/reconcile.d.cts +1 -0
  36. package/dist/types-cjs/store/store.d.cts +68 -0
  37. package/dist/types-cjs/store/storePath.d.cts +30 -0
  38. package/dist/types-cjs/store/utils.d.cts +43 -0
  39. package/package.json +31 -24
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @solidjs/signals
2
2
 
3
- The reactive core that powers [SolidJS 2.0](https://github.com/solidjs/solid). This is a standalone signals library designed for rendering — it includes first-class support for async, transitions, optimistic updates, and deeply reactive stores that go beyond what general-purpose signals libraries offer.
3
+ The reactive core that powers [SolidJS 2.0](https://github.com/solidjs/solid). It is developed in the Solid monorepo and includes first-class support for async, transitions, optimistic updates, and deeply reactive stores that go beyond what general-purpose signals libraries offer.
4
4
 
5
5
  > **Status:** Beta — this package is the reactive foundation of SolidJS 2.0 Beta. The API is stabilizing but may still have breaking changes before a final release.
6
6
 
@@ -240,14 +240,15 @@ createRoot(dispose => {
240
240
 
241
241
  ## Development
242
242
 
243
+ From the monorepo root:
244
+
243
245
  ```bash
244
246
  pnpm install
245
- pnpm build # Rollup build (dev/prod/node outputs)
246
- pnpm test # Run tests
247
- pnpm test:watch # Watch mode
248
- pnpm test:gc # Tests with GC exposed
249
- pnpm bench # Benchmarks
250
- pnpm format # Prettier + import sorting
247
+ pnpm --filter @solidjs/signals build
248
+ pnpm --filter @solidjs/signals test
249
+ pnpm --filter @solidjs/signals test:watch
250
+ pnpm --filter @solidjs/signals test:gc
251
+ pnpm --filter @solidjs/signals bench
251
252
  ```
252
253
 
253
254
  ## License
package/dist/dev.js CHANGED
@@ -426,7 +426,7 @@ class GlobalQueue extends Queue {
426
426
  stashedOptimisticReads = new Set();
427
427
  for (let i = 0; i < stashedTransition._optimisticNodes.length; i++) {
428
428
  const node = stashedTransition._optimisticNodes[i];
429
- if (node._fn || node._pureWrite) continue;
429
+ if (node._fn || node._ownedWrite) continue;
430
430
  stashedOptimisticReads.add(node);
431
431
  queueStashedOptimisticEffects(node);
432
432
  }
@@ -790,6 +790,7 @@ function unobserved(el) {
790
790
  dep = unlinkSubs(dep);
791
791
  }
792
792
  el._deps = null;
793
+ el._depsTail = null;
793
794
  disposeChildren(el, true);
794
795
  }
795
796
  function link(dep, sub) {
@@ -1081,6 +1082,7 @@ function handleAsync(el, result, setter) {
1081
1082
  if (el._inFlight !== result) return;
1082
1083
  if (el._flags & (REACTIVE_DIRTY | REACTIVE_OPTIMISTIC_DIRTY)) return;
1083
1084
  globalQueue.initTransition(resolveTransition(el));
1085
+ const wasUninitialized = !!(el._statusFlags & STATUS_UNINITIALIZED);
1084
1086
  clearStatus(el);
1085
1087
  const lane = resolveLane(el);
1086
1088
  if (lane) lane._pendingAsync.delete(el);
@@ -1094,9 +1096,10 @@ function handleAsync(el, result, setter) {
1094
1096
  }
1095
1097
  el._time = clock;
1096
1098
  } else if (lane) {
1099
+ const isEffect = el._type;
1097
1100
  const prevValue = el._value;
1098
1101
  const equals = el._equals;
1099
- if (!equals || !equals(value, prevValue)) {
1102
+ if ((!isEffect && wasUninitialized) || !equals || !equals(value, prevValue)) {
1100
1103
  el._value = value;
1101
1104
  el._time = clock;
1102
1105
  if (el._latestValueComputed) {
@@ -1359,6 +1362,7 @@ function recompute(el, create = false) {
1359
1362
  const isOptimisticDirty = !!(el._flags & REACTIVE_OPTIMISTIC_DIRTY);
1360
1363
  const hasOverride = el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING;
1361
1364
  const wasPending = !!(el._statusFlags & STATUS_PENDING);
1365
+ const wasUninitialized = !!(el._statusFlags & STATUS_UNINITIALIZED);
1362
1366
  const oldcontext = context;
1363
1367
  context = el;
1364
1368
  el._depsTail = null;
@@ -1424,7 +1428,8 @@ function recompute(el, create = false) {
1424
1428
  : el._pendingValue === NOT_PENDING
1425
1429
  ? el._value
1426
1430
  : el._pendingValue;
1427
- const valueChanged = !el._equals || !el._equals(compareValue, value);
1431
+ const valueChanged =
1432
+ (!isEffect && wasUninitialized) || !el._equals || !el._equals(compareValue, value);
1428
1433
  if (valueChanged) {
1429
1434
  const prevVisible = hasOverride ? el._overrideValue : undefined;
1430
1435
  if (create || (isEffect && activeTransition !== el._transition) || isOptimisticDirty) {
@@ -1485,7 +1490,7 @@ function computed(fn, initialValue, options) {
1485
1490
  (transparent ? context?.id : context?.id != null ? getNextChildId(context) : undefined),
1486
1491
  _transparent: transparent || undefined,
1487
1492
  _equals: options?.equals != null ? options.equals : isEqual,
1488
- _pureWrite: !!options?.pureWrite,
1493
+ _ownedWrite: !!options?.ownedWrite,
1489
1494
  _unobserved: options?.unobserved,
1490
1495
  _disposal: null,
1491
1496
  _queue: context?._queue ?? globalQueue,
@@ -1534,7 +1539,7 @@ function computed(fn, initialValue, options) {
1534
1539
  if (parent) self._height = parent._height + 1;
1535
1540
  if (snapshotCaptureActive && ownerInSnapshotScope(context)) self._inSnapshotScope = true;
1536
1541
  if (externalSourceConfig) {
1537
- const bridgeSignal = signal(undefined, { equals: false, pureWrite: true });
1542
+ const bridgeSignal = signal(undefined, { equals: false, ownedWrite: true });
1538
1543
  const source = externalSourceConfig.factory(self._fn, () => {
1539
1544
  setSignal(bridgeSignal, undefined);
1540
1545
  });
@@ -1556,7 +1561,7 @@ function computed(fn, initialValue, options) {
1556
1561
  function signal(v, options, firewall = null) {
1557
1562
  const s = {
1558
1563
  _equals: options?.equals != null ? options.equals : isEqual,
1559
- _pureWrite: !!options?.pureWrite,
1564
+ _ownedWrite: !!options?.ownedWrite,
1560
1565
  _noSnapshot: !!options?._noSnapshot,
1561
1566
  _unobserved: options?.unobserved,
1562
1567
  _value: v,
@@ -1668,10 +1673,16 @@ function read(el) {
1668
1673
  }
1669
1674
  let c = context;
1670
1675
  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);
1676
+ const computed = el;
1677
+ if (typeof computed._fn === "function") {
1678
+ const comp = el;
1679
+ if (refreshing && !(comp._flags & REACTIVE_DISPOSED)) recompute(comp);
1680
+ if (comp._flags & REACTIVE_LAZY) {
1681
+ comp._flags &= ~REACTIVE_LAZY;
1682
+ recompute(comp, true);
1683
+ } else if (comp._flags & REACTIVE_DISPOSED) {
1684
+ recompute(comp, true);
1685
+ }
1675
1686
  }
1676
1687
  const owner = el._firewall || el;
1677
1688
  if (strictRead && owner._statusFlags & STATUS_PENDING) {
@@ -1691,7 +1702,6 @@ function read(el) {
1691
1702
  throw new Error(message);
1692
1703
  }
1693
1704
  if (c && tracking) {
1694
- if (el._fn && el._flags & REACTIVE_DISPOSED) recompute(el);
1695
1705
  link(el, c);
1696
1706
  if (owner._fn) {
1697
1707
  const isZombie = el._flags & REACTIVE_ZOMBIE;
@@ -1776,7 +1786,8 @@ function read(el) {
1776
1786
  if (c && stale && shouldReadStashedOptimisticValue(el)) return el._value;
1777
1787
  return el._overrideValue;
1778
1788
  }
1779
- return !c ||
1789
+ const value =
1790
+ !c ||
1780
1791
  (currentOptimisticLane !== null &&
1781
1792
  (el._overrideValue !== undefined ||
1782
1793
  el._optimisticLane ||
@@ -1784,14 +1795,26 @@ function read(el) {
1784
1795
  !!(owner._statusFlags & STATUS_PENDING))) ||
1785
1796
  el._pendingValue === NOT_PENDING ||
1786
1797
  (stale && el._transition && activeTransition !== el._transition)
1787
- ? el._value
1788
- : el._pendingValue;
1798
+ ? el._value
1799
+ : el._pendingValue;
1800
+ if (
1801
+ !c &&
1802
+ owner === el &&
1803
+ typeof computed._fn === "function" &&
1804
+ !computed._preventAutoDisposal &&
1805
+ !(owner._statusFlags & STATUS_PENDING) &&
1806
+ !computed._parent &&
1807
+ !el._subs
1808
+ ) {
1809
+ unobserved(el);
1810
+ }
1811
+ return value;
1789
1812
  }
1790
1813
  function setSignal(el, v) {
1791
- if (!el._pureWrite && !context?._childrenForbidden && context && el._firewall !== context) {
1814
+ if (!el._ownedWrite && !context?._childrenForbidden && context && el._firewall !== context) {
1792
1815
  const message =
1793
1816
  "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.";
1817
+ "Move the write outside or set the `ownedWrite` option if this is intentional.";
1795
1818
  emitDiagnostic({
1796
1819
  code: "SIGNAL_WRITE_IN_OWNED_SCOPE",
1797
1820
  kind: "write",
@@ -1875,7 +1898,7 @@ function runWithOwner(owner, fn) {
1875
1898
  }
1876
1899
  function getPendingSignal(el) {
1877
1900
  if (!el._pendingSignal) {
1878
- el._pendingSignal = optimisticSignal(false, { pureWrite: true });
1901
+ el._pendingSignal = optimisticSignal(false, { ownedWrite: true });
1879
1902
  if (el._parentSource) {
1880
1903
  el._pendingSignal._parentSource = el;
1881
1904
  }
@@ -2061,16 +2084,18 @@ function effect(compute, effect, error, initialValue, options) {
2061
2084
  node._queue.notify(node, STATUS_PENDING | STATUS_ERROR, actualStatus, actualError);
2062
2085
  if (_hitUnhandledAsync) {
2063
2086
  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;
2087
+ if (!node._queue.notify(node, STATUS_ERROR, STATUS_ERROR)) {
2088
+ const message = "An async value must be rendered inside a Loading boundary.";
2089
+ emitDiagnostic({
2090
+ code: "ASYNC_OUTSIDE_LOADING_BOUNDARY",
2091
+ kind: "async",
2092
+ severity: "error",
2093
+ message: message,
2094
+ ownerId: node.id,
2095
+ ownerName: node._name
2096
+ });
2097
+ throw new Error(message);
2098
+ }
2074
2099
  }
2075
2100
  }
2076
2101
  };
@@ -2253,27 +2278,28 @@ function accessor(node) {
2253
2278
  fn.$r = true;
2254
2279
  return fn;
2255
2280
  }
2256
- function createSignal(first, second, third) {
2281
+ function createSignal(first, second) {
2257
2282
  if (typeof first === "function") {
2258
- const node = computed(first, second, third);
2283
+ const node = computed(first, undefined, second);
2284
+ node._preventAutoDisposal = true;
2259
2285
  return [accessor(node), setSignal.bind(null, node)];
2260
2286
  }
2261
2287
  const node = signal(first, second);
2262
2288
  registerGraph(node, getOwner());
2263
2289
  return [accessor(node), setSignal.bind(null, node)];
2264
2290
  }
2265
- function createMemo(compute, value, options) {
2266
- let node = computed(compute, value, options);
2291
+ function createMemo(compute, options) {
2292
+ let node = computed(compute, undefined, options);
2267
2293
  return accessor(node);
2268
2294
  }
2269
- function createEffect(compute, effectFn, value, options) {
2270
- effect(compute, effectFn.effect || effectFn, effectFn.error, value, {
2295
+ function createEffect(compute, effectFn, options) {
2296
+ effect(compute, effectFn.effect || effectFn, effectFn.error, undefined, {
2271
2297
  ...options,
2272
2298
  name: options?.name ?? "effect"
2273
2299
  });
2274
2300
  }
2275
- function createRenderEffect(compute, effectFn, value, options) {
2276
- effect(compute, effectFn, undefined, value, {
2301
+ function createRenderEffect(compute, effectFn, options) {
2302
+ effect(compute, effectFn, undefined, undefined, {
2277
2303
  render: true,
2278
2304
  ...{ ...options, name: options?.name ?? "effect" }
2279
2305
  });
@@ -2327,9 +2353,10 @@ function resolve(fn) {
2327
2353
  });
2328
2354
  });
2329
2355
  }
2330
- function createOptimistic(first, second, third) {
2356
+ function createOptimistic(first, second) {
2331
2357
  if (typeof first === "function") {
2332
- const node = optimisticComputed(first, second, third);
2358
+ const node = optimisticComputed(first, undefined, second);
2359
+ node._preventAutoDisposal = true;
2333
2360
  return [accessor(node), setSignal.bind(null, node)];
2334
2361
  }
2335
2362
  const node = optimisticSignal(first, second);
@@ -2495,7 +2522,7 @@ function reconcile(value, key) {
2495
2522
  applyState(value, state, keyFn);
2496
2523
  };
2497
2524
  }
2498
- function createProjectionInternal(fn, initialValue = {}, options) {
2525
+ function createProjectionInternal(fn, seed, options) {
2499
2526
  let node;
2500
2527
  const wrappedMap = new WeakMap();
2501
2528
  const wrapper = s => {
@@ -2515,7 +2542,7 @@ function createProjectionInternal(fn, initialValue = {}, options) {
2515
2542
  wrappedMap.set(source, wrapped);
2516
2543
  return wrapped;
2517
2544
  };
2518
- const wrappedStore = wrapProjection(initialValue);
2545
+ const wrappedStore = wrapProjection(seed);
2519
2546
  node = computed(() => {
2520
2547
  const owner = getOwner();
2521
2548
  let settled = false;
@@ -2538,8 +2565,8 @@ function createProjectionInternal(fn, initialValue = {}, options) {
2538
2565
  node._preventAutoDisposal = true;
2539
2566
  return { store: wrappedStore, node: node };
2540
2567
  }
2541
- function createProjection(fn, initialValue = {}, options) {
2542
- return createProjectionInternal(fn, initialValue, options).store;
2568
+ function createProjection(fn, seed, options) {
2569
+ return createProjectionInternal(fn, seed, options).store;
2543
2570
  }
2544
2571
  function createWriteTraps(isActive) {
2545
2572
  const traps = {
@@ -2690,12 +2717,55 @@ function getKeys(source, override, enumerable = true) {
2690
2717
  return Array.from(keys);
2691
2718
  }
2692
2719
  function getPropertyDescriptor(source, override, property) {
2693
- let value = source;
2694
2720
  if (override && property in override) {
2695
- if (value[property] === $DELETED) return void 0;
2696
- if (!(property in value)) value = override;
2721
+ if (override[property] === $DELETED) return void 0;
2722
+ const overrideDesc = Reflect.getOwnPropertyDescriptor(override, property);
2723
+ if (overrideDesc?.get || overrideDesc?.set || !(property in source)) return overrideDesc;
2697
2724
  }
2698
- return Reflect.getOwnPropertyDescriptor(value, property);
2725
+ return Reflect.getOwnPropertyDescriptor(source, property);
2726
+ }
2727
+ function prepareStoreWrite(target, store, property) {
2728
+ if (target[STORE_OPTIMISTIC]) {
2729
+ const firewall = target[STORE_FIREWALL];
2730
+ if (firewall?._transition) {
2731
+ globalQueue.initTransition(firewall._transition);
2732
+ }
2733
+ }
2734
+ const state = target[STORE_VALUE];
2735
+ const base = state[property];
2736
+ if (
2737
+ snapshotCaptureActive &&
2738
+ typeof property !== "symbol" &&
2739
+ !((target[STORE_FIREWALL]?._statusFlags ?? 0) & STATUS_PENDING)
2740
+ ) {
2741
+ if (!target[STORE_SNAPSHOT_PROPS]) {
2742
+ target[STORE_SNAPSHOT_PROPS] = Object.create(null);
2743
+ snapshotSources?.add(target);
2744
+ }
2745
+ if (!(property in target[STORE_SNAPSHOT_PROPS])) {
2746
+ target[STORE_SNAPSHOT_PROPS][property] = base;
2747
+ }
2748
+ }
2749
+ const useOptimistic = target[STORE_OPTIMISTIC] && !projectionWriteActive;
2750
+ const overrideKey = useOptimistic ? STORE_OPTIMISTIC_OVERRIDE : STORE_OVERRIDE;
2751
+ if (useOptimistic) trackOptimisticStore(store);
2752
+ return { base: base, overrideKey: overrideKey, state: state };
2753
+ }
2754
+ function notifyStoreProperty(target, property, mode, value) {
2755
+ if (target[STORE_HAS]?.[property]) setSignal(target[STORE_HAS][property], mode !== "delete");
2756
+ const nodes = getNodes(target, STORE_NODE);
2757
+ if (mode === "set") {
2758
+ nodes[property] &&
2759
+ setSignal(nodes[property], () => (isWrappable(value) ? wrap(value, target) : value));
2760
+ } else if (mode === "invalidate") {
2761
+ if (nodes[property]) {
2762
+ setSignal(nodes[property], {});
2763
+ delete nodes[property];
2764
+ }
2765
+ } else {
2766
+ nodes[property] && setSignal(nodes[property], undefined);
2767
+ }
2768
+ nodes[$TRACK] && setSignal(nodes[$TRACK], undefined);
2699
2769
  }
2700
2770
  let Writing = null;
2701
2771
  const storeTraps = {
@@ -2808,31 +2878,12 @@ const storeTraps = {
2808
2878
  set(target, property, rawValue) {
2809
2879
  const store = target[$PROXY];
2810
2880
  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
2881
  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);
2882
+ const {
2883
+ base: base,
2884
+ overrideKey: overrideKey,
2885
+ state: state
2886
+ } = prepareStoreWrite(target, store, property);
2836
2887
  const prev =
2837
2888
  target[STORE_OPTIMISTIC_OVERRIDE] && property in target[STORE_OPTIMISTIC_OVERRIDE]
2838
2889
  ? target[STORE_OPTIMISTIC_OVERRIDE][property]
@@ -2858,21 +2909,46 @@ const storeTraps = {
2858
2909
  override[property] = value;
2859
2910
  if (nextLength !== undefined) override.length = nextLength;
2860
2911
  }
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));
2912
+ notifyStoreProperty(target, property, "set", value);
2866
2913
  if (Array.isArray(state)) {
2914
+ const nodes = getNodes(target, STORE_NODE);
2867
2915
  const lengthValue = property === "length" ? value : nextLength;
2868
2916
  lengthValue !== undefined && nodes.length && setSignal(nodes.length, lengthValue);
2869
2917
  }
2870
- nodes[$TRACK] && setSignal(nodes[$TRACK], undefined);
2871
2918
  if (true) DEV$1.hooks.onStoreNodeUpdate?.(target[$PROXY], property, value, prev);
2872
2919
  });
2873
2920
  }
2874
2921
  return true;
2875
2922
  },
2923
+ defineProperty(target, property, descriptor) {
2924
+ const store = target[$PROXY];
2925
+ if (writeOnly(store)) {
2926
+ untrack(() => {
2927
+ const { base: base, overrideKey: overrideKey } = prepareStoreWrite(target, store, property);
2928
+ const normalizedDescriptor =
2929
+ "value" in descriptor
2930
+ ? {
2931
+ ...descriptor,
2932
+ value: descriptor.value?.[$TARGET]?.[STORE_VALUE] ?? descriptor.value
2933
+ }
2934
+ : descriptor;
2935
+ Object.defineProperty(
2936
+ target[overrideKey] || (target[overrideKey] = Object.create(null)),
2937
+ property,
2938
+ normalizedDescriptor
2939
+ );
2940
+ notifyStoreProperty(target, property, "invalidate");
2941
+ if (true) {
2942
+ const next =
2943
+ "value" in normalizedDescriptor
2944
+ ? normalizedDescriptor.value
2945
+ : normalizedDescriptor.get?.call(store);
2946
+ DEV$1.hooks.onStoreNodeUpdate?.(target[$PROXY], property, next, base);
2947
+ }
2948
+ });
2949
+ }
2950
+ return true;
2951
+ },
2876
2952
  deleteProperty(target, property) {
2877
2953
  const optDeleted = target[STORE_OPTIMISTIC_OVERRIDE]?.[property] === $DELETED;
2878
2954
  const regDeleted = target[STORE_OVERRIDE]?.[property] === $DELETED;
@@ -2895,10 +2971,7 @@ const storeTraps = {
2895
2971
  } else if (target[overrideKey] && property in target[overrideKey]) {
2896
2972
  delete target[overrideKey][property];
2897
2973
  } 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);
2974
+ notifyStoreProperty(target, property, "delete");
2902
2975
  });
2903
2976
  }
2904
2977
  return true;
@@ -2920,6 +2993,8 @@ const storeTraps = {
2920
2993
  if (property === $PROXY) return { value: target[$PROXY], writable: true, configurable: true };
2921
2994
  if (target[STORE_OPTIMISTIC_OVERRIDE] && property in target[STORE_OPTIMISTIC_OVERRIDE]) {
2922
2995
  if (target[STORE_OPTIMISTIC_OVERRIDE][property] === $DELETED) return undefined;
2996
+ const optDesc = Reflect.getOwnPropertyDescriptor(target[STORE_OPTIMISTIC_OVERRIDE], property);
2997
+ if (optDesc?.get || optDesc?.set || !(property in target[STORE_VALUE])) return optDesc;
2923
2998
  const baseDesc = getPropertyDescriptor(target[STORE_VALUE], target[STORE_OVERRIDE], property);
2924
2999
  if (baseDesc) {
2925
3000
  return { ...baseDesc, value: target[STORE_OPTIMISTIC_OVERRIDE][property] };
@@ -2969,7 +3044,7 @@ function createStore(first, second, options) {
2969
3044
  function createOptimisticStore(first, second, options) {
2970
3045
  GlobalQueue._clearOptimisticStore ||= clearOptimisticStore;
2971
3046
  const derived = typeof first === "function";
2972
- const initialValue = (derived ? second : first) ?? {};
3047
+ const initialValue = derived ? second : first;
2973
3048
  const fn = derived ? first : undefined;
2974
3049
  const { store: wrappedStore } = createOptimisticProjectionInternal(fn, initialValue, options);
2975
3050
  return [wrappedStore, fn => storeSetter(wrappedStore, fn)];
@@ -3003,7 +3078,7 @@ function clearOptimisticStore(store) {
3003
3078
  }
3004
3079
  delete target[STORE_OPTIMISTIC_OVERRIDE];
3005
3080
  }
3006
- function createOptimisticProjectionInternal(fn, initialValue = {}, options) {
3081
+ function createOptimisticProjectionInternal(fn, initialValue, options) {
3007
3082
  let node;
3008
3083
  const wrappedMap = new WeakMap();
3009
3084
  const wrapper = s => {
@@ -3113,7 +3188,12 @@ function updatePath(current, args, i = 0) {
3113
3188
  ) {
3114
3189
  const target = part !== undefined ? current[part] : current;
3115
3190
  const keys = Object.keys(value);
3116
- for (let i = 0; i < keys.length; i++) target[keys[i]] = value[keys[i]];
3191
+ for (let i = 0; i < keys.length; i++) {
3192
+ const key = keys[i];
3193
+ const desc = Object.getOwnPropertyDescriptor(value, key);
3194
+ if (desc.get || desc.set) Object.defineProperty(target, key, desc);
3195
+ else target[key] = desc.value;
3196
+ }
3117
3197
  } else {
3118
3198
  current[part] = value;
3119
3199
  }
@@ -3329,7 +3409,7 @@ function mapArray(list, map, options) {
3329
3409
  }
3330
3410
  }
3331
3411
  : map;
3332
- return createMemo(
3412
+ const node = computed(
3333
3413
  updateKeyedMap.bind({
3334
3414
  _owner: createOwner(),
3335
3415
  _len: 0,
@@ -3344,8 +3424,10 @@ function mapArray(list, map, options) {
3344
3424
  _fallback: options?.fallback
3345
3425
  })
3346
3426
  );
3427
+ node._preventAutoDisposal = true;
3428
+ return accessor(node);
3347
3429
  }
3348
- const pureOptions = { pureWrite: true };
3430
+ const pureOptions = { ownedWrite: true };
3349
3431
  function updateKeyedMap() {
3350
3432
  const newItems = this._list() || [],
3351
3433
  newLen = newItems.length;
@@ -3482,17 +3564,21 @@ function repeat(count, map, options) {
3482
3564
  }
3483
3565
  }
3484
3566
  : 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
- });
3567
+ const node = computed(
3568
+ updateRepeat.bind({
3569
+ _owner: createOwner(),
3570
+ _len: 0,
3571
+ _offset: 0,
3572
+ _count: count,
3573
+ _map: wrappedMap,
3574
+ _nodes: [],
3575
+ _mappings: [],
3576
+ _from: options?.from,
3577
+ _fallback: options?.fallback
3578
+ })
3579
+ );
3580
+ node._preventAutoDisposal = true;
3581
+ return accessor(node);
3496
3582
  }
3497
3583
  function updateRepeat() {
3498
3584
  const newLen = this._count();
@@ -3595,8 +3681,8 @@ class RevealController {
3595
3681
  _collapsedAccessor;
3596
3682
  _slots = [];
3597
3683
  _parentController;
3598
- _disabled = signal(false, { pureWrite: true, _noSnapshot: true });
3599
- _collapsed = signal(false, { pureWrite: true, _noSnapshot: true });
3684
+ _disabled = signal(false, { ownedWrite: true, _noSnapshot: true });
3685
+ _collapsed = signal(false, { ownedWrite: true, _noSnapshot: true });
3600
3686
  _ready = true;
3601
3687
  _evaluating = false;
3602
3688
  constructor(together, collapsed) {
@@ -3619,8 +3705,8 @@ class RevealController {
3619
3705
  if (this._slots.includes(slot)) return;
3620
3706
  this._slots.push(slot);
3621
3707
  const together = !!untrack(this._togetherAccessor);
3622
- setSignal(slot._disabled, true),
3623
- setSignal(slot._collapsed, together ? false : !!untrack(this._collapsedAccessor));
3708
+ (setSignal(slot._disabled, true),
3709
+ setSignal(slot._collapsed, together ? false : !!untrack(this._collapsedAccessor)));
3624
3710
  untrack(() => this.evaluate());
3625
3711
  }
3626
3712
  unregister(slot) {
@@ -3662,8 +3748,8 @@ class CollectionQueue extends Queue {
3662
3748
  _sources = new Set();
3663
3749
  _tree;
3664
3750
  _pending = true;
3665
- _disabled = signal(false, { pureWrite: true, _noSnapshot: true });
3666
- _collapsed = signal(false, { pureWrite: true, _noSnapshot: true });
3751
+ _disabled = signal(false, { ownedWrite: true, _noSnapshot: true });
3752
+ _collapsed = signal(false, { ownedWrite: true, _noSnapshot: true });
3667
3753
  _revealController;
3668
3754
  _initialized = false;
3669
3755
  _onFn;
@@ -3779,7 +3865,7 @@ function createCollectionBoundary(type, fn, fallback, onFn) {
3779
3865
  const decision = computed(() => {
3780
3866
  if (!read(queue._disabled)) {
3781
3867
  const resolved = read(tree);
3782
- if (!untrack(() => read(queue._disabled))) return (queue._initialized = true), resolved;
3868
+ if (!untrack(() => read(queue._disabled))) return ((queue._initialized = true), resolved);
3783
3869
  }
3784
3870
  if (_revealUsed && read(queue._collapsed)) return undefined;
3785
3871
  return fallback(queue);