@solidjs/signals 0.11.1 → 0.11.3

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.
package/README.md CHANGED
@@ -1,5 +1,255 @@
1
1
  # @solidjs/signals
2
2
 
3
- Standalone Reactive implementation to serve as the basis of future (post 1.x) versions of SolidJS. This package aims to be core for Signals library made with rendering in mind so it may have more features and opinions than common Signals libraries, but are still necessary core to accomplish the type of capabilities we intend.
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.
4
4
 
5
- This is not ready for production and should be considered pre-alpha. This package is completely experimental and every release may be breaking. It is also not tuned for performance as of yet as we are still focusing on capability.
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
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @solidjs/signals
11
+ # or
12
+ pnpm add @solidjs/signals
13
+ ```
14
+
15
+ ## Overview
16
+
17
+ `@solidjs/signals` is a push-pull hybrid reactive system. Signals hold values, computeds derive from them, and effects run side effects — all connected through an automatic dependency graph. Updates are **batched** and flushed asynchronously via microtask, giving you consistent state without glitches.
18
+
19
+ ```typescript
20
+ import { createEffect, createMemo, createRoot, createSignal, flush } from "@solidjs/signals";
21
+
22
+ createRoot(() => {
23
+ const [count, setCount] = createSignal(0);
24
+ const doubled = createMemo(() => count() * 2);
25
+
26
+ createEffect(
27
+ () => doubled(),
28
+ value => {
29
+ console.log("Doubled:", value);
30
+ }
31
+ );
32
+
33
+ setCount(5);
34
+ flush(); // "Doubled: 10"
35
+ });
36
+ ```
37
+
38
+ ### Batched Updates
39
+
40
+ Signal writes are batched — reads after a write won't reflect the new value until `flush()` runs. This prevents glitches and unnecessary recomputation.
41
+
42
+ ```typescript
43
+ const [a, setA] = createSignal(1);
44
+ const [b, setB] = createSignal(2);
45
+
46
+ setA(10);
47
+ setB(20);
48
+ // Neither has updated yet — both writes are batched
49
+ flush(); // Now both update and downstream effects run once
50
+ ```
51
+
52
+ ## Core Primitives
53
+
54
+ ### Signals
55
+
56
+ ```typescript
57
+ const [value, setValue] = createSignal(initialValue, options?);
58
+ ```
59
+
60
+ Reactive state with a getter/setter pair. Supports custom equality via `options.equals`.
61
+
62
+ ### Memos
63
+
64
+ ```typescript
65
+ const derived = createMemo(() => expensive(signal()));
66
+ ```
67
+
68
+ Read-only derived values that cache their result and only recompute when dependencies change. Supports async compute functions — return a `Promise` or `AsyncIterable` and downstream consumers will wait automatically.
69
+
70
+ ### Effects
71
+
72
+ ```typescript
73
+ // Two-phase: compute tracks dependencies, effect runs side effects
74
+ createEffect(
75
+ () => count(),
76
+ value => {
77
+ console.log(value);
78
+ }
79
+ );
80
+
81
+ // Render-phase effect (runs before user effects)
82
+ createRenderEffect(
83
+ () => count(),
84
+ value => {
85
+ updateDOM(value);
86
+ }
87
+ );
88
+ ```
89
+
90
+ Effects split tracking from execution. `createEffect` and `createRenderEffect` take a compute function (for tracking) and an effect function (for side effects).
91
+
92
+ ### Writable Memos
93
+
94
+ Pass a function to `createSignal` to get a writable derived value — a memo you can also set:
95
+
96
+ ```typescript
97
+ const [value, setValue] = createSignal(prev => transform(source(), prev), initialValue);
98
+ ```
99
+
100
+ ## Async
101
+
102
+ Computeds can return promises or async iterables. The reactive graph handles this automatically — previous values are held in place until the async work resolves, so downstream consumers never see an inconsistent state.
103
+
104
+ ```typescript
105
+ const data = createMemo(async () => {
106
+ const response = await fetch(`/api/items?q=${query()}`);
107
+ return response.json();
108
+ });
109
+
110
+ // Check async state
111
+ isPending(data); // true while loading
112
+ latest(data); // last resolved value
113
+ ```
114
+
115
+ Use `action()` to coordinate async workflows with the reactive graph:
116
+
117
+ ```typescript
118
+ const save = action(function* (item) {
119
+ yield fetch("/api/save", { method: "POST", body: JSON.stringify(item) });
120
+ });
121
+ ```
122
+
123
+ ## Optimistic Updates
124
+
125
+ Optimistic signals show an immediate value while async work is pending, then automatically revert when it settles:
126
+
127
+ ```typescript
128
+ const [optimisticCount, setOptimisticCount] = createOptimistic(0);
129
+
130
+ // Immediate UI update — reverts when the async work resolves
131
+ setOptimisticCount(count + 1);
132
+ ```
133
+
134
+ Also available for stores via `createOptimisticStore()`.
135
+
136
+ ## Stores
137
+
138
+ Proxy-based deeply reactive objects with per-property tracking:
139
+
140
+ ```typescript
141
+ import { createStore, reconcile } from "@solidjs/signals";
142
+
143
+ const [store, setStore] = createStore({ todos: [], filter: "all" });
144
+
145
+ // Setter takes a mutating callback — mutations are intercepted by the proxy
146
+ setStore(s => {
147
+ s.filter = "active";
148
+ });
149
+ setStore(s => {
150
+ s.todos.push({ text: "New", done: false });
151
+ });
152
+ setStore(s => {
153
+ s.todos[0].done = true;
154
+ });
155
+
156
+ // Reconcile from server data
157
+ setStore(s => {
158
+ reconcile(serverTodos, "id")(s.todos);
159
+ });
160
+ ```
161
+
162
+ ### Projections
163
+
164
+ Derived stores that transform data reactively:
165
+
166
+ ```typescript
167
+ import { createProjection } from "@solidjs/signals";
168
+
169
+ const filtered = createProjection(
170
+ draft => {
171
+ draft.items = store.todos.filter(t => !t.done);
172
+ },
173
+ { items: [] }
174
+ );
175
+ ```
176
+
177
+ ## Boundaries
178
+
179
+ Intercept async loading and error states in the reactive graph:
180
+
181
+ ```typescript
182
+ import { createErrorBoundary, createLoadBoundary } from "@solidjs/signals";
183
+
184
+ createErrorBoundary(
185
+ () => riskyComputation(),
186
+ (error, reset) => handleError(error)
187
+ );
188
+
189
+ createLoadBoundary(
190
+ () => asyncContent(),
191
+ () => showFallback()
192
+ );
193
+ ```
194
+
195
+ ## Ownership & Context
196
+
197
+ All reactive nodes exist within an **owner** tree that handles disposal and context propagation:
198
+
199
+ ```typescript
200
+ import { createContext, createRoot, getContext, onCleanup, setContext } from "@solidjs/signals";
201
+
202
+ const ThemeContext = createContext("light");
203
+
204
+ createRoot(dispose => {
205
+ setContext(ThemeContext, "dark");
206
+
207
+ createEffect(
208
+ () => getContext(ThemeContext),
209
+ theme => {
210
+ console.log("Theme:", theme);
211
+ }
212
+ );
213
+
214
+ onCleanup(() => console.log("Disposed"));
215
+
216
+ // Call dispose() to tear down the tree
217
+ });
218
+ ```
219
+
220
+ ## Utilities
221
+
222
+ | Function | Description |
223
+ | ------------------------ | ------------------------------------------------------------------ |
224
+ | `flush()` | Process all pending updates |
225
+ | `untrack(fn)` | Run `fn` without tracking dependencies |
226
+ | `isPending(accessor)` | Check if an async accessor is loading |
227
+ | `latest(accessor)` | Get the last resolved value of an async accessor |
228
+ | `refresh(accessor)` | Re-trigger an async computation |
229
+ | `isRefreshing(accessor)` | Check if an async accessor is refreshing |
230
+ | `resolve(fn)` | Returns a promise that resolves when a reactive expression settles |
231
+ | `mapArray(list, mapFn)` | Reactive array mapping with keyed reconciliation |
232
+ | `repeat(count, mapFn)` | Reactive repeat based on a reactive count |
233
+ | `onSettled(fn)` | Run a callback after the current flush cycle completes |
234
+ | `snapshot(store)` | Returns a non-reactive copy of a store, preserving unmodified references |
235
+ | `reconcile(value, key)` | Returns a diffing function for updating stores from new data |
236
+ | `merge(...sources)` | Reactively merges multiple objects/stores, last source wins |
237
+ | `omit(props, ...keys)` | Creates a reactive view of an object with specified keys removed |
238
+ | `deep(store)` | Tracks all nested changes on a store |
239
+ | `storePath(...path)` | Path-based setter for stores as an alternative to mutating callbacks |
240
+
241
+ ## Development
242
+
243
+ ```bash
244
+ 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
251
+ ```
252
+
253
+ ## License
254
+
255
+ MIT
package/dist/dev.js CHANGED
@@ -393,7 +393,7 @@ function finalizePureQueue(completingTransition = null, incomplete = false) {
393
393
  n._pendingValue = NOT_PENDING;
394
394
  if (n._type && n._type !== EFFECT_TRACKED) n._modified = true;
395
395
  }
396
- n._statusFlags &= ~STATUS_UNINITIALIZED;
396
+ if (!(n._statusFlags & STATUS_PENDING)) n._statusFlags &= ~STATUS_UNINITIALIZED;
397
397
  if (n._fn) GlobalQueue._dispose(n, false, true);
398
398
  }
399
399
  pendingNodes.length = 0;
@@ -1112,6 +1112,11 @@ function recompute(el, create = false) {
1112
1112
  let oldHeight = el._height;
1113
1113
  let prevTracking = tracking;
1114
1114
  let prevLane = currentOptimisticLane;
1115
+ let prevStrictRead = false;
1116
+ {
1117
+ prevStrictRead = strictRead;
1118
+ strictRead = false;
1119
+ }
1115
1120
  tracking = true;
1116
1121
  if (isOptimisticDirty) {
1117
1122
  const lane = resolveLane(el);
@@ -1143,6 +1148,7 @@ function recompute(el, create = false) {
1143
1148
  );
1144
1149
  } finally {
1145
1150
  tracking = prevTracking;
1151
+ strictRead = prevStrictRead;
1146
1152
  el._flags = REACTIVE_NONE | (create ? el._flags & REACTIVE_SNAPSHOT_STALE : 0);
1147
1153
  context = oldcontext;
1148
1154
  }
@@ -1374,10 +1380,16 @@ function read(el) {
1374
1380
  el._flags &= ~REACTIVE_LAZY;
1375
1381
  recompute(el, true);
1376
1382
  }
1383
+ const owner = el._firewall || el;
1384
+ if (strictRead && owner._statusFlags & STATUS_PENDING) {
1385
+ throw new Error(
1386
+ `Reading a pending async value in ${strictRead}. ` +
1387
+ `Async values must be read within a tracking scope (JSX, computations, effects).`
1388
+ );
1389
+ }
1377
1390
  if (c && tracking) {
1378
1391
  if (el._fn && el._flags & REACTIVE_DISPOSED) recompute(el);
1379
1392
  link(el, c);
1380
- const owner = el._firewall || el;
1381
1393
  if (owner._fn) {
1382
1394
  const isZombie = el._flags & REACTIVE_ZOMBIE;
1383
1395
  if (owner._height >= (isZombie ? zombieQueue._min : dirtyQueue._min)) {
@@ -1391,25 +1403,21 @@ function read(el) {
1391
1403
  }
1392
1404
  }
1393
1405
  }
1394
- const asyncCompute = el._firewall || el;
1395
- if (asyncCompute._statusFlags & STATUS_PENDING) {
1396
- if (
1397
- c &&
1398
- !(stale && asyncCompute._transition && activeTransition !== asyncCompute._transition)
1399
- ) {
1406
+ if (owner._statusFlags & STATUS_PENDING) {
1407
+ if (c && !(stale && owner._transition && activeTransition !== owner._transition)) {
1400
1408
  if (currentOptimisticLane) {
1401
- const pendingLane = asyncCompute._optimisticLane;
1409
+ const pendingLane = owner._optimisticLane;
1402
1410
  const lane = findLane(currentOptimisticLane);
1403
- if (pendingLane && findLane(pendingLane) === lane && !hasActiveOverride(asyncCompute)) {
1411
+ if (pendingLane && findLane(pendingLane) === lane && !hasActiveOverride(owner)) {
1404
1412
  if (!tracking) link(el, c);
1405
- throw asyncCompute._error;
1413
+ throw owner._error;
1406
1414
  }
1407
1415
  } else {
1408
1416
  if (!tracking) link(el, c);
1409
- throw asyncCompute._error;
1417
+ throw owner._error;
1410
1418
  }
1411
- } else if (!c && asyncCompute._statusFlags & STATUS_UNINITIALIZED) {
1412
- throw asyncCompute._error;
1419
+ } else if (!c && owner._statusFlags & STATUS_UNINITIALIZED) {
1420
+ throw owner._error;
1413
1421
  }
1414
1422
  }
1415
1423
  if (el._fn && el._statusFlags & STATUS_ERROR) {
@@ -1429,7 +1437,8 @@ function read(el) {
1429
1437
  }
1430
1438
  if (strictRead && !tracking)
1431
1439
  console.warn(
1432
- `Untracked reactive read in ${strictRead}. This value won't update use untrack() if intentional.`
1440
+ `Reactive value read at the top level of ${strictRead} will not update. ` +
1441
+ `Move it into a tracking scope (JSX, computations, effects).`
1433
1442
  );
