@solidjs/signals 2.0.0-rc.17 → 2.0.0-rc.18
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-shared.js +296 -191
- package/dist/dev.attribution.js +16 -16
- package/dist/dev.js +527 -311
- package/dist/observe/core/async.js +148 -115
- package/dist/observe/core/constants.js +3 -1
- package/dist/observe/core/core.js +27 -27
- package/dist/observe/core/effect.js +29 -32
- package/dist/observe/core/graph.js +5 -5
- package/dist/observe/core/owner.js +7 -7
- package/dist/observe/core/scheduler.js +23 -12
- package/dist/observe/core/verdict.js +2 -2
- package/dist/observe/deferred.js +16 -13
- package/dist/observe/from.js +248 -0
- package/dist/observe/index.js +2 -0
- package/dist/observe/store/reconcile.js +137 -121
- package/dist/observe/store/store.js +595 -618
- package/dist/observe/store/target.js +1 -5
- package/dist/prod/core/async.js +209 -176
- package/dist/prod/core/constants.js +3 -1
- package/dist/prod/core/core.js +33 -33
- package/dist/prod/core/effect.js +24 -27
- package/dist/prod/core/graph.js +2 -2
- package/dist/prod/core/lanes.js +14 -14
- package/dist/prod/core/scheduler.js +35 -24
- package/dist/prod/core/truth.js +4 -4
- package/dist/prod/core/verdict.js +7 -7
- package/dist/prod/deferred.js +17 -14
- package/dist/prod/from.js +248 -0
- package/dist/prod/index.js +2 -0
- package/dist/prod/store/optimistic.js +1 -1
- package/dist/prod/store/reconcile.js +137 -121
- package/dist/prod/store/store.js +94 -117
- package/dist/prod/store/target.js +13 -17
- package/dist/types/core/async.d.ts +12 -2
- package/dist/types/core/constants.d.ts +5 -0
- package/dist/types/core/core.d.ts +19 -3
- package/dist/types/core/scheduler.d.ts +15 -3
- package/dist/types/from.d.ts +47 -0
- package/dist/types/index.d.ts +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { isThenable, onSupersede } from "./core/async.js";
|
|
2
|
+
|
|
3
|
+
import { CONFIG_CHILDREN_FORBIDDEN } from "./core/constants.js";
|
|
4
|
+
|
|
5
|
+
import { cleanup, getOwner } from "./core/owner.js";
|
|
6
|
+
|
|
7
|
+
// `from` — a push source (callback subscription, Observable, AsyncIterable)
|
|
8
|
+
// as an AsyncIterable a computation can return or `for await` over:
|
|
9
|
+
// const value = createMemo(() => from(source));
|
|
10
|
+
// A subscription keeps the latest value: values that arrive between pulls
|
|
11
|
+
// coalesce. An AsyncIterable streams through unchanged. Either way the source
|
|
12
|
+
// opens when the result is iterated and closes on return(), on supersede (the
|
|
13
|
+
// owning computation re-runs) and on owner disposal, whichever comes first.
|
|
14
|
+
function toSubscribe(e) {
|
|
15
|
+
if (typeof e === "function") return e;
|
|
16
|
+
// TC39 / RxJS interop: `Symbol.observable` (or "@@observable") returns the observable.
|
|
17
|
+
// Read per call, not at module scope, so the module stays side-effect free.
|
|
18
|
+
const n = Symbol.observable;
|
|
19
|
+
const r = (n && e?.[n]) ?? e?.["@@observable"];
|
|
20
|
+
const t = typeof r === "function" ? r.call(e) : e;
|
|
21
|
+
if (t && typeof t.subscribe === "function") return (e, n, r) => t.subscribe({
|
|
22
|
+
next: e,
|
|
23
|
+
error: n,
|
|
24
|
+
complete: r
|
|
25
|
+
});
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const DONE = {
|
|
30
|
+
value: undefined,
|
|
31
|
+
done: true
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Ties an iterator's `finish` to the computation iterating it. Solid reaches
|
|
36
|
+
* an iterator's return() only when the compute returns the iterable directly.
|
|
37
|
+
* Inside an async generator the generator's own return() is queued behind its
|
|
38
|
+
* pending `await`, and owner cleanups wait for the replacing pass to commit,
|
|
39
|
+
* so close on supersede, with owner disposal as the backstop. No owner (an
|
|
40
|
+
* async compute iterating it after its first `await`, or plain iteration):
|
|
41
|
+
* no registration and no diagnostic, so only return() closes it. Scopes that
|
|
42
|
+
* forbid cleanups rely on supersede and return().
|
|
43
|
+
*/ function bindToOwner(e) {
|
|
44
|
+
const n = getOwner();
|
|
45
|
+
if (!n) return;
|
|
46
|
+
onSupersede(e);
|
|
47
|
+
if (!(n.l & CONFIG_CHILDREN_FORBIDDEN)) cleanup(e);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* An AsyncIterable as a stream bound to the iterating computation: every
|
|
52
|
+
* value passes through (no coalescing). `finish` calls the inner return()
|
|
53
|
+
* once and settles pending pulls as done, so a `for await` over it exits as
|
|
54
|
+
* soon as the computation re-runs — even when the inner iterator is an async
|
|
55
|
+
* generator whose own return() the language queues behind its pending
|
|
56
|
+
* `await`.
|
|
57
|
+
*/ function wrapIterable(e) {
|
|
58
|
+
return {
|
|
59
|
+
[Symbol.asyncIterator]() {
|
|
60
|
+
const n = e[Symbol.asyncIterator]();
|
|
61
|
+
let r = false;
|
|
62
|
+
const t = new Set;
|
|
63
|
+
const finish = () => {
|
|
64
|
+
if (r) return DONE;
|
|
65
|
+
r = true;
|
|
66
|
+
for (const e of t) e(DONE);
|
|
67
|
+
t.clear();
|
|
68
|
+
try {
|
|
69
|
+
const e = n.return?.();
|
|
70
|
+
if (isThenable(e)) e.then(undefined, () => {});
|
|
71
|
+
} catch {}
|
|
72
|
+
return DONE;
|
|
73
|
+
};
|
|
74
|
+
bindToOwner(finish);
|
|
75
|
+
return {
|
|
76
|
+
next(...e) {
|
|
77
|
+
if (r) return Promise.resolve(DONE);
|
|
78
|
+
const o = n.next(...e);
|
|
79
|
+
// A bare result (the producer's buffered fast path) passes through.
|
|
80
|
+
if (!isThenable(o)) return o;
|
|
81
|
+
return new Promise((e, n) => {
|
|
82
|
+
t.add(e);
|
|
83
|
+
o.then(n => t.delete(e) && e(n), r => t.delete(e) && n(r));
|
|
84
|
+
});
|
|
85
|
+
},
|
|
86
|
+
return() {
|
|
87
|
+
return Promise.resolve(finish());
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const toCleanup = e => typeof e === "function" ? e : e && typeof e.unsubscribe === "function" ? () => e.unsubscribe() : () => {};
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Converts a callback subscription, an Observable or an AsyncIterable into an
|
|
98
|
+
* AsyncIterable for a Solid computation. A subscription keeps only the latest
|
|
99
|
+
* value, and a value the source emits during `subscribe` is served without a
|
|
100
|
+
* loading frame; an AsyncIterable streams every value through.
|
|
101
|
+
*
|
|
102
|
+
* The source closes on supersede — the owning computation re-running — and
|
|
103
|
+
* on owner disposal. Inside an async generator memo that holds for a
|
|
104
|
+
* `for await` that starts before the first `await`; one that starts after it
|
|
105
|
+
* has no owner to bind to, so its source closes only when the loop ends.
|
|
106
|
+
* Prefer returning `from(...)` from its own memo, with awaited inputs read
|
|
107
|
+
* from upstream memos and transforms done in a downstream memo.
|
|
108
|
+
*
|
|
109
|
+
* Iterate the result with `for await` or return it from a computation: its
|
|
110
|
+
* `next()` returns an already-buffered value as a bare result, not a promise.
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```ts
|
|
114
|
+
* const position = createMemo(() =>
|
|
115
|
+
* from<Position>((next, error) => {
|
|
116
|
+
* const id = navigator.geolocation.watchPosition(next, error);
|
|
117
|
+
* return () => navigator.geolocation.clearWatch(id);
|
|
118
|
+
* })
|
|
119
|
+
* );
|
|
120
|
+
* const ticks = createMemo(() => from(interval$(rate())));
|
|
121
|
+
* ```
|
|
122
|
+
*/ function from(e) {
|
|
123
|
+
const n = toSubscribe(e);
|
|
124
|
+
if (!n) {
|
|
125
|
+
if (e && typeof e[Symbol.asyncIterator] === "function") return wrapIterable(e);
|
|
126
|
+
throw new TypeError("from(): expected a subscribe function, an Observable or an AsyncIterable");
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
[Symbol.asyncIterator]() {
|
|
130
|
+
let e;
|
|
131
|
+
let r = false;
|
|
132
|
+
let t = false;
|
|
133
|
+
let o = false;
|
|
134
|
+
let u;
|
|
135
|
+
let f = null;
|
|
136
|
+
let l = null;
|
|
137
|
+
let s = false;
|
|
138
|
+
const close = () => {
|
|
139
|
+
if (s) return;
|
|
140
|
+
s = true;
|
|
141
|
+
t = true;
|
|
142
|
+
const e = l;
|
|
143
|
+
l = null;
|
|
144
|
+
// A throwing unsubscribe must not escape: at supersede this runs
|
|
145
|
+
// inside flush(), ahead of the replacing pass (the returned-iterator
|
|
146
|
+
// path swallows it the same way).
|
|
147
|
+
try {
|
|
148
|
+
e?.();
|
|
149
|
+
} catch {}
|
|
150
|
+
};
|
|
151
|
+
const settle = () => {
|
|
152
|
+
if (!f) return;
|
|
153
|
+
const n = f;
|
|
154
|
+
if (r) {
|
|
155
|
+
f = null;
|
|
156
|
+
r = false;
|
|
157
|
+
n.resolve({
|
|
158
|
+
value: e,
|
|
159
|
+
done: false
|
|
160
|
+
});
|
|
161
|
+
} else if (o) {
|
|
162
|
+
f = null;
|
|
163
|
+
o = false;
|
|
164
|
+
n.reject(u);
|
|
165
|
+
} else if (t) {
|
|
166
|
+
f = null;
|
|
167
|
+
n.resolve({
|
|
168
|
+
value: undefined,
|
|
169
|
+
done: true
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
const i = n(n => {
|
|
174
|
+
if (t) return;
|
|
175
|
+
e = n;
|
|
176
|
+
r = true;
|
|
177
|
+
settle();
|
|
178
|
+
}, e => {
|
|
179
|
+
if (t) return;
|
|
180
|
+
o = true;
|
|
181
|
+
u = e;
|
|
182
|
+
t = true;
|
|
183
|
+
settle();
|
|
184
|
+
close();
|
|
185
|
+
}, () => {
|
|
186
|
+
if (t) return;
|
|
187
|
+
t = true;
|
|
188
|
+
settle();
|
|
189
|
+
close();
|
|
190
|
+
});
|
|
191
|
+
l = toCleanup(i);
|
|
192
|
+
// Completed or errored during subscribe: release what it just returned.
|
|
193
|
+
if (s) {
|
|
194
|
+
const e = l;
|
|
195
|
+
l = null;
|
|
196
|
+
try {
|
|
197
|
+
e();
|
|
198
|
+
} catch {}
|
|
199
|
+
}
|
|
200
|
+
// Idempotent: return(), supersede and disposal may all reach it.
|
|
201
|
+
const finish = () => {
|
|
202
|
+
close();
|
|
203
|
+
r = false;
|
|
204
|
+
if (f) {
|
|
205
|
+
const e = f;
|
|
206
|
+
f = null;
|
|
207
|
+
e.resolve(DONE);
|
|
208
|
+
}
|
|
209
|
+
return DONE;
|
|
210
|
+
};
|
|
211
|
+
bindToOwner(finish);
|
|
212
|
+
return {
|
|
213
|
+
next() {
|
|
214
|
+
// A buffered value is returned as a bare result, not a promise: the
|
|
215
|
+
// iterator consumer lands it in the same pass, so a source that
|
|
216
|
+
// emits during subscribe (BehaviorSubject-style) shows its value
|
|
217
|
+
// with no loading frame. `for await` accepts either form.
|
|
218
|
+
if (r) {
|
|
219
|
+
r = false;
|
|
220
|
+
return {
|
|
221
|
+
value: e,
|
|
222
|
+
done: false
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
if (o) {
|
|
226
|
+
o = false;
|
|
227
|
+
return Promise.reject(u);
|
|
228
|
+
}
|
|
229
|
+
if (t) return Promise.resolve({
|
|
230
|
+
value: undefined,
|
|
231
|
+
done: true
|
|
232
|
+
});
|
|
233
|
+
return new Promise((e, n) => {
|
|
234
|
+
f = {
|
|
235
|
+
resolve: e,
|
|
236
|
+
reject: n
|
|
237
|
+
};
|
|
238
|
+
});
|
|
239
|
+
},
|
|
240
|
+
return() {
|
|
241
|
+
return Promise.resolve(finish());
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export { from };
|
package/dist/observe/index.js
CHANGED
|
@@ -38,6 +38,8 @@ export { affects } from "./affects.js";
|
|
|
38
38
|
|
|
39
39
|
export { createDeferred } from "./deferred.js";
|
|
40
40
|
|
|
41
|
+
export { from } from "./from.js";
|
|
42
|
+
|
|
41
43
|
export { flatten } from "./flatten.js";
|
|
42
44
|
|
|
43
45
|
export { createErrorBoundary, createLoadingBoundary } from "./boundaries.js";
|
|
@@ -24,15 +24,15 @@ import { $TARGET, markRawIngest, isWrappable, rawValuesUsed, isRawValue } from "
|
|
|
24
24
|
* identity), unkeyed items fall back to position.
|
|
25
25
|
*/ function reconcileState(e, n, t, o = false) {
|
|
26
26
|
if (n == null) throw new Error("");
|
|
27
|
-
const f = n
|
|
28
|
-
if (f
|
|
29
|
-
const
|
|
27
|
+
const f = n[$TARGET];
|
|
28
|
+
if (f?.px !== n) throw new Error("");
|
|
29
|
+
const i = t === null ? null : typeof t === "string" ? e => e?.[t] : t;
|
|
30
30
|
// A user's reconcile on an optimistic family (S4): not an adoption of
|
|
31
31
|
// truth but an optimistic edit — the keyed diff is written into the draft
|
|
32
32
|
// (a matched row keeps its proxy, its changed leaves become its guesses),
|
|
33
33
|
// and the setter's exit turns the draft into guesses like any.
|
|
34
34
|
if (userWriting() && f.fam?.opt === true) {
|
|
35
|
-
optHooks.reconcile(n, unwrapValue(e),
|
|
35
|
+
optHooks.reconcile(n, unwrapValue(e), i);
|
|
36
36
|
return;
|
|
37
37
|
}
|
|
38
38
|
// Replace-mode root handed another store's proxy: chain to it (§7b).
|
|
@@ -43,21 +43,20 @@ import { $TARGET, markRawIngest, isWrappable, rawValuesUsed, isRawValue } from "
|
|
|
43
43
|
adoptPB(f, e);
|
|
44
44
|
return;
|
|
45
45
|
}
|
|
46
|
-
const
|
|
47
|
-
if (
|
|
46
|
+
const l = unwrapValue(e);
|
|
47
|
+
if (i) {
|
|
48
48
|
const e = f.pb ?? f.v;
|
|
49
|
-
const n =
|
|
50
|
-
if (n !== undefined && !sameKey(l
|
|
49
|
+
const n = i(e);
|
|
50
|
+
if (n !== undefined && !sameKey(i(l), n)) {
|
|
51
51
|
if (!o) throw new Error("");
|
|
52
52
|
// A different entity at the root: the old backing is disowned (wraps
|
|
53
53
|
// fresh if re-handed) and the new one adopted whole.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
adoptPB(f, i);
|
|
54
|
+
if (isOwned(e)) delete e[$OWNER]; else (f.fam?.map ?? storeLookup).delete(e);
|
|
55
|
+
adoptPB(f, l);
|
|
57
56
|
return;
|
|
58
57
|
}
|
|
59
58
|
}
|
|
60
|
-
applyAdopt(f,
|
|
59
|
+
applyAdopt(f, l, i, o);
|
|
61
60
|
}
|
|
62
61
|
|
|
63
62
|
/** Adopt `incoming` at `t` and notify its nodes — one leaf write per
|
|
@@ -70,190 +69,207 @@ import { $TARGET, markRawIngest, isWrappable, rawValuesUsed, isRawValue } from "
|
|
|
70
69
|
// a deletion here (#3743: the presence and value diffs both read `old`).
|
|
71
70
|
const f = e.ovl ? materializePB(e) : e.pb ?? e.v;
|
|
72
71
|
if (n === f && !isOwned(f)) return;
|
|
73
|
-
const l = e.fam;
|
|
74
72
|
// Q-D: a landing on an optimistic family is reconciled against the VIEW
|
|
75
73
|
// — key matching from the arrangement the guesses made (R28), so a row
|
|
76
74
|
// the guess added keeps its proxy when the server returns it.
|
|
77
|
-
const i =
|
|
78
|
-
const
|
|
79
|
-
const
|
|
80
|
-
const r = f;
|
|
75
|
+
const i = e.fam?.opt === true ? optHooks.view(e, f) : f;
|
|
76
|
+
const l = Array.isArray(n);
|
|
77
|
+
const r = e.s === true;
|
|
81
78
|
adoptPB(e, n, false);
|
|
82
|
-
if (
|
|
83
|
-
|
|
84
|
-
|
|
79
|
+
if (r) markRawIngest(n);
|
|
80
|
+
// The deep witness is bumped once per adoption (none to bump: done).
|
|
81
|
+
let u = e.dk === null;
|
|
82
|
+
if (Array.isArray(i) !== l) {
|
|
83
|
+
notifyFold(e, f, n);
|
|
85
84
|
return;
|
|
86
85
|
}
|
|
87
|
-
if (
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const u = s.length;
|
|
95
|
-
let d = false;
|
|
96
|
-
let p = 0;
|
|
86
|
+
if (l) {
|
|
87
|
+
const l = e.n;
|
|
88
|
+
let s = 0;
|
|
89
|
+
if (t && !r) {
|
|
90
|
+
const r = i.length;
|
|
91
|
+
const a = n.length;
|
|
92
|
+
let c = 0;
|
|
97
93
|
// Aligned prefix: same row (by reference or key) at the same index.
|
|
98
|
-
for (const
|
|
99
|
-
const
|
|
100
|
-
const
|
|
101
|
-
if (
|
|
94
|
+
for (const d = Math.min(r, a); c < d; c++) {
|
|
95
|
+
const r = n[c];
|
|
96
|
+
const a = i[c];
|
|
97
|
+
if (a !== r && !sameRow(a, r, t)) break;
|
|
102
98
|
// misaligned: fall to the keyed remainder below
|
|
103
|
-
if (
|
|
104
|
-
if (
|
|
99
|
+
if (r !== null && typeof r === "object" && (a !== r || isOwned(r))) descend(unwrapValue(a), r, t, o, e, c);
|
|
100
|
+
if (!u && !(r !== null && typeof r === "object" ? targetsEqual(a, r) : isEqual(a, r))) {
|
|
105
101
|
bumpDeep(e);
|
|
106
|
-
|
|
102
|
+
u = true;
|
|
107
103
|
}
|
|
108
|
-
if (
|
|
109
|
-
const e =
|
|
104
|
+
if (l !== null) {
|
|
105
|
+
const e = l[c];
|
|
110
106
|
if (e !== undefined) {
|
|
111
|
-
|
|
112
|
-
notifyKeyValue(e,
|
|
107
|
+
s++;
|
|
108
|
+
notifyKeyValue(e, c, f[c], r, f, n);
|
|
113
109
|
}
|
|
114
110
|
}
|
|
115
111
|
}
|
|
116
|
-
if (
|
|
117
|
-
const
|
|
112
|
+
if (!u && c < n.length) bumpDeep(e);
|
|
113
|
+
const d = c;
|
|
118
114
|
// misalignment point (== nlen on aligned ticks)
|
|
119
|
-
let
|
|
120
|
-
for (;
|
|
121
|
-
const
|
|
122
|
-
if (
|
|
123
|
-
const n = t(
|
|
124
|
-
let
|
|
115
|
+
let p = null;
|
|
116
|
+
for (;c < n.length; c++) {
|
|
117
|
+
const r = n[c];
|
|
118
|
+
if (r !== null && typeof r === "object") {
|
|
119
|
+
const n = t(r);
|
|
120
|
+
let f;
|
|
125
121
|
if (n !== undefined) {
|
|
126
|
-
if (
|
|
127
|
-
|
|
128
|
-
for (let e =
|
|
129
|
-
const n = unwrapValue(
|
|
122
|
+
if (p === null) {
|
|
123
|
+
p = new Map;
|
|
124
|
+
for (let e = d; e < i.length; e++) {
|
|
125
|
+
const n = unwrapValue(i[e]);
|
|
130
126
|
if (n !== null && typeof n === "object") {
|
|
131
127
|
const o = t(n);
|
|
132
128
|
if (o === undefined) continue;
|
|
133
|
-
const f =
|
|
134
|
-
if (f === undefined)
|
|
129
|
+
const f = p.get(o);
|
|
130
|
+
if (f === undefined) p.set(o, e); else if (Array.isArray(f)) f.push(e); else p.set(o, [ f, e ]);
|
|
135
131
|
}
|
|
136
132
|
}
|
|
137
133
|
}
|
|
138
|
-
const e =
|
|
139
|
-
if (e === undefined)
|
|
140
|
-
|
|
141
|
-
if (e.length === 1)
|
|
134
|
+
const e = p.get(n);
|
|
135
|
+
if (e === undefined) f = undefined; else if (Array.isArray(e)) {
|
|
136
|
+
f = unwrapValue(i[e.shift()]);
|
|
137
|
+
if (e.length === 1) p.set(n, e[0]);
|
|
142
138
|
} else {
|
|
143
|
-
|
|
144
|
-
|
|
139
|
+
f = unwrapValue(i[e]);
|
|
140
|
+
p.delete(n);
|
|
145
141
|
}
|
|
146
142
|
} else {
|
|
147
|
-
|
|
143
|
+
f = unwrapValue(i[c]);
|
|
148
144
|
// keyless item: positional fallback
|
|
149
145
|
}
|
|
150
|
-
descend(
|
|
146
|
+
descend(f, r, t, o, e, c);
|
|
151
147
|
}
|
|
152
|
-
if (
|
|
153
|
-
const e =
|
|
148
|
+
if (l !== null) {
|
|
149
|
+
const e = l[c];
|
|
154
150
|
if (e !== undefined) {
|
|
155
|
-
|
|
156
|
-
notifyKeyDiff(e,
|
|
151
|
+
s++;
|
|
152
|
+
notifyKeyDiff(e, c, f, n, false);
|
|
157
153
|
}
|
|
158
154
|
}
|
|
159
155
|
}
|
|
160
156
|
} else {
|
|
161
|
-
const
|
|
162
|
-
const
|
|
163
|
-
let
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
if (!u &&
|
|
167
|
-
if (e.dk !== null && !p && !(d !== null && typeof d === "object" ? targetsEqual(f[y], d) : isEqual(f[y], d))) {
|
|
157
|
+
const a = Math.min(i.length, n.length);
|
|
158
|
+
const c = n.length;
|
|
159
|
+
for (let d = 0; d < c; d++) {
|
|
160
|
+
const c = n[d];
|
|
161
|
+
if (!r && d < a && c !== null && typeof c === "object") descend(unwrapValue(i[d]), c, t, o, e, d);
|
|
162
|
+
if (!u && !(c !== null && typeof c === "object" ? targetsEqual(i[d], c) : isEqual(i[d], c))) {
|
|
168
163
|
bumpDeep(e);
|
|
169
|
-
|
|
164
|
+
u = true;
|
|
170
165
|
}
|
|
171
|
-
if (
|
|
172
|
-
const e =
|
|
166
|
+
if (l !== null) {
|
|
167
|
+
const e = l[d];
|
|
173
168
|
if (e !== undefined) {
|
|
174
|
-
|
|
175
|
-
notifyKeyDiff(e,
|
|
169
|
+
s++;
|
|
170
|
+
notifyKeyDiff(e, d, f, n, false);
|
|
176
171
|
}
|
|
177
172
|
}
|
|
178
173
|
}
|
|
179
174
|
}
|
|
180
175
|
// Indices past the new length (and `length` itself) still have nodes.
|
|
181
|
-
if (
|
|
182
|
-
for (const e of Reflect.ownKeys(
|
|
176
|
+
if (l !== null && s < e.nc) {
|
|
177
|
+
for (const e of Reflect.ownKeys(l)) {
|
|
183
178
|
const t = typeof e === "string" ? +e : NaN;
|
|
184
|
-
if (!(t >= 0 && t <
|
|
179
|
+
if (!(t >= 0 && t < n.length)) notifyKeyDiff(l[e], e, f, n, false);
|
|
185
180
|
}
|
|
186
181
|
}
|
|
187
|
-
notifyFoldTail(e,
|
|
182
|
+
notifyFoldTail(e, f, n);
|
|
188
183
|
return;
|
|
189
184
|
}
|
|
190
|
-
const
|
|
191
|
-
let
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
const
|
|
195
|
-
const p =
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
if (a !== null && a[f] !== undefined) c++;
|
|
185
|
+
const s = e.n;
|
|
186
|
+
let a = 0;
|
|
187
|
+
for (const l in n) {
|
|
188
|
+
const c = n[l];
|
|
189
|
+
const d = f[l];
|
|
190
|
+
const p = c !== null && typeof c === "object";
|
|
191
|
+
if (d === c && (!p || !isOwned(c)) && (s === null || s[l] === undefined || !hasAccessorFlag(s[l]))) {
|
|
192
|
+
if (s?.[l] !== undefined) a++;
|
|
199
193
|
continue;
|
|
200
194
|
}
|
|
201
|
-
if (
|
|
202
|
-
if (
|
|
195
|
+
if (p && !r) descend(unwrapValue(i[l]), c, t, o, e, l);
|
|
196
|
+
if (!u && !(p ? targetsEqual(d, c) : isEqual(d, c))) {
|
|
203
197
|
bumpDeep(e);
|
|
204
|
-
|
|
198
|
+
u = true;
|
|
205
199
|
}
|
|
206
|
-
if (
|
|
207
|
-
const e =
|
|
200
|
+
if (s !== null) {
|
|
201
|
+
const e = s[l];
|
|
208
202
|
if (e !== undefined) {
|
|
209
|
-
|
|
210
|
-
notifyKeyValue(e,
|
|
203
|
+
a++;
|
|
204
|
+
notifyKeyValue(e, l, d, c, f, n);
|
|
211
205
|
}
|
|
212
206
|
}
|
|
213
207
|
}
|
|
214
|
-
const
|
|
215
|
-
for (let
|
|
216
|
-
const
|
|
217
|
-
if (
|
|
218
|
-
const
|
|
219
|
-
if (!
|
|
220
|
-
if (
|
|
221
|
-
const e =
|
|
208
|
+
const c = Object.getOwnPropertySymbols(n);
|
|
209
|
+
for (let i = 0; i < c.length; i++) {
|
|
210
|
+
const l = c[i];
|
|
211
|
+
if (l === $OWNER) continue;
|
|
212
|
+
const u = n[l];
|
|
213
|
+
if (!r && u !== null && typeof u === "object") descend(unwrapValue(f[l]), u, t, o, e, l);
|
|
214
|
+
if (s !== null) {
|
|
215
|
+
const e = s[l];
|
|
222
216
|
if (e !== undefined) {
|
|
223
|
-
|
|
224
|
-
notifyKeyValue(e,
|
|
217
|
+
a++;
|
|
218
|
+
notifyKeyValue(e, l, f[l], u, f, n);
|
|
225
219
|
}
|
|
226
220
|
}
|
|
227
221
|
}
|
|
228
222
|
// Keys the incoming object no longer has still have nodes.
|
|
229
|
-
if (
|
|
230
|
-
for (const e of Reflect.ownKeys(
|
|
231
|
-
if (!hasOwnP.call(n, e)) notifyKeyDiff(
|
|
223
|
+
if (s !== null && a < e.nc) {
|
|
224
|
+
for (const e of Reflect.ownKeys(s)) {
|
|
225
|
+
if (!hasOwnP.call(n, e)) notifyKeyDiff(s[e], e, f, n, false);
|
|
232
226
|
}
|
|
233
227
|
}
|
|
234
|
-
notifyFoldTail(e,
|
|
228
|
+
notifyFoldTail(e, f, n);
|
|
235
229
|
}
|
|
236
230
|
|
|
237
231
|
const hasOwnP = Object.prototype.hasOwnProperty;
|
|
238
232
|
|
|
239
233
|
/** Descend into a changed child pair — only where something is proxied
|
|
240
234
|
* below (§6d), never into a raw-marked leaf, never across array/object or a
|
|
241
|
-
* key mismatch (that is a replacement, handled by the parent's slot).
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
235
|
+
* key mismatch (that is a replacement, handled by the parent's slot).
|
|
236
|
+
*
|
|
237
|
+
* A raw in both frames (the same objects swapped, reordered or shifted,
|
|
238
|
+
* #4001) must not leave two slots on one row. A raw already a live row keeps
|
|
239
|
+
* it at the slot it moved to; a row's `pk` follows the slot it sits at (a
|
|
240
|
+
* move or a pairing writes it), so a row whose raw is at that slot of the
|
|
241
|
+
* incoming frame is spoken for and not paired again here; a raw still
|
|
242
|
+
* resolving to a row that moved on drops the lookup (it wraps fresh, or is
|
|
243
|
+
* paired here). One lookup of `nv` on the common path, no allocation. */ function descend(e, n, t, o, f, i) {
|
|
244
|
+
// `nv` is an object at every call site.
|
|
245
|
+
if (e === null || typeof e !== "object") return;
|
|
246
|
+
const l = f.fam;
|
|
247
|
+
n = unwrapValue(n);
|
|
248
|
+
let r = lookupTarget(e, l);
|
|
249
|
+
const u = lookupTarget(n, l);
|
|
250
|
+
if (r !== undefined && r.pk !== i) {
|
|
251
|
+
if (r.pk != i && f.v[r.pk] === r.v) r = undefined; else if (r.u === f) r.pk = i;
|
|
252
|
+
}
|
|
253
|
+
if (u !== undefined && u !== r) {
|
|
254
|
+
if (u.v === n) {
|
|
255
|
+
if (u.u === f) u.pk = i;
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
(l?.map ?? storeLookup).delete(n);
|
|
259
|
+
}
|
|
260
|
+
if (r === undefined) return;
|
|
245
261
|
// nothing proxied below this pair
|
|
246
262
|
if (!isWrappable(n)) return;
|
|
247
263
|
if (rawValuesUsed && isRawValue(n)) return;
|
|
248
|
-
n = unwrapValue(n);
|
|
249
264
|
if (Array.isArray(e) !== Array.isArray(n)) return;
|
|
250
|
-
|
|
265
|
+
// An array slot was paired by key already (or both rows are keyless).
|
|
266
|
+
if (typeof i !== "number" && t) {
|
|
251
267
|
const o = t(e);
|
|
252
268
|
const f = t(n);
|
|
253
269
|
if (o !== undefined && f !== undefined && !sameKey(o, f)) return;
|
|
254
270
|
}
|
|
255
|
-
if (!
|
|
256
|
-
applyAdopt(
|
|
271
|
+
if (!o && t !== null && !r.d) return;
|
|
272
|
+
applyAdopt(r, n, t, o);
|
|
257
273
|
}
|
|
258
274
|
|
|
259
275
|
export { reconcileState };
|