@solidjs/signals 0.13.13 → 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 +90 -61
  3. package/dist/node.cjs +156 -137
  4. package/dist/prod.js +108 -81
  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) {
@@ -1489,7 +1490,7 @@ function computed(fn, initialValue, options) {
1489
1490
  (transparent ? context?.id : context?.id != null ? getNextChildId(context) : undefined),
1490
1491
  _transparent: transparent || undefined,
1491
1492
  _equals: options?.equals != null ? options.equals : isEqual,
1492
- _pureWrite: !!options?.pureWrite,
1493
+ _ownedWrite: !!options?.ownedWrite,
1493
1494
  _unobserved: options?.unobserved,
1494
1495
  _disposal: null,
1495
1496
  _queue: context?._queue ?? globalQueue,
@@ -1538,7 +1539,7 @@ function computed(fn, initialValue, options) {
1538
1539
  if (parent) self._height = parent._height + 1;
1539
1540
  if (snapshotCaptureActive && ownerInSnapshotScope(context)) self._inSnapshotScope = true;
1540
1541
  if (externalSourceConfig) {
1541
- const bridgeSignal = signal(undefined, { equals: false, pureWrite: true });
1542
+ const bridgeSignal = signal(undefined, { equals: false, ownedWrite: true });
1542
1543
  const source = externalSourceConfig.factory(self._fn, () => {
1543
1544
  setSignal(bridgeSignal, undefined);
1544
1545
  });
@@ -1560,7 +1561,7 @@ function computed(fn, initialValue, options) {
1560
1561
  function signal(v, options, firewall = null) {
1561
1562
  const s = {
1562
1563
  _equals: options?.equals != null ? options.equals : isEqual,
1563
- _pureWrite: !!options?.pureWrite,
1564
+ _ownedWrite: !!options?.ownedWrite,
1564
1565
  _noSnapshot: !!options?._noSnapshot,
1565
1566
  _unobserved: options?.unobserved,
1566
1567
  _value: v,
@@ -1672,10 +1673,16 @@ function read(el) {
1672
1673
  }
1673
1674
  let c = context;
1674
1675
  if (c?._root) c = c._parentComputed;
1675
- if (refreshing && el._fn) recompute(el);
1676
- if (el._flags & REACTIVE_LAZY) {
1677
- el._flags &= ~REACTIVE_LAZY;
1678
- recompute(el, true);
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
+ }
1679
1686
  }
1680
1687
  const owner = el._firewall || el;
1681
1688
  if (strictRead && owner._statusFlags & STATUS_PENDING) {
@@ -1695,7 +1702,6 @@ function read(el) {
1695
1702
  throw new Error(message);
1696
1703
  }
1697
1704
  if (c && tracking) {
1698
- if (el._fn && el._flags & REACTIVE_DISPOSED) recompute(el);
1699
1705
  link(el, c);
1700
1706
  if (owner._fn) {
1701
1707
  const isZombie = el._flags & REACTIVE_ZOMBIE;
@@ -1780,7 +1786,8 @@ function read(el) {
1780
1786
  if (c && stale && shouldReadStashedOptimisticValue(el)) return el._value;
1781
1787
  return el._overrideValue;
1782
1788
  }
1783
- return !c ||
1789
+ const value =
1790
+ !c ||
1784
1791
  (currentOptimisticLane !== null &&
1785
1792
  (el._overrideValue !== undefined ||
1786
1793
  el._optimisticLane ||
@@ -1788,14 +1795,26 @@ function read(el) {
1788
1795
  !!(owner._statusFlags & STATUS_PENDING))) ||
1789
1796
  el._pendingValue === NOT_PENDING ||
1790
1797
  (stale && el._transition && activeTransition !== el._transition)
1791
- ? el._value
1792
- : 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;
1793
1812
  }
1794
1813
  function setSignal(el, v) {
1795
- if (!el._pureWrite && !context?._childrenForbidden && context && el._firewall !== context) {
1814
+ if (!el._ownedWrite && !context?._childrenForbidden && context && el._firewall !== context) {
1796
1815
  const message =
1797
1816
  "Writing to a Signal inside an owned scope (component, computation) is not allowed. " +
1798
- "Move the write outside or set the `pureWrite` option if this is intentional.";
1817
+ "Move the write outside or set the `ownedWrite` option if this is intentional.";
1799
1818
  emitDiagnostic({
1800
1819
  code: "SIGNAL_WRITE_IN_OWNED_SCOPE",
1801
1820
  kind: "write",
@@ -1879,7 +1898,7 @@ function runWithOwner(owner, fn) {
1879
1898
  }
1880
1899
  function getPendingSignal(el) {
1881
1900
  if (!el._pendingSignal) {
1882
- el._pendingSignal = optimisticSignal(false, { pureWrite: true });
1901
+ el._pendingSignal = optimisticSignal(false, { ownedWrite: true });
1883
1902
  if (el._parentSource) {
1884
1903
  el._pendingSignal._parentSource = el;
1885
1904
  }
@@ -2065,16 +2084,18 @@ function effect(compute, effect, error, initialValue, options) {
2065
2084
  node._queue.notify(node, STATUS_PENDING | STATUS_ERROR, actualStatus, actualError);
2066
2085
  if (_hitUnhandledAsync) {
2067
2086
  resetUnhandledAsync();
2068
- const err = new Error("An async value must be rendered inside a Loading boundary.");
2069
- emitDiagnostic({
2070
- code: "ASYNC_OUTSIDE_LOADING_BOUNDARY",
2071
- kind: "async",
2072
- severity: "error",
2073
- message: err.message,
2074
- ownerId: node.id,
2075
- ownerName: node._name
2076
- });
2077
- if (!node._queue.notify(node, STATUS_ERROR, STATUS_ERROR)) throw err;
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
+ }
2078
2099
  }
2079
2100
  }
2080
2101
  };
@@ -2257,27 +2278,28 @@ function accessor(node) {
2257
2278
  fn.$r = true;
2258
2279
  return fn;
2259
2280
  }
2260
- function createSignal(first, second, third) {
2281
+ function createSignal(first, second) {
2261
2282
  if (typeof first === "function") {
2262
- const node = computed(first, second, third);
2283
+ const node = computed(first, undefined, second);
2284
+ node._preventAutoDisposal = true;
2263
2285
  return [accessor(node), setSignal.bind(null, node)];
2264
2286
  }
2265
2287
  const node = signal(first, second);
2266
2288
  registerGraph(node, getOwner());
2267
2289
  return [accessor(node), setSignal.bind(null, node)];
2268
2290
  }
2269
- function createMemo(compute, value, options) {
2270
- let node = computed(compute, value, options);
2291
+ function createMemo(compute, options) {
2292
+ let node = computed(compute, undefined, options);
2271
2293
  return accessor(node);
2272
2294
  }
2273
- function createEffect(compute, effectFn, value, options) {
2274
- effect(compute, effectFn.effect || effectFn, effectFn.error, value, {
2295
+ function createEffect(compute, effectFn, options) {
2296
+ effect(compute, effectFn.effect || effectFn, effectFn.error, undefined, {
2275
2297
  ...options,
2276
2298
  name: options?.name ?? "effect"
2277
2299
  });
2278
2300
  }
2279
- function createRenderEffect(compute, effectFn, value, options) {
2280
- effect(compute, effectFn, undefined, value, {
2301
+ function createRenderEffect(compute, effectFn, options) {
2302
+ effect(compute, effectFn, undefined, undefined, {
2281
2303
  render: true,
2282
2304
  ...{ ...options, name: options?.name ?? "effect" }
2283
2305
  });
@@ -2331,9 +2353,10 @@ function resolve(fn) {
2331
2353
  });
2332
2354
  });
2333
2355
  }
2334
- function createOptimistic(first, second, third) {
2356
+ function createOptimistic(first, second) {
2335
2357
  if (typeof first === "function") {
2336
- const node = optimisticComputed(first, second, third);
2358
+ const node = optimisticComputed(first, undefined, second);
2359
+ node._preventAutoDisposal = true;
2337
2360
  return [accessor(node), setSignal.bind(null, node)];
2338
2361
  }
2339
2362
  const node = optimisticSignal(first, second);
@@ -2499,7 +2522,7 @@ function reconcile(value, key) {
2499
2522
  applyState(value, state, keyFn);
2500
2523
  };
2501
2524
  }
2502
- function createProjectionInternal(fn, initialValue = {}, options) {
2525
+ function createProjectionInternal(fn, seed, options) {
2503
2526
  let node;
2504
2527
  const wrappedMap = new WeakMap();
2505
2528
  const wrapper = s => {
@@ -2519,7 +2542,7 @@ function createProjectionInternal(fn, initialValue = {}, options) {
2519
2542
  wrappedMap.set(source, wrapped);
2520
2543
  return wrapped;
2521
2544
  };
2522
- const wrappedStore = wrapProjection(initialValue);
2545
+ const wrappedStore = wrapProjection(seed);
2523
2546
  node = computed(() => {
2524
2547
  const owner = getOwner();
2525
2548
  let settled = false;
@@ -2542,8 +2565,8 @@ function createProjectionInternal(fn, initialValue = {}, options) {
2542
2565
  node._preventAutoDisposal = true;
2543
2566
  return { store: wrappedStore, node: node };
2544
2567
  }
2545
- function createProjection(fn, initialValue = {}, options) {
2546
- return createProjectionInternal(fn, initialValue, options).store;
2568
+ function createProjection(fn, seed, options) {
2569
+ return createProjectionInternal(fn, seed, options).store;
2547
2570
  }
2548
2571
  function createWriteTraps(isActive) {
2549
2572
  const traps = {
@@ -3021,7 +3044,7 @@ function createStore(first, second, options) {
3021
3044
  function createOptimisticStore(first, second, options) {
3022
3045
  GlobalQueue._clearOptimisticStore ||= clearOptimisticStore;
3023
3046
  const derived = typeof first === "function";
3024
- const initialValue = (derived ? second : first) ?? {};
3047
+ const initialValue = derived ? second : first;
3025
3048
  const fn = derived ? first : undefined;
3026
3049
  const { store: wrappedStore } = createOptimisticProjectionInternal(fn, initialValue, options);
3027
3050
  return [wrappedStore, fn => storeSetter(wrappedStore, fn)];
@@ -3055,7 +3078,7 @@ function clearOptimisticStore(store) {
3055
3078
  }
3056
3079
  delete target[STORE_OPTIMISTIC_OVERRIDE];
3057
3080
  }
3058
- function createOptimisticProjectionInternal(fn, initialValue = {}, options) {
3081
+ function createOptimisticProjectionInternal(fn, initialValue, options) {
3059
3082
  let node;
3060
3083
  const wrappedMap = new WeakMap();
3061
3084
  const wrapper = s => {
@@ -3386,7 +3409,7 @@ function mapArray(list, map, options) {
3386
3409
  }
3387
3410
  }
3388
3411
  : map;
3389
- return createMemo(
3412
+ const node = computed(
3390
3413
  updateKeyedMap.bind({
3391
3414
  _owner: createOwner(),
3392
3415
  _len: 0,
@@ -3401,8 +3424,10 @@ function mapArray(list, map, options) {
3401
3424
  _fallback: options?.fallback
3402
3425
  })
3403
3426
  );
3427
+ node._preventAutoDisposal = true;
3428
+ return accessor(node);
3404
3429
  }
3405
- const pureOptions = { pureWrite: true };
3430
+ const pureOptions = { ownedWrite: true };
3406
3431
  function updateKeyedMap() {
3407
3432
  const newItems = this._list() || [],
3408
3433
  newLen = newItems.length;
@@ -3539,17 +3564,21 @@ function repeat(count, map, options) {
3539
3564
  }
3540
3565
  }
3541
3566
  : map;
3542
- return updateRepeat.bind({
3543
- _owner: createOwner(),
3544
- _len: 0,
3545
- _offset: 0,
3546
- _count: count,
3547
- _map: wrappedMap,
3548
- _nodes: [],
3549
- _mappings: [],
3550
- _from: options?.from,
3551
- _fallback: options?.fallback
3552
- });
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);
3553
3582
  }
3554
3583
  function updateRepeat() {
3555
3584
  const newLen = this._count();
@@ -3652,8 +3681,8 @@ class RevealController {
3652
3681
  _collapsedAccessor;
3653
3682
  _slots = [];
3654
3683
  _parentController;
3655
- _disabled = signal(false, { pureWrite: true, _noSnapshot: true });
3656
- _collapsed = signal(false, { pureWrite: true, _noSnapshot: true });
3684
+ _disabled = signal(false, { ownedWrite: true, _noSnapshot: true });
3685
+ _collapsed = signal(false, { ownedWrite: true, _noSnapshot: true });
3657
3686
  _ready = true;
3658
3687
  _evaluating = false;
3659
3688
  constructor(together, collapsed) {
@@ -3676,8 +3705,8 @@ class RevealController {
3676
3705
  if (this._slots.includes(slot)) return;
3677
3706
  this._slots.push(slot);
3678
3707
  const together = !!untrack(this._togetherAccessor);
3679
- setSignal(slot._disabled, true),
3680
- setSignal(slot._collapsed, together ? false : !!untrack(this._collapsedAccessor));
3708
+ (setSignal(slot._disabled, true),
3709
+ setSignal(slot._collapsed, together ? false : !!untrack(this._collapsedAccessor)));
3681
3710
  untrack(() => this.evaluate());
3682
3711
  }
3683
3712
  unregister(slot) {
@@ -3719,8 +3748,8 @@ class CollectionQueue extends Queue {
3719
3748
  _sources = new Set();
3720
3749
  _tree;
3721
3750
  _pending = true;
3722
- _disabled = signal(false, { pureWrite: true, _noSnapshot: true });
3723
- _collapsed = signal(false, { pureWrite: true, _noSnapshot: true });
3751
+ _disabled = signal(false, { ownedWrite: true, _noSnapshot: true });
3752
+ _collapsed = signal(false, { ownedWrite: true, _noSnapshot: true });
3724
3753
  _revealController;
3725
3754
  _initialized = false;
3726
3755
  _onFn;
@@ -3836,7 +3865,7 @@ function createCollectionBoundary(type, fn, fallback, onFn) {
3836
3865
  const decision = computed(() => {
3837
3866
  if (!read(queue._disabled)) {
3838
3867
  const resolved = read(tree);
3839
- if (!untrack(() => read(queue._disabled))) return (queue._initialized = true), resolved;
3868
+ if (!untrack(() => read(queue._disabled))) return ((queue._initialized = true), resolved);
3840
3869
  }
3841
3870
  if (_revealUsed && read(queue._collapsed)) return undefined;
3842
3871
  return fallback(queue);