1434
1443
  return !c ||
1435
1444
  currentOptimisticLane !== null ||
@@ -1450,7 +1459,8 @@ function setSignal(el, v) {
1450
1459
  ? el._value
1451
1460
  : el._pendingValue;
1452
1461
  if (typeof v === "function") v = v(currentValue);
1453
- const valueChanged = !el._equals || !el._equals(currentValue, v);
1462
+ const valueChanged =
1463
+ !el._equals || !el._equals(currentValue, v) || !!(el._statusFlags & STATUS_UNINITIALIZED);
1454
1464
  if (!valueChanged) {
1455
1465
  if (isOptimistic && el._pendingValue !== NOT_PENDING && el._fn) {
1456
1466
  insertSubs(el, true);
@@ -2148,7 +2158,8 @@ const storeTraps = {
2148
2158
  }
2149
2159
  if (strictRead && !tracking && typeof property === "string")
2150
2160
  console.warn(
2151
- `Untracked reactive read in ${strictRead}. This value won't update use untrack() if intentional.`
2161
+ `Reactive value read at the top level of ${strictRead} will not update. ` +
2162
+ `Move it into a tracking scope (JSX, computations, effects).`
2152
2163
  );
2153
2164
  return isWrappable(value) ? wrap(value, target) : value;
2154
2165
  },
package/dist/node.cjs CHANGED
@@ -386,7 +386,7 @@ function finalizePureQueue(e = null, t = false) {
386
386
  n.ce = S;
387
387
  if (n.oe && n.oe !== g) n.ue = true;
388
388
  }
389
- n.de &= ~p;
389
+ if (!(n.de & a)) n.de &= ~p;
390
390
  if (n.R) GlobalQueue.U(n, false, true);
391
391
  }
392
392
  t.length = 0;
@@ -1293,10 +1293,10 @@ function read(e) {
1293
1293
  e.m &= ~c;
1294
1294
  recompute(e, true);
1295
1295
  }
1296
+ const n = e.I || e;
1296
1297
  if (t && I) {
1297
1298
  if (e.R && e.m & u) recompute(e);
1298
1299
  link(e, t);
1299
- const n = e.I || e;
1300
1300
  if (n.R) {
1301
1301
  const r = e.m & o;
1302
1302
  if (n.o >= (r ? P.j : v.j)) {
@@ -1310,7 +1310,6 @@ function read(e) {
1310
1310
  }
1311
1311
  }
1312
1312
  }
1313
- const n = e.I || e;
1314
1313
  if (n.de & a) {
1315
1314
  if (t && !(R && n.ne && A !== n.ne)) {
1316
1315
  if (F) {
@@ -1350,7 +1349,7 @@ function setSignal(e, t) {
1350
1349
  const n = e.we && !E;
1351
1350
  const r = n ? e.ae : e.ce === S ? e.ae : e.ce;
1352
1351
  if (typeof t === "function") t = t(r);
1353
- const i = !e.be || !e.be(r, t);
1352
+ const i = !e.be || !e.be(r, t) || !!(e.de & p);
1354
1353
  if (!i) {
1355
1354
  if (n && e.ce !== S && e.R) {
1356
1355
  insertSubs(e, true);
package/dist/prod.js CHANGED
@@ -53,11 +53,11 @@ function actualInsertIntoHeap(e, t) {
53
53
  if (r === undefined) t.l[i] = e;
54
54
  else {
55
55
  const t = r.T;
56
- t.R = e;
56
+ t.S = e;
57
57
  e.T = t;
58
58
  r.T = e;
59
59
  }
60
- if (i > t.S) t.S = i;
60
+ if (i > t.R) t.R = i;
61
61
  }
62
62
  function insertIntoHeap(e, t) {
63
63
  let n = e.O;
@@ -80,21 +80,21 @@ function deleteFromHeap(e, t) {
80
80
  const i = e.o;
81
81
  if (e.T === e) t.l[i] = undefined;
82
82
  else {
83
- const n = e.R;
83
+ const n = e.S;
84
84
  const r = t.l[i];
85
85
  const s = n ?? r;
86
86
  if (e === r) t.l[i] = n;
87
- else e.T.R = n;
87
+ else e.T.S = n;
88
88
  s.T = e.T;
89
89
  }
90
90
  e.T = e;
91
- e.R = undefined;
91
+ e.S = undefined;
92
92
  }
93
93
  function markHeap(e) {
94
94
  if (e._) return;
95
95
  e._ = true;
96
- for (let t = 0; t <= e.S; t++) {
97
- for (let n = e.l[t]; n !== undefined; n = n.R) {
96
+ for (let t = 0; t <= e.R; t++) {
97
+ for (let n = e.l[t]; n !== undefined; n = n.S) {
98
98
  if (n.O & REACTIVE_IN_HEAP) markNode(n);
99
99
  }
100
100
  }
@@ -116,20 +116,20 @@ function markNode(e, t = REACTIVE_DIRTY) {
116
116
  }
117
117
  function runHeap(e, t) {
118
118
  e._ = false;
119
- for (e.C = 0; e.C <= e.S; e.C++) {
120
- let n = e.l[e.C];
119
+ for (e.N = 0; e.N <= e.R; e.N++) {
120
+ let n = e.l[e.N];
121
121
  while (n !== undefined) {
122
122
  if (n.O & REACTIVE_IN_HEAP) t(n);
123
123
  else adjustHeight(n, e);
124
- n = e.l[e.C];
124
+ n = e.l[e.N];
125
125
  }
126
126
  }
127
- e.S = 0;
127
+ e.R = 0;
128
128
  }
129
129
  function adjustHeight(e, t) {
130
130
  deleteFromHeap(e, t);
131
131
  let n = e.o;
132
- for (let t = e.N; t; t = t.D) {
132
+ for (let t = e.C; t; t = t.D) {
133
133
  const e = t.V;
134
134
  const i = e.m || e;
135
135
  if (i.L && i.o >= n) n = i.o + 1;
@@ -142,8 +142,8 @@ function adjustHeight(e, t) {
142
142
  }
143
143
  }
144
144
  const transitions = new Set();
145
- const dirtyQueue = { l: new Array(2e3).fill(undefined), _: false, C: 0, S: 0 };
146
- const zombieQueue = { l: new Array(2e3).fill(undefined), _: false, C: 0, S: 0 };
145
+ const dirtyQueue = { l: new Array(2e3).fill(undefined), _: false, N: 0, R: 0 };
146
+ const zombieQueue = { l: new Array(2e3).fill(undefined), _: false, N: 0, R: 0 };
147
147
  let clock = 0;
148
148
  let activeTransition = null;
149
149
  let scheduled = false;
@@ -168,17 +168,17 @@ function schedule() {
168
168
  }
169
169
  class Queue {
170
170
  i = null;
171
- M = [[], []];
172
- G = [];
171
+ G = [[], []];
172
+ M = [];
173
173
  created = clock;
174
174
  addChild(e) {
175
- this.G.push(e);
175
+ this.M.push(e);
176
176
  e.i = this;
177
177
  }
178
178
  removeChild(e) {
179
- const t = this.G.indexOf(e);
179
+ const t = this.M.indexOf(e);
180
180
  if (t >= 0) {
181
- this.G.splice(t, 1);
181
+ this.M.splice(t, 1);
182
182
  e.i = null;
183
183
  }
184
184
  }
@@ -187,12 +187,12 @@ class Queue {
187
187
  return false;
188
188
  }
189
189
  run(e) {
190
- if (this.M[e - 1].length) {
191
- const t = this.M[e - 1];
192
- this.M[e - 1] = [];
190
+ if (this.G[e - 1].length) {
191
+ const t = this.G[e - 1];
192
+ this.G[e - 1] = [];
193
193
  runQueue(t, e);
194
194
  }
195
- for (let t = 0; t < this.G.length; t++) this.G[t].run?.(e);
195
+ for (let t = 0; t < this.M.length; t++) this.M[t].run?.(e);
196
196
  }
197
197
  enqueue(e, t) {
198
198
  if (e) {
@@ -200,31 +200,31 @@ class Queue {
200
200
  const n = findLane(currentOptimisticLane);
201
201
  n.W[e - 1].push(t);
202
202
  } else {
203
- this.M[e - 1].push(t);
203
+ this.G[e - 1].push(t);
204
204
  }
205
205
  }
206
206
  schedule();
207
207
  }
208
208
  stashQueues(e) {
209
- e.M[0].push(...this.M[0]);
210
- e.M[1].push(...this.M[1]);
211
- this.M = [[], []];
212
- for (let t = 0; t < this.G.length; t++) {
213
- let n = this.G[t];
214
- let i = e.G[t];
209
+ e.G[0].push(...this.G[0]);
210
+ e.G[1].push(...this.G[1]);
211
+ this.G = [[], []];
212
+ for (let t = 0; t < this.M.length; t++) {
213
+ let n = this.M[t];
214
+ let i = e.M[t];
215
215
  if (!i) {
216
- i = { M: [[], []], G: [] };
217
- e.G[t] = i;
216
+ i = { G: [[], []], M: [] };
217
+ e.M[t] = i;
218
218
  }
219
219
  n.stashQueues(i);
220
220
  }
221
221
  }
222
222
  restoreQueues(e) {
223
- this.M[0].push(...e.M[0]);
224
- this.M[1].push(...e.M[1]);
225
- for (let t = 0; t < e.G.length; t++) {
226
- const n = e.G[t];
227
- let i = this.G[t];
223
+ this.G[0].push(...e.G[0]);
224
+ this.G[1].push(...e.G[1]);
225
+ for (let t = 0; t < e.M.length; t++) {
226
+ const n = e.M[t];
227
+ let i = this.M[t];
228
228
  if (i) i.restoreQueues(n);
229
229
  }
230
230
  }
@@ -254,7 +254,7 @@ class GlobalQueue extends Queue {
254
254
  runLaneEffects(EFFECT_USER);
255
255
  this.stashQueues(activeTransition.B);
256
256
  clock++;
257
- scheduled = dirtyQueue.S >= dirtyQueue.C;
257
+ scheduled = dirtyQueue.R >= dirtyQueue.N;
258
258
  reassignPendingTransition(activeTransition.F);
259
259
  activeTransition = null;
260
260
  finalizePureQueue(null, true);
@@ -272,7 +272,7 @@ class GlobalQueue extends Queue {
272
272
  finalizePureQueue();
273
273
  }
274
274
  clock++;
275
- scheduled = dirtyQueue.S >= dirtyQueue.C;
275
+ scheduled = dirtyQueue.R >= dirtyQueue.N;
276
276
  runLaneEffects(EFFECT_RENDER);
277
277
  this.run(EFFECT_RENDER);
278
278
  runLaneEffects(EFFECT_USER);
@@ -306,7 +306,7 @@ class GlobalQueue extends Queue {
306
306
  $: [],
307
307
  j: new Set(),
308
308
  ee: [],
309
- B: { M: [[], []], G: [] },
309
+ B: { G: [[], []], M: [] },
310
310
  te: false
311
311
  };
312
312
  } else if (e) {
@@ -368,14 +368,14 @@ function insertSubs(e, t = false) {
368
368
  continue;
369
369
  }
370
370
  const s = r.h.O & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue;
371
- if (s.C > r.h.o) s.C = r.h.o;
371
+ if (s.N > r.h.o) s.N = r.h.o;
372
372
  insertIntoHeap(r.h, s);
373
373
  }
374
374
  }
375
375
  function finalizePureQueue(e = null, t = false) {
376
376
  let n = !t;
377
377
  if (!t) checkBoundaryChildren(globalQueue);
378
- if (dirtyQueue.S >= dirtyQueue.C) runHeap(dirtyQueue, GlobalQueue.K);
378
+ if (dirtyQueue.R >= dirtyQueue.N) runHeap(dirtyQueue, GlobalQueue.K);
379
379
  if (n) {
380
380
  const t = globalQueue.F;
381
381
  for (let e = 0; e < t.length; e++) {
@@ -385,7 +385,7 @@ function finalizePureQueue(e = null, t = false) {
385
385
  n.ae = NOT_PENDING;
386
386
  if (n.oe && n.oe !== EFFECT_TRACKED) n.ue = true;
387
387
  }
388
- n.Ee &= ~STATUS_UNINITIALIZED;
388
+ if (!(n.Ee & STATUS_PENDING)) n.Ee &= ~STATUS_UNINITIALIZED;
389
389
  if (n.L) GlobalQueue.Y(n, false, true);
390
390
  }
391
391
  t.length = 0;
@@ -427,7 +427,7 @@ function finalizePureQueue(e = null, t = false) {
427
427
  }
428
428
  }
429
429
  function checkBoundaryChildren(e) {
430
- for (const t of e.G) {
430
+ for (const t of e.M) {
431
431
  t.checkSources?.();
432
432
  checkBoundaryChildren(t);
433
433
  }
@@ -489,10 +489,10 @@ function getOrCreateLane(e) {
489
489
  }
490
490
  const n = e.de;
491
491
  const i = n?.ie ? findLane(n.ie) : null;
492
- t = { Te: e, U: new Set(), W: [[], []], k: null, ne: activeTransition, Re: i };
492
+ t = { Te: e, U: new Set(), W: [[], []], k: null, ne: activeTransition, Se: i };
493
493
  signalLanes.set(e, t);
494
494
  activeLanes.add(t);
495
- e.Se = e.Oe || 0;
495
+ e.Re = e.Oe || 0;
496
496
  return t;
497
497
  }
498
498
  function findLane(e) {
@@ -531,9 +531,9 @@ function assignOrMergeLane(e, t) {
531
531
  const r = findLane(i);
532
532
  if (activeLanes.has(r)) {
533
533
  if (r !== n && !hasActiveOverride(e)) {
534
- if (n.Re && findLane(n.Re) === r) {
534
+ if (n.Se && findLane(n.Se) === r) {
535
535
  e.ie = t;
536
- } else if (r.Re && findLane(r.Re) === n);
536
+ } else if (r.Se && findLane(r.Se) === n);
537
537
  else mergeLanes(n, r);
538
538
  }
539
539
  return;
@@ -704,24 +704,24 @@ function unlinkSubs(e) {
704
704
  const i = e.p;
705
705
  const r = e.Pe;
706
706
  if (i !== null) i.Pe = r;
707
- else t.ge = r;
707
+ else t.Ne = r;
708
708
  if (r !== null) r.p = i;
709
709
  else {
710
710
  t.I = i;
711
711
  if (i === null) {
712
- t.Ce?.();
713
- t.L && !t.Ne && !(t.O & REACTIVE_ZOMBIE) && unobserved(t);
712
+ t.ge?.();
713
+ t.L && !t.Ce && !(t.O & REACTIVE_ZOMBIE) && unobserved(t);
714
714
  }
715
715
  }
716
716
  return n;
717
717
  }
718
718
  function unobserved(e) {
719
719
  deleteFromHeap(e, e.O & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
720
- let t = e.N;
720
+ let t = e.C;
721
721
  while (t !== null) {
722
722
  t = unlinkSubs(t);
723
723
  }
724
- e.N = null;
724
+ e.C = null;
725
725
  disposeChildren(e, true);
726
726
  }
727
727
  function link(e, t) {
@@ -730,24 +730,24 @@ function link(e, t) {
730
730
  let i = null;
731
731
  const r = t.O & REACTIVE_RECOMPUTING_DEPS;
732
732
  if (r) {
733
- i = n !== null ? n.D : t.N;
733
+ i = n !== null ? n.D : t.C;
734
734
  if (i !== null && i.V === e) {
735
735
  t.ye = i;
736
736
  return;
737
737
  }
738
738
  }
739
- const s = e.ge;
739
+ const s = e.Ne;
740
740
  if (s !== null && s.h === t && (!r || isValidLink(s, t))) return;
741
- const o = (t.ye = e.ge = { V: e, h: t, D: i, Pe: s, p: null });
741
+ const o = (t.ye = e.Ne = { V: e, h: t, D: i, Pe: s, p: null });
742
742
  if (n !== null) n.D = o;
743
- else t.N = o;
743
+ else t.C = o;
744
744
  if (s !== null) s.p = o;
745
745
  else e.I = o;
746
746
  }
747
747
  function isValidLink(e, t) {
748
748
  const n = t.ye;
749
749
  if (n !== null) {
750
- let i = t.N;
750
+ let i = t.C;
751
751
  do {
752
752
  if (i === e) return true;
753
753
  if (i === n) break;
@@ -770,11 +770,11 @@ function markDisposal(e) {
770
770
  }
771
771
  }
772
772
  function dispose(e) {
773
- let t = e.N || null;
773
+ let t = e.C || null;
774
774
  do {
775
775
  t = unlinkSubs(t);
776
776
  } while (t !== null);
777
- e.N = null;
777
+ e.C = null;
778
778
  e.ye = null;
779
779
  disposeChildren(e, true);
780
780
  }
@@ -784,14 +784,14 @@ function disposeChildren(e, t = false, n) {
784
784
  let i = n ? e.be : e.De;
785
785
  while (i) {
786
786
  const e = i.ve;
787
- if (i.N) {
787
+ if (i.C) {
788
788
  const e = i;
789
789
  deleteFromHeap(e, e.O & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
790
- let t = e.N;
790
+ let t = e.C;
791
791
  do {
792
792
  t = unlinkSubs(t);
793
793
  } while (t !== null);
794
- e.N = null;
794
+ e.C = null;
795
795
  e.ye = null;
796
796
  }
797
797
  disposeChildren(i, true);
@@ -1013,7 +1013,7 @@ function releaseSubtree(e) {
1013
1013
  if (e.O & REACTIVE_SNAPSHOT_STALE) {
1014
1014
  e.O &= ~REACTIVE_SNAPSHOT_STALE;
1015
1015
  e.O |= REACTIVE_DIRTY;
1016
- if (dirtyQueue.C > e.o) dirtyQueue.C = e.o;
1016
+ if (dirtyQueue.N > e.o) dirtyQueue.N = e.o;
1017
1017
  insertIntoHeap(e, dirtyQueue);
1018
1018
  }
1019
1019
  }
@@ -1095,13 +1095,13 @@ function recompute(e, t = false) {
1095
1095
  }
1096
1096
  if (!e.X) {
1097
1097
  const o = e.ye;
1098
- let l = o !== null ? o.D : e.N;
1098
+ let l = o !== null ? o.D : e.C;
1099
1099
  if (l !== null) {
1100
1100
  do {
1101
1101
  l = unlinkSubs(l);
1102
1102
  } while (l !== null);
1103
1103
  if (o !== null) o.D = null;
1104
- else e.N = null;
1104
+ else e.C = null;
1105
1105
  }
1106
1106
  const a = r ? e.fe : e.ae === NOT_PENDING ? e.fe : e.ae;
1107
1107
  const f = !e.pe || !e.pe(a, u);
@@ -1111,7 +1111,7 @@ function recompute(e, t = false) {
1111
1111
  else e.ae = u;
1112
1112
  if (r && !i && s) {
1113
1113
  const t = e.Oe || 0;
1114
- const n = e.Se || 0;
1114
+ const n = e.Re || 0;
1115
1115
  if (t <= n) e.fe = u;
1116
1116
  }
1117
1117
  if (!r || i || e.fe !== o) {
@@ -1131,7 +1131,7 @@ function recompute(e, t = false) {
1131
1131
  }
1132
1132
  function updateIfNecessary(e) {
1133
1133
  if (e.O & REACTIVE_CHECK) {
1134
- for (let t = e.N; t; t = t.D) {
1134
+ for (let t = e.C; t; t = t.D) {
1135
1135
  const n = t.V;
1136
1136
  const i = n.m || n;
1137
1137
  if (i.L) {
@@ -1153,8 +1153,8 @@ function computed(e, t, n) {
1153
1153
  id: n?.id ?? (i ? context?.id : context?.id != null ? getNextChildId(context) : undefined),
1154
1154
  Le: i || undefined,
1155
1155
  pe: n?.equals != null ? n.equals : isEqual,
1156
- Me: !!n?.pureWrite,
1157
- Ce: n?.unobserved,
1156
+ Ge: !!n?.pureWrite,
1157
+ ge: n?.unobserved,
1158
1158
  me: null,
1159
1159
  ce: context?.ce ?? globalQueue,
1160
1160
  ke: context?.ke ?? defaultContext,
@@ -1163,12 +1163,12 @@ function computed(e, t, n) {
1163
1163
  fe: t,
1164
1164
  o: 0,
1165
1165
  A: null,
1166
- R: undefined,
1166
+ S: undefined,
1167
1167
  T: null,
1168
- N: null,
1168
+ C: null,
1169
1169
  ye: null,
1170
1170
  I: null,
1171
- ge: null,
1171
+ Ne: null,
1172
1172
  i: context,
1173
1173
  ve: null,
1174
1174
  De: null,
@@ -1206,18 +1206,18 @@ function computed(e, t, n) {
1206
1206
  function signal(e, t, n = null) {
1207
1207
  const i = {
1208
1208
  pe: t?.equals != null ? t.equals : isEqual,
1209
- Me: !!t?.pureWrite,
1210
- Ce: t?.unobserved,
1209
+ Ge: !!t?.pureWrite,
1210
+ ge: t?.unobserved,
1211
1211
  fe: e,
1212
1212
  I: null,
1213
- ge: null,
1213
+ Ne: null,
1214
1214
  J: clock,
1215
1215
  m: n,
1216
1216
  P: n?.A || null,
1217
1217
  ae: NOT_PENDING
1218
1218
  };
1219
1219
  n && (n.A = i);
1220
- if (snapshotCaptureActive && !i.Me) {
1220
+ if (snapshotCaptureActive && !i.Ge) {
1221
1221
  i.re = e === undefined ? NO_SNAPSHOT : e;
1222
1222
  snapshotSources.add(i);
1223
1223
  }
@@ -1293,13 +1293,13 @@ function read(e) {
1293
1293
  e.O &= ~REACTIVE_LAZY;
1294
1294
  recompute(e, true);
1295
1295
  }
1296
+ const n = e.m || e;
1296
1297
  if (t && tracking) {
1297
1298
  if (e.L && e.O & REACTIVE_DISPOSED) recompute(e);
1298
1299
  link(e, t);
1299
- const n = e.m || e;
1300
1300
  if (n.L) {
1301
1301
  const i = e.O & REACTIVE_ZOMBIE;
1302
- if (n.o >= (i ? zombieQueue.C : dirtyQueue.C)) {
1302
+ if (n.o >= (i ? zombieQueue.N : dirtyQueue.N)) {
1303
1303
  markNode(t);
1304
1304
  markHeap(i ? zombieQueue : dirtyQueue);
1305
1305
  updateIfNecessary(n);
@@ -1310,7 +1310,6 @@ function read(e) {
1310
1310
  }
1311
1311
  }
1312
1312
  }
1313
- const n = e.m || e;
1314
1313
  if (n.Ee & STATUS_PENDING) {
1315
1314
  if (t && !(stale && n.ne && activeTransition !== n.ne)) {
1316
1315
  if (currentOptimisticLane) {
@@ -1355,7 +1354,7 @@ function setSignal(e, t) {
1355
1354
  const n = e._e && !projectionWriteActive;
1356
1355
  const i = n ? e.fe : e.ae === NOT_PENDING ? e.fe : e.ae;
1357
1356
  if (typeof t === "function") t = t(i);
1358
- const r = !e.pe || !e.pe(i, t);
1357
+ const r = !e.pe || !e.pe(i, t) || !!(e.Ee & STATUS_UNINITIALIZED);
1359
1358
  if (!r) {
1360
1359
  if (n && e.ae !== NOT_PENDING && e.L) {
1361
1360
  insertSubs(e, true);
@@ -1404,14 +1403,14 @@ function runWithOwner(e, t) {
1404
1403
  }
1405
1404
  }
1406
1405
  function getPendingSignal(e) {
1407
- if (!e.Ge) {
1408
- e.Ge = optimisticSignal(false, { pureWrite: true });
1406
+ if (!e.Me) {
1407
+ e.Me = optimisticSignal(false, { pureWrite: true });
1409
1408
  if (e.de) {
1410
- e.Ge.de = e;
1409
+ e.Me.de = e;
1411
1410
  }
1412
- if (computePendingState(e)) setSignal(e.Ge, true);
1411
+ if (computePendingState(e)) setSignal(e.Me, true);
1413
1412
  }
1414
- return e.Ge;
1413
+ return e.Me;
1415
1414
  }
1416
1415
  function computePendingState(e) {
1417
1416
  const t = e;
@@ -1427,9 +1426,9 @@ function computePendingState(e) {
1427
1426
  return !!(t.Ee & STATUS_PENDING && !(t.Ee & STATUS_UNINITIALIZED));
1428
1427
  }
1429
1428
  function updatePendingSignal(e) {
1430
- if (e.Ge) {
1429
+ if (e.Me) {
1431
1430
  const t = computePendingState(e);
1432
- const n = e.Ge;
1431
+ const n = e.Me;
1433
1432
  setSignal(n, t);
1434
1433
  if (!t && n.ie) {
1435
1434
  const t = resolveLane(e);
@@ -1676,14 +1675,14 @@ function applyState(e, t, n, i) {
1676
1675
  let t = false;
1677
1676
  const l = getOverrideValue(s, o, c, "length", u);
1678
1677
  if (e.length && l && e[0] && n(e[0]) != null) {
1679
- let a, f, E, T, d, R, S, O;
1678
+ let a, f, E, T, d, S, R, O;
1680
1679
  for (
1681
1680
  E = 0, T = Math.min(l, e.length);
1682
1681
  E < T &&
1683
- ((R = getOverrideValue(s, o, c, E, u)) === e[E] || (R && e[E] && n(R) === n(e[E])));
1682
+ ((S = getOverrideValue(s, o, c, E, u)) === e[E] || (S && e[E] && n(S) === n(e[E])));
1684
1683
  E++
1685
1684
  ) {
1686
- applyState(e[E], wrap(R, r), n, i);
1685
+ applyState(e[E], wrap(S, r), n, i);
1687
1686
  }
1688
1687
  const _ = new Array(e.length),
1689
1688
  I = new Map();
@@ -1691,10 +1690,10 @@ function applyState(e, t, n, i) {
1691
1690
  T = l - 1, d = e.length - 1;
1692
1691
  T >= E &&
1693
1692
  d >= E &&
1694
- ((R = getOverrideValue(s, o, c, T, u)) === e[d] || (R && e[d] && n(R) === n(e[d])));
1693
+ ((S = getOverrideValue(s, o, c, T, u)) === e[d] || (S && e[d] && n(S) === n(e[d])));
1695
1694
  T--, d--
1696
1695
  ) {
1697
- _[d] = R;
1696
+ _[d] = S;
1698
1697
  }
1699
1698
  if (E > d || E > T) {
1700
1699
  for (f = E; f <= d; f++) {
@@ -1711,21 +1710,21 @@ function applyState(e, t, n, i) {
1711
1710
  l !== e.length && r[STORE_NODE].length && setSignal(r[STORE_NODE].length, e.length);
1712
1711
  return;
1713
1712
  }
1714
- S = new Array(d + 1);
1713
+ R = new Array(d + 1);
1715
1714
  for (f = d; f >= E; f--) {
1716
- R = e[f];
1717
- O = R ? n(R) : R;
1715
+ S = e[f];
1716
+ O = S ? n(S) : S;
1718
1717
  a = I.get(O);
1719
- S[f] = a === undefined ? -1 : a;
1718
+ R[f] = a === undefined ? -1 : a;
1720
1719
  I.set(O, f);
1721
1720
  }
1722
1721
  for (a = E; a <= T; a++) {
1723
- R = getOverrideValue(s, o, c, a, u);
1724
- O = R ? n(R) : R;
1722
+ S = getOverrideValue(s, o, c, a, u);
1723
+ O = S ? n(S) : S;
1725
1724
  f = I.get(O);
1726
1725
  if (f !== undefined && f !== -1) {
1727
- _[f] = R;
1728
- f = S[f];
1726
+ _[f] = S;
1727
+ f = R[f];
1729
1728
  I.set(O, f);
1730
1729
  }
1731
1730
  }
@@ -1816,7 +1815,7 @@ function createProjectionInternal(e, t = {}, n) {
1816
1815
  r !== i && r !== undefined && reconcile(r, n?.key || "id", n?.all)(s);
1817
1816
  });
1818
1817
  });
1819
- i.Ne = true;
1818
+ i.Ce = true;
1820
1819
  return { store: s, node: i };
1821
1820
  }
1822
1821
  function createProjection(e, t = {}, n) {
@@ -2299,7 +2298,7 @@ function createOptimisticProjectionInternal(e, t = {}, n) {
2299
2298
  setProjectionWriteActive(false);
2300
2299
  }
2301
2300
  });
2302
- i.Ne = true;
2301
+ i.Ce = true;
2303
2302
  }
2304
2303
  return { store: s, node: i };
2305
2304
  }
@@ -2620,7 +2619,7 @@ function updateKeyedMap() {
2620
2619
  E = new Array(t),
2621
2620
  T = new Array(t),
2622
2621
  d = this.qe ? new Array(t) : undefined,
2623
- R = this.ze ? new Array(t) : undefined;
2622
+ S = this.ze ? new Array(t) : undefined;
2624
2623
  for (
2625
2624
  s = 0, o = Math.min(this.$e, t);
2626
2625
  s < o && (this.Ke[s] === e[s] || (this.qe && compare(this.Xe, this.Ke[s], e[s])));
@@ -2638,7 +2637,7 @@ function updateKeyedMap() {
2638
2637
  E[u] = this.Ze[o];
2639
2638
  T[u] = this.Be[o];
2640
2639
  d && (d[u] = this.qe[o]);
2641
- R && (R[u] = this.ze[o]);
2640
+ S && (S[u] = this.ze[o]);
2642
2641
  }
2643
2642
  a = new Map();
2644
2643
  f = new Array(u + 1);
@@ -2657,7 +2656,7 @@ function updateKeyedMap() {
2657
2656
  E[i] = this.Ze[n];
2658
2657
  T[i] = this.Be[n];
2659
2658
  d && (d[i] = this.qe[n]);
2660
- R && (R[i] = this.ze[n]);
2659
+ S && (S[i] = this.ze[n]);
2661
2660
  i = f[i];
2662
2661
  a.set(l, i);
2663
2662
  } else this.Be[n].dispose();
@@ -2670,8 +2669,8 @@ function updateKeyedMap() {
2670
2669
  this.qe[i] = d[i];
2671
2670
  setSignal(this.qe[i], e[i]);
2672
2671
  }
2673
- if (R) {
2674
- this.ze[i] = R[i];
2672
+ if (S) {
2673
+ this.ze[i] = S[i];
2675
2674
  setSignal(this.ze[i], i);
2676
2675
  }
2677
2676
  } else {
@@ -2757,7 +2756,7 @@ function boundaryComputed(e, t) {
2757
2756
  n.ce.notify(n, n.it, i, r);
2758
2757
  };
2759
2758
  n.it = t;
2760
- n.Ne = true;
2759
+ n.Ce = true;
2761
2760
  recompute(n, true);
2762
2761
  return n;
2763
2762
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidjs/signals",
3
- "version": "0.11.1",
3
+ "version": "0.11.3",
4
4
  "description": "SolidJS' standalone reactivity implementation",
5
5
  "author": "Ryan Carniato",
6
6
  "license": "MIT",