@solidjs/signals 2.0.0-beta.19 → 2.0.0-beta.20
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/dist/dev.js +670 -371
- package/dist/node.cjs +1878 -1606
- package/dist/prod/affects.js +17 -21
- package/dist/prod/core/action.js +19 -6
- package/dist/prod/core/async.js +57 -71
- package/dist/prod/core/constants.js +15 -1
- package/dist/prod/core/core.js +39 -39
- package/dist/prod/core/effect.js +14 -14
- package/dist/prod/core/graph.js +1 -1
- package/dist/prod/core/heap.js +2 -2
- package/dist/prod/core/lanes.js +23 -13
- package/dist/prod/core/optimistic.js +107 -99
- package/dist/prod/core/owner.js +23 -23
- package/dist/prod/core/scheduler.js +180 -180
- package/dist/prod/core/verdict.js +12 -13
- package/dist/prod/map.js +196 -167
- package/dist/prod/signals.js +1 -1
- package/dist/prod/store/optimistic.js +103 -68
- package/dist/prod/store/reconcile.js +80 -46
- package/dist/prod/store/store.js +204 -73
- package/dist/prod/store/utils.js +61 -42
- package/dist/types/core/action.d.ts +19 -6
- package/dist/types/core/constants.d.ts +12 -0
- package/dist/types/core/dev.d.ts +7 -0
- package/dist/types/core/lanes.d.ts +2 -0
- package/dist/types/core/scheduler.d.ts +2 -6
- package/dist/types/core/types.d.ts +9 -1
- package/dist/types/store/store.d.ts +8 -2
- package/dist/types-cjs/core/action.d.cts +19 -6
- package/dist/types-cjs/core/constants.d.cts +12 -0
- package/dist/types-cjs/core/dev.d.cts +7 -0
- package/dist/types-cjs/core/lanes.d.cts +2 -0
- package/dist/types-cjs/core/scheduler.d.cts +2 -6
- package/dist/types-cjs/core/types.d.cts +9 -1
- package/dist/types-cjs/store/store.d.cts +8 -2
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@ import { computed } from "../core/core.js";
|
|
|
2
2
|
|
|
3
3
|
import { CONFIG_AUTO_DISPOSE, NOT_PENDING } from "../core/constants.js";
|
|
4
4
|
|
|
5
|
-
import { GlobalQueue, schedule,
|
|
5
|
+
import { GlobalQueue, schedule, currentTransition, insertSubs, setProjectionWriteActive, projectionWriteActive } from "../core/scheduler.js";
|
|
6
6
|
|
|
7
7
|
import "../core/invariants.js";
|
|
8
8
|
|
|
@@ -14,126 +14,161 @@ import { installOptimisticEngine } from "../core/optimistic.js";
|
|
|
14
14
|
|
|
15
15
|
import { runProjectionComputed } from "./projection.js";
|
|
16
16
|
|
|
17
|
-
import { storeSetter, $TARGET, STORE_OPTIMISTIC_OVERRIDE, STORE_NODE, getOverlayLayer, STORE_VALUE, $DELETED, isWrappable, wrap, visibleNodeValue, $TRACK, notifySelf, STORE_WRAP, createStoreProxy, storeTraps, STORE_LOOKUP, STORE_OPTIMISTIC, STORE_FIREWALL } from "./store.js";
|
|
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(
|
|
19
|
+
function createOptimisticStore(e, t, r) {
|
|
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
|
-
GlobalQueue.
|
|
25
|
-
const i = typeof
|
|
26
|
-
const o = i ?
|
|
27
|
-
const
|
|
24
|
+
GlobalQueue.Vt ||= clearOptimisticStores;
|
|
25
|
+
const i = typeof e === "function";
|
|
26
|
+
const o = i ? t : e;
|
|
27
|
+
const n = i ? e : undefined;
|
|
28
28
|
// Create optimistic projection store
|
|
29
|
-
const {store:
|
|
30
|
-
return [
|
|
29
|
+
const {store: c} = createOptimisticProjectionInternal(n, o, r);
|
|
30
|
+
return [ c, e => storeSetter(c, e) ];
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
// Clear the optimistic overrides of a settling batch of stores and notify
|
|
34
34
|
// signals. Owns the whole batch (iterate + clear + reschedule) so the
|
|
35
|
-
// scheduler's flush tail carries only a size-guarded hook call.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
// scheduler's flush tail carries only a size-guarded hook call. The
|
|
36
|
+
// completing transition scopes each clear to its own layer keys (#2899).
|
|
37
|
+
function clearOptimisticStores(e, t) {
|
|
38
|
+
for (const r of e) {
|
|
39
|
+
const e = r[$TARGET];
|
|
40
|
+
if (e?.[STORE_OPTIMISTIC_OVERRIDE]) clearOptimisticOverride(e, t);
|
|
40
41
|
}
|
|
41
|
-
|
|
42
|
+
e.clear();
|
|
42
43
|
schedule();
|
|
43
44
|
}
|
|
44
45
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Consume optimistic layer entries and reset their backing nodes to base.
|
|
48
|
+
* With `completing` (settle path, #2899) only entries the settling
|
|
49
|
+
* transaction owns are consumed — the layer is store-wide but concurrent
|
|
50
|
+
* actions revert independently, so keys stamped by a still-in-flight
|
|
51
|
+
* transition survive (node-level overrides already have this granularity via
|
|
52
|
+
* _optimisticNodes; this is the layer's half). `null` consumes ambient
|
|
53
|
+
* (transaction-less) entries at plain flush end. Omitted (projection landing:
|
|
54
|
+
* fresh authoritative data) consumes everything — the correction supersedes
|
|
55
|
+
* every tentative layer.
|
|
56
|
+
*/ function clearOptimisticOverride(e, t) {
|
|
57
|
+
const r = e[STORE_OPTIMISTIC_OVERRIDE];
|
|
58
|
+
if (!r) return;
|
|
59
|
+
const i = e[STORE_NODE];
|
|
60
|
+
const o = e[STORE_OPTIMISTIC_OWNERS];
|
|
61
|
+
const n = t !== undefined;
|
|
62
|
+
let c = false;
|
|
63
|
+
let s = false;
|
|
51
64
|
// Use projectionWriteActive to bypass optimistic signal behavior (no lane creation)
|
|
52
65
|
// This ensures reversion effects go to regular queues, not lane queues
|
|
53
|
-
const
|
|
66
|
+
const O = projectionWriteActive;
|
|
54
67
|
setProjectionWriteActive(true);
|
|
55
68
|
try {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
e.ge = NOT_PENDING;
|
|
71
|
-
e.Ue = s;
|
|
72
|
-
if (!e.Ge || !e.Ge(O, s)) {
|
|
73
|
-
insertSubs(e, true);
|
|
74
|
-
schedule();
|
|
69
|
+
for (const O of Reflect.ownKeys(r)) {
|
|
70
|
+
if (n) {
|
|
71
|
+
let e = o?.[O] ?? null;
|
|
72
|
+
// Resolve merge chains (entangled actions settle as one); path-compress
|
|
73
|
+
// so later keys skip the walk. A dead owner (`_done === true`) settled
|
|
74
|
+
// through some other path — never strand its entry. A null owner is an
|
|
75
|
+
// ambient write: its batch belongs to whichever transaction adopted it
|
|
76
|
+
// (initTransition mid-batch) or to the plain flush, so it clears on
|
|
77
|
+
// whichever clear call reaches this store first.
|
|
78
|
+
if (e) {
|
|
79
|
+
if (typeof e.cn === "object") e = o[O] = currentTransition(e);
|
|
80
|
+
if (e !== t && e.cn !== true) {
|
|
81
|
+
s = true;
|
|
82
|
+
continue;
|
|
75
83
|
}
|
|
76
84
|
}
|
|
77
85
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
86
|
+
delete r[O];
|
|
87
|
+
if (o) delete o[O];
|
|
88
|
+
c = true;
|
|
89
|
+
const T = i?.[O];
|
|
90
|
+
if (T) {
|
|
91
|
+
// Clear lane association so effects go to regular queue
|
|
92
|
+
T.Je = undefined;
|
|
93
|
+
// Re-read from base — this key left the optimistic layer above, so the
|
|
94
|
+
// overlay resolves to STORE_OVERRIDE or STORE_VALUE.
|
|
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;
|
|
99
|
+
const n = visibleNodeValue(T);
|
|
100
|
+
T.be = NOT_PENDING;
|
|
101
|
+
T.fn = null;
|
|
102
|
+
T.ge = NOT_PENDING;
|
|
103
|
+
T.Ue = o;
|
|
104
|
+
if (!T.Ge || !T.Ge(n, o)) {
|
|
105
|
+
insertSubs(T, true);
|
|
106
|
+
schedule();
|
|
107
|
+
}
|
|
82
108
|
}
|
|
83
109
|
}
|
|
110
|
+
if (!s) {
|
|
111
|
+
delete e[STORE_OPTIMISTIC_OVERRIDE];
|
|
112
|
+
delete e[STORE_OPTIMISTIC_OWNERS];
|
|
113
|
+
}
|
|
114
|
+
// Notify $TRACK
|
|
115
|
+
if (c && i?.[$TRACK]) {
|
|
116
|
+
i[$TRACK].Je = undefined;
|
|
117
|
+
notifySelf(e);
|
|
118
|
+
}
|
|
84
119
|
} finally {
|
|
85
|
-
setProjectionWriteActive(
|
|
120
|
+
setProjectionWriteActive(O);
|
|
86
121
|
}
|
|
87
122
|
}
|
|
88
123
|
|
|
89
|
-
function createOptimisticProjectionInternal(
|
|
124
|
+
function createOptimisticProjectionInternal(e, t, r) {
|
|
90
125
|
let i;
|
|
91
126
|
const o = new WeakMap;
|
|
92
|
-
const wrapper =
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
127
|
+
const wrapper = e => {
|
|
128
|
+
e[STORE_WRAP] = wrapProjection;
|
|
129
|
+
e[STORE_LOOKUP] = o;
|
|
130
|
+
e[STORE_OPTIMISTIC] = true;
|
|
96
131
|
// Mark as optimistic store
|
|
97
|
-
Object.defineProperty(
|
|
132
|
+
Object.defineProperty(e, STORE_FIREWALL, {
|
|
98
133
|
get() {
|
|
99
134
|
return i;
|
|
100
135
|
},
|
|
101
136
|
configurable: true
|
|
102
137
|
});
|
|
103
138
|
};
|
|
104
|
-
const wrapProjection =
|
|
105
|
-
if (o.has(
|
|
106
|
-
if (
|
|
107
|
-
const
|
|
108
|
-
o.set(
|
|
109
|
-
return
|
|
139
|
+
const wrapProjection = e => {
|
|
140
|
+
if (o.has(e)) return o.get(e);
|
|
141
|
+
if (e[$TARGET]?.[STORE_WRAP] === wrapProjection) return e;
|
|
142
|
+
const t = createStoreProxy(e, storeTraps, wrapper);
|
|
143
|
+
o.set(e, t);
|
|
144
|
+
return t;
|
|
110
145
|
};
|
|
111
|
-
const
|
|
146
|
+
const n = wrapProjection(t);
|
|
112
147
|
// If there's a projection function, create a computed to drive it
|
|
113
|
-
if (
|
|
148
|
+
if (e) {
|
|
114
149
|
// All writes inside firewall recompute must go to STORE_OVERRIDE (base), not
|
|
115
150
|
// STORE_OPTIMISTIC_OVERRIDE. The outer wrap covers the sync body (including
|
|
116
151
|
// `fn(draft)` and the initial commit); `wrapCommit` re-applies the flag for
|
|
117
152
|
// async yields because they fire outside any enclosing try/finally. It also
|
|
118
153
|
// consumes stale optimistic overlays once fresh projected data lands.
|
|
119
154
|
const clearProjectionOverride = () => {
|
|
120
|
-
const
|
|
121
|
-
if (
|
|
155
|
+
const e = n[$TARGET];
|
|
156
|
+
if (e?.[STORE_OPTIMISTIC_OVERRIDE]) clearOptimisticOverride(e);
|
|
122
157
|
};
|
|
123
|
-
const wrapCommit =
|
|
124
|
-
const
|
|
158
|
+
const wrapCommit = e => {
|
|
159
|
+
const t = projectionWriteActive;
|
|
125
160
|
setProjectionWriteActive(true);
|
|
126
161
|
try {
|
|
127
|
-
|
|
162
|
+
e();
|
|
128
163
|
clearProjectionOverride();
|
|
129
164
|
} finally {
|
|
130
|
-
setProjectionWriteActive(
|
|
165
|
+
setProjectionWriteActive(t);
|
|
131
166
|
}
|
|
132
167
|
};
|
|
133
168
|
i = computed(() => {
|
|
134
169
|
setProjectionWriteActive(true);
|
|
135
170
|
try {
|
|
136
|
-
runProjectionComputed(
|
|
171
|
+
runProjectionComputed(n, e, r?.key || "id", wrapCommit, clearProjectionOverride);
|
|
137
172
|
} finally {
|
|
138
173
|
setProjectionWriteActive(false);
|
|
139
174
|
}
|
|
@@ -141,7 +176,7 @@ function createOptimisticProjectionInternal(t, e, r) {
|
|
|
141
176
|
i.U &= ~CONFIG_AUTO_DISPOSE;
|
|
142
177
|
}
|
|
143
178
|
return {
|
|
144
|
-
store:
|
|
179
|
+
store: n,
|
|
145
180
|
node: i
|
|
146
181
|
};
|
|
147
182
|
}
|
|
@@ -8,7 +8,7 @@ import "../core/verdict.js";
|
|
|
8
8
|
|
|
9
9
|
import "../core/effect.js";
|
|
10
10
|
|
|
11
|
-
import { $TARGET, STORE_OVERRIDE, STORE_OPTIMISTIC_OVERRIDE, STORE_VALUE, STORE_NODE, storeLookup, STORE_LOOKUP, $PROXY, isWrappable, wrap, notifySelf, $TRACK, STORE_HAS, getKeys, $DELETED, symbolKeyedRecords } from "./store.js";
|
|
11
|
+
import { $TARGET, STORE_OVERRIDE, STORE_OPTIMISTIC_OVERRIDE, STORE_VALUE, STORE_NODE, storeLookup, STORE_LOOKUP, $PROXY, isWrappable, wrap, notifySelf, $TRACK, STORE_DESC, STORE_HAS, getKeys, $DELETED, symbolKeyedRecords, getStoreSymbols } from "./store.js";
|
|
12
12
|
|
|
13
13
|
// Enumerate a node record's keys. Keeps the common string-key path on the
|
|
14
14
|
// `Object.keys` fast path; only records currently holding a user symbol node
|
|
@@ -45,6 +45,8 @@ function addEnumSymbols(e, t, r) {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
function getAllKeys(e, t, r) {
|
|
48
|
+
// Symbols are merged explicitly below; keep the common string-key path on
|
|
49
|
+
// Object.keys() and avoid reflecting the base symbols twice.
|
|
48
50
|
const n = getKeys(e, t);
|
|
49
51
|
const a = Object.keys(r);
|
|
50
52
|
// `value` can be a wrapped store (store-in-store) whose ownKeys trap tracks;
|
|
@@ -131,6 +133,34 @@ function applyArrayItem(e, t, r, n, a) {
|
|
|
131
133
|
} else n && setSignal(n, wrapValue(e, r));
|
|
132
134
|
}
|
|
133
135
|
|
|
136
|
+
/**
|
|
137
|
+
* The captured-proxy half of the object diff (#2902): descend into keyed-
|
|
138
|
+
* matching children that have NO node at this level but shelter subscribers
|
|
139
|
+
* somewhere below (their target's sticky `STORE_DESC` flag, bubbled up by
|
|
140
|
+
* `getNode`). Without this, a proxy captured through untracked reads — a
|
|
141
|
+
* `<For>` row handed to a child component — detaches from the diff the
|
|
142
|
+
* moment no intermediate level happens to be tracked, and its live
|
|
143
|
+
* subscribers go permanently stale. Never-subscribed branches have no flag
|
|
144
|
+
* and stay pruned exactly as before; keys the main loop already visited
|
|
145
|
+
* (node present) are skipped. Callers gate on the parent's own flag and on
|
|
146
|
+
* `$TRACK` absence (an enumeration-tracked record already diffs every key).
|
|
147
|
+
*/ function applyDescendants(e, t, r, n, a, i, o) {
|
|
148
|
+
const l = r[STORE_LOOKUP] || storeLookup;
|
|
149
|
+
const s = (i ? getKeys(e, i) : Object.keys(e)).concat(getStoreSymbols(e, i));
|
|
150
|
+
for (let p = 0, f = s.length; p < f; p++) {
|
|
151
|
+
const f = s[p];
|
|
152
|
+
if (n?.[f]) continue;
|
|
153
|
+
// main loop already diffed this slot
|
|
154
|
+
const c = unwrap(i ? getOverrideValue(e, i, f, o) : e[f]);
|
|
155
|
+
if (!isWrappable(c)) continue;
|
|
156
|
+
const u = (l.get(c) ?? storeLookup.get(c))?.[$TARGET];
|
|
157
|
+
if (!u?.[STORE_DESC]) continue;
|
|
158
|
+
const S = unwrap(t[f]);
|
|
159
|
+
if (c === S || !isWrappable(S) || Array.isArray(c) !== Array.isArray(S) || a(c) != null && a(c) !== a(S)) continue;
|
|
160
|
+
applyState(S, wrap(c, r), a);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
134
164
|
// Dispatcher: every applyState call (including recursion) checks for the
|
|
135
165
|
// presence of override / optimistic-override slots once and routes to the
|
|
136
166
|
// appropriate body. The fast body never calls `getOverrideValue` and never
|
|
@@ -161,7 +191,7 @@ function applyStateFast(e, t, r) {
|
|
|
161
191
|
let i = false;
|
|
162
192
|
const o = n.length;
|
|
163
193
|
if (e.length && o && isWrappable(e[0]) && r(e[0]) != null) {
|
|
164
|
-
let l, s, p, f, c, u,
|
|
194
|
+
let l, s, p, f, c, u, S, y;
|
|
165
195
|
for (p = 0, f = Math.min(o, e.length); p < f && keyedMatch(u = n[p], e[p], r); p++) {
|
|
166
196
|
isWrappable(u) && isWrappable(e[p]) && applyState(e[p], wrap(u, t), r);
|
|
167
197
|
}
|
|
@@ -184,22 +214,22 @@ function applyStateFast(e, t, r) {
|
|
|
184
214
|
o !== e.length && a?.length && setSignal(a.length, e.length);
|
|
185
215
|
return;
|
|
186
216
|
}
|
|
187
|
-
|
|
217
|
+
S = new Array(c + 1);
|
|
188
218
|
for (s = c; s >= p; s--) {
|
|
189
219
|
u = e[s];
|
|
190
|
-
|
|
191
|
-
l = O.get(
|
|
192
|
-
|
|
193
|
-
O.set(
|
|
220
|
+
y = itemKey(u, r);
|
|
221
|
+
l = O.get(y);
|
|
222
|
+
S[s] = l === undefined ? -1 : l;
|
|
223
|
+
O.set(y, s);
|
|
194
224
|
}
|
|
195
225
|
for (l = p; l <= f; l++) {
|
|
196
226
|
u = n[l];
|
|
197
|
-
|
|
198
|
-
s = O.get(
|
|
227
|
+
y = itemKey(u, r);
|
|
228
|
+
s = O.get(y);
|
|
199
229
|
if (s !== undefined && s !== -1) {
|
|
200
230
|
E[s] = u;
|
|
201
|
-
s =
|
|
202
|
-
O.set(
|
|
231
|
+
s = S[s];
|
|
232
|
+
O.set(y, s);
|
|
203
233
|
}
|
|
204
234
|
}
|
|
205
235
|
for (s = p; s < e.length; s++) {
|
|
@@ -227,21 +257,23 @@ function applyStateFast(e, t, r) {
|
|
|
227
257
|
}
|
|
228
258
|
// values
|
|
229
259
|
let i = t[STORE_NODE];
|
|
260
|
+
let o;
|
|
230
261
|
if (i) {
|
|
231
|
-
|
|
232
|
-
const
|
|
233
|
-
for (let l = 0, s =
|
|
234
|
-
const s =
|
|
262
|
+
o = i[$TRACK];
|
|
263
|
+
const a = o ? getAllKeys(n, undefined, e) : nodeKeys(i);
|
|
264
|
+
for (let l = 0, s = a.length; l < s; l++) {
|
|
265
|
+
const s = a[l];
|
|
235
266
|
const p = i[s];
|
|
236
267
|
const f = unwrap(n[s]);
|
|
237
268
|
let c = unwrap(e[s]);
|
|
238
269
|
if (f === c) continue;
|
|
239
270
|
if (!f || !isWrappable(f) || !isWrappable(c) || Array.isArray(f) !== Array.isArray(c) || r(f) != null && r(f) !== r(c)) {
|
|
240
|
-
|
|
271
|
+
o && setSignal(o, void 0);
|
|
241
272
|
p && setSignal(p, isWrappable(c) ? wrap(c, t) : c);
|
|
242
273
|
} else applyState(c, wrap(f, t), r);
|
|
243
274
|
}
|
|
244
275
|
}
|
|
276
|
+
if (!o && t[STORE_DESC]) applyDescendants(n, e, t, i, r);
|
|
245
277
|
// has
|
|
246
278
|
if (i = t[STORE_HAS]) {
|
|
247
279
|
const t = nodeKeys(i);
|
|
@@ -266,23 +298,23 @@ function applyStateSlow(e, t, r) {
|
|
|
266
298
|
let l = false;
|
|
267
299
|
const s = getOverrideValue(n, a, "length", i);
|
|
268
300
|
if (e.length && s && isWrappable(e[0]) && r(e[0]) != null) {
|
|
269
|
-
let p, f, c, u,
|
|
270
|
-
for (c = 0, u = Math.min(s, e.length); c < u && keyedMatch(
|
|
271
|
-
isWrappable(
|
|
301
|
+
let p, f, c, u, S, y, E, O;
|
|
302
|
+
for (c = 0, u = Math.min(s, e.length); c < u && keyedMatch(y = getOverrideValue(n, a, c, i), e[c], r); c++) {
|
|
303
|
+
isWrappable(y) && isWrappable(e[c]) && applyState(e[c], wrap(y, t), r);
|
|
272
304
|
}
|
|
273
|
-
const
|
|
274
|
-
for (u = s - 1,
|
|
275
|
-
|
|
276
|
-
|
|
305
|
+
const R = new Array(e.length), d = new Map;
|
|
306
|
+
for (u = s - 1, S = e.length - 1; u >= c && S >= c && keyedMatch(y = getOverrideValue(n, a, u, i), e[S], r); u--,
|
|
307
|
+
S--) {
|
|
308
|
+
R[S] = y;
|
|
277
309
|
}
|
|
278
|
-
if (c >
|
|
279
|
-
for (f = c; f <=
|
|
310
|
+
if (c > S || c > u) {
|
|
311
|
+
for (f = c; f <= S; f++) {
|
|
280
312
|
l = true;
|
|
281
313
|
o?.[f] && setSignal(o[f], wrapValue(e[f], t));
|
|
282
314
|
}
|
|
283
315
|
for (;f < e.length; f++) {
|
|
284
316
|
l = true;
|
|
285
|
-
applyArrayItem(e[f],
|
|
317
|
+
applyArrayItem(e[f], R[f], t, o?.[f], r);
|
|
286
318
|
}
|
|
287
319
|
const n = e.length;
|
|
288
320
|
syncArrayNodeMembership(t, e);
|
|
@@ -290,27 +322,27 @@ function applyStateSlow(e, t, r) {
|
|
|
290
322
|
s !== n && o?.length && setSignal(o.length, n);
|
|
291
323
|
return;
|
|
292
324
|
}
|
|
293
|
-
E = new Array(
|
|
294
|
-
for (f =
|
|
295
|
-
|
|
296
|
-
O = itemKey(
|
|
297
|
-
p =
|
|
325
|
+
E = new Array(S + 1);
|
|
326
|
+
for (f = S; f >= c; f--) {
|
|
327
|
+
y = e[f];
|
|
328
|
+
O = itemKey(y, r);
|
|
329
|
+
p = d.get(O);
|
|
298
330
|
E[f] = p === undefined ? -1 : p;
|
|
299
|
-
|
|
331
|
+
d.set(O, f);
|
|
300
332
|
}
|
|
301
333
|
for (p = c; p <= u; p++) {
|
|
302
|
-
|
|
303
|
-
O = itemKey(
|
|
304
|
-
f =
|
|
334
|
+
y = getOverrideValue(n, a, p, i);
|
|
335
|
+
O = itemKey(y, r);
|
|
336
|
+
f = d.get(O);
|
|
305
337
|
if (f !== undefined && f !== -1) {
|
|
306
|
-
|
|
338
|
+
R[f] = y;
|
|
307
339
|
f = E[f];
|
|
308
|
-
|
|
340
|
+
d.set(O, f);
|
|
309
341
|
}
|
|
310
342
|
}
|
|
311
343
|
for (f = c; f < e.length; f++) {
|
|
312
|
-
if (f in
|
|
313
|
-
applyArrayItem(e[f],
|
|
344
|
+
if (f in R) {
|
|
345
|
+
applyArrayItem(e[f], R[f], t, o?.[f], r);
|
|
314
346
|
} else o?.[f] && setSignal(o[f], wrapValue(e[f], t));
|
|
315
347
|
}
|
|
316
348
|
if (c < e.length) l = true;
|
|
@@ -333,21 +365,23 @@ function applyStateSlow(e, t, r) {
|
|
|
333
365
|
return;
|
|
334
366
|
}
|
|
335
367
|
// values
|
|
336
|
-
|
|
337
|
-
|
|
368
|
+
let l;
|
|
369
|
+
if (o) {
|
|
370
|
+
l = o[$TRACK];
|
|
338
371
|
const s = l ? getAllKeys(n, a, e) : nodeKeys(o);
|
|
339
372
|
for (let p = 0, f = s.length; p < f; p++) {
|
|
340
373
|
const f = s[p];
|
|
341
374
|
const c = o[f];
|
|
342
375
|
const u = unwrap(getOverrideValue(n, a, f, i));
|
|
343
|
-
let
|
|
344
|
-
if (u ===
|
|
345
|
-
if (!u || !isWrappable(u) || !isWrappable(
|
|
376
|
+
let S = unwrap(e[f]);
|
|
377
|
+
if (u === S) continue;
|
|
378
|
+
if (!u || !isWrappable(u) || !isWrappable(S) || Array.isArray(u) !== Array.isArray(S) || r(u) != null && r(u) !== r(S)) {
|
|
346
379
|
l && setSignal(l, void 0);
|
|
347
|
-
c && setSignal(c, isWrappable(
|
|
348
|
-
} else applyState(
|
|
380
|
+
c && setSignal(c, isWrappable(S) ? wrap(S, t) : S);
|
|
381
|
+
} else applyState(S, wrap(u, t), r);
|
|
349
382
|
}
|
|
350
383
|
}
|
|
384
|
+
if (!l && t[STORE_DESC]) applyDescendants(n, e, t, o, r, a, i);
|
|
351
385
|
// has
|
|
352
386
|
if (o = t[STORE_HAS]) {
|
|
353
387
|
const t = nodeKeys(o);
|