@solidjs/signals 0.13.13 → 2.0.0-beta.11
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 +8 -7
- package/dist/dev.js +1230 -598
- package/dist/node.cjs +2064 -1555
- package/dist/prod.js +1783 -1251
- package/dist/types/boundaries.d.ts +126 -5
- package/dist/types/core/action.d.ts +34 -0
- package/dist/types/core/constants.d.ts +26 -0
- package/dist/types/core/context.d.ts +10 -2
- package/dist/types/core/core.d.ts +129 -9
- package/dist/types/core/dev.d.ts +1 -1
- package/dist/types/core/effect.d.ts +4 -2
- package/dist/types/core/error.d.ts +24 -0
- package/dist/types/core/external.d.ts +19 -0
- package/dist/types/core/graph.d.ts +2 -0
- package/dist/types/core/index.d.ts +1 -1
- package/dist/types/core/owner.d.ts +93 -3
- package/dist/types/core/scheduler.d.ts +43 -2
- package/dist/types/core/types.d.ts +5 -6
- package/dist/types/index.d.ts +3 -3
- package/dist/types/map.d.ts +32 -3
- package/dist/types/signals.d.ts +362 -42
- package/dist/types/src/boundaries.d.ts +173 -0
- package/dist/types/src/core/action.d.ts +35 -0
- package/dist/types/src/core/async.d.ts +6 -0
- package/dist/types/src/core/constants.d.ts +51 -0
- package/dist/types/src/core/context.d.ts +36 -0
- package/dist/types/src/core/core.d.ts +174 -0
- package/dist/types/src/core/dev.d.ts +49 -0
- package/dist/types/src/core/effect.d.ts +32 -0
- package/dist/types/src/core/error.d.ts +38 -0
- package/dist/types/src/core/external.d.ts +45 -0
- package/dist/types/src/core/graph.d.ts +5 -0
- package/dist/types/src/core/heap.d.ts +14 -0
- package/dist/types/src/core/index.d.ts +12 -0
- package/dist/types/src/core/lanes.d.ts +54 -0
- package/dist/types/src/core/owner.d.ts +116 -0
- package/dist/types/src/core/scheduler.d.ts +122 -0
- package/dist/types/src/core/types.d.ts +85 -0
- package/dist/types/src/index.d.ts +9 -0
- package/dist/types/src/map.d.ts +53 -0
- package/dist/types/src/signals.d.ts +512 -0
- package/dist/types/src/store/index.d.ts +9 -0
- package/dist/types/src/store/optimistic.d.ts +45 -0
- package/dist/types/src/store/projection.d.ts +66 -0
- package/dist/types/src/store/reconcile.d.ts +23 -0
- package/dist/types/src/store/store.d.ts +125 -0
- package/dist/types/src/store/storePath.d.ts +58 -0
- package/dist/types/src/store/utils.d.ts +114 -0
- package/dist/types/store/optimistic.d.ts +38 -12
- package/dist/types/store/projection.d.ts +55 -15
- package/dist/types/store/reconcile.d.ts +22 -0
- package/dist/types/store/store.d.ts +72 -15
- package/dist/types/store/storePath.d.ts +28 -0
- package/dist/types/store/utils.d.ts +78 -7
- package/dist/types-cjs/boundaries.d.cts +173 -0
- package/dist/types-cjs/core/action.d.cts +35 -0
- package/dist/types-cjs/core/async.d.cts +6 -0
- package/dist/types-cjs/core/constants.d.cts +51 -0
- package/dist/types-cjs/core/context.d.cts +36 -0
- package/dist/types-cjs/core/core.d.cts +174 -0
- package/dist/types-cjs/core/dev.d.cts +49 -0
- package/dist/types-cjs/core/effect.d.cts +32 -0
- package/dist/types-cjs/core/error.d.cts +38 -0
- package/dist/types-cjs/core/external.d.cts +45 -0
- package/dist/types-cjs/core/graph.d.cts +5 -0
- package/dist/types-cjs/core/heap.d.cts +14 -0
- package/dist/types-cjs/core/index.d.cts +12 -0
- package/dist/types-cjs/core/lanes.d.cts +54 -0
- package/dist/types-cjs/core/owner.d.cts +116 -0
- package/dist/types-cjs/core/scheduler.d.cts +122 -0
- package/dist/types-cjs/core/types.d.cts +85 -0
- package/dist/types-cjs/index.d.cts +9 -0
- package/dist/types-cjs/map.d.cts +53 -0
- package/dist/types-cjs/package.json +3 -0
- package/dist/types-cjs/signals.d.cts +512 -0
- package/dist/types-cjs/src/boundaries.d.cts +173 -0
- package/dist/types-cjs/src/core/action.d.cts +35 -0
- package/dist/types-cjs/src/core/async.d.cts +6 -0
- package/dist/types-cjs/src/core/constants.d.cts +51 -0
- package/dist/types-cjs/src/core/context.d.cts +36 -0
- package/dist/types-cjs/src/core/core.d.cts +174 -0
- package/dist/types-cjs/src/core/dev.d.cts +49 -0
- package/dist/types-cjs/src/core/effect.d.cts +32 -0
- package/dist/types-cjs/src/core/error.d.cts +38 -0
- package/dist/types-cjs/src/core/external.d.cts +45 -0
- package/dist/types-cjs/src/core/graph.d.cts +5 -0
- package/dist/types-cjs/src/core/heap.d.cts +14 -0
- package/dist/types-cjs/src/core/index.d.cts +12 -0
- package/dist/types-cjs/src/core/lanes.d.cts +54 -0
- package/dist/types-cjs/src/core/owner.d.cts +116 -0
- package/dist/types-cjs/src/core/scheduler.d.cts +122 -0
- package/dist/types-cjs/src/core/types.d.cts +85 -0
- package/dist/types-cjs/src/index.d.cts +9 -0
- package/dist/types-cjs/src/map.d.cts +53 -0
- package/dist/types-cjs/src/signals.d.cts +512 -0
- package/dist/types-cjs/src/store/index.d.cts +9 -0
- package/dist/types-cjs/src/store/optimistic.d.cts +45 -0
- package/dist/types-cjs/src/store/projection.d.cts +66 -0
- package/dist/types-cjs/src/store/reconcile.d.cts +23 -0
- package/dist/types-cjs/src/store/store.d.cts +125 -0
- package/dist/types-cjs/src/store/storePath.d.cts +58 -0
- package/dist/types-cjs/src/store/utils.d.cts +114 -0
- package/dist/types-cjs/store/index.d.cts +9 -0
- package/dist/types-cjs/store/optimistic.d.cts +45 -0
- package/dist/types-cjs/store/projection.d.cts +66 -0
- package/dist/types-cjs/store/reconcile.d.cts +23 -0
- package/dist/types-cjs/store/store.d.cts +125 -0
- package/dist/types-cjs/store/storePath.d.cts +58 -0
- package/dist/types-cjs/store/utils.d.cts +114 -0
- package/package.json +35 -27
package/dist/dev.js
CHANGED
|
@@ -35,6 +35,14 @@ const REACTIVE_DISPOSED = 1 << 6;
|
|
|
35
35
|
const REACTIVE_OPTIMISTIC_DIRTY = 1 << 7;
|
|
36
36
|
const REACTIVE_SNAPSHOT_STALE = 1 << 8;
|
|
37
37
|
const REACTIVE_LAZY = 1 << 9;
|
|
38
|
+
const REACTIVE_MANUAL_WRITE = 1 << 10;
|
|
39
|
+
const CONFIG_OWNED_WRITE = 1 << 0;
|
|
40
|
+
const CONFIG_NO_SNAPSHOT = 1 << 1;
|
|
41
|
+
const CONFIG_TRANSPARENT = 1 << 2;
|
|
42
|
+
const CONFIG_IN_SNAPSHOT_SCOPE = 1 << 3;
|
|
43
|
+
const CONFIG_CHILDREN_FORBIDDEN = 1 << 4;
|
|
44
|
+
const CONFIG_AUTO_DISPOSE = 1 << 5;
|
|
45
|
+
const CONFIG_SYNC = 1 << 6;
|
|
38
46
|
const STATUS_PENDING = 1 << 0;
|
|
39
47
|
const STATUS_ERROR = 1 << 1;
|
|
40
48
|
const STATUS_UNINITIALIZED = 1 << 2;
|
|
@@ -47,6 +55,91 @@ const STORE_SNAPSHOT_PROPS = "sp";
|
|
|
47
55
|
const SUPPORTS_PROXY = typeof Proxy === "function";
|
|
48
56
|
const defaultContext = {};
|
|
49
57
|
const $REFRESH = Symbol("refresh");
|
|
58
|
+
const hooks = {};
|
|
59
|
+
const diagnosticListeners = new Set();
|
|
60
|
+
const diagnosticCaptures = new Set();
|
|
61
|
+
let diagnosticSequence = 0;
|
|
62
|
+
const diagnostics = {
|
|
63
|
+
subscribe(listener) {
|
|
64
|
+
diagnosticListeners.add(listener);
|
|
65
|
+
return () => diagnosticListeners.delete(listener);
|
|
66
|
+
},
|
|
67
|
+
capture() {
|
|
68
|
+
const events = [];
|
|
69
|
+
diagnosticCaptures.add(events);
|
|
70
|
+
return {
|
|
71
|
+
get events() {
|
|
72
|
+
return events;
|
|
73
|
+
},
|
|
74
|
+
clear() {
|
|
75
|
+
events.length = 0;
|
|
76
|
+
},
|
|
77
|
+
stop() {
|
|
78
|
+
diagnosticCaptures.delete(events);
|
|
79
|
+
return [...events];
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
const DEV$1 = {
|
|
85
|
+
hooks: hooks,
|
|
86
|
+
diagnostics: diagnostics,
|
|
87
|
+
getChildren: getChildren,
|
|
88
|
+
getSignals: getSignals,
|
|
89
|
+
getParent: getParent,
|
|
90
|
+
getSources: getSources,
|
|
91
|
+
getObservers: getObservers
|
|
92
|
+
};
|
|
93
|
+
function emitDiagnostic(event) {
|
|
94
|
+
const entry = { sequence: ++diagnosticSequence, ...event };
|
|
95
|
+
for (const listener of diagnosticListeners) listener(entry);
|
|
96
|
+
for (const capture of diagnosticCaptures) capture.push(entry);
|
|
97
|
+
return entry;
|
|
98
|
+
}
|
|
99
|
+
function registerGraph(value, owner) {
|
|
100
|
+
value._owner = owner;
|
|
101
|
+
if (owner) {
|
|
102
|
+
if (!owner._signals) owner._signals = [];
|
|
103
|
+
owner._signals.push(value);
|
|
104
|
+
}
|
|
105
|
+
DEV$1.hooks.onGraph?.(value, owner);
|
|
106
|
+
}
|
|
107
|
+
function clearSignals(node) {
|
|
108
|
+
node._signals = undefined;
|
|
109
|
+
}
|
|
110
|
+
function getChildren(owner) {
|
|
111
|
+
const children = [];
|
|
112
|
+
let child = owner._firstChild;
|
|
113
|
+
while (child) {
|
|
114
|
+
children.push(child);
|
|
115
|
+
child = child._nextSibling;
|
|
116
|
+
}
|
|
117
|
+
return children;
|
|
118
|
+
}
|
|
119
|
+
function getSignals(owner) {
|
|
120
|
+
return owner._signals ? [...owner._signals] : [];
|
|
121
|
+
}
|
|
122
|
+
function getParent(owner) {
|
|
123
|
+
return owner._parent;
|
|
124
|
+
}
|
|
125
|
+
function getSources(computation) {
|
|
126
|
+
const sources = [];
|
|
127
|
+
let link = computation._deps;
|
|
128
|
+
while (link) {
|
|
129
|
+
sources.push(link._dep);
|
|
130
|
+
link = link._nextDep;
|
|
131
|
+
}
|
|
132
|
+
return sources;
|
|
133
|
+
}
|
|
134
|
+
function getObservers(node) {
|
|
135
|
+
const observers = [];
|
|
136
|
+
let link = node._subs;
|
|
137
|
+
while (link) {
|
|
138
|
+
observers.push(link._sub);
|
|
139
|
+
link = link._nextSub;
|
|
140
|
+
}
|
|
141
|
+
return observers;
|
|
142
|
+
}
|
|
50
143
|
function actualInsertIntoHeap(n, heap) {
|
|
51
144
|
const parentHeight =
|
|
52
145
|
(n._parent?._root ? n._parent._parentComputed?._height : n._parent?._height) ?? -1;
|
|
@@ -64,7 +157,7 @@ function actualInsertIntoHeap(n, heap) {
|
|
|
64
157
|
}
|
|
65
158
|
function insertIntoHeap(n, heap) {
|
|
66
159
|
let flags = n._flags;
|
|
67
|
-
if (flags & (REACTIVE_IN_HEAP | REACTIVE_RECOMPUTING_DEPS)) return;
|
|
160
|
+
if (flags & (REACTIVE_IN_HEAP | REACTIVE_RECOMPUTING_DEPS | REACTIVE_MANUAL_WRITE)) return;
|
|
68
161
|
if (flags & REACTIVE_CHECK) {
|
|
69
162
|
n._flags = (flags & -4) | REACTIVE_DIRTY | REACTIVE_IN_HEAP;
|
|
70
163
|
} else n._flags = flags | REACTIVE_IN_HEAP;
|
|
@@ -72,7 +165,11 @@ function insertIntoHeap(n, heap) {
|
|
|
72
165
|
}
|
|
73
166
|
function insertIntoHeapHeight(n, heap) {
|
|
74
167
|
let flags = n._flags;
|
|
75
|
-
if (
|
|
168
|
+
if (
|
|
169
|
+
flags &
|
|
170
|
+
(REACTIVE_IN_HEAP | REACTIVE_RECOMPUTING_DEPS | REACTIVE_IN_HEAP_HEIGHT | REACTIVE_MANUAL_WRITE)
|
|
171
|
+
)
|
|
172
|
+
return;
|
|
76
173
|
n._flags = flags | REACTIVE_IN_HEAP_HEIGHT;
|
|
77
174
|
actualInsertIntoHeap(n, heap);
|
|
78
175
|
}
|
|
@@ -144,90 +241,76 @@ function adjustHeight(el, heap) {
|
|
|
144
241
|
}
|
|
145
242
|
}
|
|
146
243
|
}
|
|
147
|
-
const
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
let
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
diagnosticListeners.add(listener);
|
|
154
|
-
return () => diagnosticListeners.delete(listener);
|
|
155
|
-
},
|
|
156
|
-
capture() {
|
|
157
|
-
const events = [];
|
|
158
|
-
diagnosticCaptures.add(events);
|
|
159
|
-
return {
|
|
160
|
-
get events() {
|
|
161
|
-
return events;
|
|
162
|
-
},
|
|
163
|
-
clear() {
|
|
164
|
-
events.length = 0;
|
|
165
|
-
},
|
|
166
|
-
stop() {
|
|
167
|
-
diagnosticCaptures.delete(events);
|
|
168
|
-
return [...events];
|
|
169
|
-
}
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
};
|
|
173
|
-
const DEV$1 = {
|
|
174
|
-
hooks: hooks,
|
|
175
|
-
diagnostics: diagnostics,
|
|
176
|
-
getChildren: getChildren,
|
|
177
|
-
getSignals: getSignals,
|
|
178
|
-
getParent: getParent,
|
|
179
|
-
getSources: getSources,
|
|
180
|
-
getObservers: getObservers
|
|
181
|
-
};
|
|
182
|
-
function emitDiagnostic(event) {
|
|
183
|
-
const entry = { sequence: ++diagnosticSequence, ...event };
|
|
184
|
-
for (const listener of diagnosticListeners) listener(entry);
|
|
185
|
-
for (const capture of diagnosticCaptures) capture.push(entry);
|
|
186
|
-
return entry;
|
|
187
|
-
}
|
|
188
|
-
function registerGraph(value, owner) {
|
|
189
|
-
value._owner = owner;
|
|
190
|
-
if (owner) {
|
|
191
|
-
if (!owner._signals) owner._signals = [];
|
|
192
|
-
owner._signals.push(value);
|
|
244
|
+
const signalLanes = new WeakMap();
|
|
245
|
+
const activeLanes = new Set();
|
|
246
|
+
function getOrCreateLane(signal) {
|
|
247
|
+
let lane = signalLanes.get(signal);
|
|
248
|
+
if (lane) {
|
|
249
|
+
return findLane(lane);
|
|
193
250
|
}
|
|
194
|
-
|
|
251
|
+
const parentSource = signal._parentSource;
|
|
252
|
+
const parentLane = parentSource?._optimisticLane ? findLane(parentSource._optimisticLane) : null;
|
|
253
|
+
lane = {
|
|
254
|
+
_source: signal,
|
|
255
|
+
_pendingAsync: new Set(),
|
|
256
|
+
_effectQueues: [[], []],
|
|
257
|
+
_mergedInto: null,
|
|
258
|
+
_transition: activeTransition,
|
|
259
|
+
_parentLane: parentLane
|
|
260
|
+
};
|
|
261
|
+
signalLanes.set(signal, lane);
|
|
262
|
+
activeLanes.add(lane);
|
|
263
|
+
signal._overrideSinceLane = false;
|
|
264
|
+
return lane;
|
|
195
265
|
}
|
|
196
|
-
function
|
|
197
|
-
|
|
266
|
+
function findLane(lane) {
|
|
267
|
+
while (lane._mergedInto) lane = lane._mergedInto;
|
|
268
|
+
return lane;
|
|
198
269
|
}
|
|
199
|
-
function
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
270
|
+
function mergeLanes(lane1, lane2) {
|
|
271
|
+
lane1 = findLane(lane1);
|
|
272
|
+
lane2 = findLane(lane2);
|
|
273
|
+
if (lane1 === lane2) return lane1;
|
|
274
|
+
lane2._mergedInto = lane1;
|
|
275
|
+
for (const node of lane2._pendingAsync) lane1._pendingAsync.add(node);
|
|
276
|
+
lane1._effectQueues[0].push(...lane2._effectQueues[0]);
|
|
277
|
+
lane1._effectQueues[1].push(...lane2._effectQueues[1]);
|
|
278
|
+
return lane1;
|
|
207
279
|
}
|
|
208
|
-
function
|
|
209
|
-
|
|
280
|
+
function resolveLane(el) {
|
|
281
|
+
const lane = el._optimisticLane;
|
|
282
|
+
if (!lane) return undefined;
|
|
283
|
+
const root = findLane(lane);
|
|
284
|
+
if (activeLanes.has(root)) return root;
|
|
285
|
+
el._optimisticLane = undefined;
|
|
286
|
+
return undefined;
|
|
210
287
|
}
|
|
211
|
-
function
|
|
212
|
-
return
|
|
288
|
+
function resolveTransition(el) {
|
|
289
|
+
return resolveLane(el)?._transition ?? el._transition;
|
|
213
290
|
}
|
|
214
|
-
function
|
|
215
|
-
|
|
216
|
-
let link = computation._deps;
|
|
217
|
-
while (link) {
|
|
218
|
-
sources.push(link._dep);
|
|
219
|
-
link = link._nextDep;
|
|
220
|
-
}
|
|
221
|
-
return sources;
|
|
291
|
+
function hasActiveOverride(el) {
|
|
292
|
+
return !!(el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING);
|
|
222
293
|
}
|
|
223
|
-
function
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
294
|
+
function assignOrMergeLane(el, sourceLane) {
|
|
295
|
+
const sourceRoot = findLane(sourceLane);
|
|
296
|
+
const existing = el._optimisticLane;
|
|
297
|
+
if (existing) {
|
|
298
|
+
if (existing._mergedInto) {
|
|
299
|
+
el._optimisticLane = sourceLane;
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
const existingRoot = findLane(existing);
|
|
303
|
+
if (activeLanes.has(existingRoot)) {
|
|
304
|
+
if (existingRoot !== sourceRoot && !hasActiveOverride(el)) {
|
|
305
|
+
if (sourceRoot._parentLane && findLane(sourceRoot._parentLane) === existingRoot) {
|
|
306
|
+
el._optimisticLane = sourceLane;
|
|
307
|
+
} else if (existingRoot._parentLane && findLane(existingRoot._parentLane) === sourceRoot);
|
|
308
|
+
else mergeLanes(sourceRoot, existingRoot);
|
|
309
|
+
}
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
229
312
|
}
|
|
230
|
-
|
|
313
|
+
el._optimisticLane = sourceLane;
|
|
231
314
|
}
|
|
232
315
|
const transitions = new Set();
|
|
233
316
|
const dirtyQueue = { _heap: new Array(2e3).fill(undefined), _marked: false, _min: 0, _max: 0 };
|
|
@@ -235,11 +318,39 @@ const zombieQueue = { _heap: new Array(2e3).fill(undefined), _marked: false, _mi
|
|
|
235
318
|
let clock = 0;
|
|
236
319
|
let activeTransition = null;
|
|
237
320
|
let scheduled = false;
|
|
321
|
+
let syncDepth = 0;
|
|
238
322
|
let projectionWriteActive = false;
|
|
239
323
|
let inTrackedQueueCallback = false;
|
|
240
324
|
let _enforceLoadingBoundary = false;
|
|
241
325
|
let _hitUnhandledAsync = false;
|
|
242
326
|
let stashedOptimisticReads = null;
|
|
327
|
+
const transientStoreNodes = new Set();
|
|
328
|
+
function registerTransientStoreNode(node) {
|
|
329
|
+
transientStoreNodes.add(node);
|
|
330
|
+
}
|
|
331
|
+
function canUseSimpleSyncFlush(queue) {
|
|
332
|
+
return (
|
|
333
|
+
transitions.size === 0 &&
|
|
334
|
+
activeLanes.size === 0 &&
|
|
335
|
+
queue._children.length === 0 &&
|
|
336
|
+
queue._optimisticNodes.length === 0 &&
|
|
337
|
+
queue._optimisticStores.size === 0 &&
|
|
338
|
+
transientStoreNodes.size === 0
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
function sweepTransientStoreNodes() {
|
|
342
|
+
if (transientStoreNodes.size === 0) return;
|
|
343
|
+
for (const node of transientStoreNodes) {
|
|
344
|
+
if (node._subs !== null) {
|
|
345
|
+
transientStoreNodes.delete(node);
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
if (node._pendingValue !== NOT_PENDING) continue;
|
|
349
|
+
if (node._overrideValue !== undefined && node._overrideValue !== NOT_PENDING) continue;
|
|
350
|
+
transientStoreNodes.delete(node);
|
|
351
|
+
node._unobserved?.();
|
|
352
|
+
}
|
|
353
|
+
}
|
|
243
354
|
function resetUnhandledAsync() {
|
|
244
355
|
_hitUnhandledAsync = false;
|
|
245
356
|
}
|
|
@@ -292,6 +403,7 @@ function mergeTransitionState(target, outgoing) {
|
|
|
292
403
|
if (!targetReporters) target._asyncReporters.set(source, (targetReporters = new Set()));
|
|
293
404
|
for (const reporter of reporters) targetReporters.add(reporter);
|
|
294
405
|
}
|
|
406
|
+
for (const sub of outgoing._gatedSubs) target._gatedSubs.add(sub);
|
|
295
407
|
}
|
|
296
408
|
function resolveOptimisticNodes(nodes) {
|
|
297
409
|
for (let i = 0; i < nodes.length; i++) {
|
|
@@ -329,7 +441,7 @@ function cleanupCompletedLanes(completingTransition) {
|
|
|
329
441
|
function schedule() {
|
|
330
442
|
if (scheduled) return;
|
|
331
443
|
scheduled = true;
|
|
332
|
-
if (!globalQueue._running && !projectionWriteActive) queueMicrotask(flush);
|
|
444
|
+
if (!syncDepth && !globalQueue._running && !projectionWriteActive) queueMicrotask(flush);
|
|
333
445
|
}
|
|
334
446
|
class Queue {
|
|
335
447
|
_parent = null;
|
|
@@ -396,11 +508,13 @@ class Queue {
|
|
|
396
508
|
}
|
|
397
509
|
class GlobalQueue extends Queue {
|
|
398
510
|
_running = false;
|
|
511
|
+
_pendingNode = null;
|
|
399
512
|
_pendingNodes = [];
|
|
400
513
|
_optimisticNodes = [];
|
|
401
514
|
_optimisticStores = new Set();
|
|
402
515
|
static _update;
|
|
403
516
|
static _dispose;
|
|
517
|
+
static _runEffect;
|
|
404
518
|
static _clearOptimisticStore = null;
|
|
405
519
|
flush() {
|
|
406
520
|
if (this._running) return;
|
|
@@ -412,6 +526,7 @@ class GlobalQueue extends Queue {
|
|
|
412
526
|
if (!isComplete) {
|
|
413
527
|
const stashedTransition = activeTransition;
|
|
414
528
|
runHeap(zombieQueue, GlobalQueue._update);
|
|
529
|
+
this._pendingNode = null;
|
|
415
530
|
this._pendingNodes = [];
|
|
416
531
|
this._optimisticNodes = [];
|
|
417
532
|
this._optimisticStores = new Set();
|
|
@@ -422,11 +537,15 @@ class GlobalQueue extends Queue {
|
|
|
422
537
|
scheduled = dirtyQueue._max >= dirtyQueue._min;
|
|
423
538
|
reassignPendingTransition(stashedTransition._pendingNodes);
|
|
424
539
|
activeTransition = null;
|
|
425
|
-
if (
|
|
540
|
+
if (
|
|
541
|
+
!stashedTransition._actions.length &&
|
|
542
|
+
!stashedTransition._asyncReporters.size &&
|
|
543
|
+
stashedTransition._optimisticNodes.length
|
|
544
|
+
) {
|
|
426
545
|
stashedOptimisticReads = new Set();
|
|
427
546
|
for (let i = 0; i < stashedTransition._optimisticNodes.length; i++) {
|
|
428
547
|
const node = stashedTransition._optimisticNodes[i];
|
|
429
|
-
if (node._fn || node.
|
|
548
|
+
if (node._fn || node._config & CONFIG_OWNED_WRITE) continue;
|
|
430
549
|
stashedOptimisticReads.add(node);
|
|
431
550
|
queueStashedOptimisticEffects(node);
|
|
432
551
|
}
|
|
@@ -447,14 +566,22 @@ class GlobalQueue extends Queue {
|
|
|
447
566
|
reassignPendingTransition(this._pendingNodes);
|
|
448
567
|
finalizePureQueue(completingTransition);
|
|
449
568
|
} else {
|
|
450
|
-
if (
|
|
451
|
-
|
|
569
|
+
if (canUseSimpleSyncFlush(this)) {
|
|
570
|
+
commitPendingNodes();
|
|
571
|
+
if (dirtyQueue._max >= dirtyQueue._min) {
|
|
572
|
+
runHeap(dirtyQueue, GlobalQueue._update);
|
|
573
|
+
commitPendingNodes();
|
|
574
|
+
}
|
|
575
|
+
} else {
|
|
576
|
+
if (transitions.size) runHeap(zombieQueue, GlobalQueue._update);
|
|
577
|
+
finalizePureQueue();
|
|
578
|
+
}
|
|
452
579
|
}
|
|
453
580
|
clock++;
|
|
454
581
|
scheduled = dirtyQueue._max >= dirtyQueue._min;
|
|
455
|
-
runLaneEffects(EFFECT_RENDER);
|
|
582
|
+
activeLanes.size && runLaneEffects(EFFECT_RENDER);
|
|
456
583
|
this.run(EFFECT_RENDER);
|
|
457
|
-
runLaneEffects(EFFECT_USER);
|
|
584
|
+
activeLanes.size && runLaneEffects(EFFECT_USER);
|
|
458
585
|
this.run(EFFECT_USER);
|
|
459
586
|
if (true) DEV$1.hooks.onUpdate?.();
|
|
460
587
|
} finally {
|
|
@@ -492,7 +619,8 @@ class GlobalQueue extends Queue {
|
|
|
492
619
|
_optimisticStores: new Set(),
|
|
493
620
|
_actions: [],
|
|
494
621
|
_queueStash: { _queues: [[], []], _children: [] },
|
|
495
|
-
_done: false
|
|
622
|
+
_done: false,
|
|
623
|
+
_gatedSubs: new Set()
|
|
496
624
|
};
|
|
497
625
|
} else if (transition) {
|
|
498
626
|
const outgoing = activeTransition;
|
|
@@ -502,6 +630,11 @@ class GlobalQueue extends Queue {
|
|
|
502
630
|
}
|
|
503
631
|
transitions.add(activeTransition);
|
|
504
632
|
activeTransition._time = clock;
|
|
633
|
+
if (this._pendingNode !== null) {
|
|
634
|
+
this._pendingNode._transition = activeTransition;
|
|
635
|
+
activeTransition._pendingNodes.push(this._pendingNode);
|
|
636
|
+
this._pendingNode = null;
|
|
637
|
+
}
|
|
505
638
|
if (this._pendingNodes !== activeTransition._pendingNodes) {
|
|
506
639
|
for (let i = 0; i < this._pendingNodes.length; i++) {
|
|
507
640
|
const node = this._pendingNodes[i];
|
|
@@ -527,11 +660,26 @@ class GlobalQueue extends Queue {
|
|
|
527
660
|
}
|
|
528
661
|
}
|
|
529
662
|
}
|
|
663
|
+
function queuePendingNode(node) {
|
|
664
|
+
if (activeTransition) {
|
|
665
|
+
globalQueue._pendingNodes.push(node);
|
|
666
|
+
return;
|
|
667
|
+
}
|
|
668
|
+
if (globalQueue._pendingNode === null && globalQueue._pendingNodes.length === 0) {
|
|
669
|
+
globalQueue._pendingNode = node;
|
|
670
|
+
return;
|
|
671
|
+
}
|
|
672
|
+
if (globalQueue._pendingNode !== null) {
|
|
673
|
+
globalQueue._pendingNodes.push(globalQueue._pendingNode);
|
|
674
|
+
globalQueue._pendingNode = null;
|
|
675
|
+
}
|
|
676
|
+
globalQueue._pendingNodes.push(node);
|
|
677
|
+
}
|
|
530
678
|
function insertSubs(node, optimistic = false) {
|
|
531
679
|
const sourceLane = node._optimisticLane || currentOptimisticLane;
|
|
532
680
|
const hasSnapshot = node._snapshotValue !== undefined;
|
|
533
681
|
for (let s = node._subs; s !== null; s = s._nextSub) {
|
|
534
|
-
if (hasSnapshot && s._sub.
|
|
682
|
+
if (hasSnapshot && s._sub._config & CONFIG_IN_SNAPSHOT_SCOPE) {
|
|
535
683
|
s._sub._flags |= REACTIVE_SNAPSHOT_STALE;
|
|
536
684
|
continue;
|
|
537
685
|
}
|
|
@@ -555,30 +703,63 @@ function insertSubs(node, optimistic = false) {
|
|
|
555
703
|
insertIntoHeap(s._sub, queue);
|
|
556
704
|
}
|
|
557
705
|
}
|
|
558
|
-
function
|
|
559
|
-
const
|
|
560
|
-
|
|
561
|
-
const n = pendingNodes[i];
|
|
706
|
+
function commitPendingNode(n) {
|
|
707
|
+
const c = n;
|
|
708
|
+
if (!c._fn) {
|
|
562
709
|
if (n._pendingValue !== NOT_PENDING) {
|
|
563
710
|
n._value = n._pendingValue;
|
|
564
711
|
n._pendingValue = NOT_PENDING;
|
|
565
|
-
if (n._type && n._type !== EFFECT_TRACKED) n._modified = true;
|
|
566
712
|
}
|
|
567
|
-
|
|
568
|
-
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
if (n._pendingValue !== NOT_PENDING) {
|
|
716
|
+
n._value = n._pendingValue;
|
|
717
|
+
n._pendingValue = NOT_PENDING;
|
|
718
|
+
if (n._type && n._type !== EFFECT_TRACKED) n._modified = true;
|
|
719
|
+
}
|
|
720
|
+
c._flags &= ~REACTIVE_MANUAL_WRITE;
|
|
721
|
+
if (!(c._statusFlags & STATUS_PENDING)) c._statusFlags &= ~STATUS_UNINITIALIZED;
|
|
722
|
+
if (c._pendingFirstChild !== null || c._pendingDisposal !== null)
|
|
723
|
+
GlobalQueue._dispose(c, false, true);
|
|
724
|
+
}
|
|
725
|
+
function commitPendingNodes() {
|
|
726
|
+
if (globalQueue._pendingNode !== null) {
|
|
727
|
+
commitPendingNode(globalQueue._pendingNode);
|
|
728
|
+
globalQueue._pendingNode = null;
|
|
729
|
+
}
|
|
730
|
+
const pendingNodes = globalQueue._pendingNodes;
|
|
731
|
+
for (let i = 0; i < pendingNodes.length; i++) {
|
|
732
|
+
commitPendingNode(pendingNodes[i]);
|
|
569
733
|
}
|
|
570
734
|
pendingNodes.length = 0;
|
|
571
735
|
}
|
|
572
736
|
function finalizePureQueue(completingTransition = null, incomplete = false) {
|
|
573
737
|
const resolvePending = !incomplete;
|
|
574
738
|
if (resolvePending) commitPendingNodes();
|
|
575
|
-
if (!incomplete) checkBoundaryChildren(globalQueue);
|
|
576
|
-
|
|
739
|
+
if (!incomplete && globalQueue._children.length) checkBoundaryChildren(globalQueue);
|
|
740
|
+
const ranHeap = dirtyQueue._max >= dirtyQueue._min;
|
|
741
|
+
if (ranHeap) runHeap(dirtyQueue, GlobalQueue._update);
|
|
577
742
|
if (resolvePending) {
|
|
578
|
-
commitPendingNodes();
|
|
743
|
+
if (ranHeap) commitPendingNodes();
|
|
579
744
|
resolveOptimisticNodes(
|
|
580
745
|
completingTransition ? completingTransition._optimisticNodes : globalQueue._optimisticNodes
|
|
581
746
|
);
|
|
747
|
+
if (completingTransition && completingTransition._gatedSubs.size) {
|
|
748
|
+
for (const sub of completingTransition._gatedSubs) {
|
|
749
|
+
if (sub._flags & REACTIVE_DISPOSED) continue;
|
|
750
|
+
if (sub._type === EFFECT_TRACKED) {
|
|
751
|
+
if (!sub._modified) {
|
|
752
|
+
sub._modified = true;
|
|
753
|
+
sub._queue.enqueue(EFFECT_USER, sub._run);
|
|
754
|
+
}
|
|
755
|
+
continue;
|
|
756
|
+
}
|
|
757
|
+
const queue = sub._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue;
|
|
758
|
+
if (queue._min > sub._height) queue._min = sub._height;
|
|
759
|
+
insertIntoHeap(sub, queue);
|
|
760
|
+
}
|
|
761
|
+
completingTransition._gatedSubs.clear();
|
|
762
|
+
}
|
|
582
763
|
const optimisticStores = completingTransition
|
|
583
764
|
? completingTransition._optimisticStores
|
|
584
765
|
: globalQueue._optimisticStores;
|
|
@@ -589,6 +770,7 @@ function finalizePureQueue(completingTransition = null, incomplete = false) {
|
|
|
589
770
|
optimisticStores.clear();
|
|
590
771
|
schedule();
|
|
591
772
|
}
|
|
773
|
+
sweepTransientStoreNodes();
|
|
592
774
|
cleanupCompletedLanes(completingTransition);
|
|
593
775
|
}
|
|
594
776
|
}
|
|
@@ -608,7 +790,16 @@ function reassignPendingTransition(pendingNodes) {
|
|
|
608
790
|
}
|
|
609
791
|
}
|
|
610
792
|
const globalQueue = new GlobalQueue();
|
|
611
|
-
function flush() {
|
|
793
|
+
function flush(fn) {
|
|
794
|
+
if (fn) {
|
|
795
|
+
syncDepth++;
|
|
796
|
+
try {
|
|
797
|
+
return fn();
|
|
798
|
+
} finally {
|
|
799
|
+
flush();
|
|
800
|
+
syncDepth--;
|
|
801
|
+
}
|
|
802
|
+
}
|
|
612
803
|
if (globalQueue._running) {
|
|
613
804
|
if (inTrackedQueueCallback) {
|
|
614
805
|
throw new Error(
|
|
@@ -673,160 +864,27 @@ function transitionComplete(transition) {
|
|
|
673
864
|
) {
|
|
674
865
|
done = false;
|
|
675
866
|
break;
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
done && (transition._done = true);
|
|
680
|
-
return done;
|
|
681
|
-
}
|
|
682
|
-
function currentTransition(transition) {
|
|
683
|
-
while (transition._done && typeof transition._done === "object") transition = transition._done;
|
|
684
|
-
return transition;
|
|
685
|
-
}
|
|
686
|
-
function setActiveTransition(transition) {
|
|
687
|
-
activeTransition = transition;
|
|
688
|
-
}
|
|
689
|
-
function runInTransition(transition, fn) {
|
|
690
|
-
const prevTransition = activeTransition;
|
|
691
|
-
try {
|
|
692
|
-
activeTransition = currentTransition(transition);
|
|
693
|
-
return fn();
|
|
694
|
-
} finally {
|
|
695
|
-
activeTransition = prevTransition;
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
const signalLanes = new WeakMap();
|
|
699
|
-
const activeLanes = new Set();
|
|
700
|
-
function getOrCreateLane(signal) {
|
|
701
|
-
let lane = signalLanes.get(signal);
|
|
702
|
-
if (lane) {
|
|
703
|
-
return findLane(lane);
|
|
704
|
-
}
|
|
705
|
-
const parentSource = signal._parentSource;
|
|
706
|
-
const parentLane = parentSource?._optimisticLane ? findLane(parentSource._optimisticLane) : null;
|
|
707
|
-
lane = {
|
|
708
|
-
_source: signal,
|
|
709
|
-
_pendingAsync: new Set(),
|
|
710
|
-
_effectQueues: [[], []],
|
|
711
|
-
_mergedInto: null,
|
|
712
|
-
_transition: activeTransition,
|
|
713
|
-
_parentLane: parentLane
|
|
714
|
-
};
|
|
715
|
-
signalLanes.set(signal, lane);
|
|
716
|
-
activeLanes.add(lane);
|
|
717
|
-
signal._overrideSinceLane = false;
|
|
718
|
-
return lane;
|
|
719
|
-
}
|
|
720
|
-
function findLane(lane) {
|
|
721
|
-
while (lane._mergedInto) lane = lane._mergedInto;
|
|
722
|
-
return lane;
|
|
723
|
-
}
|
|
724
|
-
function mergeLanes(lane1, lane2) {
|
|
725
|
-
lane1 = findLane(lane1);
|
|
726
|
-
lane2 = findLane(lane2);
|
|
727
|
-
if (lane1 === lane2) return lane1;
|
|
728
|
-
lane2._mergedInto = lane1;
|
|
729
|
-
for (const node of lane2._pendingAsync) lane1._pendingAsync.add(node);
|
|
730
|
-
lane1._effectQueues[0].push(...lane2._effectQueues[0]);
|
|
731
|
-
lane1._effectQueues[1].push(...lane2._effectQueues[1]);
|
|
732
|
-
return lane1;
|
|
733
|
-
}
|
|
734
|
-
function resolveLane(el) {
|
|
735
|
-
const lane = el._optimisticLane;
|
|
736
|
-
if (!lane) return undefined;
|
|
737
|
-
const root = findLane(lane);
|
|
738
|
-
if (activeLanes.has(root)) return root;
|
|
739
|
-
el._optimisticLane = undefined;
|
|
740
|
-
return undefined;
|
|
741
|
-
}
|
|
742
|
-
function resolveTransition(el) {
|
|
743
|
-
return resolveLane(el)?._transition ?? el._transition;
|
|
744
|
-
}
|
|
745
|
-
function hasActiveOverride(el) {
|
|
746
|
-
return !!(el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING);
|
|
747
|
-
}
|
|
748
|
-
function assignOrMergeLane(el, sourceLane) {
|
|
749
|
-
const sourceRoot = findLane(sourceLane);
|
|
750
|
-
const existing = el._optimisticLane;
|
|
751
|
-
if (existing) {
|
|
752
|
-
if (existing._mergedInto) {
|
|
753
|
-
el._optimisticLane = sourceLane;
|
|
754
|
-
return;
|
|
755
|
-
}
|
|
756
|
-
const existingRoot = findLane(existing);
|
|
757
|
-
if (activeLanes.has(existingRoot)) {
|
|
758
|
-
if (existingRoot !== sourceRoot && !hasActiveOverride(el)) {
|
|
759
|
-
if (sourceRoot._parentLane && findLane(sourceRoot._parentLane) === existingRoot) {
|
|
760
|
-
el._optimisticLane = sourceLane;
|
|
761
|
-
} else if (existingRoot._parentLane && findLane(existingRoot._parentLane) === sourceRoot);
|
|
762
|
-
else mergeLanes(sourceRoot, existingRoot);
|
|
763
|
-
}
|
|
764
|
-
return;
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
el._optimisticLane = sourceLane;
|
|
768
|
-
}
|
|
769
|
-
function unlinkSubs(link) {
|
|
770
|
-
const dep = link._dep;
|
|
771
|
-
const nextDep = link._nextDep;
|
|
772
|
-
const nextSub = link._nextSub;
|
|
773
|
-
const prevSub = link._prevSub;
|
|
774
|
-
if (nextSub !== null) nextSub._prevSub = prevSub;
|
|
775
|
-
else dep._subsTail = prevSub;
|
|
776
|
-
if (prevSub !== null) prevSub._nextSub = nextSub;
|
|
777
|
-
else {
|
|
778
|
-
dep._subs = nextSub;
|
|
779
|
-
if (nextSub === null) {
|
|
780
|
-
dep._unobserved?.();
|
|
781
|
-
dep._fn && !dep._preventAutoDisposal && !(dep._flags & REACTIVE_ZOMBIE) && unobserved(dep);
|
|
867
|
+
}
|
|
782
868
|
}
|
|
783
869
|
}
|
|
784
|
-
|
|
870
|
+
done && (transition._done = true);
|
|
871
|
+
return done;
|
|
785
872
|
}
|
|
786
|
-
function
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
while (dep !== null) {
|
|
790
|
-
dep = unlinkSubs(dep);
|
|
791
|
-
}
|
|
792
|
-
el._deps = null;
|
|
793
|
-
disposeChildren(el, true);
|
|
873
|
+
function currentTransition(transition) {
|
|
874
|
+
while (transition._done && typeof transition._done === "object") transition = transition._done;
|
|
875
|
+
return transition;
|
|
794
876
|
}
|
|
795
|
-
function
|
|
796
|
-
|
|
797
|
-
if (prevDep !== null && prevDep._dep === dep) return;
|
|
798
|
-
let nextDep = null;
|
|
799
|
-
const isRecomputing = sub._flags & REACTIVE_RECOMPUTING_DEPS;
|
|
800
|
-
if (isRecomputing) {
|
|
801
|
-
nextDep = prevDep !== null ? prevDep._nextDep : sub._deps;
|
|
802
|
-
if (nextDep !== null && nextDep._dep === dep) {
|
|
803
|
-
sub._depsTail = nextDep;
|
|
804
|
-
return;
|
|
805
|
-
}
|
|
806
|
-
}
|
|
807
|
-
const prevSub = dep._subsTail;
|
|
808
|
-
if (prevSub !== null && prevSub._sub === sub && (!isRecomputing || isValidLink(prevSub, sub)))
|
|
809
|
-
return;
|
|
810
|
-
const newLink =
|
|
811
|
-
(sub._depsTail =
|
|
812
|
-
dep._subsTail =
|
|
813
|
-
{ _dep: dep, _sub: sub, _nextDep: nextDep, _prevSub: prevSub, _nextSub: null });
|
|
814
|
-
if (prevDep !== null) prevDep._nextDep = newLink;
|
|
815
|
-
else sub._deps = newLink;
|
|
816
|
-
if (prevSub !== null) prevSub._nextSub = newLink;
|
|
817
|
-
else dep._subs = newLink;
|
|
877
|
+
function setActiveTransition(transition) {
|
|
878
|
+
activeTransition = transition;
|
|
818
879
|
}
|
|
819
|
-
function
|
|
820
|
-
const
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
link = link._nextDep;
|
|
827
|
-
} while (link !== null);
|
|
880
|
+
function runInTransition(transition, fn) {
|
|
881
|
+
const prevTransition = activeTransition;
|
|
882
|
+
try {
|
|
883
|
+
activeTransition = currentTransition(transition);
|
|
884
|
+
return fn();
|
|
885
|
+
} finally {
|
|
886
|
+
activeTransition = prevTransition;
|
|
828
887
|
}
|
|
829
|
-
return false;
|
|
830
888
|
}
|
|
831
889
|
const PENDING_OWNER = {};
|
|
832
890
|
function markDisposal(el) {
|
|
@@ -851,8 +909,9 @@ function dispose(node) {
|
|
|
851
909
|
disposeChildren(node, true);
|
|
852
910
|
}
|
|
853
911
|
function disposeChildren(node, self = false, zombie) {
|
|
854
|
-
|
|
855
|
-
if (
|
|
912
|
+
const flags = node._flags;
|
|
913
|
+
if (flags & REACTIVE_DISPOSED) return;
|
|
914
|
+
if (self) node._flags = flags | REACTIVE_DISPOSED;
|
|
856
915
|
if (self && true) clearSignals(node);
|
|
857
916
|
if (self && node._fn) node._inFlight = null;
|
|
858
917
|
let child = zombie ? node._pendingFirstChild : node._firstChild;
|
|
@@ -877,6 +936,20 @@ function disposeChildren(node, self = false, zombie) {
|
|
|
877
936
|
node._firstChild = null;
|
|
878
937
|
node._childCount = 0;
|
|
879
938
|
}
|
|
939
|
+
if (
|
|
940
|
+
self &&
|
|
941
|
+
!zombie &&
|
|
942
|
+
!(flags & REACTIVE_ZOMBIE) &&
|
|
943
|
+
node._parent !== null &&
|
|
944
|
+
!(node._parent._flags & REACTIVE_DISPOSED)
|
|
945
|
+
) {
|
|
946
|
+
const prev = node._prevSibling;
|
|
947
|
+
const next = node._nextSibling;
|
|
948
|
+
if (prev !== null) prev._nextSibling = next;
|
|
949
|
+
else node._parent._firstChild = next;
|
|
950
|
+
if (next !== null) next._prevSibling = prev;
|
|
951
|
+
node._prevSibling = null;
|
|
952
|
+
}
|
|
880
953
|
runDisposal(node, zombie);
|
|
881
954
|
}
|
|
882
955
|
function runDisposal(node, zombie) {
|
|
@@ -894,7 +967,7 @@ function runDisposal(node, zombie) {
|
|
|
894
967
|
}
|
|
895
968
|
function childId(owner, consume) {
|
|
896
969
|
let counter = owner;
|
|
897
|
-
while (counter.
|
|
970
|
+
while (counter._config & CONFIG_TRANSPARENT && counter._parent) counter = counter._parent;
|
|
898
971
|
if (counter.id != null)
|
|
899
972
|
return formatId(counter.id, consume ? counter._childCount++ : counter._childCount);
|
|
900
973
|
throw new Error("Cannot get child id from owner without an id");
|
|
@@ -927,6 +1000,9 @@ function cleanup(fn) {
|
|
|
927
1000
|
function isDisposed(node) {
|
|
928
1001
|
return !!(node._flags & (REACTIVE_DISPOSED | REACTIVE_ZOMBIE));
|
|
929
1002
|
}
|
|
1003
|
+
function disposeRootSelf(self = true) {
|
|
1004
|
+
disposeChildren(this, self);
|
|
1005
|
+
}
|
|
930
1006
|
function createOwner(options) {
|
|
931
1007
|
const parent = context;
|
|
932
1008
|
const transparent = options?.transparent ?? false;
|
|
@@ -934,11 +1010,12 @@ function createOwner(options) {
|
|
|
934
1010
|
id:
|
|
935
1011
|
options?.id ??
|
|
936
1012
|
(transparent ? parent?.id : parent?.id != null ? getNextChildId(parent) : undefined),
|
|
937
|
-
|
|
1013
|
+
_config: transparent ? CONFIG_TRANSPARENT : 0,
|
|
938
1014
|
_root: true,
|
|
939
1015
|
_parentComputed: parent?._root ? parent._parentComputed : parent,
|
|
940
1016
|
_firstChild: null,
|
|
941
1017
|
_nextSibling: null,
|
|
1018
|
+
_prevSibling: null,
|
|
942
1019
|
_disposal: null,
|
|
943
1020
|
_queue: parent?._queue ?? globalQueue,
|
|
944
1021
|
_context: parent?._context || defaultContext,
|
|
@@ -946,14 +1023,18 @@ function createOwner(options) {
|
|
|
946
1023
|
_pendingDisposal: null,
|
|
947
1024
|
_pendingFirstChild: null,
|
|
948
1025
|
_parent: parent,
|
|
949
|
-
dispose
|
|
950
|
-
disposeChildren(owner, self);
|
|
951
|
-
}
|
|
1026
|
+
dispose: disposeRootSelf
|
|
952
1027
|
};
|
|
953
|
-
if (parent
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
1028
|
+
if (parent && parent._config & CONFIG_CHILDREN_FORBIDDEN) {
|
|
1029
|
+
emitDiagnostic({
|
|
1030
|
+
code: "PRIMITIVE_IN_FORBIDDEN_SCOPE",
|
|
1031
|
+
kind: "lifecycle",
|
|
1032
|
+
severity: "error",
|
|
1033
|
+
message: PRIMITIVE_IN_FORBIDDEN_SCOPE_MESSAGE,
|
|
1034
|
+
ownerId: parent.id,
|
|
1035
|
+
ownerName: parent._name
|
|
1036
|
+
});
|
|
1037
|
+
throw new Error(PRIMITIVE_IN_FORBIDDEN_SCOPE_MESSAGE);
|
|
957
1038
|
}
|
|
958
1039
|
if (parent) {
|
|
959
1040
|
const lastChild = parent._firstChild;
|
|
@@ -961,6 +1042,7 @@ function createOwner(options) {
|
|
|
961
1042
|
parent._firstChild = owner;
|
|
962
1043
|
} else {
|
|
963
1044
|
owner._nextSibling = lastChild;
|
|
1045
|
+
lastChild._prevSibling = owner;
|
|
964
1046
|
parent._firstChild = owner;
|
|
965
1047
|
}
|
|
966
1048
|
}
|
|
@@ -969,7 +1051,82 @@ function createOwner(options) {
|
|
|
969
1051
|
}
|
|
970
1052
|
function createRoot(init, options) {
|
|
971
1053
|
const owner = createOwner(options);
|
|
972
|
-
return runWithOwner(owner, () => init(owner.dispose));
|
|
1054
|
+
return runWithOwner(owner, () => init(() => owner.dispose()));
|
|
1055
|
+
}
|
|
1056
|
+
function unlinkSubs(link) {
|
|
1057
|
+
const dep = link._dep;
|
|
1058
|
+
const nextDep = link._nextDep;
|
|
1059
|
+
const nextSub = link._nextSub;
|
|
1060
|
+
const prevSub = link._prevSub;
|
|
1061
|
+
if (nextSub !== null) nextSub._prevSub = prevSub;
|
|
1062
|
+
else dep._subsTail = prevSub;
|
|
1063
|
+
if (prevSub !== null) prevSub._nextSub = nextSub;
|
|
1064
|
+
else {
|
|
1065
|
+
dep._subs = nextSub;
|
|
1066
|
+
if (nextSub === null) {
|
|
1067
|
+
dep._unobserved?.();
|
|
1068
|
+
const c = dep;
|
|
1069
|
+
c._fn && c._config & CONFIG_AUTO_DISPOSE && !(c._flags & REACTIVE_ZOMBIE) && unobserved(c);
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
return nextDep;
|
|
1073
|
+
}
|
|
1074
|
+
function trimStaleDeps(el) {
|
|
1075
|
+
const depsTail = el._depsTail;
|
|
1076
|
+
let toRemove = depsTail !== null ? depsTail._nextDep : el._deps;
|
|
1077
|
+
if (toRemove !== null) {
|
|
1078
|
+
do {
|
|
1079
|
+
toRemove = unlinkSubs(toRemove);
|
|
1080
|
+
} while (toRemove !== null);
|
|
1081
|
+
if (depsTail !== null) depsTail._nextDep = null;
|
|
1082
|
+
else el._deps = null;
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
function unobserved(el) {
|
|
1086
|
+
deleteFromHeap(el, el._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
|
|
1087
|
+
let dep = el._deps;
|
|
1088
|
+
while (dep !== null) {
|
|
1089
|
+
dep = unlinkSubs(dep);
|
|
1090
|
+
}
|
|
1091
|
+
el._deps = null;
|
|
1092
|
+
el._depsTail = null;
|
|
1093
|
+
disposeChildren(el, true);
|
|
1094
|
+
}
|
|
1095
|
+
function link(dep, sub) {
|
|
1096
|
+
const prevDep = sub._depsTail;
|
|
1097
|
+
if (prevDep !== null && prevDep._dep === dep) return;
|
|
1098
|
+
let nextDep = null;
|
|
1099
|
+
const isRecomputing = sub._flags & REACTIVE_RECOMPUTING_DEPS;
|
|
1100
|
+
if (isRecomputing) {
|
|
1101
|
+
nextDep = prevDep !== null ? prevDep._nextDep : sub._deps;
|
|
1102
|
+
if (nextDep !== null && nextDep._dep === dep) {
|
|
1103
|
+
sub._depsTail = nextDep;
|
|
1104
|
+
return;
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
const prevSub = dep._subsTail;
|
|
1108
|
+
if (prevSub !== null && prevSub._sub === sub && (!isRecomputing || isValidLink(prevSub, sub)))
|
|
1109
|
+
return;
|
|
1110
|
+
const newLink =
|
|
1111
|
+
(sub._depsTail =
|
|
1112
|
+
dep._subsTail =
|
|
1113
|
+
{ _dep: dep, _sub: sub, _nextDep: nextDep, _prevSub: prevSub, _nextSub: null });
|
|
1114
|
+
if (prevDep !== null) prevDep._nextDep = newLink;
|
|
1115
|
+
else sub._deps = newLink;
|
|
1116
|
+
if (prevSub !== null) prevSub._nextSub = newLink;
|
|
1117
|
+
else dep._subs = newLink;
|
|
1118
|
+
}
|
|
1119
|
+
function isValidLink(checkLink, sub) {
|
|
1120
|
+
const depsTail = sub._depsTail;
|
|
1121
|
+
if (depsTail !== null) {
|
|
1122
|
+
let link = sub._deps;
|
|
1123
|
+
do {
|
|
1124
|
+
if (link === checkLink) return true;
|
|
1125
|
+
if (link === depsTail) break;
|
|
1126
|
+
link = link._nextDep;
|
|
1127
|
+
} while (link !== null);
|
|
1128
|
+
}
|
|
1129
|
+
return false;
|
|
973
1130
|
}
|
|
974
1131
|
function addPendingSource(el, source) {
|
|
975
1132
|
if (el._pendingSource === source || el._pendingSources?.has(source)) return false;
|
|
@@ -1062,13 +1219,34 @@ function settlePendingSource(el) {
|
|
|
1062
1219
|
if (scheduled) schedule();
|
|
1063
1220
|
}
|
|
1064
1221
|
function handleAsync(el, result, setter) {
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1222
|
+
let iterator = false;
|
|
1223
|
+
let isThenable = false;
|
|
1224
|
+
if (typeof result === "object" && result !== null) {
|
|
1225
|
+
untrack(() => {
|
|
1226
|
+
iterator = result[Symbol.asyncIterator];
|
|
1227
|
+
isThenable = !iterator && typeof result.then === "function";
|
|
1228
|
+
});
|
|
1229
|
+
}
|
|
1068
1230
|
if (!isThenable && !iterator) {
|
|
1069
1231
|
el._inFlight = null;
|
|
1070
1232
|
return result;
|
|
1071
1233
|
}
|
|
1234
|
+
if (el._config & CONFIG_SYNC) {
|
|
1235
|
+
const message =
|
|
1236
|
+
`[SYNC_NODE_RECEIVED_ASYNC] A computed/effect created with \`sync: true\` returned ` +
|
|
1237
|
+
`${isThenable ? "a Promise" : "an AsyncIterable"}. The value would be stored as-is and ` +
|
|
1238
|
+
`never awaited in production; remove \`sync: true\` to use async-aware behavior, or ` +
|
|
1239
|
+
`unwrap the value before returning.`;
|
|
1240
|
+
emitDiagnostic({
|
|
1241
|
+
code: "SYNC_NODE_RECEIVED_ASYNC",
|
|
1242
|
+
kind: "lifecycle",
|
|
1243
|
+
severity: "error",
|
|
1244
|
+
message: message,
|
|
1245
|
+
ownerId: el.id,
|
|
1246
|
+
ownerName: el._name
|
|
1247
|
+
});
|
|
1248
|
+
throw new Error(message);
|
|
1249
|
+
}
|
|
1072
1250
|
el._inFlight = result;
|
|
1073
1251
|
let syncValue;
|
|
1074
1252
|
const handleError = error => {
|
|
@@ -1082,6 +1260,7 @@ function handleAsync(el, result, setter) {
|
|
|
1082
1260
|
if (el._flags & (REACTIVE_DIRTY | REACTIVE_OPTIMISTIC_DIRTY)) return;
|
|
1083
1261
|
globalQueue.initTransition(resolveTransition(el));
|
|
1084
1262
|
const wasUninitialized = !!(el._statusFlags & STATUS_UNINITIALIZED);
|
|
1263
|
+
trimStaleDeps(el);
|
|
1085
1264
|
clearStatus(el);
|
|
1086
1265
|
const lane = resolveLane(el);
|
|
1087
1266
|
if (lane) lane._pendingAsync.delete(el);
|
|
@@ -1191,12 +1370,12 @@ function handleAsync(el, result, setter) {
|
|
|
1191
1370
|
return syncValue;
|
|
1192
1371
|
}
|
|
1193
1372
|
function clearStatus(el, clearUninitialized = false) {
|
|
1194
|
-
clearPendingSources(el);
|
|
1195
|
-
el._blocked = false;
|
|
1373
|
+
if (el._pendingSource || el._pendingSources) clearPendingSources(el);
|
|
1374
|
+
if (el._blocked) el._blocked = false;
|
|
1196
1375
|
el._statusFlags = clearUninitialized ? 0 : el._statusFlags & STATUS_UNINITIALIZED;
|
|
1197
|
-
setPendingError(el);
|
|
1198
|
-
updatePendingSignal(el);
|
|
1199
|
-
el._notifyStatus
|
|
1376
|
+
if (el._error) setPendingError(el);
|
|
1377
|
+
if (el._pendingSignal) updatePendingSignal(el);
|
|
1378
|
+
if (el._notifyStatus) el._notifyStatus();
|
|
1200
1379
|
}
|
|
1201
1380
|
function notifyStatus(el, status, error, blockStatus, lane) {
|
|
1202
1381
|
if (
|
|
@@ -1250,7 +1429,7 @@ function notifyStatus(el, status, error, blockStatus, lane) {
|
|
|
1250
1429
|
(status !== STATUS_PENDING &&
|
|
1251
1430
|
(sub._error !== error || sub._pendingSource || sub._pendingSources))
|
|
1252
1431
|
) {
|
|
1253
|
-
if (!downstreamBlockStatus && !sub._transition)
|
|
1432
|
+
if (!downstreamBlockStatus && !sub._transition) queuePendingNode(sub);
|
|
1254
1433
|
notifyStatus(sub, status, error, downstreamBlockStatus, downstreamLane);
|
|
1255
1434
|
}
|
|
1256
1435
|
});
|
|
@@ -1280,6 +1459,8 @@ function enableExternalSource(config) {
|
|
|
1280
1459
|
}
|
|
1281
1460
|
GlobalQueue._update = recompute;
|
|
1282
1461
|
GlobalQueue._dispose = disposeChildren;
|
|
1462
|
+
const PRIMITIVE_IN_FORBIDDEN_SCOPE_MESSAGE =
|
|
1463
|
+
"[PRIMITIVE_IN_FORBIDDEN_SCOPE] Cannot create reactive primitives inside createTrackedEffect or owner-backed onSettled";
|
|
1283
1464
|
let tracking = false;
|
|
1284
1465
|
let stale = false;
|
|
1285
1466
|
let refreshing = false;
|
|
@@ -1318,7 +1499,7 @@ function releaseSubtree(owner) {
|
|
|
1318
1499
|
}
|
|
1319
1500
|
if (child._fn) {
|
|
1320
1501
|
const comp = child;
|
|
1321
|
-
comp.
|
|
1502
|
+
comp._config &= ~CONFIG_IN_SNAPSHOT_SCOPE;
|
|
1322
1503
|
if (comp._flags & REACTIVE_SNAPSHOT_STALE) {
|
|
1323
1504
|
comp._flags &= ~REACTIVE_SNAPSHOT_STALE;
|
|
1324
1505
|
comp._flags |= REACTIVE_DIRTY;
|
|
@@ -1348,7 +1529,7 @@ function recompute(el, create = false) {
|
|
|
1348
1529
|
deleteFromHeap(el, el._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
|
|
1349
1530
|
el._inFlight = null;
|
|
1350
1531
|
if (el._transition || isEffect === EFFECT_TRACKED) disposeChildren(el);
|
|
1351
|
-
else {
|
|
1532
|
+
else if (el._firstChild !== null || el._disposal !== null) {
|
|
1352
1533
|
markDisposal(el);
|
|
1353
1534
|
el._pendingDisposal = el._disposal;
|
|
1354
1535
|
el._pendingFirstChild = el._firstChild;
|
|
@@ -1356,9 +1537,9 @@ function recompute(el, create = false) {
|
|
|
1356
1537
|
el._firstChild = null;
|
|
1357
1538
|
el._childCount = 0;
|
|
1358
1539
|
clearSignals(el);
|
|
1359
|
-
}
|
|
1540
|
+
} else clearSignals(el);
|
|
1360
1541
|
}
|
|
1361
|
-
|
|
1542
|
+
let isOptimisticDirty = !!(el._flags & REACTIVE_OPTIMISTIC_DIRTY);
|
|
1362
1543
|
const hasOverride = el._overrideValue !== undefined && el._overrideValue !== NOT_PENDING;
|
|
1363
1544
|
const wasPending = !!(el._statusFlags & STATUS_PENDING);
|
|
1364
1545
|
const wasUninitialized = !!(el._statusFlags & STATUS_UNINITIALIZED);
|
|
@@ -1380,14 +1561,41 @@ function recompute(el, create = false) {
|
|
|
1380
1561
|
if (isOptimisticDirty) {
|
|
1381
1562
|
const lane = resolveLane(el);
|
|
1382
1563
|
if (lane) currentOptimisticLane = lane;
|
|
1564
|
+
} else if (activeTransition && !create && activeTransition._optimisticNodes.length) {
|
|
1565
|
+
for (let d = el._deps; d; d = d._nextDep) {
|
|
1566
|
+
const dep = d._dep;
|
|
1567
|
+
if (dep._flags & REACTIVE_OPTIMISTIC_DIRTY) {
|
|
1568
|
+
const depLane = resolveLane(dep);
|
|
1569
|
+
if (depLane) {
|
|
1570
|
+
isOptimisticDirty = true;
|
|
1571
|
+
currentOptimisticLane = depLane;
|
|
1572
|
+
el._flags |= REACTIVE_OPTIMISTIC_DIRTY;
|
|
1573
|
+
assignOrMergeLane(el, depLane);
|
|
1574
|
+
break;
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1383
1578
|
}
|
|
1579
|
+
const isStaleEffect = isEffect && isEffect !== EFFECT_USER;
|
|
1580
|
+
const prevStale = stale;
|
|
1581
|
+
if (isStaleEffect) stale = true;
|
|
1384
1582
|
try {
|
|
1385
|
-
|
|
1583
|
+
if (!true && el._config & CONFIG_SYNC);
|
|
1584
|
+
else {
|
|
1585
|
+
const prevInFlight = el._inFlight;
|
|
1586
|
+
const fnResult = el._fn(value);
|
|
1587
|
+
const isAsyncResult = typeof fnResult === "object" && fnResult !== null;
|
|
1588
|
+
const inFlightChanged = el._inFlight !== prevInFlight;
|
|
1589
|
+
value = inFlightChanged || !isAsyncResult ? fnResult : handleAsync(el, fnResult);
|
|
1590
|
+
if (!inFlightChanged && !isAsyncResult) el._inFlight = null;
|
|
1591
|
+
}
|
|
1386
1592
|
clearStatus(el, create);
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
resolvedLane
|
|
1390
|
-
|
|
1593
|
+
if (el._optimisticLane) {
|
|
1594
|
+
const resolvedLane = resolveLane(el);
|
|
1595
|
+
if (resolvedLane) {
|
|
1596
|
+
resolvedLane._pendingAsync.delete(el);
|
|
1597
|
+
updatePendingSignal(resolvedLane._source);
|
|
1598
|
+
}
|
|
1391
1599
|
}
|
|
1392
1600
|
} catch (e) {
|
|
1393
1601
|
if (e instanceof NotReadyError && currentOptimisticLane) {
|
|
@@ -1409,19 +1617,12 @@ function recompute(el, create = false) {
|
|
|
1409
1617
|
} finally {
|
|
1410
1618
|
tracking = prevTracking;
|
|
1411
1619
|
strictRead = prevStrictRead;
|
|
1620
|
+
if (isStaleEffect) stale = prevStale;
|
|
1412
1621
|
el._flags = REACTIVE_NONE | (create ? el._flags & REACTIVE_SNAPSHOT_STALE : 0);
|
|
1413
1622
|
context = oldcontext;
|
|
1414
1623
|
}
|
|
1415
1624
|
if (!el._error) {
|
|
1416
|
-
|
|
1417
|
-
let toRemove = depsTail !== null ? depsTail._nextDep : el._deps;
|
|
1418
|
-
if (toRemove !== null) {
|
|
1419
|
-
do {
|
|
1420
|
-
toRemove = unlinkSubs(toRemove);
|
|
1421
|
-
} while (toRemove !== null);
|
|
1422
|
-
if (depsTail !== null) depsTail._nextDep = null;
|
|
1423
|
-
else el._deps = null;
|
|
1424
|
-
}
|
|
1625
|
+
trimStaleDeps(el);
|
|
1425
1626
|
const compareValue = hasOverride
|
|
1426
1627
|
? el._overrideValue
|
|
1427
1628
|
: el._pendingValue === NOT_PENDING
|
|
@@ -1429,6 +1630,10 @@ function recompute(el, create = false) {
|
|
|
1429
1630
|
: el._pendingValue;
|
|
1430
1631
|
const valueChanged =
|
|
1431
1632
|
(!isEffect && wasUninitialized) || !el._equals || !el._equals(compareValue, value);
|
|
1633
|
+
if (isEffect && valueChanged) {
|
|
1634
|
+
el._modified = !el._error;
|
|
1635
|
+
if (!create) el._queue.enqueue(isEffect, GlobalQueue._runEffect.bind(null, el));
|
|
1636
|
+
}
|
|
1432
1637
|
if (valueChanged) {
|
|
1433
1638
|
const prevVisible = hasOverride ? el._overrideValue : undefined;
|
|
1434
1639
|
if (create || (isEffect && activeTransition !== el._transition) || isOptimisticDirty) {
|
|
@@ -1451,10 +1656,16 @@ function recompute(el, create = false) {
|
|
|
1451
1656
|
}
|
|
1452
1657
|
}
|
|
1453
1658
|
currentOptimisticLane = prevLane;
|
|
1454
|
-
|
|
1659
|
+
const needsPendingCommit =
|
|
1660
|
+
el._pendingValue !== NOT_PENDING ||
|
|
1661
|
+
el._pendingFirstChild !== null ||
|
|
1662
|
+
el._pendingDisposal !== null ||
|
|
1663
|
+
!!(el._statusFlags & (STATUS_PENDING | STATUS_UNINITIALIZED));
|
|
1664
|
+
needsPendingCommit &&
|
|
1665
|
+
(!create || el._statusFlags & STATUS_PENDING) &&
|
|
1455
1666
|
!el._transition &&
|
|
1456
1667
|
!(activeTransition && hasOverride) &&
|
|
1457
|
-
|
|
1668
|
+
queuePendingNode(el);
|
|
1458
1669
|
el._transition &&
|
|
1459
1670
|
isEffect &&
|
|
1460
1671
|
activeTransition !== el._transition &&
|
|
@@ -1481,22 +1692,26 @@ function updateIfNecessary(el) {
|
|
|
1481
1692
|
}
|
|
1482
1693
|
el._flags = el._flags & (REACTIVE_SNAPSHOT_STALE | REACTIVE_IN_HEAP | REACTIVE_IN_HEAP_HEIGHT);
|
|
1483
1694
|
}
|
|
1484
|
-
function computed(fn,
|
|
1695
|
+
function computed(fn, options) {
|
|
1485
1696
|
const transparent = options?.transparent ?? false;
|
|
1486
1697
|
const self = {
|
|
1487
1698
|
id:
|
|
1488
1699
|
options?.id ??
|
|
1489
1700
|
(transparent ? context?.id : context?.id != null ? getNextChildId(context) : undefined),
|
|
1490
|
-
|
|
1701
|
+
_config:
|
|
1702
|
+
(transparent ? CONFIG_TRANSPARENT : 0) |
|
|
1703
|
+
(options?.ownedWrite ? CONFIG_OWNED_WRITE : 0) |
|
|
1704
|
+
(!context || options?.lazy ? CONFIG_AUTO_DISPOSE : 0) |
|
|
1705
|
+
(options?.sync ? CONFIG_SYNC : 0) |
|
|
1706
|
+
(snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
|
|
1491
1707
|
_equals: options?.equals != null ? options.equals : isEqual,
|
|
1492
|
-
_pureWrite: !!options?.pureWrite,
|
|
1493
1708
|
_unobserved: options?.unobserved,
|
|
1494
1709
|
_disposal: null,
|
|
1495
1710
|
_queue: context?._queue ?? globalQueue,
|
|
1496
1711
|
_context: context?._context ?? defaultContext,
|
|
1497
1712
|
_childCount: 0,
|
|
1498
1713
|
_fn: fn,
|
|
1499
|
-
_value:
|
|
1714
|
+
_value: undefined,
|
|
1500
1715
|
_height: 0,
|
|
1501
1716
|
_child: null,
|
|
1502
1717
|
_nextHeap: undefined,
|
|
@@ -1507,6 +1722,7 @@ function computed(fn, initialValue, options) {
|
|
|
1507
1722
|
_subsTail: null,
|
|
1508
1723
|
_parent: context,
|
|
1509
1724
|
_nextSibling: null,
|
|
1725
|
+
_prevSibling: null,
|
|
1510
1726
|
_firstChild: null,
|
|
1511
1727
|
_flags: options?.lazy ? REACTIVE_LAZY : REACTIVE_NONE,
|
|
1512
1728
|
_statusFlags: STATUS_UNINITIALIZED,
|
|
@@ -1518,12 +1734,75 @@ function computed(fn, initialValue, options) {
|
|
|
1518
1734
|
_transition: null
|
|
1519
1735
|
};
|
|
1520
1736
|
self._name = options?.name ?? "computed";
|
|
1737
|
+
setupComputedNode(self, options);
|
|
1738
|
+
return self;
|
|
1739
|
+
}
|
|
1740
|
+
function createEffectNode(fn, effectFn, errorFn, type, notifyStatus, options) {
|
|
1741
|
+
const transparent = options?.transparent ?? false;
|
|
1742
|
+
const self = {
|
|
1743
|
+
id:
|
|
1744
|
+
options?.id ??
|
|
1745
|
+
(transparent ? context?.id : context?.id != null ? getNextChildId(context) : undefined),
|
|
1746
|
+
_config:
|
|
1747
|
+
(transparent ? CONFIG_TRANSPARENT : 0) |
|
|
1748
|
+
(options?.ownedWrite ? CONFIG_OWNED_WRITE : 0) |
|
|
1749
|
+
(options?.sync ? CONFIG_SYNC : 0) |
|
|
1750
|
+
(snapshotCaptureActive && ownerInSnapshotScope(context) ? CONFIG_IN_SNAPSHOT_SCOPE : 0),
|
|
1751
|
+
_equals: false,
|
|
1752
|
+
_unobserved: options?.unobserved,
|
|
1753
|
+
_disposal: null,
|
|
1754
|
+
_queue: context?._queue ?? globalQueue,
|
|
1755
|
+
_context: context?._context ?? defaultContext,
|
|
1756
|
+
_childCount: 0,
|
|
1757
|
+
_fn: fn,
|
|
1758
|
+
_value: undefined,
|
|
1759
|
+
_height: 0,
|
|
1760
|
+
_child: null,
|
|
1761
|
+
_nextHeap: undefined,
|
|
1762
|
+
_prevHeap: null,
|
|
1763
|
+
_deps: null,
|
|
1764
|
+
_depsTail: null,
|
|
1765
|
+
_subs: null,
|
|
1766
|
+
_subsTail: null,
|
|
1767
|
+
_parent: context,
|
|
1768
|
+
_nextSibling: null,
|
|
1769
|
+
_prevSibling: null,
|
|
1770
|
+
_firstChild: null,
|
|
1771
|
+
_flags: REACTIVE_LAZY,
|
|
1772
|
+
_statusFlags: STATUS_UNINITIALIZED,
|
|
1773
|
+
_time: clock,
|
|
1774
|
+
_pendingValue: NOT_PENDING,
|
|
1775
|
+
_pendingDisposal: null,
|
|
1776
|
+
_pendingFirstChild: null,
|
|
1777
|
+
_inFlight: null,
|
|
1778
|
+
_transition: null,
|
|
1779
|
+
_modified: false,
|
|
1780
|
+
_prevValue: undefined,
|
|
1781
|
+
_effectFn: effectFn,
|
|
1782
|
+
_errorFn: errorFn,
|
|
1783
|
+
_cleanup: undefined,
|
|
1784
|
+
_cleanupRegistered: false,
|
|
1785
|
+
_type: type,
|
|
1786
|
+
_notifyStatus: notifyStatus
|
|
1787
|
+
};
|
|
1788
|
+
self._name = options?.name ?? "effect";
|
|
1789
|
+
setupComputedNode(self, lazyOptions);
|
|
1790
|
+
return self;
|
|
1791
|
+
}
|
|
1792
|
+
const lazyOptions = { lazy: true };
|
|
1793
|
+
function setupComputedNode(self, options) {
|
|
1521
1794
|
self._prevHeap = self;
|
|
1522
1795
|
const parent = context?._root ? context._parentComputed : context;
|
|
1523
|
-
if (context
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1796
|
+
if (context && context._config & CONFIG_CHILDREN_FORBIDDEN) {
|
|
1797
|
+
emitDiagnostic({
|
|
1798
|
+
code: "PRIMITIVE_IN_FORBIDDEN_SCOPE",
|
|
1799
|
+
kind: "lifecycle",
|
|
1800
|
+
severity: "error",
|
|
1801
|
+
message: PRIMITIVE_IN_FORBIDDEN_SCOPE_MESSAGE,
|
|
1802
|
+
ownerId: context.id,
|
|
1803
|
+
ownerName: context._name
|
|
1804
|
+
});
|
|
1805
|
+
throw new Error(PRIMITIVE_IN_FORBIDDEN_SCOPE_MESSAGE);
|
|
1527
1806
|
}
|
|
1528
1807
|
if (context) {
|
|
1529
1808
|
const lastChild = context._firstChild;
|
|
@@ -1531,14 +1810,14 @@ function computed(fn, initialValue, options) {
|
|
|
1531
1810
|
context._firstChild = self;
|
|
1532
1811
|
} else {
|
|
1533
1812
|
self._nextSibling = lastChild;
|
|
1813
|
+
lastChild._prevSibling = self;
|
|
1534
1814
|
context._firstChild = self;
|
|
1535
1815
|
}
|
|
1536
1816
|
}
|
|
1537
1817
|
DEV$1.hooks.onOwner?.(self);
|
|
1538
1818
|
if (parent) self._height = parent._height + 1;
|
|
1539
|
-
if (snapshotCaptureActive && ownerInSnapshotScope(context)) self._inSnapshotScope = true;
|
|
1540
1819
|
if (externalSourceConfig) {
|
|
1541
|
-
const bridgeSignal = signal(undefined, { equals: false,
|
|
1820
|
+
const bridgeSignal = signal(undefined, { equals: false, ownedWrite: true });
|
|
1542
1821
|
const source = externalSourceConfig.factory(self._fn, () => {
|
|
1543
1822
|
setSignal(bridgeSignal, undefined);
|
|
1544
1823
|
});
|
|
@@ -1555,13 +1834,13 @@ function computed(fn, initialValue, options) {
|
|
|
1555
1834
|
snapshotSources.add(self);
|
|
1556
1835
|
}
|
|
1557
1836
|
}
|
|
1558
|
-
return self;
|
|
1559
1837
|
}
|
|
1560
1838
|
function signal(v, options, firewall = null) {
|
|
1561
1839
|
const s = {
|
|
1562
1840
|
_equals: options?.equals != null ? options.equals : isEqual,
|
|
1563
|
-
|
|
1564
|
-
|
|
1841
|
+
_config:
|
|
1842
|
+
(options?.ownedWrite ? CONFIG_OWNED_WRITE : 0) |
|
|
1843
|
+
(options?._noSnapshot ? CONFIG_NO_SNAPSHOT : 0),
|
|
1565
1844
|
_unobserved: options?.unobserved,
|
|
1566
1845
|
_value: v,
|
|
1567
1846
|
_subs: null,
|
|
@@ -1578,7 +1857,7 @@ function signal(v, options, firewall = null) {
|
|
|
1578
1857
|
firewall && (firewall._child = s);
|
|
1579
1858
|
if (
|
|
1580
1859
|
snapshotCaptureActive &&
|
|
1581
|
-
!s.
|
|
1860
|
+
!(s._config & CONFIG_NO_SNAPSHOT) &&
|
|
1582
1861
|
!((firewall?._statusFlags ?? 0) & STATUS_PENDING)
|
|
1583
1862
|
) {
|
|
1584
1863
|
s._snapshotValue = v === undefined ? NO_SNAPSHOT : v;
|
|
@@ -1591,8 +1870,8 @@ function optimisticSignal(v, options) {
|
|
|
1591
1870
|
s._overrideValue = NOT_PENDING;
|
|
1592
1871
|
return s;
|
|
1593
1872
|
}
|
|
1594
|
-
function optimisticComputed(fn,
|
|
1595
|
-
const c = computed(fn,
|
|
1873
|
+
function optimisticComputed(fn, options) {
|
|
1874
|
+
const c = computed(fn, options);
|
|
1596
1875
|
c._overrideValue = NOT_PENDING;
|
|
1597
1876
|
return c;
|
|
1598
1877
|
}
|
|
@@ -1672,15 +1951,33 @@ function read(el) {
|
|
|
1672
1951
|
}
|
|
1673
1952
|
let c = context;
|
|
1674
1953
|
if (c?._root) c = c._parentComputed;
|
|
1675
|
-
|
|
1676
|
-
if (
|
|
1677
|
-
|
|
1678
|
-
|
|
1954
|
+
const computed = el;
|
|
1955
|
+
if (typeof computed._fn === "function") {
|
|
1956
|
+
const comp = el;
|
|
1957
|
+
if (comp._flags & REACTIVE_LAZY) {
|
|
1958
|
+
comp._flags &= ~REACTIVE_LAZY;
|
|
1959
|
+
recompute(comp, true);
|
|
1960
|
+
} else if (comp._flags & REACTIVE_DISPOSED) {
|
|
1961
|
+
recompute(comp, true);
|
|
1962
|
+
}
|
|
1679
1963
|
}
|
|
1680
1964
|
const owner = el._firewall || el;
|
|
1965
|
+
if (
|
|
1966
|
+
!computed._fn &&
|
|
1967
|
+
owner === el &&
|
|
1968
|
+
el._overrideValue === undefined &&
|
|
1969
|
+
el._snapshotValue === undefined &&
|
|
1970
|
+
activeTransition === null &&
|
|
1971
|
+
currentOptimisticLane === null &&
|
|
1972
|
+
!snapshotCaptureActive &&
|
|
1973
|
+
!strictRead
|
|
1974
|
+
) {
|
|
1975
|
+
if (c && tracking) link(el, c);
|
|
1976
|
+
return !c || el._pendingValue === NOT_PENDING ? el._value : el._pendingValue;
|
|
1977
|
+
}
|
|
1681
1978
|
if (strictRead && owner._statusFlags & STATUS_PENDING) {
|
|
1682
1979
|
const message =
|
|
1683
|
-
`Reading a pending async value directly in ${strictRead}. ` +
|
|
1980
|
+
`[PENDING_ASYNC_UNTRACKED_READ] Reading a pending async value directly in ${strictRead}. ` +
|
|
1684
1981
|
`Async values must be read within a tracking scope (JSX, a memo, or an effect's compute function).`;
|
|
1685
1982
|
emitDiagnostic({
|
|
1686
1983
|
code: "PENDING_ASYNC_UNTRACKED_READ",
|
|
@@ -1695,7 +1992,6 @@ function read(el) {
|
|
|
1695
1992
|
throw new Error(message);
|
|
1696
1993
|
}
|
|
1697
1994
|
if (c && tracking) {
|
|
1698
|
-
if (el._fn && el._flags & REACTIVE_DISPOSED) recompute(el);
|
|
1699
1995
|
link(el, c);
|
|
1700
1996
|
if (owner._fn) {
|
|
1701
1997
|
const isZombie = el._flags & REACTIVE_ZOMBIE;
|
|
@@ -1712,9 +2008,9 @@ function read(el) {
|
|
|
1712
2008
|
}
|
|
1713
2009
|
if (owner._statusFlags & STATUS_PENDING) {
|
|
1714
2010
|
if (c && !(stale && owner._transition && activeTransition !== owner._transition)) {
|
|
1715
|
-
if (c
|
|
2011
|
+
if (c && c._config & CONFIG_CHILDREN_FORBIDDEN) {
|
|
1716
2012
|
const message =
|
|
1717
|
-
"Reading a pending async value inside createTrackedEffect or onSettled will throw. " +
|
|
2013
|
+
"[PENDING_ASYNC_FORBIDDEN_SCOPE] Reading a pending async value inside createTrackedEffect or onSettled will throw. " +
|
|
1718
2014
|
"Use createEffect instead which supports async-aware reactivity.";
|
|
1719
2015
|
emitDiagnostic({
|
|
1720
2016
|
code: "PENDING_ASYNC_FORBIDDEN_SCOPE",
|
|
@@ -1751,7 +2047,7 @@ function read(el) {
|
|
|
1751
2047
|
return read(el);
|
|
1752
2048
|
} else throw el._error;
|
|
1753
2049
|
}
|
|
1754
|
-
if (snapshotCaptureActive && c && c.
|
|
2050
|
+
if (snapshotCaptureActive && c && c._config & CONFIG_IN_SNAPSHOT_SCOPE) {
|
|
1755
2051
|
const sv = el._snapshotValue;
|
|
1756
2052
|
if (sv !== undefined) {
|
|
1757
2053
|
const snapshot = sv === NO_SNAPSHOT ? undefined : sv;
|
|
@@ -1762,7 +2058,7 @@ function read(el) {
|
|
|
1762
2058
|
}
|
|
1763
2059
|
if (strictRead) {
|
|
1764
2060
|
const message =
|
|
1765
|
-
`Reactive value read directly in ${strictRead} will not update. ` +
|
|
2061
|
+
`[STRICT_READ_UNTRACKED] Reactive value read directly in ${strictRead} will not update. ` +
|
|
1766
2062
|
`Move it into a tracking scope (JSX, a memo, or an effect's compute function).`;
|
|
1767
2063
|
emitDiagnostic({
|
|
1768
2064
|
code: "STRICT_READ_UNTRACKED",
|
|
@@ -1780,7 +2076,20 @@ function read(el) {
|
|
|
1780
2076
|
if (c && stale && shouldReadStashedOptimisticValue(el)) return el._value;
|
|
1781
2077
|
return el._overrideValue;
|
|
1782
2078
|
}
|
|
1783
|
-
|
|
2079
|
+
if (
|
|
2080
|
+
activeTransition !== null &&
|
|
2081
|
+
currentOptimisticLane !== null &&
|
|
2082
|
+
!latestReadActive &&
|
|
2083
|
+
el._pendingValue !== NOT_PENDING &&
|
|
2084
|
+
owner === el &&
|
|
2085
|
+
!el._fn &&
|
|
2086
|
+
c
|
|
2087
|
+
) {
|
|
2088
|
+
activeTransition._gatedSubs.add(c);
|
|
2089
|
+
return el._value;
|
|
2090
|
+
}
|
|
2091
|
+
const value =
|
|
2092
|
+
!c ||
|
|
1784
2093
|
(currentOptimisticLane !== null &&
|
|
1785
2094
|
(el._overrideValue !== undefined ||
|
|
1786
2095
|
el._optimisticLane ||
|
|
@@ -1788,14 +2097,30 @@ function read(el) {
|
|
|
1788
2097
|
!!(owner._statusFlags & STATUS_PENDING))) ||
|
|
1789
2098
|
el._pendingValue === NOT_PENDING ||
|
|
1790
2099
|
(stale && el._transition && activeTransition !== el._transition)
|
|
1791
|
-
|
|
1792
|
-
|
|
2100
|
+
? el._value
|
|
2101
|
+
: el._pendingValue;
|
|
2102
|
+
if (
|
|
2103
|
+
!c &&
|
|
2104
|
+
owner === el &&
|
|
2105
|
+
typeof computed._fn === "function" &&
|
|
2106
|
+
el._config & CONFIG_AUTO_DISPOSE &&
|
|
2107
|
+
!(owner._statusFlags & STATUS_PENDING) &&
|
|
2108
|
+
!el._subs
|
|
2109
|
+
) {
|
|
2110
|
+
unobserved(el);
|
|
2111
|
+
}
|
|
2112
|
+
return value;
|
|
1793
2113
|
}
|
|
1794
2114
|
function setSignal(el, v) {
|
|
1795
|
-
if (
|
|
2115
|
+
if (
|
|
2116
|
+
!(el._config & CONFIG_OWNED_WRITE) &&
|
|
2117
|
+
!(context && context._config & CONFIG_CHILDREN_FORBIDDEN) &&
|
|
2118
|
+
context &&
|
|
2119
|
+
el._firewall !== context
|
|
2120
|
+
) {
|
|
1796
2121
|
const message =
|
|
1797
|
-
"Writing to a Signal inside an owned scope (component, computation) is not allowed. " +
|
|
1798
|
-
"Move the write outside or set the `
|
|
2122
|
+
"[SIGNAL_WRITE_IN_OWNED_SCOPE] Writing to a Signal inside an owned scope (component, computation) is not allowed. " +
|
|
2123
|
+
"Move the write outside or set the `ownedWrite` option if this is intentional.";
|
|
1799
2124
|
emitDiagnostic({
|
|
1800
2125
|
code: "SIGNAL_WRITE_IN_OWNED_SCOPE",
|
|
1801
2126
|
kind: "write",
|
|
@@ -1840,10 +2165,10 @@ function setSignal(el, v) {
|
|
|
1840
2165
|
el._optimisticLane = lane;
|
|
1841
2166
|
el._overrideValue = v;
|
|
1842
2167
|
} else {
|
|
1843
|
-
if (el._pendingValue === NOT_PENDING)
|
|
2168
|
+
if (el._pendingValue === NOT_PENDING) queuePendingNode(el);
|
|
1844
2169
|
el._pendingValue = v;
|
|
1845
2170
|
}
|
|
1846
|
-
updatePendingSignal(el);
|
|
2171
|
+
if (el._pendingSignal) updatePendingSignal(el);
|
|
1847
2172
|
if (el._latestValueComputed) {
|
|
1848
2173
|
setSignal(el._latestValueComputed, v);
|
|
1849
2174
|
}
|
|
@@ -1852,10 +2177,21 @@ function setSignal(el, v) {
|
|
|
1852
2177
|
schedule();
|
|
1853
2178
|
return v;
|
|
1854
2179
|
}
|
|
2180
|
+
function suppressComputedRecompute(el) {
|
|
2181
|
+
deleteFromHeap(el, el._flags & REACTIVE_ZOMBIE ? zombieQueue : dirtyQueue);
|
|
2182
|
+
if (!(el._flags & REACTIVE_MANUAL_WRITE) && el._pendingValue === NOT_PENDING)
|
|
2183
|
+
queuePendingNode(el);
|
|
2184
|
+
el._flags = (el._flags & -4) | REACTIVE_MANUAL_WRITE;
|
|
2185
|
+
}
|
|
2186
|
+
function setMemo(el, v) {
|
|
2187
|
+
const result = setSignal(el, v);
|
|
2188
|
+
suppressComputedRecompute(el);
|
|
2189
|
+
return result;
|
|
2190
|
+
}
|
|
1855
2191
|
function runWithOwner(owner, fn) {
|
|
1856
2192
|
if (owner && owner._flags & REACTIVE_DISPOSED) {
|
|
1857
2193
|
const message =
|
|
1858
|
-
"runWithOwner called with a disposed owner. Children created inside will never be disposed.";
|
|
2194
|
+
"[RUN_WITH_DISPOSED_OWNER] runWithOwner called with a disposed owner. Children created inside will never be disposed.";
|
|
1859
2195
|
emitDiagnostic({
|
|
1860
2196
|
code: "RUN_WITH_DISPOSED_OWNER",
|
|
1861
2197
|
kind: "owner",
|
|
@@ -1879,7 +2215,7 @@ function runWithOwner(owner, fn) {
|
|
|
1879
2215
|
}
|
|
1880
2216
|
function getPendingSignal(el) {
|
|
1881
2217
|
if (!el._pendingSignal) {
|
|
1882
|
-
el._pendingSignal = optimisticSignal(false, {
|
|
2218
|
+
el._pendingSignal = optimisticSignal(false, { ownedWrite: true });
|
|
1883
2219
|
if (el._parentSource) {
|
|
1884
2220
|
el._pendingSignal._parentSource = el;
|
|
1885
2221
|
}
|
|
@@ -1975,15 +2311,26 @@ function isPending(fn) {
|
|
|
1975
2311
|
foundPending = prevFoundPending;
|
|
1976
2312
|
}
|
|
1977
2313
|
}
|
|
1978
|
-
function refresh(
|
|
2314
|
+
function refresh(target) {
|
|
1979
2315
|
let prevRefreshing = refreshing;
|
|
1980
2316
|
refreshing = true;
|
|
1981
2317
|
try {
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
2318
|
+
const node = target?.[$REFRESH];
|
|
2319
|
+
if (true && !node) {
|
|
2320
|
+
const message =
|
|
2321
|
+
"[INVALID_REFRESH_TARGET] refresh() expects a Solid source accessor or refreshable store. " +
|
|
2322
|
+
"Pass the original source target, not a wrapper function or derived property read.";
|
|
2323
|
+
emitDiagnostic({
|
|
2324
|
+
code: "INVALID_REFRESH_TARGET",
|
|
2325
|
+
kind: "write",
|
|
2326
|
+
severity: "error",
|
|
2327
|
+
message: message
|
|
2328
|
+
});
|
|
2329
|
+
throw new Error(message);
|
|
2330
|
+
}
|
|
2331
|
+
if (node && typeof node._fn === "function" && !(node._flags & REACTIVE_DISPOSED)) {
|
|
2332
|
+
recompute(node);
|
|
1985
2333
|
}
|
|
1986
|
-
return untrack(fn);
|
|
1987
2334
|
} finally {
|
|
1988
2335
|
refreshing = prevRefreshing;
|
|
1989
2336
|
if (!prevRefreshing) {
|
|
@@ -2022,71 +2369,24 @@ function hasContext(context, owner) {
|
|
|
2022
2369
|
function isUndefined(value) {
|
|
2023
2370
|
return typeof value === "undefined";
|
|
2024
2371
|
}
|
|
2025
|
-
function effect(compute, effect, error,
|
|
2026
|
-
|
|
2027
|
-
const node =
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
if (initialized) node._queue.enqueue(node._type, runEffect.bind(node));
|
|
2035
|
-
return false;
|
|
2036
|
-
},
|
|
2037
|
-
lazy: true
|
|
2038
|
-
}
|
|
2372
|
+
function effect(compute, effect, error, options) {
|
|
2373
|
+
const isUser = !!options?.user;
|
|
2374
|
+
const node = createEffectNode(
|
|
2375
|
+
compute,
|
|
2376
|
+
effect,
|
|
2377
|
+
error,
|
|
2378
|
+
isUser ? EFFECT_USER : EFFECT_RENDER,
|
|
2379
|
+
notifyEffectStatus,
|
|
2380
|
+
options
|
|
2039
2381
|
);
|
|
2040
|
-
node._prevValue = initialValue;
|
|
2041
|
-
node._effectFn = effect;
|
|
2042
|
-
node._errorFn = error;
|
|
2043
|
-
node._cleanup = undefined;
|
|
2044
|
-
node._type = options?.render ? EFFECT_RENDER : EFFECT_USER;
|
|
2045
|
-
node._notifyStatus = (status, error) => {
|
|
2046
|
-
const actualStatus = status !== undefined ? status : node._statusFlags;
|
|
2047
|
-
const actualError = error !== undefined ? error : node._error;
|
|
2048
|
-
if (actualStatus & STATUS_ERROR) {
|
|
2049
|
-
let err = actualError;
|
|
2050
|
-
node._queue.notify(node, STATUS_PENDING, 0);
|
|
2051
|
-
if (node._type === EFFECT_USER) {
|
|
2052
|
-
try {
|
|
2053
|
-
return node._errorFn
|
|
2054
|
-
? node._errorFn(err, () => {
|
|
2055
|
-
node._cleanup?.();
|
|
2056
|
-
node._cleanup = undefined;
|
|
2057
|
-
})
|
|
2058
|
-
: console.error(err);
|
|
2059
|
-
} catch (e) {
|
|
2060
|
-
err = e;
|
|
2061
|
-
}
|
|
2062
|
-
}
|
|
2063
|
-
if (!node._queue.notify(node, STATUS_ERROR, STATUS_ERROR)) throw err;
|
|
2064
|
-
} else if (node._type === EFFECT_RENDER) {
|
|
2065
|
-
node._queue.notify(node, STATUS_PENDING | STATUS_ERROR, actualStatus, actualError);
|
|
2066
|
-
if (_hitUnhandledAsync) {
|
|
2067
|
-
resetUnhandledAsync();
|
|
2068
|
-
const err = new Error("An async value must be rendered inside a Loading boundary.");
|
|
2069
|
-
emitDiagnostic({
|
|
2070
|
-
code: "ASYNC_OUTSIDE_LOADING_BOUNDARY",
|
|
2071
|
-
kind: "async",
|
|
2072
|
-
severity: "error",
|
|
2073
|
-
message: err.message,
|
|
2074
|
-
ownerId: node.id,
|
|
2075
|
-
ownerName: node._name
|
|
2076
|
-
});
|
|
2077
|
-
if (!node._queue.notify(node, STATUS_ERROR, STATUS_ERROR)) throw err;
|
|
2078
|
-
}
|
|
2079
|
-
}
|
|
2080
|
-
};
|
|
2081
2382
|
recompute(node, true);
|
|
2082
2383
|
!options?.defer &&
|
|
2083
|
-
(node._type === EFFECT_USER
|
|
2084
|
-
? node._queue.enqueue(node._type, runEffect.bind(node))
|
|
2085
|
-
: runEffect
|
|
2086
|
-
initialized = true;
|
|
2087
|
-
cleanup(() => node._cleanup?.());
|
|
2384
|
+
(node._type === EFFECT_USER || options?.schedule
|
|
2385
|
+
? node._queue.enqueue(node._type, runEffect.bind(null, node))
|
|
2386
|
+
: runEffect(node));
|
|
2088
2387
|
if (!node._parent) {
|
|
2089
|
-
const message =
|
|
2388
|
+
const message =
|
|
2389
|
+
"[NO_OWNER_EFFECT] Effects created outside a reactive context will never be disposed";
|
|
2090
2390
|
emitDiagnostic({
|
|
2091
2391
|
code: "NO_OWNER_EFFECT",
|
|
2092
2392
|
kind: "lifecycle",
|
|
@@ -2099,32 +2399,76 @@ function effect(compute, effect, error, initialValue, options) {
|
|
|
2099
2399
|
console.warn(message);
|
|
2100
2400
|
}
|
|
2101
2401
|
}
|
|
2102
|
-
function
|
|
2103
|
-
|
|
2402
|
+
function notifyEffectStatus(status, error) {
|
|
2403
|
+
const actualStatus = status !== undefined ? status : this._statusFlags;
|
|
2404
|
+
const actualError = error !== undefined ? error : this._error;
|
|
2405
|
+
if (actualStatus & STATUS_ERROR) {
|
|
2406
|
+
let err = actualError;
|
|
2407
|
+
this._queue.notify(this, STATUS_PENDING, 0);
|
|
2408
|
+
if (this._type === EFFECT_USER) {
|
|
2409
|
+
try {
|
|
2410
|
+
return this._errorFn
|
|
2411
|
+
? this._errorFn(err, () => {
|
|
2412
|
+
this._cleanup?.();
|
|
2413
|
+
this._cleanup = undefined;
|
|
2414
|
+
})
|
|
2415
|
+
: console.error(err);
|
|
2416
|
+
} catch (e) {
|
|
2417
|
+
err = e;
|
|
2418
|
+
}
|
|
2419
|
+
}
|
|
2420
|
+
if (!this._queue.notify(this, STATUS_ERROR, STATUS_ERROR)) throw err;
|
|
2421
|
+
} else if (this._type === EFFECT_RENDER) {
|
|
2422
|
+
this._queue.notify(this, STATUS_PENDING | STATUS_ERROR, actualStatus, actualError);
|
|
2423
|
+
if (_hitUnhandledAsync) {
|
|
2424
|
+
resetUnhandledAsync();
|
|
2425
|
+
if (!this._queue.notify(this, STATUS_ERROR, STATUS_ERROR)) {
|
|
2426
|
+
const message =
|
|
2427
|
+
"[ASYNC_OUTSIDE_LOADING_BOUNDARY] An async value was read outside a Loading boundary. The root mount will be deferred until all pending async settles.";
|
|
2428
|
+
emitDiagnostic({
|
|
2429
|
+
code: "ASYNC_OUTSIDE_LOADING_BOUNDARY",
|
|
2430
|
+
kind: "async",
|
|
2431
|
+
severity: "warn",
|
|
2432
|
+
message: message,
|
|
2433
|
+
ownerId: this.id,
|
|
2434
|
+
ownerName: this._name
|
|
2435
|
+
});
|
|
2436
|
+
console.warn(message);
|
|
2437
|
+
}
|
|
2438
|
+
}
|
|
2439
|
+
}
|
|
2440
|
+
}
|
|
2441
|
+
function runEffect(node) {
|
|
2442
|
+
if (!node._modified || node._flags & REACTIVE_DISPOSED) return;
|
|
2104
2443
|
let prevStrictRead = false;
|
|
2105
2444
|
{
|
|
2106
2445
|
prevStrictRead = setStrictRead("an effect callback");
|
|
2107
2446
|
}
|
|
2108
|
-
|
|
2109
|
-
|
|
2447
|
+
node._cleanup?.();
|
|
2448
|
+
node._cleanup = undefined;
|
|
2110
2449
|
try {
|
|
2111
|
-
const
|
|
2112
|
-
if (true &&
|
|
2450
|
+
const nextCleanup = node._effectFn(node._value, node._prevValue);
|
|
2451
|
+
if (true && nextCleanup !== undefined && typeof nextCleanup !== "function") {
|
|
2113
2452
|
throw new Error(
|
|
2114
|
-
`${
|
|
2453
|
+
`${node._name || "effect"} callback returned an invalid cleanup value. Return a cleanup function or undefined.`
|
|
2115
2454
|
);
|
|
2116
2455
|
}
|
|
2117
|
-
|
|
2456
|
+
node._cleanup = nextCleanup;
|
|
2457
|
+
if (node._cleanup && !node._cleanupRegistered) {
|
|
2458
|
+
node._cleanupRegistered = true;
|
|
2459
|
+
runWithOwner(node._parent, () => cleanup(() => node._cleanup?.()));
|
|
2460
|
+
}
|
|
2118
2461
|
} catch (error) {
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
if (!
|
|
2462
|
+
node._error = new StatusError(node, error);
|
|
2463
|
+
node._statusFlags |= STATUS_ERROR;
|
|
2464
|
+
if (!node._queue.notify(node, STATUS_ERROR, STATUS_ERROR)) throw error;
|
|
2122
2465
|
} finally {
|
|
2123
2466
|
setStrictRead(prevStrictRead);
|
|
2124
|
-
|
|
2125
|
-
|
|
2467
|
+
node._prevValue = node._value;
|
|
2468
|
+
node._modified = false;
|
|
2126
2469
|
}
|
|
2127
2470
|
}
|
|
2471
|
+
GlobalQueue._runEffect = runEffect;
|
|
2128
2472
|
function trackedEffect(fn, options) {
|
|
2129
2473
|
const run = () => {
|
|
2130
2474
|
if (!node._modified || node._flags & REACTIVE_DISPOSED) return;
|
|
@@ -2148,11 +2492,10 @@ function trackedEffect(fn, options) {
|
|
|
2148
2492
|
}
|
|
2149
2493
|
node._cleanup = cleanup;
|
|
2150
2494
|
},
|
|
2151
|
-
undefined,
|
|
2152
2495
|
{ ...options, lazy: true }
|
|
2153
2496
|
);
|
|
2154
2497
|
node._cleanup = undefined;
|
|
2155
|
-
node.
|
|
2498
|
+
node._config = (node._config & ~CONFIG_AUTO_DISPOSE) | CONFIG_CHILDREN_FORBIDDEN;
|
|
2156
2499
|
node._modified = true;
|
|
2157
2500
|
node._type = EFFECT_TRACKED;
|
|
2158
2501
|
node._notifyStatus = (status, error) => {
|
|
@@ -2167,7 +2510,8 @@ function trackedEffect(fn, options) {
|
|
|
2167
2510
|
node._queue.enqueue(EFFECT_USER, run);
|
|
2168
2511
|
cleanup(() => node._cleanup?.());
|
|
2169
2512
|
if (!node._parent) {
|
|
2170
|
-
const message =
|
|
2513
|
+
const message =
|
|
2514
|
+
"[NO_OWNER_EFFECT] Effects created outside a reactive context will never be disposed";
|
|
2171
2515
|
emitDiagnostic({
|
|
2172
2516
|
code: "NO_OWNER_EFFECT",
|
|
2173
2517
|
kind: "lifecycle",
|
|
@@ -2228,7 +2572,8 @@ function onCleanup(fn) {
|
|
|
2228
2572
|
{
|
|
2229
2573
|
const owner = getOwner();
|
|
2230
2574
|
if (!owner) {
|
|
2231
|
-
const message =
|
|
2575
|
+
const message =
|
|
2576
|
+
"[NO_OWNER_CLEANUP] onCleanup called outside a reactive context will never be run";
|
|
2232
2577
|
emitDiagnostic({
|
|
2233
2578
|
code: "NO_OWNER_CLEANUP",
|
|
2234
2579
|
kind: "lifecycle",
|
|
@@ -2236,9 +2581,9 @@ function onCleanup(fn) {
|
|
|
2236
2581
|
message: message
|
|
2237
2582
|
});
|
|
2238
2583
|
console.warn(message);
|
|
2239
|
-
} else if (owner.
|
|
2584
|
+
} else if (owner._config & CONFIG_CHILDREN_FORBIDDEN) {
|
|
2240
2585
|
const message =
|
|
2241
|
-
"Cannot use onCleanup inside createTrackedEffect or onSettled; return a cleanup function instead";
|
|
2586
|
+
"[CLEANUP_IN_FORBIDDEN_SCOPE] Cannot use onCleanup inside createTrackedEffect or onSettled; return a cleanup function instead";
|
|
2242
2587
|
emitDiagnostic({
|
|
2243
2588
|
code: "CLEANUP_IN_FORBIDDEN_SCOPE",
|
|
2244
2589
|
kind: "lifecycle",
|
|
@@ -2254,34 +2599,45 @@ function onCleanup(fn) {
|
|
|
2254
2599
|
}
|
|
2255
2600
|
function accessor(node) {
|
|
2256
2601
|
const fn = read.bind(null, node);
|
|
2257
|
-
fn
|
|
2602
|
+
fn[$REFRESH] = node;
|
|
2258
2603
|
return fn;
|
|
2259
2604
|
}
|
|
2260
|
-
function createSignal(first, second
|
|
2605
|
+
function createSignal(first, second) {
|
|
2261
2606
|
if (typeof first === "function") {
|
|
2262
|
-
const node = computed(first, second
|
|
2263
|
-
|
|
2607
|
+
const node = computed(first, second);
|
|
2608
|
+
node._config &= ~CONFIG_AUTO_DISPOSE;
|
|
2609
|
+
return [accessor(node), setMemo.bind(null, node)];
|
|
2264
2610
|
}
|
|
2265
2611
|
const node = signal(first, second);
|
|
2266
2612
|
registerGraph(node, getOwner());
|
|
2267
2613
|
return [accessor(node), setSignal.bind(null, node)];
|
|
2268
2614
|
}
|
|
2269
|
-
function createMemo(compute,
|
|
2270
|
-
|
|
2271
|
-
return accessor(node);
|
|
2272
|
-
}
|
|
2273
|
-
function createEffect(compute, effectFn, value, options) {
|
|
2274
|
-
effect(compute, effectFn.effect || effectFn, effectFn.error, value, {
|
|
2275
|
-
...options,
|
|
2276
|
-
name: options?.name ?? "effect"
|
|
2277
|
-
});
|
|
2615
|
+
function createMemo(compute, options) {
|
|
2616
|
+
return accessor(computed(compute, options));
|
|
2278
2617
|
}
|
|
2279
|
-
function
|
|
2280
|
-
|
|
2281
|
-
|
|
2618
|
+
function createEffect(compute, effectFn, options) {
|
|
2619
|
+
if (effectFn === undefined) {
|
|
2620
|
+
const message =
|
|
2621
|
+
"[MISSING_EFFECT_FN] createEffect requires both a compute function and an effect function. " +
|
|
2622
|
+
"Use `createEffect(() => signal(), value => doWork(value))`. " +
|
|
2623
|
+
"If you want a derived value, use `createMemo`. " +
|
|
2624
|
+
"If you want a one-shot side effect, just call the function directly.";
|
|
2625
|
+
emitDiagnostic({
|
|
2626
|
+
code: "MISSING_EFFECT_FN",
|
|
2627
|
+
kind: "lifecycle",
|
|
2628
|
+
severity: "error",
|
|
2629
|
+
message: message
|
|
2630
|
+
});
|
|
2631
|
+
throw new Error(message);
|
|
2632
|
+
}
|
|
2633
|
+
effect(compute, effectFn.effect || effectFn, effectFn.error, {
|
|
2634
|
+
user: true,
|
|
2282
2635
|
...{ ...options, name: options?.name ?? "effect" }
|
|
2283
2636
|
});
|
|
2284
2637
|
}
|
|
2638
|
+
function createRenderEffect(compute, effectFn, options) {
|
|
2639
|
+
effect(compute, effectFn, undefined, { ...options, name: options?.name ?? "effect" });
|
|
2640
|
+
}
|
|
2285
2641
|
function createTrackedEffect(compute, options) {
|
|
2286
2642
|
trackedEffect(compute, { ...options, name: options?.name ?? "trackedEffect" });
|
|
2287
2643
|
}
|
|
@@ -2305,8 +2661,11 @@ function createReaction(effectFn, options) {
|
|
|
2305
2661
|
dispose(node);
|
|
2306
2662
|
},
|
|
2307
2663
|
effectFn.error,
|
|
2308
|
-
|
|
2309
|
-
|
|
2664
|
+
{
|
|
2665
|
+
...(true ? { ...options, name: options?.name ?? "effect" } : options),
|
|
2666
|
+
user: true,
|
|
2667
|
+
defer: true
|
|
2668
|
+
}
|
|
2310
2669
|
);
|
|
2311
2670
|
});
|
|
2312
2671
|
};
|
|
@@ -2331,9 +2690,10 @@ function resolve(fn) {
|
|
|
2331
2690
|
});
|
|
2332
2691
|
});
|
|
2333
2692
|
}
|
|
2334
|
-
function createOptimistic(first, second
|
|
2693
|
+
function createOptimistic(first, second) {
|
|
2335
2694
|
if (typeof first === "function") {
|
|
2336
|
-
const node = optimisticComputed(first, second
|
|
2695
|
+
const node = optimisticComputed(first, second);
|
|
2696
|
+
node._config &= ~CONFIG_AUTO_DISPOSE;
|
|
2337
2697
|
return [accessor(node), setSignal.bind(null, node)];
|
|
2338
2698
|
}
|
|
2339
2699
|
const node = optimisticSignal(first, second);
|
|
@@ -2342,7 +2702,7 @@ function createOptimistic(first, second, third) {
|
|
|
2342
2702
|
}
|
|
2343
2703
|
function onSettled(callback) {
|
|
2344
2704
|
const owner = getOwner();
|
|
2345
|
-
owner && !owner.
|
|
2705
|
+
owner && !(owner._config & CONFIG_CHILDREN_FORBIDDEN)
|
|
2346
2706
|
? createTrackedEffect(() => untrack(callback), { name: "onSettled" })
|
|
2347
2707
|
: globalQueue.enqueue(EFFECT_USER, () => {
|
|
2348
2708
|
const cleanup = callback();
|
|
@@ -2357,7 +2717,7 @@ function onSettled(callback) {
|
|
|
2357
2717
|
function unwrap(value) {
|
|
2358
2718
|
return value?.[$TARGET]?.[STORE_NODE] ?? value;
|
|
2359
2719
|
}
|
|
2360
|
-
function getOverrideValue(value, override,
|
|
2720
|
+
function getOverrideValue(value, override, key, optOverride) {
|
|
2361
2721
|
if (optOverride && key in optOverride) return optOverride[key];
|
|
2362
2722
|
return override && key in override ? override[key] : value[key];
|
|
2363
2723
|
}
|
|
@@ -2369,23 +2729,147 @@ function getAllKeys(value, override, next) {
|
|
|
2369
2729
|
function applyState(next, state, keyFn) {
|
|
2370
2730
|
const target = state?.[$TARGET];
|
|
2371
2731
|
if (!target) return;
|
|
2732
|
+
if (target[STORE_OVERRIDE] || target[STORE_OPTIMISTIC_OVERRIDE]) {
|
|
2733
|
+
applyStateSlow(next, target, keyFn);
|
|
2734
|
+
} else {
|
|
2735
|
+
applyStateFast(next, target, keyFn);
|
|
2736
|
+
}
|
|
2737
|
+
}
|
|
2738
|
+
function applyStateFast(next, target, keyFn) {
|
|
2739
|
+
const previous = target[STORE_VALUE];
|
|
2740
|
+
if (next === previous) return;
|
|
2741
|
+
(target[STORE_LOOKUP] || storeLookup).set(next, target[$PROXY]);
|
|
2742
|
+
target[STORE_VALUE] = next;
|
|
2743
|
+
if (Array.isArray(previous)) {
|
|
2744
|
+
let changed = false;
|
|
2745
|
+
const prevLength = previous.length;
|
|
2746
|
+
if (next.length && prevLength && next[0] && keyFn(next[0]) != null) {
|
|
2747
|
+
let i, j, start, end, newEnd, item, newIndicesNext, keyVal;
|
|
2748
|
+
for (
|
|
2749
|
+
start = 0, end = Math.min(prevLength, next.length);
|
|
2750
|
+
start < end &&
|
|
2751
|
+
((item = previous[start]) === next[start] ||
|
|
2752
|
+
(item && next[start] && keyFn(item) === keyFn(next[start])));
|
|
2753
|
+
start++
|
|
2754
|
+
) {
|
|
2755
|
+
applyState(next[start], wrap(item, target), keyFn);
|
|
2756
|
+
}
|
|
2757
|
+
const temp = new Array(next.length),
|
|
2758
|
+
newIndices = new Map();
|
|
2759
|
+
for (
|
|
2760
|
+
end = prevLength - 1, newEnd = next.length - 1;
|
|
2761
|
+
end >= start &&
|
|
2762
|
+
newEnd >= start &&
|
|
2763
|
+
((item = previous[end]) === next[newEnd] ||
|
|
2764
|
+
(item && next[newEnd] && keyFn(item) === keyFn(next[newEnd])));
|
|
2765
|
+
end--, newEnd--
|
|
2766
|
+
) {
|
|
2767
|
+
temp[newEnd] = item;
|
|
2768
|
+
}
|
|
2769
|
+
if (start > newEnd || start > end) {
|
|
2770
|
+
for (j = start; j <= newEnd; j++) {
|
|
2771
|
+
changed = true;
|
|
2772
|
+
target[STORE_NODE][j] && setSignal(target[STORE_NODE][j], wrap(next[j], target));
|
|
2773
|
+
}
|
|
2774
|
+
for (; j < next.length; j++) {
|
|
2775
|
+
changed = true;
|
|
2776
|
+
const wrapped = wrap(temp[j], target);
|
|
2777
|
+
target[STORE_NODE][j] && setSignal(target[STORE_NODE][j], wrapped);
|
|
2778
|
+
applyState(next[j], wrapped, keyFn);
|
|
2779
|
+
}
|
|
2780
|
+
changed && target[STORE_NODE][$TRACK] && setSignal(target[STORE_NODE][$TRACK], void 0);
|
|
2781
|
+
prevLength !== next.length &&
|
|
2782
|
+
target[STORE_NODE].length &&
|
|
2783
|
+
setSignal(target[STORE_NODE].length, next.length);
|
|
2784
|
+
return;
|
|
2785
|
+
}
|
|
2786
|
+
newIndicesNext = new Array(newEnd + 1);
|
|
2787
|
+
for (j = newEnd; j >= start; j--) {
|
|
2788
|
+
item = next[j];
|
|
2789
|
+
keyVal = item ? keyFn(item) : item;
|
|
2790
|
+
i = newIndices.get(keyVal);
|
|
2791
|
+
newIndicesNext[j] = i === undefined ? -1 : i;
|
|
2792
|
+
newIndices.set(keyVal, j);
|
|
2793
|
+
}
|
|
2794
|
+
for (i = start; i <= end; i++) {
|
|
2795
|
+
item = previous[i];
|
|
2796
|
+
keyVal = item ? keyFn(item) : item;
|
|
2797
|
+
j = newIndices.get(keyVal);
|
|
2798
|
+
if (j !== undefined && j !== -1) {
|
|
2799
|
+
temp[j] = item;
|
|
2800
|
+
j = newIndicesNext[j];
|
|
2801
|
+
newIndices.set(keyVal, j);
|
|
2802
|
+
}
|
|
2803
|
+
}
|
|
2804
|
+
for (j = start; j < next.length; j++) {
|
|
2805
|
+
if (j in temp) {
|
|
2806
|
+
const wrapped = wrap(temp[j], target);
|
|
2807
|
+
target[STORE_NODE][j] && setSignal(target[STORE_NODE][j], wrapped);
|
|
2808
|
+
applyState(next[j], wrapped, keyFn);
|
|
2809
|
+
} else target[STORE_NODE][j] && setSignal(target[STORE_NODE][j], wrap(next[j], target));
|
|
2810
|
+
}
|
|
2811
|
+
if (start < next.length) changed = true;
|
|
2812
|
+
} else if (next.length) {
|
|
2813
|
+
for (let i = 0, len = next.length; i < len; i++) {
|
|
2814
|
+
const item = previous[i];
|
|
2815
|
+
isWrappable(item)
|
|
2816
|
+
? applyState(next[i], wrap(item, target), keyFn)
|
|
2817
|
+
: target[STORE_NODE][i] && setSignal(target[STORE_NODE][i], next[i]);
|
|
2818
|
+
}
|
|
2819
|
+
}
|
|
2820
|
+
if (prevLength !== next.length) {
|
|
2821
|
+
changed = true;
|
|
2822
|
+
target[STORE_NODE].length && setSignal(target[STORE_NODE].length, next.length);
|
|
2823
|
+
}
|
|
2824
|
+
changed && target[STORE_NODE][$TRACK] && setSignal(target[STORE_NODE][$TRACK], void 0);
|
|
2825
|
+
return;
|
|
2826
|
+
}
|
|
2827
|
+
let nodes = target[STORE_NODE];
|
|
2828
|
+
if (nodes) {
|
|
2829
|
+
const tracked = nodes[$TRACK];
|
|
2830
|
+
const keys = tracked ? getAllKeys(previous, undefined, next) : Object.keys(nodes);
|
|
2831
|
+
for (let i = 0, len = keys.length; i < len; i++) {
|
|
2832
|
+
const key = keys[i];
|
|
2833
|
+
const node = nodes[key];
|
|
2834
|
+
const previousValue = unwrap(previous[key]);
|
|
2835
|
+
let nextValue = unwrap(next[key]);
|
|
2836
|
+
if (previousValue === nextValue) continue;
|
|
2837
|
+
if (
|
|
2838
|
+
!previousValue ||
|
|
2839
|
+
!isWrappable(previousValue) ||
|
|
2840
|
+
!isWrappable(nextValue) ||
|
|
2841
|
+
(keyFn(previousValue) != null && keyFn(previousValue) !== keyFn(nextValue))
|
|
2842
|
+
) {
|
|
2843
|
+
tracked && setSignal(tracked, void 0);
|
|
2844
|
+
node && setSignal(node, isWrappable(nextValue) ? wrap(nextValue, target) : nextValue);
|
|
2845
|
+
} else applyState(nextValue, wrap(previousValue, target), keyFn);
|
|
2846
|
+
}
|
|
2847
|
+
}
|
|
2848
|
+
if ((nodes = target[STORE_HAS])) {
|
|
2849
|
+
const keys = Object.keys(nodes);
|
|
2850
|
+
for (let i = 0, len = keys.length; i < len; i++) {
|
|
2851
|
+
const key = keys[i];
|
|
2852
|
+
setSignal(nodes[key], key in next);
|
|
2853
|
+
}
|
|
2854
|
+
}
|
|
2855
|
+
}
|
|
2856
|
+
function applyStateSlow(next, target, keyFn) {
|
|
2372
2857
|
const previous = target[STORE_VALUE];
|
|
2373
2858
|
const override = target[STORE_OVERRIDE];
|
|
2374
2859
|
const optOverride = target[STORE_OPTIMISTIC_OVERRIDE];
|
|
2375
2860
|
let nodes = target[STORE_NODE];
|
|
2376
|
-
if (next === previous && !override && !optOverride) return;
|
|
2377
2861
|
(target[STORE_LOOKUP] || storeLookup).set(next, target[$PROXY]);
|
|
2378
2862
|
target[STORE_VALUE] = next;
|
|
2379
2863
|
target[STORE_OVERRIDE] = undefined;
|
|
2380
2864
|
if (Array.isArray(previous)) {
|
|
2381
2865
|
let changed = false;
|
|
2382
|
-
const prevLength = getOverrideValue(previous, override,
|
|
2866
|
+
const prevLength = getOverrideValue(previous, override, "length", optOverride);
|
|
2383
2867
|
if (next.length && prevLength && next[0] && keyFn(next[0]) != null) {
|
|
2384
2868
|
let i, j, start, end, newEnd, item, newIndicesNext, keyVal;
|
|
2385
2869
|
for (
|
|
2386
2870
|
start = 0, end = Math.min(prevLength, next.length);
|
|
2387
2871
|
start < end &&
|
|
2388
|
-
((item = getOverrideValue(previous, override,
|
|
2872
|
+
((item = getOverrideValue(previous, override, start, optOverride)) === next[start] ||
|
|
2389
2873
|
(item && next[start] && keyFn(item) === keyFn(next[start])));
|
|
2390
2874
|
start++
|
|
2391
2875
|
) {
|
|
@@ -2397,7 +2881,7 @@ function applyState(next, state, keyFn) {
|
|
|
2397
2881
|
end = prevLength - 1, newEnd = next.length - 1;
|
|
2398
2882
|
end >= start &&
|
|
2399
2883
|
newEnd >= start &&
|
|
2400
|
-
((item = getOverrideValue(previous, override,
|
|
2884
|
+
((item = getOverrideValue(previous, override, end, optOverride)) === next[newEnd] ||
|
|
2401
2885
|
(item && next[newEnd] && keyFn(item) === keyFn(next[newEnd])));
|
|
2402
2886
|
end--, newEnd--
|
|
2403
2887
|
) {
|
|
@@ -2429,7 +2913,7 @@ function applyState(next, state, keyFn) {
|
|
|
2429
2913
|
newIndices.set(keyVal, j);
|
|
2430
2914
|
}
|
|
2431
2915
|
for (i = start; i <= end; i++) {
|
|
2432
|
-
item = getOverrideValue(previous, override,
|
|
2916
|
+
item = getOverrideValue(previous, override, i, optOverride);
|
|
2433
2917
|
keyVal = item ? keyFn(item) : item;
|
|
2434
2918
|
j = newIndices.get(keyVal);
|
|
2435
2919
|
if (j !== undefined && j !== -1) {
|
|
@@ -2448,7 +2932,7 @@ function applyState(next, state, keyFn) {
|
|
|
2448
2932
|
if (start < next.length) changed = true;
|
|
2449
2933
|
} else if (next.length) {
|
|
2450
2934
|
for (let i = 0, len = next.length; i < len; i++) {
|
|
2451
|
-
const item = getOverrideValue(previous, override,
|
|
2935
|
+
const item = getOverrideValue(previous, override, i, optOverride);
|
|
2452
2936
|
isWrappable(item)
|
|
2453
2937
|
? applyState(next[i], wrap(item, target), keyFn)
|
|
2454
2938
|
: target[STORE_NODE][i] && setSignal(target[STORE_NODE][i], next[i]);
|
|
@@ -2467,7 +2951,7 @@ function applyState(next, state, keyFn) {
|
|
|
2467
2951
|
for (let i = 0, len = keys.length; i < len; i++) {
|
|
2468
2952
|
const key = keys[i];
|
|
2469
2953
|
const node = nodes[key];
|
|
2470
|
-
const previousValue = unwrap(getOverrideValue(previous, override,
|
|
2954
|
+
const previousValue = unwrap(getOverrideValue(previous, override, key, optOverride));
|
|
2471
2955
|
let nextValue = unwrap(next[key]);
|
|
2472
2956
|
if (previousValue === nextValue) continue;
|
|
2473
2957
|
if (
|
|
@@ -2499,7 +2983,7 @@ function reconcile(value, key) {
|
|
|
2499
2983
|
applyState(value, state, keyFn);
|
|
2500
2984
|
};
|
|
2501
2985
|
}
|
|
2502
|
-
function createProjectionInternal(fn,
|
|
2986
|
+
function createProjectionInternal(fn, seed, options) {
|
|
2503
2987
|
let node;
|
|
2504
2988
|
const wrappedMap = new WeakMap();
|
|
2505
2989
|
const wrapper = s => {
|
|
@@ -2519,31 +3003,39 @@ function createProjectionInternal(fn, initialValue = {}, options) {
|
|
|
2519
3003
|
wrappedMap.set(source, wrapped);
|
|
2520
3004
|
return wrapped;
|
|
2521
3005
|
};
|
|
2522
|
-
const wrappedStore = wrapProjection(
|
|
2523
|
-
node = computed(
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
storeSetter(draft, s => {
|
|
2532
|
-
result = fn(s);
|
|
2533
|
-
settled = true;
|
|
2534
|
-
const value = handleAsync(owner, result, value => {
|
|
2535
|
-
value !== s &&
|
|
2536
|
-
value !== undefined &&
|
|
2537
|
-
storeSetter(wrappedStore, reconcile(value, options?.key || "id"));
|
|
2538
|
-
});
|
|
2539
|
-
value !== s && value !== undefined && reconcile(value, options?.key || "id")(wrappedStore);
|
|
2540
|
-
});
|
|
2541
|
-
});
|
|
2542
|
-
node._preventAutoDisposal = true;
|
|
3006
|
+
const wrappedStore = wrapProjection(seed);
|
|
3007
|
+
node = computed(
|
|
3008
|
+
() => {
|
|
3009
|
+
if (!node) node = getOwner();
|
|
3010
|
+
runProjectionComputed(wrappedStore, fn, options?.key || "id");
|
|
3011
|
+
},
|
|
3012
|
+
options?.name ? { name: options.name } : undefined
|
|
3013
|
+
);
|
|
3014
|
+
node._config &= ~CONFIG_AUTO_DISPOSE;
|
|
2543
3015
|
return { store: wrappedStore, node: node };
|
|
2544
3016
|
}
|
|
2545
|
-
function createProjection(fn,
|
|
2546
|
-
return createProjectionInternal(fn,
|
|
3017
|
+
function createProjection(fn, seed, options) {
|
|
3018
|
+
return createProjectionInternal(fn, seed, options).store;
|
|
3019
|
+
}
|
|
3020
|
+
function runProjectionComputed(wrappedStore, fn, key, wrapCommit) {
|
|
3021
|
+
const owner = getOwner();
|
|
3022
|
+
let settled = false;
|
|
3023
|
+
let result;
|
|
3024
|
+
const draft = new Proxy(
|
|
3025
|
+
wrappedStore,
|
|
3026
|
+
createWriteTraps(() => !settled || owner._inFlight === result)
|
|
3027
|
+
);
|
|
3028
|
+
storeSetter(draft, s => {
|
|
3029
|
+
result = fn(s);
|
|
3030
|
+
settled = true;
|
|
3031
|
+
const commit = v => {
|
|
3032
|
+
if (v === s || v === undefined) return;
|
|
3033
|
+
const write = () => storeSetter(wrappedStore, reconcile(v, key));
|
|
3034
|
+
wrapCommit ? wrapCommit(write) : write();
|
|
3035
|
+
};
|
|
3036
|
+
commit(handleAsync(owner, result, commit));
|
|
3037
|
+
});
|
|
3038
|
+
return owner;
|
|
2547
3039
|
}
|
|
2548
3040
|
function createWriteTraps(isActive) {
|
|
2549
3041
|
const traps = {
|
|
@@ -2607,6 +3099,7 @@ const STORE_VALUE = "v",
|
|
|
2607
3099
|
STORE_OPTIMISTIC_OVERRIDE = "x",
|
|
2608
3100
|
STORE_NODE = "n",
|
|
2609
3101
|
STORE_HAS = "h",
|
|
3102
|
+
STORE_CUSTOM_PROTO = "c",
|
|
2610
3103
|
STORE_WRAP = "w",
|
|
2611
3104
|
STORE_LOOKUP = "l",
|
|
2612
3105
|
STORE_FIREWALL = "f",
|
|
@@ -2616,7 +3109,14 @@ function createStoreProxy(value, traps = storeTraps, extend) {
|
|
|
2616
3109
|
if (Array.isArray(value)) {
|
|
2617
3110
|
newTarget = [];
|
|
2618
3111
|
newTarget.v = value;
|
|
2619
|
-
} else
|
|
3112
|
+
} else {
|
|
3113
|
+
newTarget = { v: value };
|
|
3114
|
+
const unwrapped = value?.[$TARGET]?.[STORE_VALUE] ?? value;
|
|
3115
|
+
const proto = Object.getPrototypeOf(unwrapped);
|
|
3116
|
+
if (proto !== null && proto !== Object.prototype) {
|
|
3117
|
+
newTarget[STORE_CUSTOM_PROTO] = true;
|
|
3118
|
+
}
|
|
3119
|
+
}
|
|
2620
3120
|
extend && extend(newTarget);
|
|
2621
3121
|
return (newTarget[$PROXY] = new Proxy(newTarget, traps));
|
|
2622
3122
|
}
|
|
@@ -2628,12 +3128,8 @@ function wrap(value, target) {
|
|
|
2628
3128
|
return p;
|
|
2629
3129
|
}
|
|
2630
3130
|
function isWrappable(obj) {
|
|
2631
|
-
return
|
|
2632
|
-
|
|
2633
|
-
typeof obj === "object" &&
|
|
2634
|
-
!Object.isFrozen(obj) &&
|
|
2635
|
-
!(typeof Node !== "undefined" && obj instanceof Node)
|
|
2636
|
-
);
|
|
3131
|
+
if (obj == null || typeof obj !== "object" || Object.isFrozen(obj)) return false;
|
|
3132
|
+
return typeof Node === "undefined" || !(obj instanceof Node);
|
|
2637
3133
|
}
|
|
2638
3134
|
let writeOverride = false;
|
|
2639
3135
|
function setWriteOverride(value) {
|
|
@@ -2642,6 +3138,18 @@ function setWriteOverride(value) {
|
|
|
2642
3138
|
function writeOnly(proxy) {
|
|
2643
3139
|
return writeOverride || !!Writing?.has(proxy);
|
|
2644
3140
|
}
|
|
3141
|
+
function unwrapStoreValue(value) {
|
|
3142
|
+
return value?.[$TARGET]?.[STORE_VALUE] ?? value;
|
|
3143
|
+
}
|
|
3144
|
+
function hasInheritedAccessor(source, property) {
|
|
3145
|
+
let current = Object.getPrototypeOf(source);
|
|
3146
|
+
while (current && current !== Object.prototype) {
|
|
3147
|
+
const desc = Reflect.getOwnPropertyDescriptor(current, property);
|
|
3148
|
+
if (desc) return !!desc.get;
|
|
3149
|
+
current = Object.getPrototypeOf(current);
|
|
3150
|
+
}
|
|
3151
|
+
return false;
|
|
3152
|
+
}
|
|
2645
3153
|
function getNodes(target, type) {
|
|
2646
3154
|
let nodes = target[type];
|
|
2647
3155
|
if (!nodes) target[type] = nodes = Object.create(null);
|
|
@@ -2654,7 +3162,7 @@ function getNode(nodes, property, value, firewall, equals = isEqual, optimistic,
|
|
|
2654
3162
|
{
|
|
2655
3163
|
equals: equals,
|
|
2656
3164
|
unobserved() {
|
|
2657
|
-
delete nodes[property];
|
|
3165
|
+
if (nodes[property] === s) delete nodes[property];
|
|
2658
3166
|
}
|
|
2659
3167
|
},
|
|
2660
3168
|
firewall
|
|
@@ -2728,19 +3236,51 @@ function prepareStoreWrite(target, store, property) {
|
|
|
2728
3236
|
if (useOptimistic) trackOptimisticStore(store);
|
|
2729
3237
|
return { base: base, overrideKey: overrideKey, state: state };
|
|
2730
3238
|
}
|
|
2731
|
-
function
|
|
2732
|
-
if (
|
|
3239
|
+
function upsertStoreNode(target, nodes, property, prev, snapshotProps) {
|
|
3240
|
+
if (nodes[property]) return nodes[property];
|
|
3241
|
+
const initial = isWrappable(prev) ? wrap(prev, target) : prev;
|
|
3242
|
+
const node = getNode(
|
|
3243
|
+
nodes,
|
|
3244
|
+
property,
|
|
3245
|
+
initial,
|
|
3246
|
+
target[STORE_FIREWALL],
|
|
3247
|
+
isEqual,
|
|
3248
|
+
target[STORE_OPTIMISTIC],
|
|
3249
|
+
snapshotProps
|
|
3250
|
+
);
|
|
3251
|
+
registerTransientStoreNode(node);
|
|
3252
|
+
return node;
|
|
3253
|
+
}
|
|
3254
|
+
function notifyStoreProperty(target, property, mode, value, prev, prevHas) {
|
|
3255
|
+
const skipUpsert = projectionWriteActive || target[STORE_OPTIMISTIC];
|
|
3256
|
+
const newHas = mode !== "delete";
|
|
3257
|
+
const existingHas = target[STORE_HAS]?.[property];
|
|
3258
|
+
if (existingHas) {
|
|
3259
|
+
setSignal(existingHas, newHas);
|
|
3260
|
+
} else if (!skipUpsert && mode !== "invalidate" && prevHas !== newHas) {
|
|
3261
|
+
const hasNode = upsertStoreNode(target, getNodes(target, STORE_HAS), property, prevHas);
|
|
3262
|
+
setSignal(hasNode, newHas);
|
|
3263
|
+
}
|
|
2733
3264
|
const nodes = getNodes(target, STORE_NODE);
|
|
2734
3265
|
if (mode === "set") {
|
|
2735
|
-
nodes[property]
|
|
3266
|
+
if (nodes[property]) {
|
|
2736
3267
|
setSignal(nodes[property], () => (isWrappable(value) ? wrap(value, target) : value));
|
|
3268
|
+
} else if (!skipUpsert) {
|
|
3269
|
+
const node = upsertStoreNode(target, nodes, property, prev, target[STORE_SNAPSHOT_PROPS]);
|
|
3270
|
+
setSignal(node, () => (isWrappable(value) ? wrap(value, target) : value));
|
|
3271
|
+
}
|
|
2737
3272
|
} else if (mode === "invalidate") {
|
|
2738
3273
|
if (nodes[property]) {
|
|
2739
3274
|
setSignal(nodes[property], {});
|
|
2740
3275
|
delete nodes[property];
|
|
2741
3276
|
}
|
|
2742
3277
|
} else {
|
|
2743
|
-
|
|
3278
|
+
if (nodes[property]) {
|
|
3279
|
+
setSignal(nodes[property], undefined);
|
|
3280
|
+
} else if (!skipUpsert) {
|
|
3281
|
+
const node = upsertStoreNode(target, nodes, property, prev, target[STORE_SNAPSHOT_PROPS]);
|
|
3282
|
+
setSignal(node, undefined);
|
|
3283
|
+
}
|
|
2744
3284
|
}
|
|
2745
3285
|
nodes[$TRACK] && setSignal(nodes[$TRACK], undefined);
|
|
2746
3286
|
}
|
|
@@ -2756,6 +3296,21 @@ const storeTraps = {
|
|
|
2756
3296
|
}
|
|
2757
3297
|
const nodes = getNodes(target, STORE_NODE);
|
|
2758
3298
|
const tracked = nodes[property];
|
|
3299
|
+
const source = target[STORE_VALUE];
|
|
3300
|
+
if (
|
|
3301
|
+
!tracked &&
|
|
3302
|
+
!target[STORE_OVERRIDE] &&
|
|
3303
|
+
!target[STORE_OPTIMISTIC_OVERRIDE] &&
|
|
3304
|
+
!target[STORE_CUSTOM_PROTO] &&
|
|
3305
|
+
!target[STORE_OPTIMISTIC] &&
|
|
3306
|
+
!target[STORE_SNAPSHOT_PROPS] &&
|
|
3307
|
+
!source[$TARGET] &&
|
|
3308
|
+
!(property in source) &&
|
|
3309
|
+
getObserver() &&
|
|
3310
|
+
!writeOnly(receiver)
|
|
3311
|
+
) {
|
|
3312
|
+
return read(getNode(nodes, property, undefined, target[STORE_FIREWALL]));
|
|
3313
|
+
}
|
|
2759
3314
|
const optOverridden =
|
|
2760
3315
|
target[STORE_OPTIMISTIC_OVERRIDE] && property in target[STORE_OPTIMISTIC_OVERRIDE];
|
|
2761
3316
|
const overridden =
|
|
@@ -2769,6 +3324,12 @@ const storeTraps = {
|
|
|
2769
3324
|
if (!tracked) {
|
|
2770
3325
|
const desc = Object.getOwnPropertyDescriptor(storeValue, property);
|
|
2771
3326
|
if (desc && desc.get) return desc.get.call(receiver);
|
|
3327
|
+
if (!desc && !overridden && target[STORE_CUSTOM_PROTO]) {
|
|
3328
|
+
const source = unwrapStoreValue(storeValue);
|
|
3329
|
+
if (hasInheritedAccessor(source, property)) {
|
|
3330
|
+
return Reflect.get(storeValue, property, receiver);
|
|
3331
|
+
}
|
|
3332
|
+
}
|
|
2772
3333
|
}
|
|
2773
3334
|
if (writeOnly(receiver)) {
|
|
2774
3335
|
let value =
|
|
@@ -2815,7 +3376,7 @@ const storeTraps = {
|
|
|
2815
3376
|
}
|
|
2816
3377
|
if (strictRead && typeof property === "string") {
|
|
2817
3378
|
const message =
|
|
2818
|
-
`Reactive value read directly in ${strictRead} will not update. ` +
|
|
3379
|
+
`[STRICT_READ_UNTRACKED] Reactive value read directly in ${strictRead} will not update. ` +
|
|
2819
3380
|
`Move it into a tracking scope (JSX, a memo, or an effect's compute function).`;
|
|
2820
3381
|
emitDiagnostic({
|
|
2821
3382
|
code: "STRICT_READ_UNTRACKED",
|
|
@@ -2837,18 +3398,13 @@ const storeTraps = {
|
|
|
2837
3398
|
: target[STORE_OVERRIDE] && property in target[STORE_OVERRIDE]
|
|
2838
3399
|
? target[STORE_OVERRIDE][property] !== $DELETED
|
|
2839
3400
|
: property in target[STORE_VALUE];
|
|
2840
|
-
if (
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
target[STORE_FIREWALL],
|
|
2848
|
-
isEqual,
|
|
2849
|
-
target[STORE_OPTIMISTIC]
|
|
2850
|
-
)
|
|
2851
|
-
);
|
|
3401
|
+
if (writeOnly(target[$PROXY])) return has;
|
|
3402
|
+
const nodes = getNodes(target, STORE_HAS);
|
|
3403
|
+
if (nodes[property]) return read(nodes[property]);
|
|
3404
|
+
if (getObserver()) {
|
|
3405
|
+
return read(
|
|
3406
|
+
getNode(nodes, property, has, target[STORE_FIREWALL], isEqual, target[STORE_OPTIMISTIC])
|
|
3407
|
+
);
|
|
2852
3408
|
}
|
|
2853
3409
|
return has;
|
|
2854
3410
|
},
|
|
@@ -2867,7 +3423,13 @@ const storeTraps = {
|
|
|
2867
3423
|
: target[STORE_OVERRIDE] && property in target[STORE_OVERRIDE]
|
|
2868
3424
|
? target[STORE_OVERRIDE][property]
|
|
2869
3425
|
: base;
|
|
2870
|
-
const
|
|
3426
|
+
const prevHas =
|
|
3427
|
+
target[STORE_OPTIMISTIC_OVERRIDE] && property in target[STORE_OPTIMISTIC_OVERRIDE]
|
|
3428
|
+
? target[STORE_OPTIMISTIC_OVERRIDE][property] !== $DELETED
|
|
3429
|
+
: target[STORE_OVERRIDE] && property in target[STORE_OVERRIDE]
|
|
3430
|
+
? target[STORE_OVERRIDE][property] !== $DELETED
|
|
3431
|
+
: property in target[STORE_VALUE];
|
|
3432
|
+
const value = unwrapStoreValue(rawValue);
|
|
2871
3433
|
const isArrayIndexWrite = Array.isArray(state) && property !== "length";
|
|
2872
3434
|
const nextIndex = isArrayIndexWrite ? parseInt(property) + 1 : 0;
|
|
2873
3435
|
const len =
|
|
@@ -2886,11 +3448,21 @@ const storeTraps = {
|
|
|
2886
3448
|
override[property] = value;
|
|
2887
3449
|
if (nextLength !== undefined) override.length = nextLength;
|
|
2888
3450
|
}
|
|
2889
|
-
notifyStoreProperty(target, property, "set", value);
|
|
2890
|
-
if (Array.isArray(state)) {
|
|
3451
|
+
notifyStoreProperty(target, property, "set", value, prev, prevHas);
|
|
3452
|
+
if (Array.isArray(state) && property !== "length" && nextLength !== undefined) {
|
|
2891
3453
|
const nodes = getNodes(target, STORE_NODE);
|
|
2892
|
-
|
|
2893
|
-
|
|
3454
|
+
if (nodes.length) {
|
|
3455
|
+
setSignal(nodes.length, nextLength);
|
|
3456
|
+
} else if (!projectionWriteActive && !target[STORE_OPTIMISTIC]) {
|
|
3457
|
+
const node = upsertStoreNode(
|
|
3458
|
+
target,
|
|
3459
|
+
nodes,
|
|
3460
|
+
"length",
|
|
3461
|
+
len,
|
|
3462
|
+
target[STORE_SNAPSHOT_PROPS]
|
|
3463
|
+
);
|
|
3464
|
+
setSignal(node, nextLength);
|
|
3465
|
+
}
|
|
2894
3466
|
}
|
|
2895
3467
|
if (true) DEV$1.hooks.onStoreNodeUpdate?.(target[$PROXY], property, value, prev);
|
|
2896
3468
|
});
|
|
@@ -2904,10 +3476,7 @@ const storeTraps = {
|
|
|
2904
3476
|
const { base: base, overrideKey: overrideKey } = prepareStoreWrite(target, store, property);
|
|
2905
3477
|
const normalizedDescriptor =
|
|
2906
3478
|
"value" in descriptor
|
|
2907
|
-
? {
|
|
2908
|
-
...descriptor,
|
|
2909
|
-
value: descriptor.value?.[$TARGET]?.[STORE_VALUE] ?? descriptor.value
|
|
2910
|
-
}
|
|
3479
|
+
? { ...descriptor, value: unwrapStoreValue(descriptor.value) }
|
|
2911
3480
|
: descriptor;
|
|
2912
3481
|
Object.defineProperty(
|
|
2913
3482
|
target[overrideKey] || (target[overrideKey] = Object.create(null)),
|
|
@@ -2948,7 +3517,7 @@ const storeTraps = {
|
|
|
2948
3517
|
} else if (target[overrideKey] && property in target[overrideKey]) {
|
|
2949
3518
|
delete target[overrideKey][property];
|
|
2950
3519
|
} else return true;
|
|
2951
|
-
notifyStoreProperty(target, property, "delete");
|
|
3520
|
+
notifyStoreProperty(target, property, "delete", undefined, prev, true);
|
|
2952
3521
|
});
|
|
2953
3522
|
}
|
|
2954
3523
|
return true;
|
|
@@ -3016,12 +3585,17 @@ function createStore(first, second, options) {
|
|
|
3016
3585
|
const derived = typeof first === "function",
|
|
3017
3586
|
wrappedStore = derived ? createProjectionInternal(first, second, options).store : wrap(first);
|
|
3018
3587
|
registerGraph(wrappedStore, getOwner());
|
|
3019
|
-
return [
|
|
3588
|
+
return [
|
|
3589
|
+
wrappedStore,
|
|
3590
|
+
derived
|
|
3591
|
+
? fn => (storeSetter(wrappedStore, fn), suppressComputedRecompute(wrappedStore[$REFRESH]))
|
|
3592
|
+
: fn => storeSetter(wrappedStore, fn)
|
|
3593
|
+
];
|
|
3020
3594
|
}
|
|
3021
3595
|
function createOptimisticStore(first, second, options) {
|
|
3022
3596
|
GlobalQueue._clearOptimisticStore ||= clearOptimisticStore;
|
|
3023
3597
|
const derived = typeof first === "function";
|
|
3024
|
-
const initialValue =
|
|
3598
|
+
const initialValue = derived ? second : first;
|
|
3025
3599
|
const fn = derived ? first : undefined;
|
|
3026
3600
|
const { store: wrappedStore } = createOptimisticProjectionInternal(fn, initialValue, options);
|
|
3027
3601
|
return [wrappedStore, fn => storeSetter(wrappedStore, fn)];
|
|
@@ -3055,7 +3629,7 @@ function clearOptimisticStore(store) {
|
|
|
3055
3629
|
}
|
|
3056
3630
|
delete target[STORE_OPTIMISTIC_OVERRIDE];
|
|
3057
3631
|
}
|
|
3058
|
-
function createOptimisticProjectionInternal(fn, initialValue
|
|
3632
|
+
function createOptimisticProjectionInternal(fn, initialValue, options) {
|
|
3059
3633
|
let node;
|
|
3060
3634
|
const wrappedMap = new WeakMap();
|
|
3061
3635
|
const wrapper = s => {
|
|
@@ -3078,42 +3652,33 @@ function createOptimisticProjectionInternal(fn, initialValue = {}, options) {
|
|
|
3078
3652
|
};
|
|
3079
3653
|
const wrappedStore = wrapProjection(initialValue);
|
|
3080
3654
|
if (fn) {
|
|
3081
|
-
|
|
3082
|
-
const owner = getOwner();
|
|
3083
|
-
let settled = false;
|
|
3084
|
-
let result;
|
|
3085
|
-
const draft = new Proxy(
|
|
3086
|
-
wrappedStore,
|
|
3087
|
-
createWriteTraps(() => !settled || owner._inFlight === result)
|
|
3088
|
-
);
|
|
3655
|
+
const wrapCommit = write => {
|
|
3089
3656
|
setProjectionWriteActive(true);
|
|
3090
3657
|
try {
|
|
3091
|
-
|
|
3092
|
-
result = fn(s);
|
|
3093
|
-
settled = true;
|
|
3094
|
-
const value = handleAsync(owner, result, value => {
|
|
3095
|
-
setProjectionWriteActive(true);
|
|
3096
|
-
try {
|
|
3097
|
-
value !== s &&
|
|
3098
|
-
value !== undefined &&
|
|
3099
|
-
storeSetter(wrappedStore, reconcile(value, options?.key || "id"));
|
|
3100
|
-
} finally {
|
|
3101
|
-
setProjectionWriteActive(false);
|
|
3102
|
-
}
|
|
3103
|
-
});
|
|
3104
|
-
value !== s &&
|
|
3105
|
-
value !== undefined &&
|
|
3106
|
-
reconcile(value, options?.key || "id")(wrappedStore);
|
|
3107
|
-
});
|
|
3658
|
+
write();
|
|
3108
3659
|
} finally {
|
|
3109
3660
|
setProjectionWriteActive(false);
|
|
3110
3661
|
}
|
|
3111
|
-
}
|
|
3112
|
-
node
|
|
3662
|
+
};
|
|
3663
|
+
node = computed(
|
|
3664
|
+
() => {
|
|
3665
|
+
setProjectionWriteActive(true);
|
|
3666
|
+
try {
|
|
3667
|
+
runProjectionComputed(wrappedStore, fn, options?.key || "id", wrapCommit);
|
|
3668
|
+
} finally {
|
|
3669
|
+
setProjectionWriteActive(false);
|
|
3670
|
+
}
|
|
3671
|
+
},
|
|
3672
|
+
options?.name ? { name: options.name } : undefined
|
|
3673
|
+
);
|
|
3674
|
+
node._config &= ~CONFIG_AUTO_DISPOSE;
|
|
3113
3675
|
}
|
|
3114
3676
|
return { store: wrappedStore, node: node };
|
|
3115
3677
|
}
|
|
3116
3678
|
const DELETE = Symbol("STORE_PATH_DELETE");
|
|
3679
|
+
function isPrototypePollutionKey(part) {
|
|
3680
|
+
return part === "__proto__" || part === "constructor" || part === "prototype";
|
|
3681
|
+
}
|
|
3117
3682
|
function updatePath(current, args, i = 0) {
|
|
3118
3683
|
let part,
|
|
3119
3684
|
prev = current;
|
|
@@ -3121,6 +3686,7 @@ function updatePath(current, args, i = 0) {
|
|
|
3121
3686
|
part = args[i];
|
|
3122
3687
|
const partType = typeof part;
|
|
3123
3688
|
const isArray = Array.isArray(current);
|
|
3689
|
+
if (partType === "string" && isPrototypePollutionKey(part)) return;
|
|
3124
3690
|
if (Array.isArray(part)) {
|
|
3125
3691
|
for (let j = 0; j < part.length; j++) {
|
|
3126
3692
|
args[i] = part[j];
|
|
@@ -3167,6 +3733,7 @@ function updatePath(current, args, i = 0) {
|
|
|
3167
3733
|
const keys = Object.keys(value);
|
|
3168
3734
|
for (let i = 0; i < keys.length; i++) {
|
|
3169
3735
|
const key = keys[i];
|
|
3736
|
+
if (isPrototypePollutionKey(key)) continue;
|
|
3170
3737
|
const desc = Object.getOwnPropertyDescriptor(value, key);
|
|
3171
3738
|
if (desc.get || desc.set) Object.defineProperty(target, key, desc);
|
|
3172
3739
|
else target[key] = desc.value;
|
|
@@ -3281,8 +3848,9 @@ function merge(...sources) {
|
|
|
3281
3848
|
const s = sources[i];
|
|
3282
3849
|
proxy = proxy || (!!s && $PROXY in s);
|
|
3283
3850
|
const childSources = !!s && s[$SOURCES];
|
|
3284
|
-
if (childSources)
|
|
3285
|
-
|
|
3851
|
+
if (childSources) {
|
|
3852
|
+
for (let i = 0; i < childSources.length; i++) flattened.push(childSources[i]);
|
|
3853
|
+
} else flattened.push(typeof s === "function" ? ((proxy = true), createMemo(s)) : s);
|
|
3286
3854
|
}
|
|
3287
3855
|
if (SUPPORTS_PROXY && proxy) {
|
|
3288
3856
|
return new Proxy(
|
|
@@ -3301,10 +3869,12 @@ function merge(...sources) {
|
|
|
3301
3869
|
return false;
|
|
3302
3870
|
},
|
|
3303
3871
|
keys() {
|
|
3304
|
-
const keys =
|
|
3305
|
-
for (let i = 0; i < flattened.length; i++)
|
|
3306
|
-
|
|
3307
|
-
|
|
3872
|
+
const keys = new Set();
|
|
3873
|
+
for (let i = 0; i < flattened.length; i++) {
|
|
3874
|
+
const sourceKeys = Object.keys(resolveSource(flattened[i]));
|
|
3875
|
+
for (let j = 0; j < sourceKeys.length; j++) keys.add(sourceKeys[j]);
|
|
3876
|
+
}
|
|
3877
|
+
return [...keys];
|
|
3308
3878
|
}
|
|
3309
3879
|
},
|
|
3310
3880
|
propTraps
|
|
@@ -3345,26 +3915,27 @@ function merge(...sources) {
|
|
|
3345
3915
|
return target;
|
|
3346
3916
|
}
|
|
3347
3917
|
function omit(props, ...keys) {
|
|
3348
|
-
const blocked = new Set(keys);
|
|
3349
3918
|
if (SUPPORTS_PROXY && $PROXY in props) {
|
|
3350
3919
|
return new Proxy(
|
|
3351
3920
|
{
|
|
3352
3921
|
get(property) {
|
|
3353
|
-
return
|
|
3922
|
+
return keys.includes(property) ? undefined : props[property];
|
|
3354
3923
|
},
|
|
3355
3924
|
has(property) {
|
|
3356
|
-
return !
|
|
3925
|
+
return !keys.includes(property) && property in props;
|
|
3357
3926
|
},
|
|
3358
3927
|
keys() {
|
|
3359
|
-
return Object.keys(props).filter(k => !
|
|
3928
|
+
return Object.keys(props).filter(k => !keys.includes(k));
|
|
3360
3929
|
}
|
|
3361
3930
|
},
|
|
3362
3931
|
propTraps
|
|
3363
3932
|
);
|
|
3364
3933
|
}
|
|
3365
3934
|
const result = {};
|
|
3366
|
-
|
|
3367
|
-
|
|
3935
|
+
const propNames = Object.getOwnPropertyNames(props);
|
|
3936
|
+
const blocked = keys.length > 4 && propNames.length > keys.length ? new Set(keys) : undefined;
|
|
3937
|
+
for (const propName of propNames) {
|
|
3938
|
+
if (blocked ? !blocked.has(propName) : !keys.includes(propName)) {
|
|
3368
3939
|
const desc = Object.getOwnPropertyDescriptor(props, propName);
|
|
3369
3940
|
!desc.get && !desc.set && desc.enumerable && desc.writable && desc.configurable
|
|
3370
3941
|
? (result[propName] = desc.value)
|
|
@@ -3386,23 +3957,25 @@ function mapArray(list, map, options) {
|
|
|
3386
3957
|
}
|
|
3387
3958
|
}
|
|
3388
3959
|
: map;
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3960
|
+
const data = {
|
|
3961
|
+
_owner: createOwner(),
|
|
3962
|
+
_len: 0,
|
|
3963
|
+
_list: list,
|
|
3964
|
+
_items: [],
|
|
3965
|
+
_map: wrappedMap,
|
|
3966
|
+
_mappings: [],
|
|
3967
|
+
_nodes: [],
|
|
3968
|
+
_key: keyFn,
|
|
3969
|
+
_rows: keyFn || options?.keyed === false ? [] : undefined,
|
|
3970
|
+
_indexes: indexes ? [] : undefined,
|
|
3971
|
+
_fallback: options?.fallback
|
|
3972
|
+
};
|
|
3973
|
+
const node = computed(updateKeyedMap.bind(data));
|
|
3974
|
+
data._owner._parentComputed = node;
|
|
3975
|
+
node._config &= ~CONFIG_AUTO_DISPOSE;
|
|
3976
|
+
return accessor(node);
|
|
3404
3977
|
}
|
|
3405
|
-
const pureOptions = {
|
|
3978
|
+
const pureOptions = { ownedWrite: true };
|
|
3406
3979
|
function updateKeyedMap() {
|
|
3407
3980
|
const newItems = this._list() || [],
|
|
3408
3981
|
newLen = newItems.length;
|
|
@@ -3539,17 +4112,21 @@ function repeat(count, map, options) {
|
|
|
3539
4112
|
}
|
|
3540
4113
|
}
|
|
3541
4114
|
: map;
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
4115
|
+
const node = computed(
|
|
4116
|
+
updateRepeat.bind({
|
|
4117
|
+
_owner: createOwner(),
|
|
4118
|
+
_len: 0,
|
|
4119
|
+
_offset: 0,
|
|
4120
|
+
_count: count,
|
|
4121
|
+
_map: wrappedMap,
|
|
4122
|
+
_nodes: [],
|
|
4123
|
+
_mappings: [],
|
|
4124
|
+
_from: options?.from,
|
|
4125
|
+
_fallback: options?.fallback
|
|
4126
|
+
})
|
|
4127
|
+
);
|
|
4128
|
+
node._config &= ~CONFIG_AUTO_DISPOSE;
|
|
4129
|
+
return accessor(node);
|
|
3553
4130
|
}
|
|
3554
4131
|
function updateRepeat() {
|
|
3555
4132
|
const newLen = this._count();
|
|
@@ -3606,7 +4183,7 @@ function compare(key, a, b) {
|
|
|
3606
4183
|
return key ? key(a) === key(b) : true;
|
|
3607
4184
|
}
|
|
3608
4185
|
function boundaryComputed(fn, propagationMask) {
|
|
3609
|
-
const node = computed(fn,
|
|
4186
|
+
const node = computed(fn, { lazy: true });
|
|
3610
4187
|
node._notifyStatus = (status, error) => {
|
|
3611
4188
|
const flags = status !== undefined ? status : node._statusFlags;
|
|
3612
4189
|
const actualError = error !== undefined ? error : node._error;
|
|
@@ -3614,7 +4191,7 @@ function boundaryComputed(fn, propagationMask) {
|
|
|
3614
4191
|
node._queue.notify(node, node._propagationMask, flags, actualError);
|
|
3615
4192
|
};
|
|
3616
4193
|
node._propagationMask = propagationMask;
|
|
3617
|
-
node.
|
|
4194
|
+
node._config &= ~CONFIG_AUTO_DISPOSE;
|
|
3618
4195
|
recompute(node, true);
|
|
3619
4196
|
return node;
|
|
3620
4197
|
}
|
|
@@ -3631,12 +4208,16 @@ const ON_INIT = Symbol();
|
|
|
3631
4208
|
const RevealControllerContext = createContext(null);
|
|
3632
4209
|
let _revealUsed = false;
|
|
3633
4210
|
const FALSE_ACCESSOR = () => false;
|
|
4211
|
+
const SEQUENTIAL_ACCESSOR = () => "sequential";
|
|
3634
4212
|
function isRevealController(slot) {
|
|
3635
4213
|
return slot instanceof RevealController;
|
|
3636
4214
|
}
|
|
3637
4215
|
function isSlotReady(slot) {
|
|
3638
4216
|
return isRevealController(slot) ? slot.isReady() : slot._sources.size === 0 && !slot._pending;
|
|
3639
4217
|
}
|
|
4218
|
+
function isSlotMinimallyReady(slot) {
|
|
4219
|
+
return isRevealController(slot) ? slot.isMinimallyReady() : isSlotReady(slot);
|
|
4220
|
+
}
|
|
3640
4221
|
function setSlotState(slot, controller, disabled, collapsed) {
|
|
3641
4222
|
setSignal(slot._disabled, disabled);
|
|
3642
4223
|
setSignal(slot._collapsed, collapsed);
|
|
@@ -3648,16 +4229,17 @@ function setSlotState(slot, controller, disabled, collapsed) {
|
|
|
3648
4229
|
slot._revealController = undefined;
|
|
3649
4230
|
}
|
|
3650
4231
|
class RevealController {
|
|
3651
|
-
|
|
4232
|
+
_orderAccessor;
|
|
3652
4233
|
_collapsedAccessor;
|
|
3653
4234
|
_slots = [];
|
|
3654
4235
|
_parentController;
|
|
3655
|
-
_disabled = signal(false, {
|
|
3656
|
-
_collapsed = signal(false, {
|
|
4236
|
+
_disabled = signal(false, { ownedWrite: true, _noSnapshot: true });
|
|
4237
|
+
_collapsed = signal(false, { ownedWrite: true, _noSnapshot: true });
|
|
3657
4238
|
_ready = true;
|
|
4239
|
+
_minimallyReady = true;
|
|
3658
4240
|
_evaluating = false;
|
|
3659
|
-
constructor(
|
|
3660
|
-
this.
|
|
4241
|
+
constructor(order, collapsed) {
|
|
4242
|
+
this._orderAccessor = order;
|
|
3661
4243
|
this._collapsedAccessor = collapsed;
|
|
3662
4244
|
}
|
|
3663
4245
|
_forEachOwnedSlot(fn) {
|
|
@@ -3672,12 +4254,37 @@ class RevealController {
|
|
|
3672
4254
|
isReady() {
|
|
3673
4255
|
return this._forEachOwnedSlot(isSlotReady);
|
|
3674
4256
|
}
|
|
4257
|
+
isMinimallyReady() {
|
|
4258
|
+
const order = untrack(this._orderAccessor);
|
|
4259
|
+
if (order === "together") return this.isReady();
|
|
4260
|
+
if (order === "natural") {
|
|
4261
|
+
let hasSlot = false;
|
|
4262
|
+
let anyReady = false;
|
|
4263
|
+
this._forEachOwnedSlot(slot => {
|
|
4264
|
+
hasSlot = true;
|
|
4265
|
+
if (isSlotMinimallyReady(slot)) {
|
|
4266
|
+
anyReady = true;
|
|
4267
|
+
return false;
|
|
4268
|
+
}
|
|
4269
|
+
});
|
|
4270
|
+
return !hasSlot || anyReady;
|
|
4271
|
+
}
|
|
4272
|
+
let firstReady = true;
|
|
4273
|
+
this._forEachOwnedSlot(slot => {
|
|
4274
|
+
firstReady = isSlotMinimallyReady(slot);
|
|
4275
|
+
return false;
|
|
4276
|
+
});
|
|
4277
|
+
return firstReady;
|
|
4278
|
+
}
|
|
3675
4279
|
register(slot) {
|
|
3676
4280
|
if (this._slots.includes(slot)) return;
|
|
3677
4281
|
this._slots.push(slot);
|
|
3678
|
-
const
|
|
3679
|
-
setSignal(slot._disabled, true),
|
|
3680
|
-
setSignal(
|
|
4282
|
+
const order = untrack(this._orderAccessor);
|
|
4283
|
+
(setSignal(slot._disabled, true),
|
|
4284
|
+
setSignal(
|
|
4285
|
+
slot._collapsed,
|
|
4286
|
+
order === "sequential" ? !!untrack(this._collapsedAccessor) : false
|
|
4287
|
+
));
|
|
3681
4288
|
untrack(() => this.evaluate());
|
|
3682
4289
|
}
|
|
3683
4290
|
unregister(slot) {
|
|
@@ -3689,29 +4296,52 @@ class RevealController {
|
|
|
3689
4296
|
if (this._evaluating) return;
|
|
3690
4297
|
this._evaluating = true;
|
|
3691
4298
|
const wasReady = this._ready;
|
|
4299
|
+
const wasMinReady = this._minimallyReady;
|
|
3692
4300
|
try {
|
|
3693
4301
|
const disabled = disabledOverride ?? read(this._disabled),
|
|
3694
|
-
|
|
4302
|
+
order = untrack(this._orderAccessor),
|
|
4303
|
+
collapseTail = order === "sequential" && !!untrack(this._collapsedAccessor),
|
|
3695
4304
|
collapsed = collapsedOverride ?? collapseTail;
|
|
3696
|
-
if (disabled
|
|
3697
|
-
this._forEachOwnedSlot(slot => setSlotState(slot, this, true,
|
|
3698
|
-
else if (
|
|
3699
|
-
|
|
3700
|
-
|
|
4305
|
+
if (disabled) {
|
|
4306
|
+
this._forEachOwnedSlot(slot => setSlotState(slot, this, true, collapsed));
|
|
4307
|
+
} else if (order === "natural") {
|
|
4308
|
+
this._forEachOwnedSlot(slot => {
|
|
4309
|
+
if (isRevealController(slot)) {
|
|
4310
|
+
setSignal(slot._collapsed, false);
|
|
4311
|
+
setSignal(slot._disabled, false);
|
|
4312
|
+
slot.evaluate(false, false);
|
|
4313
|
+
} else {
|
|
4314
|
+
setSlotState(slot, this, !isSlotReady(slot), false);
|
|
4315
|
+
}
|
|
4316
|
+
});
|
|
4317
|
+
} else if (order === "together") {
|
|
4318
|
+
const minReady = this._forEachOwnedSlot(isSlotMinimallyReady);
|
|
4319
|
+
this._forEachOwnedSlot(slot => setSlotState(slot, this, !minReady, false));
|
|
3701
4320
|
} else {
|
|
3702
4321
|
let pendingSeen = false;
|
|
3703
4322
|
this._forEachOwnedSlot(slot => {
|
|
3704
4323
|
if (pendingSeen) return setSlotState(slot, this, true, collapseTail);
|
|
3705
4324
|
if (isSlotReady(slot)) return setSlotState(slot, this, false, false);
|
|
3706
4325
|
pendingSeen = true;
|
|
3707
|
-
|
|
4326
|
+
if (isRevealController(slot)) {
|
|
4327
|
+
setSignal(slot._collapsed, false);
|
|
4328
|
+
setSignal(slot._disabled, false);
|
|
4329
|
+
slot.evaluate(false, false);
|
|
4330
|
+
} else {
|
|
4331
|
+
setSlotState(slot, this, true, false);
|
|
4332
|
+
}
|
|
3708
4333
|
});
|
|
3709
4334
|
}
|
|
3710
4335
|
} finally {
|
|
3711
4336
|
this._ready = this.isReady();
|
|
4337
|
+
this._minimallyReady = this.isMinimallyReady();
|
|
3712
4338
|
this._evaluating = false;
|
|
3713
4339
|
}
|
|
3714
|
-
if (
|
|
4340
|
+
if (
|
|
4341
|
+
this._parentController &&
|
|
4342
|
+
(wasReady !== this._ready || wasMinReady !== this._minimallyReady)
|
|
4343
|
+
)
|
|
4344
|
+
this._parentController.evaluate();
|
|
3715
4345
|
}
|
|
3716
4346
|
}
|
|
3717
4347
|
class CollectionQueue extends Queue {
|
|
@@ -3719,8 +4349,8 @@ class CollectionQueue extends Queue {
|
|
|
3719
4349
|
_sources = new Set();
|
|
3720
4350
|
_tree;
|
|
3721
4351
|
_pending = true;
|
|
3722
|
-
_disabled = signal(false, {
|
|
3723
|
-
_collapsed = signal(false, {
|
|
4352
|
+
_disabled = signal(false, { ownedWrite: true, _noSnapshot: true });
|
|
4353
|
+
_collapsed = signal(false, { ownedWrite: true, _noSnapshot: true });
|
|
3724
4354
|
_revealController;
|
|
3725
4355
|
_initialized = false;
|
|
3726
4356
|
_onFn;
|
|
@@ -3800,7 +4430,8 @@ class CollectionQueue extends Queue {
|
|
|
3800
4430
|
}
|
|
3801
4431
|
function createCollectionBoundary(type, fn, fallback, onFn) {
|
|
3802
4432
|
if (!getOwner()) {
|
|
3803
|
-
const message =
|
|
4433
|
+
const message =
|
|
4434
|
+
"[NO_OWNER_BOUNDARY] Boundaries created outside a reactive context will never be disposed.";
|
|
3804
4435
|
emitDiagnostic({
|
|
3805
4436
|
code: "NO_OWNER_BOUNDARY",
|
|
3806
4437
|
kind: "lifecycle",
|
|
@@ -3833,15 +4464,16 @@ function createCollectionBoundary(type, fn, fallback, onFn) {
|
|
|
3833
4464
|
controller.register(queue);
|
|
3834
4465
|
cleanup(() => controller.unregister(queue));
|
|
3835
4466
|
}
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3841
|
-
|
|
3842
|
-
|
|
3843
|
-
|
|
3844
|
-
|
|
4467
|
+
return accessor(
|
|
4468
|
+
computed(() => {
|
|
4469
|
+
if (!read(queue._disabled)) {
|
|
4470
|
+
const resolved = read(tree);
|
|
4471
|
+
if (!untrack(() => read(queue._disabled))) return ((queue._initialized = true), resolved);
|
|
4472
|
+
}
|
|
4473
|
+
if (_revealUsed && read(queue._collapsed)) return undefined;
|
|
4474
|
+
return fallback(queue);
|
|
4475
|
+
})
|
|
4476
|
+
);
|
|
3845
4477
|
}
|
|
3846
4478
|
function createLoadingBoundary(fn, fallback, options) {
|
|
3847
4479
|
return createCollectionBoundary(STATUS_PENDING, fn, () => fallback(), options?.on);
|
|
@@ -3860,14 +4492,14 @@ function createRevealOrder(fn, options) {
|
|
|
3860
4492
|
_revealUsed = true;
|
|
3861
4493
|
const owner = createOwner();
|
|
3862
4494
|
const parentController = getContext(RevealControllerContext);
|
|
3863
|
-
const
|
|
4495
|
+
const order = options?.order || SEQUENTIAL_ACCESSOR,
|
|
3864
4496
|
collapsed = options?.collapsed || FALSE_ACCESSOR;
|
|
3865
|
-
const controller = new RevealController(
|
|
4497
|
+
const controller = new RevealController(order, collapsed);
|
|
3866
4498
|
setContext(RevealControllerContext, controller, owner);
|
|
3867
4499
|
return runWithOwner(owner, () => {
|
|
3868
4500
|
const value = fn();
|
|
3869
4501
|
computed(() => {
|
|
3870
|
-
|
|
4502
|
+
order();
|
|
3871
4503
|
collapsed();
|
|
3872
4504
|
controller.evaluate();
|
|
3873
4505
|
});
|