@solidjs/signals 2.0.0-rc.16 → 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 +1972 -1751
- package/dist/dev.attribution.js +16 -16
- package/dist/dev.js +672 -319
- package/dist/observe/boundaries.js +2 -2
- package/dist/observe/core/async.js +151 -116
- package/dist/observe/core/constants.js +3 -1
- package/dist/observe/core/context.js +2 -0
- package/dist/observe/core/core.js +51 -35
- package/dist/observe/core/effect.js +29 -30
- package/dist/observe/core/graph.js +13 -11
- package/dist/observe/core/lanes.js +25 -14
- package/dist/observe/core/owner.js +77 -51
- package/dist/observe/core/scheduler.js +202 -175
- package/dist/observe/core/verdict.js +5 -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/map.js +2 -2
- package/dist/observe/signals.js +6 -1
- package/dist/observe/store/affects.js +13 -13
- package/dist/observe/store/optimistic.js +112 -71
- package/dist/observe/store/reconcile.js +137 -121
- package/dist/observe/store/store.js +612 -626
- package/dist/observe/store/target.js +1 -5
- package/dist/prod/boundaries.js +2 -2
- package/dist/prod/core/async.js +211 -176
- package/dist/prod/core/constants.js +3 -1
- package/dist/prod/core/context.js +2 -0
- package/dist/prod/core/core.js +63 -47
- package/dist/prod/core/effect.js +24 -25
- package/dist/prod/core/graph.js +12 -10
- package/dist/prod/core/heap.js +1 -1
- package/dist/prod/core/lanes.js +39 -28
- package/dist/prod/core/owner.js +70 -44
- package/dist/prod/core/scheduler.js +78 -51
- package/dist/prod/core/truth.js +4 -4
- package/dist/prod/core/verdict.js +11 -8
- package/dist/prod/deferred.js +17 -14
- package/dist/prod/from.js +248 -0
- package/dist/prod/index.js +2 -0
- package/dist/prod/map.js +2 -2
- package/dist/prod/signals.js +18 -13
- package/dist/prod/store/optimistic.js +112 -71
- package/dist/prod/store/reconcile.js +137 -121
- package/dist/prod/store/store.js +109 -121
- 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 +29 -6
- package/dist/types/core/dev.d.ts +9 -1
- package/dist/types/core/error.d.ts +9 -1
- package/dist/types/core/owner.d.ts +4 -0
- package/dist/types/core/scheduler.d.ts +38 -7
- package/dist/types/from.d.ts +47 -0
- package/dist/types/index.d.ts +1 -0
- package/package.json +1 -1
|
@@ -139,8 +139,8 @@ let probeFound = false;
|
|
|
139
139
|
* when every flight it waits on is. */ function quietPending(e) {
|
|
140
140
|
const t = e.T;
|
|
141
141
|
if (t === null) return false;
|
|
142
|
-
if (t.
|
|
143
|
-
for (const e of t.
|
|
142
|
+
if (t.se !== undefined) {
|
|
143
|
+
for (const e of t.se) if (!e.T?.ut) return false;
|
|
144
144
|
return true;
|
|
145
145
|
}
|
|
146
146
|
return t.ut;
|
|
@@ -323,6 +323,9 @@ let probeFound = false;
|
|
|
323
323
|
const u = (n.m & STATUS_PENDING) !== 0 && !quietPending(n);
|
|
324
324
|
if (e.l & CONFIG_GUESS) {
|
|
325
325
|
if (probing && (u || e.ue !== NOT_PENDING && (!e.Ye || !e.Ye(e.T.V, e.ue)))) probeFound = true;
|
|
326
|
+
// A lane a correction folded under (D-34): `latest()` shows the hold's
|
|
327
|
+
// world whole — the truth beneath each guess, else what it covered.
|
|
328
|
+
if (latestActive && r.folded) return r.folded(null, e);
|
|
326
329
|
return e.T.V;
|
|
327
330
|
}
|
|
328
331
|
if (probing && u) probeFound = true;
|
package/dist/observe/deferred.js
CHANGED
|
@@ -135,26 +135,26 @@ GlobalQueue.er = e => lagging.size !== 0 ? lagOf(e, new Set) : undefined;
|
|
|
135
135
|
// Sticky, and read before this wrapper ever opens the window itself.
|
|
136
136
|
const n = l ||= !(t.m & STATUS_UNINITIALIZED) && !t.ce;
|
|
137
137
|
if (n) t.ce = true, t.l |= CONFIG_LAGS;
|
|
138
|
-
let
|
|
138
|
+
let s;
|
|
139
139
|
try {
|
|
140
|
-
|
|
140
|
+
s = e(r);
|
|
141
141
|
} catch (e) {
|
|
142
142
|
// The wrapping form: an unready source parks the node in the window,
|
|
143
143
|
// and the wait is its flight until the source's settle re-runs it.
|
|
144
|
-
if (n && e instanceof NotReadyError) ask(e);
|
|
144
|
+
if (n && e instanceof NotReadyError) ask(e); else land(o);
|
|
145
145
|
throw e;
|
|
146
146
|
}
|
|
147
|
-
if (n && typeof
|
|
148
|
-
if (isThenable(
|
|
149
|
-
ask(
|
|
150
|
-
const done = () => land(
|
|
151
|
-
|
|
152
|
-
return serve(
|
|
147
|
+
if (n && typeof s === "object" && s !== null) {
|
|
148
|
+
if (isThenable(s)) {
|
|
149
|
+
ask(s);
|
|
150
|
+
const done = () => land(s, true);
|
|
151
|
+
s.then(done, done);
|
|
152
|
+
return serve(s);
|
|
153
153
|
}
|
|
154
|
-
const e =
|
|
154
|
+
const e = s[Symbol.asyncIterator];
|
|
155
155
|
if (e) {
|
|
156
156
|
// A stream's flight ends at its first yield (or its end).
|
|
157
|
-
const r = e.call(
|
|
157
|
+
const r = e.call(s);
|
|
158
158
|
let t = true;
|
|
159
159
|
const done = () => land(o, true);
|
|
160
160
|
const o = {
|
|
@@ -162,7 +162,10 @@ GlobalQueue.er = e => lagging.size !== 0 ? lagOf(e, new Set) : undefined;
|
|
|
162
162
|
// promise, as for a plain flight: verdict and value in one flush.
|
|
163
163
|
next: e => {
|
|
164
164
|
const o = r.next(e);
|
|
165
|
-
if (t)
|
|
165
|
+
if (t) {
|
|
166
|
+
t = false;
|
|
167
|
+
if (isThenable(o)) o.then(done, done); else done();
|
|
168
|
+
}
|
|
166
169
|
return o;
|
|
167
170
|
},
|
|
168
171
|
return: e => r.return?.(e) ?? Promise.resolve({
|
|
@@ -177,7 +180,7 @@ GlobalQueue.er = e => lagging.size !== 0 ? lagOf(e, new Set) : undefined;
|
|
|
177
180
|
}
|
|
178
181
|
}
|
|
179
182
|
land(o);
|
|
180
|
-
return
|
|
183
|
+
return s;
|
|
181
184
|
}, r));
|
|
182
185
|
}
|
|
183
186
|
|
|
@@ -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";
|
package/dist/observe/map.js
CHANGED
|
@@ -305,7 +305,7 @@ function updateKeyedMap() {
|
|
|
305
305
|
this.Kt && (this.Kt = []);
|
|
306
306
|
this.xt && (this.xt = []);
|
|
307
307
|
}
|
|
308
|
-
if (this.L && !this.vt
|
|
308
|
+
if (this.L && !this.vt.length) {
|
|
309
309
|
// an aborted fallback attempt leaves an owner without a mapping;
|
|
310
310
|
// dispose it before re-creating
|
|
311
311
|
this.je[0]?.dispose();
|
|
@@ -543,7 +543,7 @@ function updateRepeat() {
|
|
|
543
543
|
// Reset offset to match the cleared data (#2767, repro 2).
|
|
544
544
|
this.$t = 0;
|
|
545
545
|
}
|
|
546
|
-
if (this.L && !this.vt
|
|
546
|
+
if (this.L && !this.vt.length) {
|
|
547
547
|
// an aborted fallback attempt leaves an owner without a mapping;
|
|
548
548
|
// dispose it before re-creating
|
|
549
549
|
this.je[0]?.dispose();
|
package/dist/observe/signals.js
CHANGED
|
@@ -296,7 +296,12 @@ function createMemo(e, t) {
|
|
|
296
296
|
o = undefined;
|
|
297
297
|
}
|
|
298
298
|
runWithOwner(n, () => {
|
|
299
|
-
effect(() =>
|
|
299
|
+
effect(() => {
|
|
300
|
+
const e = getOwner();
|
|
301
|
+
o = e;
|
|
302
|
+
c();
|
|
303
|
+
return e;
|
|
304
|
+
}, t => {
|
|
300
305
|
o = undefined;
|
|
301
306
|
r?.();
|
|
302
307
|
const n = (e.effect || e)?.();
|
|
@@ -38,8 +38,8 @@ const scopes = new Map;
|
|
|
38
38
|
function scopeOf(e, o) {
|
|
39
39
|
let n = scopes.get(e);
|
|
40
40
|
if (n === undefined) scopes.set(e, n = {
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
oo: new Set,
|
|
42
|
+
no: [],
|
|
43
43
|
Vt: o
|
|
44
44
|
});
|
|
45
45
|
return n;
|
|
@@ -47,15 +47,15 @@ function scopeOf(e, o) {
|
|
|
47
47
|
|
|
48
48
|
/** The nodes an `affects(store[, key])` declaration marks (affects.ts
|
|
49
49
|
* registers each). */ function storeMarks(e, o) {
|
|
50
|
-
const n = GlobalQueue.
|
|
50
|
+
const n = GlobalQueue.so(e, o === undefined ? $AFFECTS : o);
|
|
51
51
|
const t = scopeOf(n, o);
|
|
52
52
|
if (o === undefined) {
|
|
53
53
|
const o = [ n ];
|
|
54
54
|
walk(e.px, t, o, e.fam, new Set);
|
|
55
55
|
return o;
|
|
56
56
|
}
|
|
57
|
-
t.
|
|
58
|
-
if (e.pb !== null) t.
|
|
57
|
+
t.oo.add(e.v);
|
|
58
|
+
if (e.pb !== null) t.oo.add(e.pb);
|
|
59
59
|
return [ n ];
|
|
60
60
|
}
|
|
61
61
|
|
|
@@ -63,14 +63,14 @@ function scopeOf(e, o) {
|
|
|
63
63
|
* the committed backing both, when a draft is open; an optimistic family's
|
|
64
64
|
* view), every live node under each record into `found`. Untracked by
|
|
65
65
|
* construction: raws, never traps. */ function walk(e, o, n, t, s) {
|
|
66
|
-
if (!GlobalQueue.
|
|
66
|
+
if (!GlobalQueue.fo(e)) return;
|
|
67
67
|
const f = e[$TARGET] ?? lookupTarget(e, t);
|
|
68
68
|
let r = f !== undefined ? f.pb ?? f.v : e;
|
|
69
69
|
if (s.has(r)) return;
|
|
70
70
|
s.add(r);
|
|
71
|
-
o.
|
|
71
|
+
o.oo.add(r);
|
|
72
72
|
if (f !== undefined) {
|
|
73
|
-
if (f.pb !== null) o.
|
|
73
|
+
if (f.pb !== null) o.oo.add(f.v);
|
|
74
74
|
// The writer's view: the tick's own unflushed guesses are in motion too.
|
|
75
75
|
if (f.fam?.opt === true) r = optHooks.view(f, r, true);
|
|
76
76
|
const e = f.n;
|
|
@@ -96,7 +96,7 @@ function scopeOf(e, o) {
|
|
|
96
96
|
for (const [t, s] of scopes) {
|
|
97
97
|
if (t === n || s.Vt !== undefined && s.Vt !== o) continue;
|
|
98
98
|
for (let o = e.v; ;) {
|
|
99
|
-
if (s.
|
|
99
|
+
if (s.oo.has(o)) return t;
|
|
100
100
|
const e = o?.[$TARGET];
|
|
101
101
|
if (e === undefined) break;
|
|
102
102
|
const n = e.pb ?? e.v;
|
|
@@ -112,17 +112,17 @@ function scopeOf(e, o) {
|
|
|
112
112
|
* no work. */ const hooks = {
|
|
113
113
|
// A node born on a record a live mark covers inherits it (released with
|
|
114
114
|
// the carrier's last registration).
|
|
115
|
-
|
|
115
|
+
ro(e, o, n) {
|
|
116
116
|
if (scopes.size === 0 || n === $AFFECTS) return;
|
|
117
117
|
const t = covering(e, n, o);
|
|
118
118
|
if (!t) return;
|
|
119
119
|
GlobalQueue.N(o);
|
|
120
|
-
scopes.get(t).
|
|
120
|
+
scopes.get(t).no.push(o);
|
|
121
121
|
},
|
|
122
122
|
// An untracked probe (`isPending(() => s.x)` with no observer) reading a
|
|
123
123
|
// record a live mark covers: no node carries the mark for it — the
|
|
124
124
|
// verdict is told directly.
|
|
125
|
-
|
|
125
|
+
io(e, o) {
|
|
126
126
|
if (e.n?.[$AFFECTS]?.T?.I || covering(e, o)) GlobalQueue.bt();
|
|
127
127
|
}
|
|
128
128
|
};
|
|
@@ -136,7 +136,7 @@ function scopeOf(e, o) {
|
|
|
136
136
|
const o = scopes.get(e);
|
|
137
137
|
if (o === undefined) return;
|
|
138
138
|
scopes.delete(e);
|
|
139
|
-
releaseMarksHook(o.
|
|
139
|
+
releaseMarksHook(o.no);
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
export { installStoreAffects, releaseMarkScope, storeMarks };
|