@solidjs/signals 2.0.0-beta.22 → 2.0.0-beta.24

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.
@@ -32,15 +32,15 @@ let pendingProbe = null;
32
32
  * Get or create the pending signal for a node (lazy).
33
33
  * Used by isPending() to track pending state reactively.
34
34
  */ function getPendingSignal(e) {
35
- if (!e.ge) {
35
+ if (!e.be) {
36
36
  // Start false, write true if pending - ensures reversion returns to false
37
- e.ge = optimisticSignal(false, {
37
+ e.be = optimisticSignal(false, {
38
38
  ownedWrite: true
39
39
  });
40
- e.ge.nn = e;
41
- if (computePendingState(e)) setSignal(e.ge, true);
40
+ e.be.nn = e;
41
+ if (computePendingState(e)) setSignal(e.be, true);
42
42
  }
43
- return e.ge;
43
+ return e.be;
44
44
  }
45
45
 
46
46
  function collectPendingSources(e) {
@@ -102,10 +102,10 @@ function collectPendingSources(e) {
102
102
 
103
103
  function quietPending(e) {
104
104
  if (e.oe) {
105
- for (const t of e.oe) if (!t.be) return false;
105
+ for (const t of e.oe) if (!t._e) return false;
106
106
  return true;
107
107
  }
108
- return e.be;
108
+ return e._e;
109
109
  }
110
110
 
111
111
  function newQuestionInFlight(e) {
@@ -129,27 +129,27 @@ function computePendingState(e) {
129
129
  return !!(n.se & REACTIVE_MANUAL_WRITE) || !n.Te && !(n.S & STATUS_PENDING) || !!(n.S & STATUS_PENDING) && quietPending(n);
130
130
  }
131
131
  if (e.Ne !== NOT_PENDING && !(t.S & STATUS_UNINITIALIZED)) {
132
- if (hasActiveOverride(e)) return !e.Pe || !e.Pe(e.Ne, unwrapOverride(e.Ee));
132
+ if (hasActiveOverride(e)) return !e.Re || !e.Re(e.Ne, unwrapOverride(e.Ee));
133
133
  return true;
134
134
  }
135
135
  return newQuestionInFlight(t);
136
136
  }
137
137
 
138
138
  function syncCompanions(e, t) {
139
- if (e.ge) updatePendingSignal(e);
140
- if (e.he) setSignal(e.he, t);
139
+ if (e.be) updatePendingSignal(e);
140
+ if (e.ge) setSignal(e.ge, t);
141
141
  }
142
142
 
143
143
  function updatePendingSignal(e) {
144
- if (e.ge) {
145
- setSignal(e.ge, computePendingState(e));
144
+ if (e.be) {
145
+ setSignal(e.be, computePendingState(e));
146
146
  }
147
- if (e.he) updatePendingSignal(e.he);
147
+ if (e.ge) updatePendingSignal(e.ge);
148
148
  }
149
149
 
150
150
  function updateChildCompanions(e) {
151
151
  for (let t = e.u; t !== null; t = t.fe) {
152
- if (t.ge || t.he) updatePendingSignal(t);
152
+ if (t.be || t.ge) updatePendingSignal(t);
153
153
  }
154
154
  }
155
155
 
@@ -167,7 +167,7 @@ function updateChildCompanions(e) {
167
167
  const visit = e => {
168
168
  if (i.has(e)) return;
169
169
  i.add(e);
170
- if (e.ge || e.he) n(e);
170
+ if (e.be || e.ge) n(e);
171
171
  for (let t = e.o; t !== null; t = t.ue) visit(t.le);
172
172
  for (let t = e.u ?? null; t !== null; t = t.fe) {
173
173
  visit(t);
@@ -177,20 +177,20 @@ function updateChildCompanions(e) {
177
177
  }
178
178
 
179
179
  function snapCompanionsToState(e) {
180
- const t = e.ge;
180
+ const t = e.be;
181
181
  if (t && (t.Ee === undefined || t.Ee === NOT_PENDING)) {
182
182
  const n = computePendingState(e);
183
- if (t.Re !== n || t.Ne !== NOT_PENDING) {
184
- t.Re = n;
183
+ if (t.Pe !== n || t.Ne !== NOT_PENDING) {
184
+ t.Pe = n;
185
185
  t.Ne = NOT_PENDING;
186
186
  t.ce = clock;
187
187
  insertSubs(t);
188
188
  schedule();
189
189
  }
190
190
  }
191
- const n = e.he;
191
+ const n = e.ge;
192
192
  if (n && !(n.se & REACTIVE_DISPOSED)) {
193
- if ((n.Ee === undefined || n.Ee === NOT_PENDING) && n.Ne === NOT_PENDING && !Object.is(n.Re, e.Re) && !(n.se & (REACTIVE_DIRTY | REACTIVE_CHECK))) {
193
+ if ((n.Ee === undefined || n.Ee === NOT_PENDING) && n.Ne === NOT_PENDING && !Object.is(n.Pe, e.Pe) && !(n.se & (REACTIVE_DIRTY | REACTIVE_CHECK))) {
194
194
  n.se |= REACTIVE_DIRTY;
195
195
  insertIntoHeap(n, queueFor(n));
196
196
  insertSubs(n);
@@ -201,7 +201,7 @@ function snapCompanionsToState(e) {
201
201
  }
202
202
 
203
203
  function getLatestValueComputed(e) {
204
- if (!e.he) {
204
+ if (!e.ge) {
205
205
  const t = latestReadActive;
206
206
  setLatestReadActive(false);
207
207
  const n = pendingCheckActive;
@@ -209,21 +209,21 @@ function getLatestValueComputed(e) {
209
209
  const i = context;
210
210
  setContextInternal(null);
211
211
  // Detach from owner so it isn't disposed with effects
212
- e.he = optimisticComputed(() => read(e));
213
- e.he.nn = e;
212
+ e.ge = optimisticComputed(() => read(e));
213
+ e.ge.nn = e;
214
214
  // Parent-child lane relationship
215
215
  setContextInternal(i);
216
216
  setPendingCheckActive(n);
217
217
  setLatestReadActive(t);
218
218
  }
219
- return e.he;
219
+ return e.ge;
220
220
  }
221
221
 
222
222
  /** The latest()-mode read path, installed as GlobalQueue._latestRead. */ function latestRead(e) {
223
223
  const t = getLatestValueComputed(e);
224
224
  const n = latestReadActive;
225
225
  setLatestReadActive(false);
226
- const i = e.Ee !== undefined && e.Ee !== NOT_PENDING ? unwrapOverride(e.Ee) : e.Re;
226
+ const i = e.Ee !== undefined && e.Ee !== NOT_PENDING ? unwrapOverride(e.Ee) : e.Pe;
227
227
  let r;
228
228
  try {
229
229
  // An untracked latest() read has no reading context, so read() never
@@ -232,7 +232,7 @@ function getLatestValueComputed(e) {
232
232
  // until the flush (#2922). Mirror the tracked-read pull here: mark the
233
233
  // queued staleness through the graph, then bring the shadow up to date.
234
234
  const e = queueFor(t);
235
- if (t.He >= e.Fe && !(t.se & (REACTIVE_DISPOSED | REACTIVE_ZOMBIE))) {
235
+ if (t.Fe >= e.He && !(t.se & (REACTIVE_DISPOSED | REACTIVE_ZOMBIE))) {
236
236
  markHeap(e);
237
237
  prepareComputed(t, true);
238
238
  }
@@ -279,9 +279,9 @@ function recordFreshRead(e, t) {
279
279
 
280
280
  function applyReask(e, t) {
281
281
  const n = !!(e.S & STATUS_PENDING);
282
- const i = t && !(n && !e.be);
283
- const r = n && e.be !== i;
284
- e.be = i;
282
+ const i = t && !(n && !e._e);
283
+ const r = n && e._e !== i;
284
+ e._e = i;
285
285
  return r;
286
286
  }
287
287
 
@@ -339,7 +339,7 @@ GlobalQueue.Ie = syncCompanions;
339
339
 
340
340
  GlobalQueue.ae = updatePendingSignal;
341
341
 
342
- GlobalQueue._e = updateChildCompanions;
342
+ GlobalQueue.he = updateChildCompanions;
343
343
 
344
344
  GlobalQueue.un = snapCompanionsToState;
345
345
 
package/dist/prod/map.js CHANGED
@@ -118,22 +118,29 @@ function updateKeyedMap() {
118
118
  this.Mt = t.slice(0);
119
119
  this.jt = s;
120
120
  } else {
121
- let o, c, a, f, u, p, w, l, d, O = new Array(s), m = new Array(s);
122
- r = this.Ut ? new Array(s) : undefined;
123
- n = this.$t ? new Array(s) : undefined;
121
+ let o, c, a, f, u, p, w, l, d;
124
122
  // skip common prefix
125
123
  for (o = 0, c = Math.min(this.jt, s); o < c && (this.Mt[o] === t[o] || this.Ut && compare(this.Gt, this.Mt[o], t[o])); o++) {
126
124
  if (this.Ut) setSignal(this.Ut[o], t[o]);
127
125
  }
128
- // common suffix
126
+ // skip common suffix — counted only; retained entries land in one pass
127
+ // at commit instead of being staged and copied twice
129
128
  for (c = this.jt - 1, a = s - 1; c >= o && a >= o && (this.Mt[c] === t[a] || this.Ut && compare(this.Gt, this.Mt[c], t[a])); c--,
130
- a--) {
131
- O[a] = this.xt[c];
132
- m[a] = this.Ft[c];
133
- r && (r[a] = this.Ut[c]);
134
- n && (n[a] = this.$t[c]);
129
+ a--) ;
130
+ // no structural change (every position matched in place at equal
131
+ // length — the common post-reconcile shape): keep the same mapped
132
+ // array identity so downstream consumers don't re-run at all
133
+ if (o === s && this.jt === s) {
134
+ this.Mt = t.slice(0);
135
+ return;
135
136
  }
136
- // 0) prepare a map of all indices in newItems, scanning backwards so we encounter them in natural order
137
+ const O = s - this.jt;
138
+ const m = new Array(s);
139
+ const _ = new Array(s);
140
+ r = this.Ut ? new Array(s) : undefined;
141
+ n = this.$t ? new Array(s) : undefined;
142
+ // 0) prepare a map of all indices in the changed window of newItems,
143
+ // scanning backwards so we encounter them in natural order
137
144
  p = new Map;
138
145
  w = new Array(a + 1);
139
146
  for (e = a; e >= o; e--) {
@@ -143,14 +150,16 @@ function updateKeyedMap() {
143
150
  w[e] = i === undefined ? -1 : i;
144
151
  p.set(u, e);
145
152
  }
146
- // 1) step through all old items and see if they can be found in the new set; if so, save them in a temp array and mark them moved; if not, queue them for disposal at commit
153
+ // 1) step through the old changed window and see if items can be found
154
+ // in the new set; if so, stage them at their new positions; if not,
155
+ // queue them for disposal at commit
147
156
  for (i = o; i <= c; i++) {
148
157
  f = this.Mt[i];
149
158
  u = this.Gt ? this.Gt(f) : f;
150
159
  e = p.get(u);
151
160
  if (e !== undefined && e !== -1) {
152
- O[e] = this.xt[i];
153
- m[e] = this.Ft[i];
161
+ m[e] = this.xt[i];
162
+ _[e] = this.Ft[i];
154
163
  r && (r[e] = this.Ut[i]);
155
164
  n && (n[e] = this.$t[i]);
156
165
  e = w[e];
@@ -159,33 +168,48 @@ function updateKeyedMap() {
159
168
  }
160
169
  // 2) create new rows into the temp arrays; an abort disposes only these
161
170
  try {
162
- for (e = o; e < s; e++) {
163
- if (e in O) continue;
164
- (d ??= []).push(m[e] = createOwner());
165
- O[e] = runWithOwner(m[e], h);
171
+ for (e = o; e <= a; e++) {
172
+ if (_[e] !== undefined) continue;
173
+ (d ??= []).push(_[e] = createOwner());
174
+ m[e] = runWithOwner(_[e], h);
166
175
  }
167
176
  } catch (t) {
168
177
  if (d) for (i = 0; i < d.length; i++) d[i].dispose();
169
178
  throw t;
170
179
  }
171
- // 3) commit: land positions, then dispose exited rows
172
- for (e = o; e < s; e++) {
173
- this.xt[e] = O[e];
174
- this.Ft[e] = m[e];
180
+ // 3) commit: land the retained prefix and suffix plus the staged window
181
+ // into the fresh arrays, swap them in (new identity for downstream
182
+ // change propagation), then dispose exited rows
183
+ for (i = 0; i < o; i++) {
184
+ m[i] = this.xt[i];
185
+ _[i] = this.Ft[i];
186
+ r && (r[i] = this.Ut[i]);
187
+ n && (n[i] = this.$t[i]);
188
+ }
189
+ for (e = o; e <= a; e++) {
190
+ if (r) setSignal(r[e], t[e]);
191
+ if (n) setSignal(n[e], e);
192
+ }
193
+ for (e = a + 1; e < s; e++) {
194
+ m[e] = this.xt[e - O];
195
+ _[e] = this.Ft[e - O];
175
196
  if (r) {
176
- this.Ut[e] = r[e];
177
- setSignal(this.Ut[e], t[e]);
197
+ r[e] = this.Ut[e - O];
198
+ setSignal(r[e], t[e]);
178
199
  }
179
200
  if (n) {
180
- this.$t[e] = n[e];
181
- setSignal(this.$t[e], e);
201
+ n[e] = this.$t[e - O];
202
+ if (O !== 0) setSignal(n[e], e);
182
203
  }
183
204
  }
184
- if (l) for (i = 0; i < l.length; i++) l[i].dispose();
185
- // 4) in case the new set is shorter than the old, set the length of the mapped array
186
- this.xt = this.xt.slice(0, this.jt = s);
187
- // 5) save a copy of the mapped items for the next update
205
+ this.xt = m;
206
+ this.Ft = _;
207
+ r && (this.Ut = r);
208
+ n && (this.$t = n);
209
+ this.jt = s;
210
+ // save a copy of the mapped items for the next update
188
211
  this.Mt = t.slice(0);
212
+ if (l) for (i = 0; i < l.length; i++) l[i].dispose();
189
213
  }
190
214
  });
191
215
  return this.xt;
@@ -16,17 +16,17 @@ import { runProjectionComputed } from "./projection.js";
16
16
 
17
17
  import { storeSetter, $TARGET, STORE_OPTIMISTIC_OVERRIDE, STORE_NODE, STORE_OPTIMISTIC_OWNERS, getOverlayLayer, STORE_VALUE, $DELETED, isWrappable, wrap, visibleNodeValue, $TRACK, notifySelf, STORE_WRAP, createStoreProxy, storeTraps, STORE_LOOKUP, STORE_OPTIMISTIC, STORE_FIREWALL } from "./store.js";
18
18
 
19
- function createOptimisticStore(e, t, r) {
19
+ function createOptimisticStore(e, t, i) {
20
20
  // Register clear function with scheduler; store nodes marked
21
21
  // STORE_OPTIMISTIC take the engine's write path, so install it before any
22
22
  // node can be created.
23
23
  installOptimisticEngine();
24
24
  GlobalQueue.Dt ||= clearOptimisticStores;
25
- const i = typeof e === "function";
26
- const o = i ? t : e;
27
- const n = i ? e : undefined;
25
+ const r = typeof e === "function";
26
+ const o = r ? t : e;
27
+ const n = r ? e : undefined;
28
28
  // Create optimistic projection store
29
- const {store: c} = createOptimisticProjectionInternal(n, o, r);
29
+ const {store: c} = createOptimisticProjectionInternal(n, o, i);
30
30
  return [ c, e => storeSetter(c, e) ];
31
31
  }
32
32
 
@@ -35,8 +35,8 @@ function createOptimisticStore(e, t, r) {
35
35
  // scheduler's flush tail carries only a size-guarded hook call. The
36
36
  // completing transition scopes each clear to its own layer keys (#2899).
37
37
  function clearOptimisticStores(e, t) {
38
- for (const r of e) {
39
- const e = r[$TARGET];
38
+ for (const i of e) {
39
+ const e = i[$TARGET];
40
40
  if (e?.[STORE_OPTIMISTIC_OVERRIDE]) clearOptimisticOverride(e, t);
41
41
  }
42
42
  e.clear();
@@ -54,9 +54,9 @@ function clearOptimisticStores(e, t) {
54
54
  * fresh authoritative data) consumes everything — the correction supersedes
55
55
  * every tentative layer.
56
56
  */ function clearOptimisticOverride(e, t) {
57
- const r = e[STORE_OPTIMISTIC_OVERRIDE];
58
- if (!r) return;
59
- const i = e[STORE_NODE];
57
+ const i = e[STORE_OPTIMISTIC_OVERRIDE];
58
+ if (!i) return;
59
+ const r = e[STORE_NODE];
60
60
  const o = e[STORE_OPTIMISTIC_OWNERS];
61
61
  const n = t !== undefined;
62
62
  let c = false;
@@ -66,7 +66,7 @@ function clearOptimisticStores(e, t) {
66
66
  const O = projectionWriteActive;
67
67
  setProjectionWriteActive(true);
68
68
  try {
69
- for (const O of Reflect.ownKeys(r)) {
69
+ for (const O of Reflect.ownKeys(i)) {
70
70
  if (n) {
71
71
  let e = o?.[O] ?? null;
72
72
  // Resolve merge chains (entangled actions settle as one); path-compress
@@ -83,37 +83,39 @@ function clearOptimisticStores(e, t) {
83
83
  }
84
84
  }
85
85
  }
86
- delete r[O];
86
+ delete i[O];
87
87
  if (o) delete o[O];
88
88
  c = true;
89
- const T = i?.[O];
89
+ const T = r?.[O];
90
90
  if (T) {
91
91
  // Clear lane association so effects go to regular queue
92
92
  T.je = undefined;
93
93
  // Re-read from base — this key left the optimistic layer above, so the
94
94
  // overlay resolves to STORE_OVERRIDE or STORE_VALUE.
95
95
  const t = getOverlayLayer(e, O);
96
- const r = t ? t[O] : e[STORE_VALUE][O];
97
- const i = r === $DELETED ? undefined : r;
98
- const o = isWrappable(i) ? wrap(i, e) : i;
96
+ const i = t ? t[O] : e[STORE_VALUE][O];
97
+ const r = i === $DELETED ? undefined : i;
98
+ const o = isWrappable(r) ? wrap(r, e) : r;
99
99
  const n = visibleNodeValue(T);
100
100
  T.Ee = NOT_PENDING;
101
101
  T.sn = null;
102
102
  T.Ne = NOT_PENDING;
103
- T.Re = o;
104
- if (!T.Pe || !T.Pe(n, o)) {
103
+ T.Pe = o;
104
+ if (!T.Re || !T.Re(n, o)) {
105
105
  insertSubs(T, true);
106
106
  schedule();
107
107
  }
108
108
  }
109
109
  }
110
110
  if (!s) {
111
- delete e[STORE_OPTIMISTIC_OVERRIDE];
112
- delete e[STORE_OPTIMISTIC_OWNERS];
111
+ // Assignment, not delete: StoreNode targets share one pre-initialized
112
+ // hidden class (see createStoreProxy) and a delete would demote it.
113
+ e[STORE_OPTIMISTIC_OVERRIDE] = undefined;
114
+ e[STORE_OPTIMISTIC_OWNERS] = undefined;
113
115
  }
114
116
  // Notify $TRACK
115
- if (c && i?.[$TRACK]) {
116
- i[$TRACK].je = undefined;
117
+ if (c && r?.[$TRACK]) {
118
+ r[$TRACK].je = undefined;
117
119
  notifySelf(e);
118
120
  }
119
121
  } finally {
@@ -121,8 +123,8 @@ function clearOptimisticStores(e, t) {
121
123
  }
122
124
  }
123
125
 
124
- function createOptimisticProjectionInternal(e, t, r) {
125
- let i;
126
+ function createOptimisticProjectionInternal(e, t, i) {
127
+ let r;
126
128
  const o = new WeakMap;
127
129
  const wrapper = e => {
128
130
  e[STORE_WRAP] = wrapProjection;
@@ -131,7 +133,7 @@ function createOptimisticProjectionInternal(e, t, r) {
131
133
  // Mark as optimistic store
132
134
  Object.defineProperty(e, STORE_FIREWALL, {
133
135
  get() {
134
- return i;
136
+ return r;
135
137
  },
136
138
  configurable: true
137
139
  });
@@ -165,19 +167,19 @@ function createOptimisticProjectionInternal(e, t, r) {
165
167
  setProjectionWriteActive(t);
166
168
  }
167
169
  };
168
- i = computed(() => {
170
+ r = computed(() => {
169
171
  setProjectionWriteActive(true);
170
172
  try {
171
- runProjectionComputed(n, e, r?.key || "id", wrapCommit, clearProjectionOverride);
173
+ runProjectionComputed(n, e, i?.key || "id", wrapCommit, clearProjectionOverride);
172
174
  } finally {
173
175
  setProjectionWriteActive(false);
174
176
  }
175
177
  }, undefined);
176
- i.T &= ~CONFIG_AUTO_DISPOSE;
178
+ r.T &= ~CONFIG_AUTO_DISPOSE;
177
179
  }
178
180
  return {
179
181
  store: n,
180
- node: i
182
+ node: r
181
183
  };
182
184
  }
183
185