mutts 1.0.9 → 1.0.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 +60 -35
- package/dist/browser.cjs +1333 -1760
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.ts +2 -1392
- package/dist/browser.dev.cjs +114 -0
- package/dist/browser.dev.cjs.map +1 -0
- package/dist/browser.dev.d.ts +2 -0
- package/dist/browser.dev.esm.js +5 -0
- package/dist/browser.dev.esm.js.map +1 -0
- package/dist/browser.esm.js +18 -97
- package/dist/browser.esm.js.map +1 -1
- package/dist/chunks/{async-browser-lvzLOCgk.cjs → async-browser-Dgr5CreQ.cjs} +16 -95
- package/dist/chunks/async-browser-Dgr5CreQ.cjs.map +1 -0
- package/dist/chunks/{async-node-C3DeIb0y.cjs → async-node-3PrbVAbB.cjs} +3 -1
- package/dist/chunks/async-node-3PrbVAbB.cjs.map +1 -0
- package/dist/chunks/index-Sf74wXTV.esm.js +2577 -0
- package/dist/chunks/index-Sf74wXTV.esm.js.map +1 -0
- package/dist/chunks/node-Bo7WU5S2.esm.js +96 -0
- package/dist/chunks/node-Bo7WU5S2.esm.js.map +1 -0
- package/dist/chunks/{index-VTO-b2vR.cjs → proxy-Cc79Lrzj.cjs} +2593 -3216
- package/dist/chunks/proxy-Cc79Lrzj.cjs.map +1 -0
- package/dist/chunks/{index-CtA2AWl3.esm.js → proxy-D2C49sXH.esm.js} +2570 -3174
- package/dist/chunks/proxy-D2C49sXH.esm.js.map +1 -0
- package/dist/debug.cjs +987 -28
- package/dist/debug.cjs.map +1 -1
- package/dist/debug.d.ts +37 -38
- package/dist/debug.esm.js +963 -1
- package/dist/debug.esm.js.map +1 -1
- package/dist/devtools/manifest.json +1 -1
- package/dist/devtools/panel.html +1 -1
- package/dist/devtools/panel.js +107 -94
- package/dist/devtools/panel.js.map +1 -1
- package/dist/index.d.ts +1322 -1
- package/dist/mutts.umd.js +6647 -1
- package/dist/mutts.umd.js.map +1 -1
- package/dist/mutts.umd.min.js +1 -1
- package/dist/mutts.umd.min.js.map +1 -1
- package/dist/node.cjs +69 -63
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.ts +2 -2
- package/dist/node.dev.cjs +114 -0
- package/dist/node.dev.cjs.map +1 -0
- package/dist/node.dev.d.ts +2 -0
- package/dist/node.dev.esm.js +6 -0
- package/dist/node.dev.esm.js.map +1 -0
- package/dist/node.esm.js +4 -97
- package/dist/node.esm.js.map +1 -1
- package/dist/{types-DaHFfhlN.d.ts → types-Bx2PhORg.d.ts} +134 -88
- package/docs/ai/api-reference.md +11 -32
- package/docs/ai/manual.md +297 -239
- package/docs/reactive/advanced.md +318 -9
- package/docs/reactive/attend.md +2 -4
- package/docs/reactive/collections.md +22 -187
- package/docs/reactive/core.md +223 -131
- package/docs/reactive/debugging.md +119 -12
- package/docs/reactive/error-handling.md +10 -10
- package/docs/reactive/resource.md +125 -0
- package/docs/reactive.md +3 -4
- package/docs/utils.md +70 -0
- package/docs/zone.md +1 -1
- package/package.json +76 -38
- package/dist/chunks/async-browser-lvzLOCgk.cjs.map +0 -1
- package/dist/chunks/async-node-C3DeIb0y.cjs.map +0 -1
- package/dist/chunks/index-2vea86wD.esm.js +0 -3011
- package/dist/chunks/index-2vea86wD.esm.js.map +0 -1
- package/dist/chunks/index-CtA2AWl3.esm.js.map +0 -1
- package/dist/chunks/index-VTO-b2vR.cjs.map +0 -1
- package/dist/debug/debug.d.ts +0 -122
- package/dist/debug/debug.d.ts.map +0 -1
- package/dist/debug/index.d.ts +0 -4
- package/dist/debug/index.d.ts.map +0 -1
- package/dist/debug/lineage-panel.d.ts +0 -5
- package/dist/debug/lineage-panel.d.ts.map +0 -1
- package/dist/debug/lineage.d.ts +0 -79
- package/dist/debug/lineage.d.ts.map +0 -1
- package/dist/src/async/browser.d.ts +0 -2
- package/dist/src/async/browser.d.ts.map +0 -1
- package/dist/src/async/index.d.ts +0 -19
- package/dist/src/async/index.d.ts.map +0 -1
- package/dist/src/async/node.d.ts +0 -2
- package/dist/src/async/node.d.ts.map +0 -1
- package/dist/src/decorator.d.ts +0 -106
- package/dist/src/decorator.d.ts.map +0 -1
- package/dist/src/destroyable.d.ts +0 -87
- package/dist/src/destroyable.d.ts.map +0 -1
- package/dist/src/entry-browser.d.ts +0 -3
- package/dist/src/entry-browser.d.ts.map +0 -1
- package/dist/src/entry-node.d.ts +0 -3
- package/dist/src/entry-node.d.ts.map +0 -1
- package/dist/src/eventful.d.ts +0 -20
- package/dist/src/eventful.d.ts.map +0 -1
- package/dist/src/flavored.d.ts +0 -33
- package/dist/src/flavored.d.ts.map +0 -1
- package/dist/src/index.d.ts +0 -14
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/indexable.d.ts +0 -243
- package/dist/src/indexable.d.ts.map +0 -1
- package/dist/src/introspection.d.ts +0 -27
- package/dist/src/introspection.d.ts.map +0 -1
- package/dist/src/iterableWeak.d.ts +0 -53
- package/dist/src/iterableWeak.d.ts.map +0 -1
- package/dist/src/mixins.d.ts +0 -25
- package/dist/src/mixins.d.ts.map +0 -1
- package/dist/src/promiseChain.d.ts +0 -20
- package/dist/src/promiseChain.d.ts.map +0 -1
- package/dist/src/reactive/array.d.ts +0 -48
- package/dist/src/reactive/array.d.ts.map +0 -1
- package/dist/src/reactive/buffer.d.ts +0 -120
- package/dist/src/reactive/buffer.d.ts.map +0 -1
- package/dist/src/reactive/change.d.ts +0 -29
- package/dist/src/reactive/change.d.ts.map +0 -1
- package/dist/src/reactive/deep-touch.d.ts +0 -28
- package/dist/src/reactive/deep-touch.d.ts.map +0 -1
- package/dist/src/reactive/deep-watch-state.d.ts +0 -25
- package/dist/src/reactive/deep-watch-state.d.ts.map +0 -1
- package/dist/src/reactive/deep-watch.d.ts +0 -20
- package/dist/src/reactive/deep-watch.d.ts.map +0 -1
- package/dist/src/reactive/describe.d.ts +0 -12
- package/dist/src/reactive/describe.d.ts.map +0 -1
- package/dist/src/reactive/effect-context.d.ts +0 -34
- package/dist/src/reactive/effect-context.d.ts.map +0 -1
- package/dist/src/reactive/effects.d.ts +0 -164
- package/dist/src/reactive/effects.d.ts.map +0 -1
- package/dist/src/reactive/index.d.ts +0 -19
- package/dist/src/reactive/index.d.ts.map +0 -1
- package/dist/src/reactive/map.d.ts +0 -28
- package/dist/src/reactive/map.d.ts.map +0 -1
- package/dist/src/reactive/memoize.d.ts +0 -28
- package/dist/src/reactive/memoize.d.ts.map +0 -1
- package/dist/src/reactive/non-reactive-state.d.ts +0 -9
- package/dist/src/reactive/non-reactive-state.d.ts.map +0 -1
- package/dist/src/reactive/non-reactive.d.ts +0 -11
- package/dist/src/reactive/non-reactive.d.ts.map +0 -1
- package/dist/src/reactive/project.d.ts +0 -40
- package/dist/src/reactive/project.d.ts.map +0 -1
- package/dist/src/reactive/proxy-state.d.ts +0 -8
- package/dist/src/reactive/proxy-state.d.ts.map +0 -1
- package/dist/src/reactive/proxy.d.ts +0 -23
- package/dist/src/reactive/proxy.d.ts.map +0 -1
- package/dist/src/reactive/record.d.ts +0 -115
- package/dist/src/reactive/record.d.ts.map +0 -1
- package/dist/src/reactive/register.d.ts +0 -125
- package/dist/src/reactive/register.d.ts.map +0 -1
- package/dist/src/reactive/registry.d.ts +0 -21
- package/dist/src/reactive/registry.d.ts.map +0 -1
- package/dist/src/reactive/set.d.ts +0 -26
- package/dist/src/reactive/set.d.ts.map +0 -1
- package/dist/src/reactive/tracking.d.ts +0 -7
- package/dist/src/reactive/tracking.d.ts.map +0 -1
- package/dist/src/reactive/types.d.ts +0 -424
- package/dist/src/reactive/types.d.ts.map +0 -1
- package/dist/src/reactive/watch.d.ts +0 -48
- package/dist/src/reactive/watch.d.ts.map +0 -1
- package/dist/src/std-decorators.d.ts +0 -45
- package/dist/src/std-decorators.d.ts.map +0 -1
- package/dist/src/utils.d.ts +0 -49
- package/dist/src/utils.d.ts.map +0 -1
- package/dist/src/zone.d.ts +0 -40
- package/dist/src/zone.d.ts.map +0 -1
- package/docs/reactive/describe.md +0 -85
- package/docs/reactive/project.md +0 -93
- package/docs/reactive/scan.md +0 -293
- package/src/async/browser.ts +0 -323
- package/src/async/index.ts +0 -27
- package/src/async/node.ts +0 -92
- package/src/decorator.ts +0 -272
- package/src/destroyable.ts +0 -199
- package/src/entry-browser.ts +0 -5
- package/src/entry-node.ts +0 -5
- package/src/eventful.ts +0 -110
- package/src/flavored.ts +0 -106
- package/src/index.d.ts +0 -12
- package/src/index.ts +0 -64
- package/src/indexable.ts +0 -526
- package/src/introspection.ts +0 -59
- package/src/iterableWeak.ts +0 -233
- package/src/mixins.ts +0 -123
- package/src/promiseChain.ts +0 -110
- package/src/reactive/array.ts +0 -500
- package/src/reactive/buffer.ts +0 -328
- package/src/reactive/change.ts +0 -131
- package/src/reactive/deep-touch.ts +0 -273
- package/src/reactive/deep-watch-state.ts +0 -82
- package/src/reactive/deep-watch.ts +0 -171
- package/src/reactive/describe.ts +0 -39
- package/src/reactive/effect-context.ts +0 -83
- package/src/reactive/effects.ts +0 -1434
- package/src/reactive/index.ts +0 -72
- package/src/reactive/map.ts +0 -142
- package/src/reactive/memoize.ts +0 -186
- package/src/reactive/non-reactive-state.ts +0 -49
- package/src/reactive/non-reactive.ts +0 -43
- package/src/reactive/project.md +0 -107
- package/src/reactive/project.ts +0 -430
- package/src/reactive/proxy-state.ts +0 -27
- package/src/reactive/proxy.ts +0 -282
- package/src/reactive/record.ts +0 -181
- package/src/reactive/register.ts +0 -538
- package/src/reactive/registry.ts +0 -72
- package/src/reactive/set.ts +0 -117
- package/src/reactive/tracking.ts +0 -41
- package/src/reactive/types.ts +0 -520
- package/src/reactive/watch.ts +0 -180
- package/src/std-decorators.ts +0 -256
- package/src/utils.ts +0 -300
- package/src/zone.ts +0 -142
package/dist/browser.cjs
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
require('./chunks/async-browser-
|
|
4
|
-
var
|
|
3
|
+
require('./chunks/async-browser-Dgr5CreQ.cjs');
|
|
4
|
+
var proxy = require('./chunks/proxy-Cc79Lrzj.cjs');
|
|
5
5
|
var asyncCore = require('./chunks/async-core-CRLKP3l-.cjs');
|
|
6
|
-
require('./chunks/async-node-
|
|
6
|
+
require('./chunks/async-node-3PrbVAbB.cjs');
|
|
7
7
|
require('node:async_hooks');
|
|
8
8
|
|
|
9
|
+
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
9
10
|
// Integrated with `using` statement via Symbol.dispose
|
|
10
11
|
const fr = new FinalizationRegistry((f) => f());
|
|
11
12
|
/**
|
|
@@ -86,7 +87,7 @@ function Destroyable(base, destructorObj) {
|
|
|
86
87
|
* Decorator that marks properties to be stored in the allocated object and passed to the destructor
|
|
87
88
|
* Use with accessor properties or explicit get/set pairs
|
|
88
89
|
*/
|
|
89
|
-
const allocated =
|
|
90
|
+
const allocated = proxy.decorator({
|
|
90
91
|
setter(original, _target, propertyKey) {
|
|
91
92
|
return function (value) {
|
|
92
93
|
this[allocatedValues][propertyKey] = value;
|
|
@@ -111,6 +112,154 @@ function callOnGC(cb) {
|
|
|
111
112
|
return forward;
|
|
112
113
|
}
|
|
113
114
|
|
|
115
|
+
/** Max edit distance before bailing out to a single "replace all" patch */
|
|
116
|
+
const BAILOUT_D = 256;
|
|
117
|
+
/**
|
|
118
|
+
* Myers' diff producing grouped patches: `{indexA, indexB, sliceA, sliceB}[]`.
|
|
119
|
+
* - O(N) for identical or prefix/suffix-only differences
|
|
120
|
+
* - O(ND) for small D, with a hard bailout at D=BAILOUT_D → single replacement patch
|
|
121
|
+
*/
|
|
122
|
+
function arrayDiff(A, B) {
|
|
123
|
+
let start = 0;
|
|
124
|
+
let endA = A.length;
|
|
125
|
+
let endB = B.length;
|
|
126
|
+
// Trim common prefix
|
|
127
|
+
while (start < endA && start < endB && A[start] === B[start])
|
|
128
|
+
start++;
|
|
129
|
+
// Trim common suffix
|
|
130
|
+
while (endA > start && endB > start && A[endA - 1] === B[endB - 1]) {
|
|
131
|
+
endA--;
|
|
132
|
+
endB--;
|
|
133
|
+
}
|
|
134
|
+
const lenA = endA - start;
|
|
135
|
+
const lenB = endB - start;
|
|
136
|
+
if (lenA === 0 && lenB === 0)
|
|
137
|
+
return [];
|
|
138
|
+
if (lenA === 0)
|
|
139
|
+
return [{ indexA: start, indexB: start, sliceA: [], sliceB: B.slice(start, endB) }];
|
|
140
|
+
if (lenB === 0)
|
|
141
|
+
return [{ indexA: start, indexB: start, sliceA: A.slice(start, endA), sliceB: [] }];
|
|
142
|
+
// Myers with bailout
|
|
143
|
+
const maxD = Math.min(lenA + lenB, BAILOUT_D);
|
|
144
|
+
const vSize = 2 * maxD + 1;
|
|
145
|
+
const vOffset = maxD;
|
|
146
|
+
const V = new Int32Array(vSize);
|
|
147
|
+
V[vOffset + 1] = 0;
|
|
148
|
+
const history = [];
|
|
149
|
+
for (let d = 0; d <= maxD; d++) {
|
|
150
|
+
for (let k = -d; k <= d; k += 2) {
|
|
151
|
+
let x;
|
|
152
|
+
if (k === -d || (k !== d && V[vOffset + k - 1] < V[vOffset + k + 1])) {
|
|
153
|
+
x = V[vOffset + k + 1];
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
x = V[vOffset + k - 1] + 1;
|
|
157
|
+
}
|
|
158
|
+
let y = x - k;
|
|
159
|
+
while (x < lenA && y < lenB && A[start + x] === B[start + y]) {
|
|
160
|
+
x++;
|
|
161
|
+
y++;
|
|
162
|
+
}
|
|
163
|
+
V[vOffset + k] = x;
|
|
164
|
+
if (x >= lenA && y >= lenB)
|
|
165
|
+
return buildPatches(history, A, B, start, x, y, d, k, vOffset);
|
|
166
|
+
}
|
|
167
|
+
history.push(new Int32Array(V));
|
|
168
|
+
}
|
|
169
|
+
// Bailout: too many differences
|
|
170
|
+
return [
|
|
171
|
+
{ indexA: start, indexB: start, sliceA: A.slice(start, endA), sliceB: B.slice(start, endB) },
|
|
172
|
+
];
|
|
173
|
+
}
|
|
174
|
+
function buildPatches(history, A, B, offset, finalX, finalY, finalD, finalK, vOffset) {
|
|
175
|
+
// Backtrack from (finalX, finalY) at step finalD to step 0, collecting ops in reverse
|
|
176
|
+
const ops = []; // 0=eq, 1=ins, 2=del
|
|
177
|
+
let x = finalX;
|
|
178
|
+
let y = finalY;
|
|
179
|
+
let k = finalK;
|
|
180
|
+
for (let d = finalD; d > 0; d--) {
|
|
181
|
+
const prev = history[d - 1];
|
|
182
|
+
let prevK;
|
|
183
|
+
let down;
|
|
184
|
+
if (k === -d) {
|
|
185
|
+
prevK = k + 1;
|
|
186
|
+
down = true;
|
|
187
|
+
}
|
|
188
|
+
else if (k === d) {
|
|
189
|
+
prevK = k - 1;
|
|
190
|
+
down = false;
|
|
191
|
+
}
|
|
192
|
+
else if (prev[vOffset + k - 1] < prev[vOffset + k + 1]) {
|
|
193
|
+
prevK = k + 1;
|
|
194
|
+
down = true;
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
prevK = k - 1;
|
|
198
|
+
down = false;
|
|
199
|
+
}
|
|
200
|
+
const prevXEnd = prev[vOffset + prevK];
|
|
201
|
+
const prevYEnd = prevXEnd - prevK;
|
|
202
|
+
const xStart = down ? prevXEnd : prevXEnd + 1;
|
|
203
|
+
const yStart = down ? prevYEnd + 1 : prevXEnd + 1 - k;
|
|
204
|
+
// Diagonal matches (pushed in reverse)
|
|
205
|
+
while (x > xStart && y > yStart) {
|
|
206
|
+
ops.push(0);
|
|
207
|
+
x--;
|
|
208
|
+
y--;
|
|
209
|
+
}
|
|
210
|
+
// The edit step
|
|
211
|
+
if (down) {
|
|
212
|
+
ops.push(1); // ins
|
|
213
|
+
y--;
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
ops.push(2); // del
|
|
217
|
+
x--;
|
|
218
|
+
}
|
|
219
|
+
k = prevK;
|
|
220
|
+
}
|
|
221
|
+
// Walk ops forward (they were pushed in reverse), grouping contiguous edits
|
|
222
|
+
const patches = [];
|
|
223
|
+
let currA = offset;
|
|
224
|
+
let currB = offset;
|
|
225
|
+
let sliceA = [];
|
|
226
|
+
let sliceB = [];
|
|
227
|
+
let patchA = -1;
|
|
228
|
+
let patchB = -1;
|
|
229
|
+
const flush = () => {
|
|
230
|
+
if (patchA !== -1) {
|
|
231
|
+
patches.push({ indexA: patchA, indexB: patchB, sliceA, sliceB });
|
|
232
|
+
sliceA = [];
|
|
233
|
+
sliceB = [];
|
|
234
|
+
patchA = -1;
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
for (let i = ops.length - 1; i >= 0; i--) {
|
|
238
|
+
const op = ops[i];
|
|
239
|
+
if (op === 0) {
|
|
240
|
+
flush();
|
|
241
|
+
currA++;
|
|
242
|
+
currB++;
|
|
243
|
+
}
|
|
244
|
+
else if (op === 1) {
|
|
245
|
+
if (patchA === -1) {
|
|
246
|
+
patchA = currA;
|
|
247
|
+
patchB = currB;
|
|
248
|
+
}
|
|
249
|
+
sliceB.push(B[currB++]);
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
if (patchA === -1) {
|
|
253
|
+
patchA = currA;
|
|
254
|
+
patchB = currB;
|
|
255
|
+
}
|
|
256
|
+
sliceA.push(A[currA++]);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
flush();
|
|
260
|
+
return patches;
|
|
261
|
+
}
|
|
262
|
+
|
|
114
263
|
var _a, _b;
|
|
115
264
|
const events = Symbol('events');
|
|
116
265
|
const hooks = Symbol('hooks');
|
|
@@ -602,151 +751,6 @@ function chainPromise(given) {
|
|
|
602
751
|
return chained;
|
|
603
752
|
}
|
|
604
753
|
|
|
605
|
-
const memoizedRegistry = new WeakMap();
|
|
606
|
-
const wrapperRegistry = new WeakMap();
|
|
607
|
-
function getBranch(tree, key) {
|
|
608
|
-
tree.branches ?? (tree.branches = new WeakMap());
|
|
609
|
-
let branch = tree.branches.get(key);
|
|
610
|
-
if (!branch) {
|
|
611
|
-
branch = {};
|
|
612
|
-
tree.branches.set(key, branch);
|
|
613
|
-
}
|
|
614
|
-
return branch;
|
|
615
|
-
}
|
|
616
|
-
function memoizeFunction(fn) {
|
|
617
|
-
const fnRoot = debug.getRoot(fn);
|
|
618
|
-
const existing = memoizedRegistry.get(fnRoot);
|
|
619
|
-
if (existing)
|
|
620
|
-
return existing;
|
|
621
|
-
const cacheRoot = {};
|
|
622
|
-
const memoized = debug.markWithRoot((...args) => {
|
|
623
|
-
const localArgs = args; //: Args = maxArgs !== undefined ? (args.slice(0, maxArgs) as Args) : args
|
|
624
|
-
if (localArgs.some((arg) => !(arg && ['object', 'symbol', 'function'].includes(typeof arg))))
|
|
625
|
-
throw new Error('memoize expects non-null object arguments');
|
|
626
|
-
let node = cacheRoot;
|
|
627
|
-
// Note: decorators add `this` as first argument
|
|
628
|
-
for (const arg of localArgs) {
|
|
629
|
-
node = getBranch(node, arg);
|
|
630
|
-
}
|
|
631
|
-
debug.dependant(node, 'memoize');
|
|
632
|
-
if ('result' in node) {
|
|
633
|
-
if (debug.options.onMemoizationDiscrepancy) {
|
|
634
|
-
const wasVerification = debug.options.isVerificationRun;
|
|
635
|
-
debug.options.isVerificationRun = true;
|
|
636
|
-
try {
|
|
637
|
-
const fresh = debug.untracked(() => fn(...localArgs));
|
|
638
|
-
if (!debug.deepCompare(node.result, fresh)) {
|
|
639
|
-
debug.optionCall('onMemoizationDiscrepancy', node.result, fresh, fn, localArgs, 'calculation');
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
finally {
|
|
643
|
-
debug.options.isVerificationRun = wasVerification;
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
return node.result;
|
|
647
|
-
}
|
|
648
|
-
// Create memoize internal effect to track dependencies and invalidate cache
|
|
649
|
-
// Use untracked to prevent the effect creation from being affected by parent effects
|
|
650
|
-
node.cleanup = debug.root(() => debug.effect(() => {
|
|
651
|
-
// Execute the function and track its dependencies
|
|
652
|
-
// The function execution will automatically track dependencies on reactive objects
|
|
653
|
-
node.result = fn(...localArgs);
|
|
654
|
-
return () => {
|
|
655
|
-
// When dependencies change, clear the cache and notify consumers
|
|
656
|
-
delete node.result;
|
|
657
|
-
debug.touched1(node, { type: 'invalidate', prop: localArgs }, 'memoize');
|
|
658
|
-
// Lazy memoization: stop the effect so it doesn't re-run immediately.
|
|
659
|
-
// It will be re-created on next access.
|
|
660
|
-
if (node.cleanup) {
|
|
661
|
-
node.cleanup();
|
|
662
|
-
node.cleanup = undefined;
|
|
663
|
-
}
|
|
664
|
-
};
|
|
665
|
-
}, { opaque: true }));
|
|
666
|
-
if (debug.options.onMemoizationDiscrepancy) {
|
|
667
|
-
const wasVerification = debug.options.isVerificationRun;
|
|
668
|
-
debug.options.isVerificationRun = true;
|
|
669
|
-
try {
|
|
670
|
-
const fresh = debug.untracked(() => fn(...localArgs));
|
|
671
|
-
if (!debug.deepCompare(node.result, fresh)) {
|
|
672
|
-
debug.optionCall('onMemoizationDiscrepancy', node.result, fresh, fn, localArgs, 'comparison');
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
finally {
|
|
676
|
-
debug.options.isVerificationRun = wasVerification;
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
return node.result;
|
|
680
|
-
}, fn);
|
|
681
|
-
memoizedRegistry.set(fnRoot, memoized);
|
|
682
|
-
memoizedRegistry.set(memoized, memoized);
|
|
683
|
-
return memoized;
|
|
684
|
-
}
|
|
685
|
-
/**
|
|
686
|
-
* Decorator and function wrapper for memoizing computed values based on reactive dependencies.
|
|
687
|
-
*
|
|
688
|
-
* When used as a decorator on getters or methods, it caches the result and automatically
|
|
689
|
-
* invalidates the cache when reactive dependencies change.
|
|
690
|
-
*
|
|
691
|
-
* When used as a function wrapper, it memoizes based on object arguments (WeakMap-based cache).
|
|
692
|
-
*
|
|
693
|
-
* @example
|
|
694
|
-
* ```typescript
|
|
695
|
-
* class User {
|
|
696
|
-
* @memoize
|
|
697
|
-
* get fullName() {
|
|
698
|
-
* return `${this.firstName} ${this.lastName}`
|
|
699
|
-
* }
|
|
700
|
-
* }
|
|
701
|
-
*
|
|
702
|
-
* // Or as a function wrapper
|
|
703
|
-
* const expensive = memoize((obj: SomeObject) => {
|
|
704
|
-
* return heavyComputation(obj)
|
|
705
|
-
* })
|
|
706
|
-
* ```
|
|
707
|
-
*/
|
|
708
|
-
const memoize = debug.decorator({
|
|
709
|
-
getter(original, target, propertyKey) {
|
|
710
|
-
return function () {
|
|
711
|
-
let wrapper = wrapperRegistry.get(original);
|
|
712
|
-
if (!wrapper) {
|
|
713
|
-
wrapper = debug.markWithRoot(debug.renamed((that) => {
|
|
714
|
-
return original.call(that);
|
|
715
|
-
}, `${String(target?.constructor?.name ?? target?.name ?? 'Object')}.${String(propertyKey)}`), {
|
|
716
|
-
method: original,
|
|
717
|
-
propertyKey,
|
|
718
|
-
...(original[debug.rootFunction]
|
|
719
|
-
? { [debug.rootFunction]: original[debug.rootFunction] }
|
|
720
|
-
: {}),
|
|
721
|
-
});
|
|
722
|
-
wrapperRegistry.set(original, wrapper);
|
|
723
|
-
}
|
|
724
|
-
const memoized = memoizeFunction(wrapper);
|
|
725
|
-
return memoized(this);
|
|
726
|
-
};
|
|
727
|
-
},
|
|
728
|
-
method(original, target, name) {
|
|
729
|
-
return function (...args) {
|
|
730
|
-
let wrapper = wrapperRegistry.get(original);
|
|
731
|
-
if (!wrapper) {
|
|
732
|
-
wrapper = debug.markWithRoot(debug.renamed((that, ...args) => {
|
|
733
|
-
return original.call(that, ...args);
|
|
734
|
-
}, `${String(target?.constructor?.name ?? target?.name ?? 'Object')}.${String(name)}`), {
|
|
735
|
-
method: original,
|
|
736
|
-
propertyKey: name,
|
|
737
|
-
...(original[debug.rootFunction]
|
|
738
|
-
? { [debug.rootFunction]: original[debug.rootFunction] }
|
|
739
|
-
: {}),
|
|
740
|
-
});
|
|
741
|
-
wrapperRegistry.set(original, wrapper);
|
|
742
|
-
}
|
|
743
|
-
const memoized = memoizeFunction(wrapper);
|
|
744
|
-
return memoized(this, ...args);
|
|
745
|
-
};
|
|
746
|
-
},
|
|
747
|
-
default: memoizeFunction,
|
|
748
|
-
});
|
|
749
|
-
|
|
750
754
|
function attend(source, callback) {
|
|
751
755
|
const enumerate = typeof source === 'function'
|
|
752
756
|
? source
|
|
@@ -758,14 +762,14 @@ function attend(source, callback) {
|
|
|
758
762
|
? () => source.values()
|
|
759
763
|
: () => Object.keys(source);
|
|
760
764
|
const keyEffects = new Map();
|
|
761
|
-
const outer =
|
|
765
|
+
const outer = proxy.effect.named('attend')(({ ascend }) => {
|
|
762
766
|
const keys = new Set();
|
|
763
767
|
for (const key of enumerate())
|
|
764
768
|
keys.add(key);
|
|
765
769
|
for (const key of keys) {
|
|
766
770
|
if (keyEffects.has(key))
|
|
767
771
|
continue;
|
|
768
|
-
keyEffects.set(key, ascend(() =>
|
|
772
|
+
keyEffects.set(key, ascend(() => proxy.effect.named(`attend:${key}`)((access) => callback(key, access))));
|
|
769
773
|
}
|
|
770
774
|
for (const key of Array.from(keyEffects.keys())) {
|
|
771
775
|
if (!keys.has(key)) {
|
|
@@ -774,189 +778,404 @@ function attend(source, callback) {
|
|
|
774
778
|
}
|
|
775
779
|
}
|
|
776
780
|
});
|
|
777
|
-
return () => {
|
|
778
|
-
outer();
|
|
781
|
+
return (reason) => {
|
|
782
|
+
outer(reason);
|
|
779
783
|
for (const stop of keyEffects.values())
|
|
780
|
-
stop();
|
|
784
|
+
stop(reason);
|
|
781
785
|
keyEffects.clear();
|
|
782
786
|
};
|
|
783
787
|
}
|
|
788
|
+
function lift(cb) {
|
|
789
|
+
let result;
|
|
790
|
+
let rawResult;
|
|
791
|
+
const liftCleanup = proxy.effect.named(`lift:${cb.name}`)(proxy.markWithRoot((access) => {
|
|
792
|
+
const source = cb(access);
|
|
793
|
+
if (!source || typeof source !== 'object')
|
|
794
|
+
throw new Error('lift callback must return an array or object');
|
|
795
|
+
const sourceProto = Object.getPrototypeOf(source);
|
|
796
|
+
if (!result) {
|
|
797
|
+
rawResult = Array.isArray(source) ? [] : Object.create(sourceProto);
|
|
798
|
+
result = proxy.reactive(rawResult);
|
|
799
|
+
}
|
|
800
|
+
if (sourceProto !== Object.getPrototypeOf(result))
|
|
801
|
+
throw new Error('lift callback must return the same type as the previous result');
|
|
802
|
+
if (Array.isArray(source)) {
|
|
803
|
+
const res = result;
|
|
804
|
+
for (const { indexA, sliceA, sliceB } of arrayDiff(res, source).sort((a, b) => a.indexA - b.indexA))
|
|
805
|
+
res.splice(indexA, sliceA.length, ...sliceB);
|
|
806
|
+
}
|
|
807
|
+
else {
|
|
808
|
+
for (const key of Object.keys(source)) {
|
|
809
|
+
const had = key in rawResult;
|
|
810
|
+
const newDesc = Object.getOwnPropertyDescriptor(source, key);
|
|
811
|
+
if (had) {
|
|
812
|
+
const oldDesc = Object.getOwnPropertyDescriptor(rawResult, key);
|
|
813
|
+
const sameAccessor = oldDesc && newDesc.get && oldDesc.get === newDesc.get;
|
|
814
|
+
Object.defineProperty(rawResult, key, newDesc);
|
|
815
|
+
if (!sameAccessor &&
|
|
816
|
+
rawResult[key] !==
|
|
817
|
+
(oldDesc ? (oldDesc.get ? oldDesc.get() : oldDesc.value) : undefined))
|
|
818
|
+
proxy.touched1(rawResult, { type: 'set', prop: key }, key);
|
|
819
|
+
}
|
|
820
|
+
else {
|
|
821
|
+
Object.defineProperty(rawResult, key, newDesc);
|
|
822
|
+
proxy.touched1(rawResult, { type: 'add', prop: key }, key);
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
for (const key of Object.keys(rawResult))
|
|
826
|
+
if (!(key in source)) {
|
|
827
|
+
delete rawResult[key];
|
|
828
|
+
proxy.touched1(rawResult, { type: 'del', prop: key }, key);
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
}, cb));
|
|
832
|
+
return proxy.link(result, liftCleanup);
|
|
833
|
+
}
|
|
784
834
|
/**
|
|
785
|
-
*
|
|
786
|
-
*
|
|
787
|
-
* This implementation is highly optimized for performance and fine-grained reactivity:
|
|
788
|
-
* - **Incremental Updates**: Changes to an item only trigger re-computation from that
|
|
789
|
-
* point onwards in the result chain.
|
|
790
|
-
* - **Move Optimization**: If items are moved within the array, their accumulated
|
|
791
|
-
* values are reused as long as their predecessor remains the same.
|
|
792
|
-
* - **Duplicate Support**: Correctly handles multiple occurrences of the same object
|
|
793
|
-
* instance using an internal occurrence tracking mechanism.
|
|
794
|
-
* - **Memory Efficient**: Uses `WeakMap` for caching intermediates, which are
|
|
795
|
-
* automatically cleared when source items are garbage collected.
|
|
835
|
+
* Reactively maps an array source through `fn`, producing a lazy reactive output array.
|
|
796
836
|
*
|
|
797
|
-
*
|
|
798
|
-
*
|
|
799
|
-
*
|
|
800
|
-
* const sum = scan(source, (acc, item) => acc + item.val, 0)
|
|
837
|
+
* Each source item gets its own isolated effect (via `root()`) so that changes to one item
|
|
838
|
+
* only recompute that item's projection. Structural changes (push, splice, reorder) are detected
|
|
839
|
+
* via `arrayDiff` and surgically applied to the output cache.
|
|
801
840
|
*
|
|
802
|
-
*
|
|
841
|
+
* The source can be a reactive array or a function returning an array. When a function is provided,
|
|
842
|
+
* the function is re-evaluated inside an effect whenever its dependencies change.
|
|
803
843
|
*
|
|
804
|
-
*
|
|
805
|
-
* source[1].val = 10
|
|
806
|
-
* expect([...sum]).toEqual([1, 11, 14])
|
|
807
|
-
* ```
|
|
844
|
+
* Output elements are computed lazily — accessing `result[i]` triggers computation if not yet cached.
|
|
808
845
|
*
|
|
809
|
-
* @param source
|
|
810
|
-
* @param
|
|
811
|
-
* @param
|
|
812
|
-
* @returns A reactive array
|
|
846
|
+
* @param source - A reactive array or a function returning an array
|
|
847
|
+
* @param fn - Mapping function applied to each element
|
|
848
|
+
* @param options - Optional purity hints to skip per-item effects
|
|
849
|
+
* @returns A readonly reactive array with a `[cleanup]` method to dispose all effects
|
|
813
850
|
*/
|
|
814
|
-
function
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
const
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
851
|
+
function morphArray(source, fn, options) {
|
|
852
|
+
if (typeof source !== 'function' && !proxy.isReactive(source) && options?.pure === true) {
|
|
853
|
+
return source.map((i) => fn(i));
|
|
854
|
+
}
|
|
855
|
+
let track;
|
|
856
|
+
const itemEffects = new Map();
|
|
857
|
+
const cache = [];
|
|
858
|
+
let input = [];
|
|
859
|
+
function stopItem(key) {
|
|
860
|
+
const entry = itemEffects.get(key);
|
|
861
|
+
if (entry) {
|
|
862
|
+
entry.stop({ type: 'stopped' });
|
|
863
|
+
itemEffects.delete(key);
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
function computeItem(key, input) {
|
|
867
|
+
const isPure = options?.pure === true || (typeof options?.pure === 'function' && options.pure(input));
|
|
868
|
+
if (isPure) {
|
|
869
|
+
track(() => {
|
|
870
|
+
cache[key] = fn(input);
|
|
871
|
+
});
|
|
872
|
+
}
|
|
873
|
+
else {
|
|
874
|
+
const indexRef = { value: key };
|
|
875
|
+
const stop = track(() => proxy.effect.named(`morph:${fn.name}:${key}`).opaque((access) => {
|
|
876
|
+
cache[indexRef.value] = fn(input, access);
|
|
877
|
+
return (reason) => {
|
|
878
|
+
delete cache[indexRef.value];
|
|
879
|
+
proxy.touched1(cache, { type: 'invalidate', prop: 'morph' }, String(key));
|
|
880
|
+
stop?.({ type: 'invalidate', cause: reason });
|
|
881
|
+
};
|
|
882
|
+
}));
|
|
883
|
+
itemEffects.set(key, { stop, index: indexRef });
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
const proxy$1 = proxy.reactive(cache, {
|
|
887
|
+
get(cache, prop) {
|
|
888
|
+
const n = typeof prop === 'string' ? Number(prop) : NaN;
|
|
889
|
+
if (Number.isNaN(n))
|
|
890
|
+
return cache[prop];
|
|
891
|
+
if (!(n in cache))
|
|
892
|
+
computeItem(n, input[n]);
|
|
893
|
+
return cache[n];
|
|
894
|
+
},
|
|
895
|
+
has(_cache, prop) {
|
|
896
|
+
return Reflect.has(input, prop);
|
|
897
|
+
},
|
|
898
|
+
});
|
|
899
|
+
const stopMain = proxy.effect.named(`morph:${fn.name}`)(({ ascend }) => {
|
|
900
|
+
track = ascend;
|
|
901
|
+
const newInput = [...(typeof source === 'function' ? source() : source)];
|
|
902
|
+
const diffs = arrayDiff(input, newInput).toSorted((a, b) => b.indexA - a.indexA);
|
|
903
|
+
if (diffs.length > 0) {
|
|
904
|
+
for (const diff of diffs) {
|
|
905
|
+
// Stop items in removed range
|
|
906
|
+
for (let i = diff.indexA; i < diff.indexA + diff.sliceA.length; i++)
|
|
907
|
+
stopItem(i);
|
|
908
|
+
// Shift existing itemEffects in the Map to match the new indices
|
|
909
|
+
const shift = diff.sliceB.length - diff.sliceA.length;
|
|
910
|
+
if (shift !== 0) {
|
|
911
|
+
// We need to move entries in the Map.
|
|
912
|
+
const entries = Array.from(itemEffects.entries()).sort((a, b) => a[0] - b[0]);
|
|
913
|
+
// Remove entries that will be shifted
|
|
914
|
+
for (const [idx, _entry] of entries) {
|
|
915
|
+
if (idx >= diff.indexA + diff.sliceA.length) {
|
|
916
|
+
itemEffects.delete(idx);
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
// Re-add them with shifted indices
|
|
920
|
+
for (const [idx, entry] of entries) {
|
|
921
|
+
if (idx >= diff.indexA + diff.sliceA.length) {
|
|
922
|
+
const newIdx = idx + shift;
|
|
923
|
+
entry.index.value = newIdx;
|
|
924
|
+
itemEffects.set(newIdx, entry);
|
|
925
|
+
}
|
|
926
|
+
}
|
|
834
927
|
}
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
928
|
+
// Splice the cache
|
|
929
|
+
cache.splice(diff.indexA, diff.sliceA.length, ...new Array(diff.sliceB.length).fill(undefined));
|
|
930
|
+
// Make holes for lazy computation
|
|
931
|
+
for (let i = diff.indexA; i < diff.indexA + diff.sliceB.length; i++)
|
|
932
|
+
delete cache[i];
|
|
933
|
+
}
|
|
934
|
+
const invalidates = new Set([proxy.keysOf]);
|
|
935
|
+
if (input.length !== newInput.length)
|
|
936
|
+
invalidates.add('length');
|
|
937
|
+
for (const diff of diffs) {
|
|
938
|
+
const max = Math.max(diff.sliceA.length, diff.sliceB.length);
|
|
939
|
+
for (let i = 0; i < max; i++)
|
|
940
|
+
invalidates.add(String(diff.indexA + i));
|
|
941
|
+
}
|
|
942
|
+
proxy.touched(cache, { type: 'bunch', method: 'morph-input' }, invalidates);
|
|
943
|
+
}
|
|
944
|
+
input = newInput;
|
|
945
|
+
});
|
|
946
|
+
return proxy.link(proxy$1, (reason) => {
|
|
947
|
+
stopMain(reason);
|
|
948
|
+
for (const entry of itemEffects.values())
|
|
949
|
+
entry.stop(reason);
|
|
950
|
+
itemEffects.clear();
|
|
951
|
+
});
|
|
952
|
+
}
|
|
953
|
+
/**
|
|
954
|
+
* Reactively maps a `Map` source through `fn`, producing a reactive output Map.
|
|
955
|
+
*
|
|
956
|
+
* Each key gets its own isolated effect so that value changes for one key only recompute
|
|
957
|
+
* that key's projection. Key additions and removals are tracked via `keysOf` dependency.
|
|
958
|
+
*
|
|
959
|
+
* @param source - A reactive Map
|
|
960
|
+
* @param fn - Mapping function applied to each value
|
|
961
|
+
* @param options - Optional purity hints to skip per-key effects
|
|
962
|
+
* @returns A reactive Map with a `[cleanup]` method to dispose all effects
|
|
963
|
+
*/
|
|
964
|
+
function morphMap(source, fn, options) {
|
|
965
|
+
if (!proxy.isReactive(source) && options?.pure === true) {
|
|
966
|
+
const res = new Map();
|
|
967
|
+
for (const [k, v] of source)
|
|
968
|
+
res.set(k, fn(v, k));
|
|
969
|
+
return res;
|
|
970
|
+
}
|
|
971
|
+
let track;
|
|
972
|
+
const itemEffects = new Map();
|
|
973
|
+
const cache = new Map();
|
|
974
|
+
Object.defineProperty(cache, 'constructor', { value: Object, enumerable: false });
|
|
975
|
+
function stopItem(key) {
|
|
976
|
+
const stop = itemEffects.get(key);
|
|
846
977
|
if (stop) {
|
|
847
|
-
stop();
|
|
848
|
-
|
|
849
|
-
debug.untracked(() => {
|
|
850
|
-
Reflect.deleteProperty(indexToIntermediate, index);
|
|
851
|
-
Reflect.deleteProperty(result, index);
|
|
852
|
-
});
|
|
978
|
+
stop({ type: 'stopped' });
|
|
979
|
+
itemEffects.delete(key);
|
|
853
980
|
}
|
|
854
981
|
}
|
|
855
|
-
|
|
856
|
-
const
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
for (let i = 0; i < length; i++) {
|
|
860
|
-
const val = debug.FoolProof.get(observedSource, i, observedSource);
|
|
861
|
-
if (!(val && (typeof val === 'object' || typeof val === 'function' || typeof val === 'symbol'))) {
|
|
862
|
-
throw new Error('scan: items must be objects (WeakKey) for intermediate caching');
|
|
863
|
-
}
|
|
864
|
-
const count = occurrenceCount.get(val) ?? 0;
|
|
865
|
-
occurrenceCount.set(val, count + 1);
|
|
866
|
-
let list = intermediaries.get(val);
|
|
867
|
-
if (!list) {
|
|
868
|
-
list = [];
|
|
869
|
-
intermediaries.set(val, list);
|
|
870
|
-
}
|
|
871
|
-
let intermediate = list[count];
|
|
872
|
-
if (!intermediate) {
|
|
873
|
-
intermediate = debug.reactive(new Intermediate(val, prev));
|
|
874
|
-
list[count] = intermediate;
|
|
875
|
-
}
|
|
876
|
-
else {
|
|
877
|
-
// Update the link.
|
|
878
|
-
if (debug.untracked(() => intermediate.prev) !== prev) {
|
|
879
|
-
intermediate.prev = prev;
|
|
880
|
-
}
|
|
881
|
-
}
|
|
882
|
-
// Update the reactive mapping for this index
|
|
883
|
-
if (indexToIntermediate[i] !== intermediate) {
|
|
884
|
-
indexToIntermediate[i] = intermediate;
|
|
885
|
-
}
|
|
886
|
-
// If we don't have an effect for this index yet, create one
|
|
887
|
-
if (!indexEffects.has(i)) {
|
|
888
|
-
ascend(() => {
|
|
889
|
-
const index = i;
|
|
890
|
-
const stop = debug.effect(function scanIndexSyncEffect() {
|
|
891
|
-
const inter = indexToIntermediate[index];
|
|
892
|
-
if (inter) {
|
|
893
|
-
const accValue = inter.acc;
|
|
894
|
-
debug.untracked(() => {
|
|
895
|
-
result[index] = accValue;
|
|
896
|
-
});
|
|
897
|
-
}
|
|
898
|
-
});
|
|
899
|
-
indexEffects.set(index, stop);
|
|
900
|
-
});
|
|
901
|
-
}
|
|
902
|
-
prev = intermediate;
|
|
982
|
+
function computeItem(key, val) {
|
|
983
|
+
const isPure = options?.pure === true || (typeof options?.pure === 'function' && options.pure(val));
|
|
984
|
+
if (isPure) {
|
|
985
|
+
cache.set(key, track(() => fn(val, key)));
|
|
903
986
|
}
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
987
|
+
else {
|
|
988
|
+
const stop = track(() => proxy.effect.named(`morph:${fn.name}:${key}`).opaque((access) => {
|
|
989
|
+
cache.set(key, fn(source.get(key), key, access));
|
|
990
|
+
return (reason) => {
|
|
991
|
+
cache.delete(key);
|
|
992
|
+
proxy.touched1(cache, { type: 'invalidate', prop: 'morph' }, String(key));
|
|
993
|
+
stop?.({ type: 'invalidate', cause: reason });
|
|
994
|
+
};
|
|
995
|
+
}));
|
|
996
|
+
itemEffects.set(key, stop);
|
|
908
997
|
}
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
998
|
+
}
|
|
999
|
+
const proxy$1 = proxy.reactive(cache, {
|
|
1000
|
+
get(cache, prop) {
|
|
1001
|
+
if (prop === 'get')
|
|
1002
|
+
return (key) => {
|
|
1003
|
+
if (!cache.has(key) && source.has(key))
|
|
1004
|
+
computeItem(key, source.get(key));
|
|
1005
|
+
return cache.get(key);
|
|
1006
|
+
};
|
|
1007
|
+
if (prop === 'has')
|
|
1008
|
+
return (key) => {
|
|
1009
|
+
return source.has(key);
|
|
1010
|
+
};
|
|
1011
|
+
if (prop === 'keys')
|
|
1012
|
+
return () => {
|
|
1013
|
+
return source.keys();
|
|
1014
|
+
};
|
|
1015
|
+
if (prop === 'values')
|
|
1016
|
+
return function* () {
|
|
1017
|
+
for (const key of source.keys()) {
|
|
1018
|
+
yield proxy$1.get(key);
|
|
1019
|
+
}
|
|
1020
|
+
};
|
|
1021
|
+
if (prop === 'entries')
|
|
1022
|
+
return function* () {
|
|
1023
|
+
for (const key of source.keys()) {
|
|
1024
|
+
yield [key, proxy$1.get(key)];
|
|
1025
|
+
}
|
|
1026
|
+
};
|
|
1027
|
+
if (prop === Symbol.iterator)
|
|
1028
|
+
return function* () {
|
|
1029
|
+
for (const key of source.keys()) {
|
|
1030
|
+
yield [key, proxy$1.get(key)];
|
|
1031
|
+
}
|
|
1032
|
+
};
|
|
1033
|
+
return cache[prop];
|
|
1034
|
+
},
|
|
915
1035
|
});
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
if (Array.isArray(source)) {
|
|
931
|
-
result = debug.reactive([]);
|
|
932
|
-
}
|
|
933
|
-
else {
|
|
934
|
-
result = debug.reactive({});
|
|
1036
|
+
let stateSnapshot = proxy.getState(source);
|
|
1037
|
+
const stopMain = proxy.effect.named(`morph:${fn.name}`)(({ ascend }) => {
|
|
1038
|
+
track = ascend;
|
|
1039
|
+
proxy.dependant(source, proxy.keysOf);
|
|
1040
|
+
while ('evolution' in stateSnapshot) {
|
|
1041
|
+
const { evolution } = stateSnapshot;
|
|
1042
|
+
stateSnapshot = stateSnapshot.next;
|
|
1043
|
+
if (evolution.type === 'add') {
|
|
1044
|
+
proxy.touched1(cache, evolution, evolution.prop);
|
|
1045
|
+
}
|
|
1046
|
+
else if (evolution.type === 'del') {
|
|
1047
|
+
stopItem(evolution.prop);
|
|
1048
|
+
cache.delete(evolution.prop);
|
|
1049
|
+
proxy.touched1(cache, evolution, evolution.prop);
|
|
935
1050
|
}
|
|
936
1051
|
}
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
1052
|
+
});
|
|
1053
|
+
return proxy.link(proxy$1, (reason) => {
|
|
1054
|
+
stopMain(reason);
|
|
1055
|
+
for (const stop of itemEffects.values())
|
|
1056
|
+
stop(reason);
|
|
1057
|
+
itemEffects.clear();
|
|
1058
|
+
});
|
|
1059
|
+
}
|
|
1060
|
+
/**
|
|
1061
|
+
* Reactively maps a record/object source through `fn`, producing a reactive output record.
|
|
1062
|
+
*
|
|
1063
|
+
* Each key gets its own isolated effect so that value changes for one key only recompute
|
|
1064
|
+
* that key's projection. Key additions and removals are tracked automatically.
|
|
1065
|
+
*
|
|
1066
|
+
* @param source - A reactive record
|
|
1067
|
+
* @param fn - Mapping function applied to each value
|
|
1068
|
+
* @param options - Optional purity hints to skip per-key effects
|
|
1069
|
+
* @returns A reactive record with a `[cleanup]` method to dispose all effects
|
|
1070
|
+
*/
|
|
1071
|
+
function morphRecord(source, fn, options) {
|
|
1072
|
+
if (!proxy.isReactive(source) && options?.pure === true) {
|
|
1073
|
+
const res = {};
|
|
1074
|
+
for (const k of Object.keys(source))
|
|
1075
|
+
res[k] = fn(source[k], k);
|
|
1076
|
+
return res;
|
|
1077
|
+
}
|
|
1078
|
+
let track;
|
|
1079
|
+
const itemEffects = new Map();
|
|
1080
|
+
const cache = {};
|
|
1081
|
+
function stopItem(key) {
|
|
1082
|
+
const stop = itemEffects.get(key);
|
|
1083
|
+
if (stop) {
|
|
1084
|
+
stop({ type: 'stopped' });
|
|
1085
|
+
itemEffects.delete(key);
|
|
943
1086
|
}
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
1087
|
+
}
|
|
1088
|
+
function computeItem(key, val) {
|
|
1089
|
+
const isPure = options?.pure === true || (typeof options?.pure === 'function' && options.pure(val));
|
|
1090
|
+
if (isPure) {
|
|
1091
|
+
cache[key] = track(() => fn(val, key));
|
|
949
1092
|
}
|
|
950
1093
|
else {
|
|
951
|
-
|
|
1094
|
+
const stop = track(() => proxy.effect.named(`morph:${fn.name}:${key}`).opaque((access) => {
|
|
1095
|
+
cache[key] = fn(source[key], key, access);
|
|
1096
|
+
return (reason) => {
|
|
1097
|
+
delete cache[key];
|
|
1098
|
+
proxy.touched1(cache, { type: 'invalidate', prop: 'morph' }, String(key));
|
|
1099
|
+
stop?.({ type: 'invalidate', cause: reason });
|
|
1100
|
+
};
|
|
1101
|
+
}));
|
|
1102
|
+
itemEffects.set(key, stop);
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
function get(prop) {
|
|
1106
|
+
if (!(prop in cache) && prop in source)
|
|
1107
|
+
computeItem(prop, source[prop]);
|
|
1108
|
+
return cache[prop];
|
|
1109
|
+
}
|
|
1110
|
+
const proxy$1 = proxy.reactive(cache, {
|
|
1111
|
+
get(_, prop) {
|
|
1112
|
+
return get(prop);
|
|
1113
|
+
},
|
|
1114
|
+
has(_, prop) {
|
|
1115
|
+
return prop in source;
|
|
1116
|
+
},
|
|
1117
|
+
ownKeys() {
|
|
1118
|
+
return Reflect.ownKeys(source);
|
|
1119
|
+
},
|
|
1120
|
+
getOwnPropertyDescriptor(_cache, prop) {
|
|
1121
|
+
if (prop in source)
|
|
1122
|
+
return { configurable: true, enumerable: true, get: () => get(prop) };
|
|
1123
|
+
},
|
|
1124
|
+
});
|
|
1125
|
+
let stateSnapshot = proxy.getState(source);
|
|
1126
|
+
const stopMain = proxy.effect.named(`morph:${fn.name}`)(({ ascend }) => {
|
|
1127
|
+
track = ascend;
|
|
1128
|
+
// Track only structural changes on source
|
|
1129
|
+
proxy.dependant(source, proxy.keysOf);
|
|
1130
|
+
while ('evolution' in stateSnapshot) {
|
|
1131
|
+
const { evolution } = stateSnapshot;
|
|
1132
|
+
stateSnapshot = stateSnapshot.next;
|
|
1133
|
+
if (evolution.type === 'add') {
|
|
1134
|
+
proxy.touched1(cache, evolution, evolution.prop);
|
|
1135
|
+
}
|
|
1136
|
+
else if (evolution.type === 'del') {
|
|
1137
|
+
stopItem(evolution.prop);
|
|
1138
|
+
delete cache[evolution.prop];
|
|
1139
|
+
proxy.touched1(cache, evolution, evolution.prop);
|
|
1140
|
+
}
|
|
952
1141
|
}
|
|
953
1142
|
});
|
|
954
|
-
return
|
|
1143
|
+
return proxy.link(proxy$1, (reason) => {
|
|
1144
|
+
stopMain(reason);
|
|
1145
|
+
for (const stop of itemEffects.values())
|
|
1146
|
+
stop(reason);
|
|
1147
|
+
itemEffects.clear();
|
|
1148
|
+
});
|
|
955
1149
|
}
|
|
1150
|
+
/**
|
|
1151
|
+
* Reactively maps a collection (array, Map, or record) through a per-entry function.
|
|
1152
|
+
*
|
|
1153
|
+
* Each entry in the source gets its own reactive context — when only one entry's dependencies
|
|
1154
|
+
* change, only that entry's projection recomputes. Structural changes (additions, removals,
|
|
1155
|
+
* reorders) are detected via diffing and applied surgically.
|
|
1156
|
+
*
|
|
1157
|
+
* Use `morph.pure(source, fn)` when `fn` has no reactive reads (skips per-item effects).
|
|
1158
|
+
*
|
|
1159
|
+
* @example
|
|
1160
|
+
* ```ts
|
|
1161
|
+
* const users = reactive([{ name: 'John' }, { name: 'Jane' }])
|
|
1162
|
+
* const names = morph(users, u => u.name.toUpperCase())
|
|
1163
|
+
* // names[0] = 'JOHN', names[1] = 'JANE'
|
|
1164
|
+
* // Changing users[0].name only recomputes names[0]
|
|
1165
|
+
* ```
|
|
1166
|
+
*/
|
|
1167
|
+
const morph = proxy.flavored(function morph(source, fn, options) {
|
|
1168
|
+
if (Array.isArray(source) || typeof source === 'function')
|
|
1169
|
+
return morphArray(source, fn, options);
|
|
1170
|
+
if (source instanceof Map)
|
|
1171
|
+
return morphMap(source, fn, options);
|
|
1172
|
+
return morphRecord(source, fn, options);
|
|
1173
|
+
}, {
|
|
1174
|
+
get pure() {
|
|
1175
|
+
return (source, fn, _opt) => this(source, fn, { pure: true });
|
|
1176
|
+
},
|
|
1177
|
+
});
|
|
956
1178
|
|
|
957
|
-
function isObject(value) {
|
|
958
|
-
return typeof value === 'object' && value !== null;
|
|
959
|
-
}
|
|
960
1179
|
/**
|
|
961
1180
|
* Deep watch an object and all its nested properties
|
|
962
1181
|
* @param target - The object to watch deeply
|
|
@@ -977,16 +1196,17 @@ function deepWatch(target, callback, { immediate = false } = {}) {
|
|
|
977
1196
|
if (typeof target !== 'object')
|
|
978
1197
|
throw new Error('Target of deep watching must be an object');
|
|
979
1198
|
// Create a wrapper callback that matches EffectTrigger signature
|
|
980
|
-
const wrappedCallback =
|
|
1199
|
+
const wrappedCallback = proxy.markWithRoot((() => callback(target)), callback);
|
|
1200
|
+
proxy.registerDeepWatcher();
|
|
981
1201
|
// Use the existing effect system to register dependencies
|
|
982
|
-
return
|
|
1202
|
+
return proxy.effect.named('deepWatch')(() => {
|
|
983
1203
|
// Mark the target object as having deep watchers
|
|
984
|
-
|
|
1204
|
+
proxy.objectsWithDeepWatchers.add(target);
|
|
985
1205
|
// Track which objects this effect is watching for cleanup
|
|
986
|
-
let effectObjects =
|
|
1206
|
+
let effectObjects = proxy.effectToDeepWatchedObjects.get(wrappedCallback);
|
|
987
1207
|
if (!effectObjects) {
|
|
988
1208
|
effectObjects = new Set();
|
|
989
|
-
|
|
1209
|
+
proxy.effectToDeepWatchedObjects.set(wrappedCallback, effectObjects);
|
|
990
1210
|
}
|
|
991
1211
|
effectObjects.add(target);
|
|
992
1212
|
// Traverse the object graph and register dependencies
|
|
@@ -994,56 +1214,45 @@ function deepWatch(target, callback, { immediate = false } = {}) {
|
|
|
994
1214
|
const visited = new WeakSet();
|
|
995
1215
|
function traverseAndTrack(obj, depth = 0) {
|
|
996
1216
|
// Prevent infinite recursion and excessive depth
|
|
997
|
-
if (!obj || visited.has(obj) ||
|
|
1217
|
+
if (!obj || visited.has(obj) || typeof obj !== 'object' || depth > proxy.options.maxDeepWatchDepth)
|
|
998
1218
|
return;
|
|
999
1219
|
// Do not traverse into unreactive objects
|
|
1000
|
-
if (
|
|
1220
|
+
if (proxy.isNonReactive(obj))
|
|
1001
1221
|
return;
|
|
1002
1222
|
visited.add(obj);
|
|
1003
1223
|
// Mark this object as having deep watchers
|
|
1004
|
-
|
|
1224
|
+
proxy.objectsWithDeepWatchers.add(obj);
|
|
1005
1225
|
effectObjects.add(obj);
|
|
1006
1226
|
// Traverse all properties to register dependencies
|
|
1007
1227
|
// unwrap to avoid kicking dependency
|
|
1008
|
-
for (const key in
|
|
1228
|
+
for (const key in proxy.unwrap(obj)) {
|
|
1009
1229
|
if (Object.hasOwn(obj, key)) {
|
|
1010
1230
|
// Access the property to register dependency
|
|
1011
1231
|
const value = obj[key];
|
|
1012
1232
|
// Make the value reactive if it's an object
|
|
1013
|
-
const reactiveValue = typeof value === 'object' && value !== null ?
|
|
1233
|
+
const reactiveValue = typeof value === 'object' && value !== null ? proxy.reactive(value) : value;
|
|
1014
1234
|
traverseAndTrack(reactiveValue, depth + 1);
|
|
1015
1235
|
}
|
|
1016
1236
|
}
|
|
1017
1237
|
// Also handle array indices and length
|
|
1018
|
-
//
|
|
1019
|
-
if (
|
|
1020
|
-
// Access
|
|
1021
|
-
const length = obj.length;
|
|
1022
|
-
// Access all current array elements to register dependencies
|
|
1023
|
-
for (let i = 0; i < length; i++) {
|
|
1024
|
-
// Access the array element to register dependency
|
|
1025
|
-
const value = obj[i];
|
|
1026
|
-
// Make the value reactive if it's an object
|
|
1027
|
-
const reactiveValue = typeof value === 'object' && value !== null ? debug.reactive(value) : value;
|
|
1028
|
-
traverseAndTrack(reactiveValue, depth + 1);
|
|
1029
|
-
}
|
|
1030
|
-
}
|
|
1031
|
-
// Handle Set values (deep watch values only, not keys since Sets don't have separate keys)
|
|
1032
|
-
else if (obj instanceof Set) {
|
|
1033
|
-
// Access all Set values to register dependencies
|
|
1238
|
+
// Handle arrays and collections using iterators to ensure proxy tracking is triggered
|
|
1239
|
+
if (typeof obj[Symbol.iterator] === 'function') {
|
|
1240
|
+
// Access the iterator to track additions/removals/collection changes
|
|
1034
1241
|
for (const value of obj) {
|
|
1035
1242
|
// Make the value reactive if it's an object
|
|
1036
|
-
const reactiveValue = typeof value === 'object' && value !== null ?
|
|
1243
|
+
const reactiveValue = typeof value === 'object' && value !== null ? proxy.reactive(value) : value;
|
|
1037
1244
|
traverseAndTrack(reactiveValue, depth + 1);
|
|
1038
1245
|
}
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
const
|
|
1046
|
-
|
|
1246
|
+
// Explicitly depend on length so array mutations changing count trigger re-evaluation
|
|
1247
|
+
if ('length' in obj) {
|
|
1248
|
+
proxy.dependant(obj, 'length');
|
|
1249
|
+
}
|
|
1250
|
+
// For Maps, also ensure we track values explicitly if the iterator yields entries
|
|
1251
|
+
if (obj instanceof Map) {
|
|
1252
|
+
for (const value of obj.values()) {
|
|
1253
|
+
const reactiveValue = typeof value === 'object' && value !== null ? proxy.reactive(value) : value;
|
|
1254
|
+
traverseAndTrack(reactiveValue, depth + 1);
|
|
1255
|
+
}
|
|
1047
1256
|
}
|
|
1048
1257
|
}
|
|
1049
1258
|
// Note: WeakSet and WeakMap cannot be iterated, so we can't deep watch their contents
|
|
@@ -1053,911 +1262,243 @@ function deepWatch(target, callback, { immediate = false } = {}) {
|
|
|
1053
1262
|
// This will register dependencies on all current properties and array elements
|
|
1054
1263
|
traverseAndTrack(target);
|
|
1055
1264
|
// Only call the callback if immediate is true or if it's not the first run
|
|
1056
|
-
if (immediate)
|
|
1057
|
-
callback(target);
|
|
1265
|
+
if (immediate) {
|
|
1266
|
+
proxy.untracked(() => callback(target));
|
|
1267
|
+
}
|
|
1058
1268
|
immediate = true;
|
|
1059
1269
|
// Return a cleanup function that properly removes deep watcher tracking
|
|
1060
1270
|
return () => {
|
|
1061
1271
|
// Get the objects this effect was watching
|
|
1062
|
-
const effectObjects =
|
|
1272
|
+
const effectObjects = proxy.effectToDeepWatchedObjects.get(wrappedCallback);
|
|
1063
1273
|
if (effectObjects) {
|
|
1064
1274
|
// Remove deep watcher tracking from all objects this effect was watching
|
|
1065
1275
|
for (const obj of effectObjects) {
|
|
1066
1276
|
// Check if this object still has other deep watchers
|
|
1067
|
-
const watchers =
|
|
1277
|
+
const watchers = proxy.deepWatchers.get(obj);
|
|
1068
1278
|
if (watchers) {
|
|
1069
1279
|
// Remove this effect's callback from the watchers
|
|
1070
1280
|
watchers.delete(wrappedCallback);
|
|
1071
1281
|
// If no more watchers, remove the object from deep watchers tracking
|
|
1072
1282
|
if (watchers.size === 0) {
|
|
1073
|
-
|
|
1074
|
-
|
|
1283
|
+
proxy.deepWatchers.delete(obj);
|
|
1284
|
+
proxy.objectsWithDeepWatchers.delete(obj);
|
|
1075
1285
|
}
|
|
1076
1286
|
}
|
|
1077
1287
|
else {
|
|
1078
1288
|
// No watchers found, remove from deep watchers tracking
|
|
1079
|
-
|
|
1289
|
+
proxy.objectsWithDeepWatchers.delete(obj);
|
|
1080
1290
|
}
|
|
1081
1291
|
}
|
|
1082
1292
|
// Clean up the tracking data
|
|
1083
|
-
|
|
1293
|
+
proxy.effectToDeepWatchedObjects.delete(wrappedCallback);
|
|
1084
1294
|
}
|
|
1085
1295
|
};
|
|
1086
1296
|
});
|
|
1087
1297
|
}
|
|
1088
1298
|
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
let
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1299
|
+
const memoizedRegistry = new WeakMap();
|
|
1300
|
+
const wrapperRegistry = new WeakMap();
|
|
1301
|
+
function getBranch(tree, key) {
|
|
1302
|
+
tree.branches ?? (tree.branches = new WeakMap());
|
|
1303
|
+
let branch = tree.branches.get(key);
|
|
1304
|
+
if (!branch) {
|
|
1305
|
+
branch = {};
|
|
1306
|
+
tree.branches.set(key, branch);
|
|
1097
1307
|
}
|
|
1308
|
+
return branch;
|
|
1098
1309
|
}
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
//#region watch
|
|
1112
|
-
const unsetYet = Symbol('unset-yet');
|
|
1113
|
-
function watch(value, //object | ((dep: DependencyAccess) => object),
|
|
1114
|
-
changed, options = {}) {
|
|
1115
|
-
return typeof value === 'function'
|
|
1116
|
-
? watchCallBack(value, changed, options)
|
|
1117
|
-
: typeof value === 'object' && value !== null
|
|
1118
|
-
? watchObject(value, changed, options)
|
|
1119
|
-
: (() => {
|
|
1120
|
-
throw new Error('watch: value must be a function or an object');
|
|
1121
|
-
})();
|
|
1122
|
-
}
|
|
1123
|
-
function watchObject(value, changed, { immediate = false, deep = false } = {}) {
|
|
1124
|
-
if (deep)
|
|
1125
|
-
return deepWatch(value, changed, { immediate });
|
|
1126
|
-
return debug.effect(function watchObjectEffect() {
|
|
1127
|
-
debug.dependant(value);
|
|
1128
|
-
if (immediate)
|
|
1129
|
-
changed(value);
|
|
1130
|
-
immediate = true;
|
|
1131
|
-
});
|
|
1132
|
-
}
|
|
1133
|
-
function watchCallBack(value, changed, { immediate = false, deep = false } = {}) {
|
|
1134
|
-
let oldValue = unsetYet;
|
|
1135
|
-
let deepCleanup;
|
|
1136
|
-
const cbCleanup = debug.effect(debug.markWithRoot(function watchCallBackEffect(access) {
|
|
1137
|
-
const newValue = value(access);
|
|
1138
|
-
if (oldValue !== newValue)
|
|
1139
|
-
if (oldValue === unsetYet) {
|
|
1140
|
-
if (immediate)
|
|
1141
|
-
changed(newValue);
|
|
1142
|
-
}
|
|
1143
|
-
else
|
|
1144
|
-
changed(newValue, oldValue);
|
|
1145
|
-
oldValue = newValue;
|
|
1146
|
-
if (deep) {
|
|
1147
|
-
if (deepCleanup)
|
|
1148
|
-
deepCleanup();
|
|
1149
|
-
deepCleanup = deepWatch(newValue, (value) => changed(value, value));
|
|
1150
|
-
}
|
|
1151
|
-
}, value));
|
|
1152
|
-
return Object.defineProperties(() => {
|
|
1153
|
-
cbCleanup();
|
|
1154
|
-
if (deepCleanup)
|
|
1155
|
-
deepCleanup();
|
|
1156
|
-
}, {
|
|
1157
|
-
[debug.stopped]: { get: () => cbCleanup[debug.stopped] },
|
|
1158
|
-
});
|
|
1159
|
-
}
|
|
1160
|
-
//#endregion
|
|
1161
|
-
//#region nonReactive
|
|
1162
|
-
/**
|
|
1163
|
-
* Mark an object as non-reactive. This object and all its properties will never be made reactive.
|
|
1164
|
-
* @param obj - The object to mark as non-reactive
|
|
1165
|
-
*/
|
|
1166
|
-
function shallowNonReactive(obj) {
|
|
1167
|
-
obj = debug.unwrap(obj);
|
|
1168
|
-
if (debug.isNonReactive(obj))
|
|
1169
|
-
return obj;
|
|
1170
|
-
try {
|
|
1171
|
-
Object.defineProperty(obj, debug.nonReactiveMark, {
|
|
1172
|
-
value: true,
|
|
1173
|
-
writable: false,
|
|
1174
|
-
enumerable: false,
|
|
1175
|
-
configurable: true,
|
|
1176
|
-
});
|
|
1177
|
-
}
|
|
1178
|
-
catch { }
|
|
1179
|
-
if (!(debug.nonReactiveMark in obj))
|
|
1180
|
-
debug.nonReactiveObjects.add(obj);
|
|
1181
|
-
// Finally, not deep
|
|
1182
|
-
//for (const key in obj) deepNonReactive(obj[key])
|
|
1183
|
-
return obj;
|
|
1184
|
-
}
|
|
1185
|
-
function unreactiveApplication(arg1, ...args) {
|
|
1186
|
-
return typeof arg1 === 'object'
|
|
1187
|
-
? shallowNonReactive(arg1)
|
|
1188
|
-
: ((original) => {
|
|
1189
|
-
// Copy the parent's unreactive properties if they exist
|
|
1190
|
-
original.prototype[debug.unreactiveProperties] = new Set(original.prototype[debug.unreactiveProperties] || []);
|
|
1191
|
-
// Add all arguments (including the first one)
|
|
1192
|
-
original.prototype[debug.unreactiveProperties].add(arg1);
|
|
1193
|
-
for (const arg of args)
|
|
1194
|
-
original.prototype[debug.unreactiveProperties].add(arg);
|
|
1195
|
-
return original; // Return the class
|
|
1196
|
-
});
|
|
1197
|
-
}
|
|
1198
|
-
/**
|
|
1199
|
-
* Decorator that marks classes or properties as non-reactive
|
|
1200
|
-
* Prevents objects from being made reactive
|
|
1201
|
-
*/
|
|
1202
|
-
const unreactive = debug.decorator({
|
|
1203
|
-
class(original) {
|
|
1204
|
-
// Called without arguments, mark entire class as non-reactive
|
|
1205
|
-
debug.nonReactiveClass(original);
|
|
1206
|
-
},
|
|
1207
|
-
default: unreactiveApplication,
|
|
1208
|
-
});
|
|
1209
|
-
//#endregion
|
|
1210
|
-
|
|
1211
|
-
// Helper to work around TypeScript limitation: base class expressions cannot reference class type parameters
|
|
1212
|
-
function getRegisterBase() {
|
|
1213
|
-
class RegisterBase extends Indexable(ArrayReadForward, {
|
|
1214
|
-
get(index) {
|
|
1215
|
-
return this[getAt](index);
|
|
1216
|
-
},
|
|
1217
|
-
set(index, value) {
|
|
1218
|
-
this[setAt](index, value);
|
|
1219
|
-
},
|
|
1220
|
-
getLength() {
|
|
1221
|
-
return this.length;
|
|
1222
|
-
},
|
|
1223
|
-
setLength(value) {
|
|
1224
|
-
this.length = value;
|
|
1225
|
-
},
|
|
1226
|
-
}) {
|
|
1227
|
-
toArray() {
|
|
1228
|
-
return Array.from(this);
|
|
1229
|
-
}
|
|
1230
|
-
}
|
|
1231
|
-
return RegisterBase;
|
|
1232
|
-
}
|
|
1233
|
-
let RegisterClass = (() => {
|
|
1234
|
-
var _RegisterClass_instances, _RegisterClass_keyFn, _RegisterClass_keys, _RegisterClass_values, _RegisterClass_usage, _RegisterClass_valueInfo, _RegisterClass_keyEffects, _RegisterClass_ascend, _RegisterClass_events, _RegisterClass_rekeyValue;
|
|
1235
|
-
let _classDecorators = [unreactive];
|
|
1236
|
-
let _classDescriptor;
|
|
1237
|
-
let _classExtraInitializers = [];
|
|
1238
|
-
let _classThis;
|
|
1239
|
-
let _classSuper = getRegisterBase();
|
|
1240
|
-
_classThis = class extends _classSuper {
|
|
1241
|
-
get [(_RegisterClass_keyFn = new WeakMap(), _RegisterClass_keys = new WeakMap(), _RegisterClass_values = new WeakMap(), _RegisterClass_usage = new WeakMap(), _RegisterClass_valueInfo = new WeakMap(), _RegisterClass_keyEffects = new WeakMap(), _RegisterClass_ascend = new WeakMap(), _RegisterClass_events = new WeakMap(), _RegisterClass_instances = new WeakSet(), forwardArray)]() {
|
|
1242
|
-
return this.toArray();
|
|
1243
|
-
}
|
|
1244
|
-
on(eventOrEvents, cb) {
|
|
1245
|
-
// @ts-expect-error Delegate to Eventful
|
|
1246
|
-
return debug.__classPrivateFieldGet(this, _RegisterClass_events, "f").on(eventOrEvents, cb);
|
|
1247
|
-
}
|
|
1248
|
-
off(eventOrEvents, cb) {
|
|
1249
|
-
// @ts-expect-error Delegate to Eventful
|
|
1250
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_events, "f").off(eventOrEvents, cb);
|
|
1251
|
-
}
|
|
1252
|
-
/**
|
|
1253
|
-
* Register a global hook that receives all events
|
|
1254
|
-
*/
|
|
1255
|
-
hook(cb) {
|
|
1256
|
-
return debug.__classPrivateFieldGet(this, _RegisterClass_events, "f").hook(cb);
|
|
1257
|
-
}
|
|
1258
|
-
constructor(keyFn, initial) {
|
|
1259
|
-
super();
|
|
1260
|
-
_RegisterClass_instances.add(this);
|
|
1261
|
-
_RegisterClass_keyFn.set(this, void 0);
|
|
1262
|
-
_RegisterClass_keys.set(this, void 0);
|
|
1263
|
-
_RegisterClass_values.set(this, void 0);
|
|
1264
|
-
_RegisterClass_usage.set(this, new Map());
|
|
1265
|
-
_RegisterClass_valueInfo.set(this, new Map());
|
|
1266
|
-
_RegisterClass_keyEffects.set(this, new Set());
|
|
1267
|
-
_RegisterClass_ascend.set(this, void 0);
|
|
1268
|
-
_RegisterClass_events.set(this, new Eventful()
|
|
1269
|
-
/**
|
|
1270
|
-
* Register event listeners for CRUD operations
|
|
1271
|
-
*/
|
|
1272
|
-
);
|
|
1273
|
-
/* Moved below initialization */
|
|
1274
|
-
let ascendGet;
|
|
1275
|
-
debug.effect(({ ascend }) => {
|
|
1276
|
-
ascendGet = ascend;
|
|
1277
|
-
});
|
|
1278
|
-
debug.__classPrivateFieldSet(this, _RegisterClass_ascend, ascendGet, "f");
|
|
1279
|
-
if (typeof keyFn !== 'function')
|
|
1280
|
-
throw new Error('Register requires a key function');
|
|
1281
|
-
debug.__classPrivateFieldSet(this, _RegisterClass_keyFn, keyFn, "f");
|
|
1282
|
-
debug.__classPrivateFieldSet(this, _RegisterClass_keys, debug.reactive([]), "f");
|
|
1283
|
-
debug.__classPrivateFieldSet(this, _RegisterClass_values, debug.reactive(new Map()), "f");
|
|
1284
|
-
if (initial)
|
|
1285
|
-
this.push(...initial);
|
|
1286
|
-
}
|
|
1287
|
-
ensureKey(value) {
|
|
1288
|
-
let info = debug.__classPrivateFieldGet(this, _RegisterClass_valueInfo, "f").get(value);
|
|
1289
|
-
if (info)
|
|
1290
|
-
return info.key;
|
|
1291
|
-
info = { key: undefined };
|
|
1292
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_valueInfo, "f").set(value, info);
|
|
1293
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_ascend, "f").call(this, () => {
|
|
1294
|
-
const stop = debug.effect(({ reaction }) => {
|
|
1295
|
-
const nextKey = debug.__classPrivateFieldGet(this, _RegisterClass_keyFn, "f").call(this, value);
|
|
1296
|
-
this.assertValidKey(nextKey);
|
|
1297
|
-
const previousKey = info.key;
|
|
1298
|
-
if (reaction && previousKey !== undefined && !Object.is(nextKey, previousKey))
|
|
1299
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_instances, "m", _RegisterClass_rekeyValue).call(this, value, previousKey, nextKey);
|
|
1300
|
-
info.key = nextKey;
|
|
1301
|
-
});
|
|
1302
|
-
info.stop = stop;
|
|
1303
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_keyEffects, "f").add(stop);
|
|
1304
|
-
});
|
|
1305
|
-
if (info.key === undefined)
|
|
1306
|
-
throw new Error('Register key function must return a property key');
|
|
1307
|
-
return info.key;
|
|
1308
|
-
}
|
|
1309
|
-
assertValidKey(key) {
|
|
1310
|
-
const type = typeof key;
|
|
1311
|
-
if (type !== 'string' && type !== 'number' && type !== 'symbol')
|
|
1312
|
-
throw new Error('Register key function must return a property key');
|
|
1313
|
-
}
|
|
1314
|
-
setKeyValue(key, value, index) {
|
|
1315
|
-
const existing = debug.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(key);
|
|
1316
|
-
if (existing !== undefined && existing !== value) {
|
|
1317
|
-
this.cleanupValue(existing);
|
|
1318
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_values, "f").set(key, value);
|
|
1319
|
-
if (index !== undefined) {
|
|
1320
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_events, "f").emit('update', existing, value, key, index);
|
|
1321
|
-
}
|
|
1322
|
-
}
|
|
1323
|
-
else {
|
|
1324
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_values, "f").set(key, value);
|
|
1325
|
-
}
|
|
1326
|
-
}
|
|
1327
|
-
cleanupValue(value) {
|
|
1328
|
-
const info = debug.__classPrivateFieldGet(this, _RegisterClass_valueInfo, "f").get(value);
|
|
1329
|
-
if (!info)
|
|
1330
|
-
return;
|
|
1331
|
-
const stop = info.stop;
|
|
1332
|
-
if (stop) {
|
|
1333
|
-
info.stop = undefined;
|
|
1334
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_keyEffects, "f").delete(stop);
|
|
1335
|
-
stop();
|
|
1336
|
-
}
|
|
1337
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_valueInfo, "f").delete(value);
|
|
1338
|
-
}
|
|
1339
|
-
disposeKeyEffects() {
|
|
1340
|
-
for (const value of Array.from(debug.__classPrivateFieldGet(this, _RegisterClass_valueInfo, "f").keys()))
|
|
1341
|
-
this.cleanupValue(value);
|
|
1342
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_keyEffects, "f").clear();
|
|
1343
|
-
}
|
|
1344
|
-
incrementUsage(key) {
|
|
1345
|
-
const count = debug.__classPrivateFieldGet(this, _RegisterClass_usage, "f").get(key) ?? 0;
|
|
1346
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_usage, "f").set(key, count + 1);
|
|
1347
|
-
}
|
|
1348
|
-
decrementUsage(key, index) {
|
|
1349
|
-
const count = debug.__classPrivateFieldGet(this, _RegisterClass_usage, "f").get(key);
|
|
1350
|
-
if (!count)
|
|
1351
|
-
return;
|
|
1352
|
-
if (count <= 1) {
|
|
1353
|
-
const value = debug.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(key);
|
|
1354
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_usage, "f").delete(key);
|
|
1355
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_values, "f").delete(key);
|
|
1356
|
-
if (value !== undefined) {
|
|
1357
|
-
this.cleanupValue(value);
|
|
1358
|
-
const idx = index ?? debug.__classPrivateFieldGet(this, _RegisterClass_keys, "f").indexOf(key);
|
|
1359
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_events, "f").emit('delete', value, key, idx);
|
|
1360
|
-
}
|
|
1361
|
-
}
|
|
1362
|
-
else {
|
|
1363
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_usage, "f").set(key, count - 1);
|
|
1364
|
-
}
|
|
1310
|
+
function memoizeFunction(fn, opts) {
|
|
1311
|
+
const fnRoot = proxy.getRoot(fn);
|
|
1312
|
+
const existing = memoizedRegistry.get(fnRoot);
|
|
1313
|
+
if (existing)
|
|
1314
|
+
return existing;
|
|
1315
|
+
const cacheRoot = {};
|
|
1316
|
+
const memoized = proxy.markWithRoot(function memoized(...args) {
|
|
1317
|
+
if (args.some((arg) => !(arg && ['object', 'symbol', 'function'].includes(typeof arg)))) {
|
|
1318
|
+
if (opts?.lenient)
|
|
1319
|
+
return fn.apply(this, args);
|
|
1320
|
+
throw new Error('memoize expects non-null object arguments');
|
|
1365
1321
|
}
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
resolved = Math.max(length + resolved, 0);
|
|
1371
|
-
if (resolved > length) {
|
|
1372
|
-
if (allowEnd)
|
|
1373
|
-
resolved = length;
|
|
1374
|
-
else
|
|
1375
|
-
throw new RangeError('Index out of bounds');
|
|
1376
|
-
}
|
|
1377
|
-
if (!allowEnd && resolved === length)
|
|
1378
|
-
throw new RangeError('Index out of bounds');
|
|
1379
|
-
return resolved;
|
|
1322
|
+
let node = cacheRoot;
|
|
1323
|
+
// Note: decorators add `this` as first argument
|
|
1324
|
+
for (const arg of args) {
|
|
1325
|
+
node = getBranch(node, arg);
|
|
1380
1326
|
}
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
if (
|
|
1384
|
-
const
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1327
|
+
proxy.dependant(node, 'memoize');
|
|
1328
|
+
if ('result' in node) {
|
|
1329
|
+
if (proxy.options.onMemoizationDiscrepancy) {
|
|
1330
|
+
const wasVerification = proxy.options.isVerificationRun;
|
|
1331
|
+
proxy.options.isVerificationRun = true;
|
|
1332
|
+
try {
|
|
1333
|
+
const fresh = proxy.untracked(() => fn.apply(this, args));
|
|
1334
|
+
if (!proxy.deepCompare(node.result, fresh)) {
|
|
1335
|
+
proxy.optionCall('onMemoizationDiscrepancy', node.result, fresh, fn, args, 'calculation');
|
|
1336
|
+
}
|
|
1388
1337
|
}
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
if (oldKey !== undefined)
|
|
1392
|
-
this.decrementUsage(oldKey);
|
|
1393
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_keys, "f")[index] = key;
|
|
1394
|
-
this.incrementUsage(key);
|
|
1395
|
-
this.setKeyValue(key, value);
|
|
1396
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_events, "f").emit('add', value, key, index);
|
|
1397
|
-
}
|
|
1398
|
-
insertKeyValue(index, key, value) {
|
|
1399
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_keys, "f").splice(index, 0, key);
|
|
1400
|
-
this.incrementUsage(key);
|
|
1401
|
-
this.setKeyValue(key, value);
|
|
1402
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_events, "f").emit('add', value, key, index);
|
|
1403
|
-
}
|
|
1404
|
-
rebuildFrom(values) {
|
|
1405
|
-
this.disposeKeyEffects();
|
|
1406
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_keys, "f").splice(0, debug.__classPrivateFieldGet(this, _RegisterClass_keys, "f").length);
|
|
1407
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_usage, "f").clear();
|
|
1408
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_values, "f").clear();
|
|
1409
|
-
for (const value of values) {
|
|
1410
|
-
const key = this.ensureKey(value);
|
|
1411
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_keys, "f").push(key);
|
|
1412
|
-
this.incrementUsage(key);
|
|
1413
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_values, "f").set(key, value);
|
|
1414
|
-
}
|
|
1415
|
-
}
|
|
1416
|
-
get length() {
|
|
1417
|
-
return debug.__classPrivateFieldGet(this, _RegisterClass_keys, "f").length;
|
|
1418
|
-
}
|
|
1419
|
-
[(_RegisterClass_rekeyValue = function _RegisterClass_rekeyValue(value, oldKey, newKey) {
|
|
1420
|
-
if (Object.is(oldKey, newKey))
|
|
1421
|
-
return;
|
|
1422
|
-
const existingValue = debug.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(newKey);
|
|
1423
|
-
if (existingValue !== undefined && existingValue !== value)
|
|
1424
|
-
throw new Error(`Register key collision for key ${String(newKey)}`);
|
|
1425
|
-
const count = debug.__classPrivateFieldGet(this, _RegisterClass_usage, "f").get(oldKey);
|
|
1426
|
-
if (!count)
|
|
1427
|
-
return;
|
|
1428
|
-
const existingCount = debug.__classPrivateFieldGet(this, _RegisterClass_usage, "f").get(newKey) ?? 0;
|
|
1429
|
-
this.setKeyValue(newKey, value);
|
|
1430
|
-
let index = -1;
|
|
1431
|
-
for (let i = 0; i < debug.__classPrivateFieldGet(this, _RegisterClass_keys, "f").length; i++)
|
|
1432
|
-
if (Object.is(debug.__classPrivateFieldGet(this, _RegisterClass_keys, "f")[i], oldKey)) {
|
|
1433
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_keys, "f")[i] = newKey;
|
|
1434
|
-
if (index === -1)
|
|
1435
|
-
index = i;
|
|
1338
|
+
finally {
|
|
1339
|
+
proxy.options.isVerificationRun = wasVerification;
|
|
1436
1340
|
}
|
|
1437
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_usage, "f").set(newKey, existingCount + count);
|
|
1438
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_usage, "f").delete(oldKey);
|
|
1439
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_values, "f").delete(oldKey);
|
|
1440
|
-
const updatedInfo = debug.__classPrivateFieldGet(this, _RegisterClass_valueInfo, "f").get(value);
|
|
1441
|
-
if (updatedInfo)
|
|
1442
|
-
updatedInfo.key = newKey;
|
|
1443
|
-
if (index !== -1) {
|
|
1444
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_events, "f").emit('rekey', value, oldKey, newKey, index);
|
|
1445
|
-
}
|
|
1446
|
-
}, getAt)](index) {
|
|
1447
|
-
const key = debug.__classPrivateFieldGet(this, _RegisterClass_keys, "f")[index];
|
|
1448
|
-
return key === undefined ? undefined : debug.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(key);
|
|
1449
|
-
}
|
|
1450
|
-
[setAt](index, value) {
|
|
1451
|
-
const key = this.ensureKey(value);
|
|
1452
|
-
if (index === this.length) {
|
|
1453
|
-
this.insertKeyValue(index, key, value);
|
|
1454
|
-
return;
|
|
1455
|
-
}
|
|
1456
|
-
const normalized = this.normalizeIndex(index);
|
|
1457
|
-
this.assignAt(normalized, key, value);
|
|
1458
|
-
}
|
|
1459
|
-
push(...items) {
|
|
1460
|
-
for (const item of items) {
|
|
1461
|
-
const key = this.ensureKey(item);
|
|
1462
|
-
this.insertKeyValue(this.length, key, item);
|
|
1463
|
-
}
|
|
1464
|
-
return this.length;
|
|
1465
|
-
}
|
|
1466
|
-
pop() {
|
|
1467
|
-
if (!this.length)
|
|
1468
|
-
return undefined;
|
|
1469
|
-
return this.removeAt(this.length - 1);
|
|
1470
|
-
}
|
|
1471
|
-
shift() {
|
|
1472
|
-
if (!this.length)
|
|
1473
|
-
return undefined;
|
|
1474
|
-
return this.removeAt(0);
|
|
1475
|
-
}
|
|
1476
|
-
unshift(...items) {
|
|
1477
|
-
let index = 0;
|
|
1478
|
-
for (const item of items) {
|
|
1479
|
-
const key = this.ensureKey(item);
|
|
1480
|
-
this.insertKeyValue(index++, key, item);
|
|
1481
|
-
}
|
|
1482
|
-
return this.length;
|
|
1483
|
-
}
|
|
1484
|
-
splice(start, deleteCount, ...items) {
|
|
1485
|
-
const normalizedStart = this.normalizeIndex(start, true);
|
|
1486
|
-
const maxDeletions = this.length - normalizedStart;
|
|
1487
|
-
const actualDelete = Math.min(deleteCount === undefined ? maxDeletions : Math.max(deleteCount, 0), maxDeletions);
|
|
1488
|
-
const keysToInsert = [];
|
|
1489
|
-
for (const item of items)
|
|
1490
|
-
keysToInsert.push(this.ensureKey(item));
|
|
1491
|
-
const removedKeys = debug.__classPrivateFieldGet(this, _RegisterClass_keys, "f").splice(normalizedStart, actualDelete, ...keysToInsert);
|
|
1492
|
-
const removedValues = [];
|
|
1493
|
-
for (let i = 0; i < removedKeys.length; i++) {
|
|
1494
|
-
const key = removedKeys[i];
|
|
1495
|
-
if (key === undefined)
|
|
1496
|
-
continue;
|
|
1497
|
-
const value = debug.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(key);
|
|
1498
|
-
this.decrementUsage(key, normalizedStart + i);
|
|
1499
|
-
removedValues.push(value);
|
|
1500
|
-
}
|
|
1501
|
-
for (let i = 0; i < keysToInsert.length; i++) {
|
|
1502
|
-
const key = keysToInsert[i];
|
|
1503
|
-
const value = items[i];
|
|
1504
|
-
this.incrementUsage(key);
|
|
1505
|
-
this.setKeyValue(key, value);
|
|
1506
|
-
}
|
|
1507
|
-
return removedValues;
|
|
1508
|
-
}
|
|
1509
|
-
clear() {
|
|
1510
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_keys, "f").length = 0;
|
|
1511
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_usage, "f").clear();
|
|
1512
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_values, "f").clear();
|
|
1513
|
-
this.disposeKeyEffects();
|
|
1514
|
-
}
|
|
1515
|
-
get(key) {
|
|
1516
|
-
return debug.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(key);
|
|
1517
|
-
}
|
|
1518
|
-
set(key, value) {
|
|
1519
|
-
if (debug.__classPrivateFieldGet(this, _RegisterClass_values, "f").has(key))
|
|
1520
|
-
this.setKeyValue(key, value);
|
|
1521
|
-
}
|
|
1522
|
-
remove(key) {
|
|
1523
|
-
let index = this.indexOfKey(key);
|
|
1524
|
-
while (index !== -1) {
|
|
1525
|
-
this.removeAt(index);
|
|
1526
|
-
index = this.indexOfKey(key);
|
|
1527
1341
|
}
|
|
1342
|
+
return node.result;
|
|
1528
1343
|
}
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
return
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
keep(predicate) {
|
|
1545
|
-
const decisions = new Map();
|
|
1546
|
-
for (const [index, key] of debug.__classPrivateFieldGet(this, _RegisterClass_keys, "f").entries()) {
|
|
1547
|
-
if (decisions.has(key)) {
|
|
1548
|
-
if (!decisions.get(key))
|
|
1549
|
-
this.removeAt(index);
|
|
1550
|
-
continue;
|
|
1344
|
+
// Create memoize internal effect to track dependencies and invalidate cache
|
|
1345
|
+
// Use untracked to prevent the effect creation from being affected by parent effects
|
|
1346
|
+
node.cleanup = proxy.root(() => proxy.effect.named('memoize')(() => {
|
|
1347
|
+
// Execute the function and track its dependencies
|
|
1348
|
+
// The function execution will automatically track dependencies on reactive objects
|
|
1349
|
+
node.result = fn.apply(this, args);
|
|
1350
|
+
return (reason) => {
|
|
1351
|
+
// When dependencies change, clear the cache and notify consumers
|
|
1352
|
+
delete node.result;
|
|
1353
|
+
proxy.touched1(node, { type: 'invalidate', prop: args }, 'memoize');
|
|
1354
|
+
// Lazy memoization: stop the effect so it doesn't re-run immediately.
|
|
1355
|
+
// It will be re-created on next access.
|
|
1356
|
+
if (node.cleanup) {
|
|
1357
|
+
node.cleanup({ type: 'invalidate', cause: reason });
|
|
1358
|
+
node.cleanup = undefined;
|
|
1551
1359
|
}
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
}
|
|
1562
|
-
indexOfKey(key) {
|
|
1563
|
-
return debug.__classPrivateFieldGet(this, _RegisterClass_keys, "f").indexOf(key);
|
|
1564
|
-
}
|
|
1565
|
-
mapKeys() {
|
|
1566
|
-
return debug.__classPrivateFieldGet(this, _RegisterClass_values, "f").keys();
|
|
1567
|
-
}
|
|
1568
|
-
update(...values) {
|
|
1569
|
-
for (const value of values) {
|
|
1570
|
-
const key = this.ensureKey(value);
|
|
1571
|
-
if (debug.__classPrivateFieldGet(this, _RegisterClass_values, "f").has(key)) {
|
|
1572
|
-
const index = debug.__classPrivateFieldGet(this, _RegisterClass_keys, "f").indexOf(key);
|
|
1573
|
-
this.setKeyValue(key, value, index);
|
|
1360
|
+
};
|
|
1361
|
+
}, { opaque: true }));
|
|
1362
|
+
if (proxy.options.onMemoizationDiscrepancy) {
|
|
1363
|
+
const wasVerification = proxy.options.isVerificationRun;
|
|
1364
|
+
proxy.options.isVerificationRun = true;
|
|
1365
|
+
try {
|
|
1366
|
+
const fresh = proxy.untracked(() => fn.apply(this, args));
|
|
1367
|
+
if (!proxy.deepCompare(node.result, fresh)) {
|
|
1368
|
+
proxy.optionCall('onMemoizationDiscrepancy', node.result, fresh, fn, args, 'comparison');
|
|
1574
1369
|
}
|
|
1575
1370
|
}
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
for (const value of values) {
|
|
1579
|
-
const key = this.ensureKey(value);
|
|
1580
|
-
if (debug.__classPrivateFieldGet(this, _RegisterClass_values, "f").has(key))
|
|
1581
|
-
this.setKeyValue(key, value);
|
|
1582
|
-
else
|
|
1583
|
-
insert(value);
|
|
1584
|
-
}
|
|
1585
|
-
}
|
|
1586
|
-
entries() {
|
|
1587
|
-
const self = this;
|
|
1588
|
-
function* iterator() {
|
|
1589
|
-
for (let i = 0; i < debug.__classPrivateFieldGet(self, _RegisterClass_keys, "f").length; i++) {
|
|
1590
|
-
const val = debug.__classPrivateFieldGet(self, _RegisterClass_values, "f").get(debug.__classPrivateFieldGet(self, _RegisterClass_keys, "f")[i]);
|
|
1591
|
-
if (val !== undefined)
|
|
1592
|
-
yield [i, val];
|
|
1593
|
-
}
|
|
1371
|
+
finally {
|
|
1372
|
+
proxy.options.isVerificationRun = wasVerification;
|
|
1594
1373
|
}
|
|
1595
|
-
return iterator();
|
|
1596
1374
|
}
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1375
|
+
return node.result;
|
|
1376
|
+
}, fn);
|
|
1377
|
+
memoizedRegistry.set(fnRoot, memoized);
|
|
1378
|
+
memoizedRegistry.set(memoized, memoized);
|
|
1379
|
+
return memoized;
|
|
1380
|
+
}
|
|
1381
|
+
function memoizeObject(target, opts) {
|
|
1382
|
+
const existing = memoizedRegistry.get(target);
|
|
1383
|
+
if (existing)
|
|
1384
|
+
return existing;
|
|
1385
|
+
const proxy$1 = new Proxy(target, {
|
|
1386
|
+
get(source, prop, receiver) {
|
|
1387
|
+
// 1. Walk prototype chain to find descriptor
|
|
1388
|
+
let current = source;
|
|
1389
|
+
let desc;
|
|
1390
|
+
while (current) {
|
|
1391
|
+
desc = Object.getOwnPropertyDescriptor(current, prop);
|
|
1392
|
+
if (desc)
|
|
1393
|
+
break;
|
|
1394
|
+
current = Object.getPrototypeOf(current);
|
|
1395
|
+
}
|
|
1396
|
+
if (!desc)
|
|
1397
|
+
return Reflect.get(source, prop, receiver);
|
|
1398
|
+
// 2. If getter, memoize
|
|
1399
|
+
if (desc.get) {
|
|
1400
|
+
const originalGetter = desc.get;
|
|
1401
|
+
let wrapper = wrapperRegistry.get(originalGetter);
|
|
1402
|
+
if (!wrapper) {
|
|
1403
|
+
wrapper = proxy.markWithRoot(proxy.named(`${String(source?.constructor?.name ?? 'Object')}.${String(prop)}`, (that) => {
|
|
1404
|
+
return originalGetter.call(that);
|
|
1405
|
+
}), {
|
|
1406
|
+
propertyKey: prop,
|
|
1407
|
+
});
|
|
1408
|
+
const origRoot = originalGetter[proxy.rootFunctionSymbol];
|
|
1409
|
+
if (origRoot)
|
|
1410
|
+
wrapper[proxy.rootFunctionSymbol] = origRoot;
|
|
1411
|
+
wrapperRegistry.set(originalGetter, wrapper);
|
|
1604
1412
|
}
|
|
1413
|
+
const memoized = memoizeFunction(wrapper, opts);
|
|
1414
|
+
return memoized(receiver);
|
|
1605
1415
|
}
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
}
|
|
1621
|
-
sort(compareFn) {
|
|
1622
|
-
const fwdCompareFn = compareFn
|
|
1623
|
-
? (a, b) => compareFn(debug.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(a), debug.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(b))
|
|
1624
|
-
: undefined;
|
|
1625
|
-
debug.__classPrivateFieldGet(this, _RegisterClass_keys, "f").sort(fwdCompareFn);
|
|
1626
|
-
return this;
|
|
1627
|
-
}
|
|
1628
|
-
fill(value, start = 0, end = this.length) {
|
|
1629
|
-
const values = this.toArray();
|
|
1630
|
-
values.fill(value, start, end);
|
|
1631
|
-
this.rebuildFrom(values);
|
|
1632
|
-
return this;
|
|
1633
|
-
}
|
|
1634
|
-
copyWithin(target, start, end) {
|
|
1635
|
-
const values = this.toArray();
|
|
1636
|
-
values.copyWithin(target, start, end);
|
|
1637
|
-
this.rebuildFrom(values);
|
|
1638
|
-
return this;
|
|
1639
|
-
}
|
|
1640
|
-
};
|
|
1641
|
-
debug.__setFunctionName(_classThis, "RegisterClass");
|
|
1642
|
-
(() => {
|
|
1643
|
-
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
1644
|
-
debug.__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
1645
|
-
_classThis = _classDescriptor.value;
|
|
1646
|
-
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
1647
|
-
debug.__runInitializers(_classThis, _classExtraInitializers);
|
|
1648
|
-
})();
|
|
1649
|
-
return _classThis;
|
|
1650
|
-
})();
|
|
1651
|
-
const Register = RegisterClass;
|
|
1416
|
+
// 3. Otherwise forward
|
|
1417
|
+
return Reflect.get(source, prop, receiver);
|
|
1418
|
+
},
|
|
1419
|
+
// Forward set to the target (source) to ensure it acts as the receiver for reactivity notifications
|
|
1420
|
+
set(source, prop, value, _receiver) {
|
|
1421
|
+
// By strictly passing `source` as receiver, we ensure that if `source` is a reactive proxy,
|
|
1422
|
+
// it recognizes itself and triggers change notifications.
|
|
1423
|
+
return Reflect.set(source, prop, value, source);
|
|
1424
|
+
},
|
|
1425
|
+
});
|
|
1426
|
+
proxy.proxyToObject.set(proxy$1, target);
|
|
1427
|
+
memoizedRegistry.set(target, proxy$1);
|
|
1428
|
+
return proxy$1;
|
|
1429
|
+
}
|
|
1652
1430
|
/**
|
|
1653
|
-
*
|
|
1431
|
+
* Decorator and function wrapper for memoizing computed values based on reactive dependencies.
|
|
1654
1432
|
*
|
|
1655
|
-
*
|
|
1656
|
-
*
|
|
1657
|
-
* for UI lists keyed by IDs or when you need to preserve identity across reorders.
|
|
1433
|
+
* When used as a decorator on getters or methods, it caches the result and automatically
|
|
1434
|
+
* invalidates the cache when reactive dependencies change.
|
|
1658
1435
|
*
|
|
1659
|
-
*
|
|
1660
|
-
* @param initial - Optional initial items to populate the register
|
|
1661
|
-
* @returns A reactive Register instance
|
|
1436
|
+
* When used as a function wrapper, it memoizes based on object arguments (WeakMap-based cache).
|
|
1662
1437
|
*
|
|
1663
1438
|
* @example
|
|
1664
1439
|
* ```typescript
|
|
1665
|
-
*
|
|
1666
|
-
*
|
|
1667
|
-
*
|
|
1668
|
-
*
|
|
1440
|
+
* class User {
|
|
1441
|
+
* @memoize
|
|
1442
|
+
* get fullName() {
|
|
1443
|
+
* return `${this.firstName} ${this.lastName}`
|
|
1444
|
+
* }
|
|
1445
|
+
* }
|
|
1669
1446
|
*
|
|
1670
|
-
*
|
|
1671
|
-
* const
|
|
1447
|
+
* // Or as a function wrapper
|
|
1448
|
+
* const expensive = memoize((obj: SomeObject) => {
|
|
1449
|
+
* return heavyComputation(obj)
|
|
1450
|
+
* })
|
|
1672
1451
|
* ```
|
|
1673
1452
|
*/
|
|
1674
|
-
function
|
|
1675
|
-
return
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
}
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
}
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
}
|
|
1718
|
-
function projectArray(source, apply) {
|
|
1719
|
-
source = debug.reactive(source);
|
|
1720
|
-
const target = debug.reactive([]);
|
|
1721
|
-
const indexEffects = new Map();
|
|
1722
|
-
function normalizeTargetLength(length) {
|
|
1723
|
-
debug.FoolProof.set(target, 'length', length, target);
|
|
1724
|
-
}
|
|
1725
|
-
function disposeIndex(index) {
|
|
1726
|
-
const stopEffect = indexEffects.get(index);
|
|
1727
|
-
if (stopEffect) {
|
|
1728
|
-
indexEffects.delete(index);
|
|
1729
|
-
stopEffect();
|
|
1730
|
-
Reflect.deleteProperty(target, index);
|
|
1731
|
-
}
|
|
1732
|
-
}
|
|
1733
|
-
const parent = getActiveProjection();
|
|
1734
|
-
const depth = parent ? parent.depth + 1 : 0;
|
|
1735
|
-
const cleanupLength = debug.effect(debug.named(`project:${source[Symbol.toStringTag]}.length`, ({ ascend }) => {
|
|
1736
|
-
const length = source.length;
|
|
1737
|
-
normalizeTargetLength(length);
|
|
1738
|
-
const existing = Array.from(indexEffects.keys());
|
|
1739
|
-
for (let i = 0; i < length; i++) {
|
|
1740
|
-
if (indexEffects.has(i))
|
|
1741
|
-
continue;
|
|
1742
|
-
ascend(function projectArrayIndexAscend() {
|
|
1743
|
-
const index = i;
|
|
1744
|
-
const stop = debug.effect(debug.named(`project:${source[Symbol.toStringTag]}[${index}]`, ({ reaction }) => {
|
|
1745
|
-
if (!reaction)
|
|
1746
|
-
setActiveProjection({ source, key: index, target, depth, parent });
|
|
1747
|
-
const previous = debug.untracked(() => target[index]);
|
|
1748
|
-
const accessBase = {
|
|
1749
|
-
key: index,
|
|
1750
|
-
source,
|
|
1751
|
-
get: () => debug.FoolProof.get(source, index, source),
|
|
1752
|
-
set: (value) => debug.FoolProof.set(source, index, value, source),
|
|
1753
|
-
old: previous,
|
|
1754
|
-
};
|
|
1755
|
-
defineAccessValue(accessBase);
|
|
1756
|
-
target[index] = apply(accessBase, target);
|
|
1757
|
-
}));
|
|
1758
|
-
debug.setEffectName(stop, `project[${depth}]:${index}`);
|
|
1759
|
-
indexEffects.set(i, stop);
|
|
1760
|
-
});
|
|
1761
|
-
}
|
|
1762
|
-
for (const index of existing)
|
|
1763
|
-
if (index >= length)
|
|
1764
|
-
disposeIndex(index);
|
|
1765
|
-
}));
|
|
1766
|
-
return makeCleanup(target, indexEffects, () => cleanupLength(), {
|
|
1767
|
-
source,
|
|
1768
|
-
target,
|
|
1769
|
-
apply,
|
|
1770
|
-
depth,
|
|
1771
|
-
parent,
|
|
1772
|
-
});
|
|
1773
|
-
}
|
|
1774
|
-
function projectRegister(source, apply) {
|
|
1775
|
-
source = debug.reactive(source);
|
|
1776
|
-
const rawTarget = new Map();
|
|
1777
|
-
const target = debug.reactive(rawTarget);
|
|
1778
|
-
const keyEffects = new Map();
|
|
1779
|
-
function disposeKey(key) {
|
|
1780
|
-
const stopEffect = keyEffects.get(key);
|
|
1781
|
-
if (stopEffect) {
|
|
1782
|
-
stopEffect();
|
|
1783
|
-
keyEffects.delete(key);
|
|
1784
|
-
target.delete(key);
|
|
1785
|
-
}
|
|
1786
|
-
}
|
|
1787
|
-
const parent = getActiveProjection();
|
|
1788
|
-
const depth = parent ? parent.depth + 1 : 0;
|
|
1789
|
-
const cleanupKeys = debug.effect(function projectRegisterEffect({ ascend }) {
|
|
1790
|
-
const keys = new Set();
|
|
1791
|
-
for (const key of source.mapKeys())
|
|
1792
|
-
keys.add(key);
|
|
1793
|
-
for (const key of keys) {
|
|
1794
|
-
if (keyEffects.has(key))
|
|
1795
|
-
continue;
|
|
1796
|
-
ascend(() => {
|
|
1797
|
-
const stop = debug.effect(function projectRegisterKeyEffect({ reaction }) {
|
|
1798
|
-
if (!reaction)
|
|
1799
|
-
setActiveProjection({ source, key, target, depth, parent });
|
|
1800
|
-
const previous = debug.untracked(() => target.get(key));
|
|
1801
|
-
const accessBase = {
|
|
1802
|
-
key,
|
|
1803
|
-
source: source,
|
|
1804
|
-
get: () => source.get(key),
|
|
1805
|
-
set: (value) => {
|
|
1806
|
-
source.set(key, value);
|
|
1807
|
-
return true;
|
|
1808
|
-
},
|
|
1809
|
-
old: previous,
|
|
1810
|
-
};
|
|
1811
|
-
defineAccessValue(accessBase);
|
|
1812
|
-
const produced = apply(accessBase, target);
|
|
1813
|
-
target.set(key, produced);
|
|
1814
|
-
});
|
|
1815
|
-
debug.setEffectName(stop, `project[${depth}]:${String(key)}`);
|
|
1816
|
-
keyEffects.set(key, stop);
|
|
1817
|
-
});
|
|
1818
|
-
}
|
|
1819
|
-
for (const key of Array.from(keyEffects.keys()))
|
|
1820
|
-
if (!keys.has(key))
|
|
1821
|
-
disposeKey(key);
|
|
1822
|
-
});
|
|
1823
|
-
return makeCleanup(target, keyEffects, () => cleanupKeys(), {
|
|
1824
|
-
source: source,
|
|
1825
|
-
target,
|
|
1826
|
-
apply,
|
|
1827
|
-
depth,
|
|
1828
|
-
parent,
|
|
1829
|
-
});
|
|
1830
|
-
}
|
|
1831
|
-
function projectRecord(source, apply) {
|
|
1832
|
-
source = debug.reactive(source);
|
|
1833
|
-
const target = debug.reactive({});
|
|
1834
|
-
const keyEffects = new Map();
|
|
1835
|
-
function disposeKey(key) {
|
|
1836
|
-
const stopEffect = keyEffects.get(key);
|
|
1837
|
-
if (stopEffect) {
|
|
1838
|
-
stopEffect();
|
|
1839
|
-
keyEffects.delete(key);
|
|
1840
|
-
Reflect.deleteProperty(target, key);
|
|
1841
|
-
}
|
|
1842
|
-
}
|
|
1843
|
-
const parent = getActiveProjection();
|
|
1844
|
-
const depth = parent ? parent.depth + 1 : 0;
|
|
1845
|
-
const cleanupKeys = debug.effect(function projectRecordEffect({ ascend }) {
|
|
1846
|
-
const keys = new Set();
|
|
1847
|
-
for (const key in source)
|
|
1848
|
-
keys.add(key);
|
|
1849
|
-
const observed = Reflect.ownKeys(source);
|
|
1850
|
-
for (const key of observed)
|
|
1851
|
-
keys.add(key);
|
|
1852
|
-
for (const key of keys) {
|
|
1853
|
-
if (keyEffects.has(key))
|
|
1854
|
-
continue;
|
|
1855
|
-
ascend(() => {
|
|
1856
|
-
const stop = debug.effect(function projectRecordKeyEffect({ reaction }) {
|
|
1857
|
-
if (!reaction)
|
|
1858
|
-
setActiveProjection({ source, key, target, depth, parent });
|
|
1859
|
-
const sourceKey = key;
|
|
1860
|
-
const previous = debug.untracked(() => target[key]);
|
|
1861
|
-
const accessBase = {
|
|
1862
|
-
key: sourceKey,
|
|
1863
|
-
source: source,
|
|
1864
|
-
get: () => debug.FoolProof.get(source, sourceKey, source),
|
|
1865
|
-
set: (value) => debug.FoolProof.set(source, sourceKey, value, source),
|
|
1866
|
-
old: previous,
|
|
1867
|
-
};
|
|
1868
|
-
defineAccessValue(accessBase);
|
|
1869
|
-
const produced = apply(accessBase, target);
|
|
1870
|
-
target[sourceKey] = produced;
|
|
1871
|
-
});
|
|
1872
|
-
debug.setEffectName(stop, `project[${depth}]:${String(key)}`);
|
|
1873
|
-
keyEffects.set(key, stop);
|
|
1874
|
-
});
|
|
1875
|
-
}
|
|
1876
|
-
for (const key of Array.from(keyEffects.keys()))
|
|
1877
|
-
if (!keys.has(key))
|
|
1878
|
-
disposeKey(key);
|
|
1879
|
-
});
|
|
1880
|
-
return makeCleanup(target, keyEffects, () => cleanupKeys(), {
|
|
1881
|
-
source: source,
|
|
1882
|
-
target,
|
|
1883
|
-
apply,
|
|
1884
|
-
depth,
|
|
1885
|
-
parent,
|
|
1886
|
-
});
|
|
1887
|
-
}
|
|
1888
|
-
function projectMap(source, apply) {
|
|
1889
|
-
source = debug.reactive(source);
|
|
1890
|
-
const rawTarget = new Map();
|
|
1891
|
-
const target = debug.reactive(rawTarget);
|
|
1892
|
-
const keyEffects = new Map();
|
|
1893
|
-
function disposeKey(key) {
|
|
1894
|
-
const stopEffect = keyEffects.get(key);
|
|
1895
|
-
if (stopEffect) {
|
|
1896
|
-
stopEffect();
|
|
1897
|
-
keyEffects.delete(key);
|
|
1898
|
-
target.delete(key);
|
|
1899
|
-
}
|
|
1900
|
-
}
|
|
1901
|
-
const parent = getActiveProjection();
|
|
1902
|
-
const depth = parent ? parent.depth + 1 : 0;
|
|
1903
|
-
const cleanupKeys = debug.effect(function projectMapEffect({ ascend }) {
|
|
1904
|
-
const keys = new Set();
|
|
1905
|
-
for (const key of source.keys())
|
|
1906
|
-
keys.add(key);
|
|
1907
|
-
for (const key of keys) {
|
|
1908
|
-
if (keyEffects.has(key))
|
|
1909
|
-
continue;
|
|
1910
|
-
ascend(() => {
|
|
1911
|
-
const stop = debug.effect(function projectMapKeyEffect({ reaction }) {
|
|
1912
|
-
if (!reaction)
|
|
1913
|
-
setActiveProjection({ source, key, target, depth, parent });
|
|
1914
|
-
const previous = debug.untracked(() => target.get(key));
|
|
1915
|
-
const accessBase = {
|
|
1916
|
-
key,
|
|
1917
|
-
source: source,
|
|
1918
|
-
get: () => source.get(key),
|
|
1919
|
-
set: (value) => {
|
|
1920
|
-
source.set(key, value);
|
|
1921
|
-
return true;
|
|
1922
|
-
},
|
|
1923
|
-
old: previous,
|
|
1924
|
-
};
|
|
1925
|
-
defineAccessValue(accessBase);
|
|
1926
|
-
const produced = apply(accessBase, target);
|
|
1927
|
-
target.set(key, produced);
|
|
1928
|
-
});
|
|
1929
|
-
debug.setEffectName(stop, `project[${depth}]:${String(key)}`);
|
|
1930
|
-
keyEffects.set(key, stop);
|
|
1931
|
-
});
|
|
1932
|
-
}
|
|
1933
|
-
for (const key of Array.from(keyEffects.keys()))
|
|
1934
|
-
if (!keys.has(key))
|
|
1935
|
-
disposeKey(key);
|
|
1936
|
-
});
|
|
1937
|
-
return makeCleanup(target, keyEffects, () => cleanupKeys(), {
|
|
1938
|
-
source: source,
|
|
1939
|
-
target,
|
|
1940
|
-
apply,
|
|
1941
|
-
depth,
|
|
1942
|
-
parent,
|
|
1453
|
+
function makeMemoizeDecorator(memoizeOpts) {
|
|
1454
|
+
return proxy.decorator({
|
|
1455
|
+
getter(original, target, propertyKey) {
|
|
1456
|
+
return function () {
|
|
1457
|
+
let wrapper = wrapperRegistry.get(original);
|
|
1458
|
+
if (!wrapper) {
|
|
1459
|
+
wrapper = proxy.markWithRoot(proxy.named(`${String(target?.constructor?.name ?? target?.name ?? 'Object')}.${String(propertyKey)}`, (that) => {
|
|
1460
|
+
return original.call(that);
|
|
1461
|
+
}), {
|
|
1462
|
+
method: original,
|
|
1463
|
+
propertyKey,
|
|
1464
|
+
});
|
|
1465
|
+
const origRoot = original[proxy.rootFunctionSymbol];
|
|
1466
|
+
if (origRoot)
|
|
1467
|
+
wrapper[proxy.rootFunctionSymbol] = origRoot;
|
|
1468
|
+
wrapperRegistry.set(original, wrapper);
|
|
1469
|
+
}
|
|
1470
|
+
const memoized = memoizeFunction(wrapper, memoizeOpts);
|
|
1471
|
+
return memoized(this);
|
|
1472
|
+
};
|
|
1473
|
+
},
|
|
1474
|
+
method(original, target, name) {
|
|
1475
|
+
return function (...args) {
|
|
1476
|
+
let wrapper = wrapperRegistry.get(original);
|
|
1477
|
+
if (!wrapper) {
|
|
1478
|
+
wrapper = proxy.markWithRoot(proxy.named(`${String(target?.constructor?.name ?? target?.name ?? 'Object')}.${String(name)}`, (that, ...args) => {
|
|
1479
|
+
return original.call(that, ...args);
|
|
1480
|
+
}), {
|
|
1481
|
+
method: original,
|
|
1482
|
+
propertyKey: name,
|
|
1483
|
+
});
|
|
1484
|
+
const origRoot = original[proxy.rootFunctionSymbol];
|
|
1485
|
+
if (origRoot)
|
|
1486
|
+
wrapper[proxy.rootFunctionSymbol] = origRoot;
|
|
1487
|
+
wrapperRegistry.set(original, wrapper);
|
|
1488
|
+
}
|
|
1489
|
+
const memoized = memoizeFunction(wrapper, memoizeOpts);
|
|
1490
|
+
return memoized(this, ...args);
|
|
1491
|
+
};
|
|
1492
|
+
},
|
|
1493
|
+
default: (target) => typeof target === 'object'
|
|
1494
|
+
? memoizeObject(target, memoizeOpts)
|
|
1495
|
+
: memoizeFunction(target, memoizeOpts),
|
|
1943
1496
|
});
|
|
1944
1497
|
}
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
return
|
|
1948
|
-
|
|
1949
|
-
return projectMap(source, apply);
|
|
1950
|
-
if (source instanceof Register)
|
|
1951
|
-
return projectRegister(source, apply);
|
|
1952
|
-
if (source && (source.constructor === Object || source.constructor === undefined))
|
|
1953
|
-
return projectRecord(source, apply);
|
|
1954
|
-
throw new Error('Unsupported source type');
|
|
1955
|
-
}
|
|
1956
|
-
const project = Object.assign(projectCore, {
|
|
1957
|
-
array: projectArray,
|
|
1958
|
-
register: projectRegister,
|
|
1959
|
-
record: projectRecord,
|
|
1960
|
-
map: projectMap,
|
|
1498
|
+
const memoize = proxy.flavored(makeMemoizeDecorator(), {
|
|
1499
|
+
get lenient() {
|
|
1500
|
+
return makeMemoizeDecorator({ lenient: true });
|
|
1501
|
+
},
|
|
1961
1502
|
});
|
|
1962
1503
|
|
|
1963
1504
|
/**
|
|
@@ -2012,8 +1553,8 @@ const project = Object.assign(projectCore, {
|
|
|
2012
1553
|
* });
|
|
2013
1554
|
*/
|
|
2014
1555
|
function organized(source, apply, baseTarget = {}) {
|
|
2015
|
-
const observedSource =
|
|
2016
|
-
const target =
|
|
1556
|
+
const observedSource = proxy.reactive(source);
|
|
1557
|
+
const target = proxy.reactive(baseTarget);
|
|
2017
1558
|
const stop = attend(() => {
|
|
2018
1559
|
const keys = [];
|
|
2019
1560
|
for (const key in observedSource)
|
|
@@ -2023,8 +1564,8 @@ function organized(source, apply, baseTarget = {}) {
|
|
|
2023
1564
|
const sourceKey = key;
|
|
2024
1565
|
const accessBase = {
|
|
2025
1566
|
key: sourceKey,
|
|
2026
|
-
get: () =>
|
|
2027
|
-
set: (value) =>
|
|
1567
|
+
get: () => proxy.FoolProof.get(observedSource, sourceKey, observedSource),
|
|
1568
|
+
set: (value) => proxy.FoolProof.set(observedSource, sourceKey, value, observedSource),
|
|
2028
1569
|
};
|
|
2029
1570
|
Object.defineProperty(accessBase, 'value', {
|
|
2030
1571
|
get: accessBase.get,
|
|
@@ -2034,7 +1575,7 @@ function organized(source, apply, baseTarget = {}) {
|
|
|
2034
1575
|
});
|
|
2035
1576
|
return apply(accessBase, target);
|
|
2036
1577
|
});
|
|
2037
|
-
return
|
|
1578
|
+
return proxy.link(target, (reason) => stop(reason));
|
|
2038
1579
|
}
|
|
2039
1580
|
/**
|
|
2040
1581
|
* Organizes a property on a target object
|
|
@@ -2051,35 +1592,246 @@ function organize(target, property, access) {
|
|
|
2051
1592
|
configurable: true,
|
|
2052
1593
|
enumerable: true,
|
|
2053
1594
|
});
|
|
2054
|
-
|
|
1595
|
+
proxy.touched1(target, { type: 'set', prop: property }, property);
|
|
2055
1596
|
return () => delete target[property];
|
|
2056
1597
|
}
|
|
2057
1598
|
|
|
1599
|
+
//#region watch
|
|
1600
|
+
const unsetYet = Symbol('unset-yet');
|
|
1601
|
+
const watch = proxy.flavored(function watch(value, //object | ((dep: DependencyAccess) => object),
|
|
1602
|
+
changed, options = {}) {
|
|
1603
|
+
return typeof value === 'function'
|
|
1604
|
+
? watchCallBack(value, changed, options)
|
|
1605
|
+
: typeof value === 'object' && value !== null
|
|
1606
|
+
? watchObject(value, changed, options)
|
|
1607
|
+
: (() => {
|
|
1608
|
+
throw new Error('watch: value must be a function or an object');
|
|
1609
|
+
})();
|
|
1610
|
+
}, {
|
|
1611
|
+
get deep() {
|
|
1612
|
+
return proxy.flavorOptions(this, { deep: true });
|
|
1613
|
+
},
|
|
1614
|
+
get immediate() {
|
|
1615
|
+
return proxy.flavorOptions(this, { immediate: true });
|
|
1616
|
+
},
|
|
1617
|
+
});
|
|
1618
|
+
function watchObject(value, changed, { immediate = false, deep = false } = {}) {
|
|
1619
|
+
if (deep)
|
|
1620
|
+
return deepWatch(value, changed, { immediate });
|
|
1621
|
+
return proxy.effect.named('watch:object')(() => {
|
|
1622
|
+
proxy.dependant(value);
|
|
1623
|
+
if (immediate)
|
|
1624
|
+
changed(value);
|
|
1625
|
+
immediate = true;
|
|
1626
|
+
});
|
|
1627
|
+
}
|
|
1628
|
+
function watchCallBack(value, changed, { immediate = false, deep = false } = {}) {
|
|
1629
|
+
let oldValue = unsetYet;
|
|
1630
|
+
let deepCleanup;
|
|
1631
|
+
const cbCleanup = proxy.effect.named('watch:callback')(proxy.markWithRoot((access) => {
|
|
1632
|
+
const newValue = value(access);
|
|
1633
|
+
if (oldValue !== newValue) {
|
|
1634
|
+
const old = oldValue;
|
|
1635
|
+
if (old === unsetYet) {
|
|
1636
|
+
if (immediate)
|
|
1637
|
+
proxy.untracked(() => changed(newValue));
|
|
1638
|
+
}
|
|
1639
|
+
else
|
|
1640
|
+
proxy.untracked(() => changed(newValue, old));
|
|
1641
|
+
}
|
|
1642
|
+
oldValue = newValue;
|
|
1643
|
+
if (deep) {
|
|
1644
|
+
if (deepCleanup)
|
|
1645
|
+
deepCleanup();
|
|
1646
|
+
deepCleanup = deepWatch(newValue, (value) => changed(value, value));
|
|
1647
|
+
}
|
|
1648
|
+
}, value));
|
|
1649
|
+
return (() => {
|
|
1650
|
+
cbCleanup();
|
|
1651
|
+
if (deepCleanup)
|
|
1652
|
+
deepCleanup();
|
|
1653
|
+
});
|
|
1654
|
+
}
|
|
1655
|
+
//#endregion
|
|
1656
|
+
//#region when
|
|
2058
1657
|
/**
|
|
2059
|
-
*
|
|
2060
|
-
*
|
|
2061
|
-
*
|
|
2062
|
-
*
|
|
2063
|
-
*
|
|
2064
|
-
* @param descriptors - A reactive record of property descriptors.
|
|
2065
|
-
* @param target - The object to define properties on (defaults to a new object).
|
|
2066
|
-
* @returns The target object with reactive property definitions.
|
|
1658
|
+
* Returns a promise that resolves when the predicate returns a truthy value.
|
|
1659
|
+
* The predicate is evaluated reactively — it re-runs whenever its dependencies change.
|
|
1660
|
+
* @param predicate - Reactive function that returns a value; resolves when truthy
|
|
1661
|
+
* @param timeout - Optional timeout in milliseconds — rejects if condition is not met within this duration
|
|
1662
|
+
* @returns Promise that resolves with the first truthy return value
|
|
2067
1663
|
*/
|
|
2068
|
-
function
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
const
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
1664
|
+
function when(predicate, timeout) {
|
|
1665
|
+
return new Promise((resolve, reject) => {
|
|
1666
|
+
let timer;
|
|
1667
|
+
const stop = proxy.effect.named('watch:when')((access) => {
|
|
1668
|
+
try {
|
|
1669
|
+
const value = predicate(access);
|
|
1670
|
+
if (value) {
|
|
1671
|
+
if (timer !== undefined)
|
|
1672
|
+
clearTimeout(timer);
|
|
1673
|
+
timer = undefined;
|
|
1674
|
+
queueMicrotask(() => stop());
|
|
1675
|
+
resolve(value);
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
catch (error) {
|
|
1679
|
+
if (timer !== undefined)
|
|
1680
|
+
clearTimeout(timer);
|
|
1681
|
+
timer = undefined;
|
|
1682
|
+
reject(error);
|
|
1683
|
+
}
|
|
1684
|
+
});
|
|
1685
|
+
if (timeout !== undefined) {
|
|
1686
|
+
timer = setTimeout(() => {
|
|
1687
|
+
stop();
|
|
1688
|
+
timer = undefined;
|
|
1689
|
+
reject(new Error(`when: timed out after ${timeout}ms`));
|
|
1690
|
+
}, timeout);
|
|
2079
1691
|
}
|
|
2080
|
-
return () => Reflect.deleteProperty(target, key);
|
|
2081
1692
|
});
|
|
2082
|
-
|
|
1693
|
+
}
|
|
1694
|
+
//#endregion
|
|
1695
|
+
//#region nonReactive
|
|
1696
|
+
/**
|
|
1697
|
+
* Mark an object as non-reactive. This object and all its properties will never be made reactive.
|
|
1698
|
+
* @param obj - The object to mark as non-reactive
|
|
1699
|
+
*/
|
|
1700
|
+
function shallowNonReactive(obj) {
|
|
1701
|
+
obj = proxy.unwrap(obj);
|
|
1702
|
+
if (proxy.isNonReactive(obj))
|
|
1703
|
+
return obj;
|
|
1704
|
+
obj[proxy.unreactiveProperties] = true;
|
|
1705
|
+
return obj;
|
|
1706
|
+
}
|
|
1707
|
+
function unreactiveApplication(arg1, ...args) {
|
|
1708
|
+
return typeof arg1 === 'object'
|
|
1709
|
+
? shallowNonReactive(arg1)
|
|
1710
|
+
: ((original) => {
|
|
1711
|
+
// Copy the parent's unreactive properties if they exist
|
|
1712
|
+
const parentMarker = original.prototype[proxy.unreactiveProperties];
|
|
1713
|
+
// If parent is fully unreactive, child is too
|
|
1714
|
+
if (parentMarker === true) {
|
|
1715
|
+
original.prototype[proxy.unreactiveProperties] = true;
|
|
1716
|
+
}
|
|
1717
|
+
else {
|
|
1718
|
+
const set = new Set(parentMarker || []);
|
|
1719
|
+
// Add all arguments (including the first one)
|
|
1720
|
+
set.add(arg1);
|
|
1721
|
+
for (const arg of args)
|
|
1722
|
+
set.add(arg);
|
|
1723
|
+
proxy.addUnreactiveProps(original.prototype, set);
|
|
1724
|
+
}
|
|
1725
|
+
return original; // Return the class
|
|
1726
|
+
});
|
|
1727
|
+
}
|
|
1728
|
+
/**
|
|
1729
|
+
* Decorator that marks classes or properties as non-reactive
|
|
1730
|
+
* Prevents objects from being made reactive
|
|
1731
|
+
*/
|
|
1732
|
+
const unreactive = proxy.decorator({
|
|
1733
|
+
class(original) {
|
|
1734
|
+
original.prototype[proxy.unreactiveProperties] = true;
|
|
1735
|
+
},
|
|
1736
|
+
default: unreactiveApplication,
|
|
1737
|
+
});
|
|
1738
|
+
//#endregion
|
|
1739
|
+
//#region resource
|
|
1740
|
+
function lazyInit(resource, load) {
|
|
1741
|
+
const creation = proxy.effectHistory.active;
|
|
1742
|
+
let fresh = true;
|
|
1743
|
+
return new Proxy(resource, {
|
|
1744
|
+
[Symbol.toStringTag]: 'LazyInit',
|
|
1745
|
+
get(target, prop) {
|
|
1746
|
+
if (fresh) {
|
|
1747
|
+
proxy.captured(creation, load)();
|
|
1748
|
+
fresh = false;
|
|
1749
|
+
}
|
|
1750
|
+
return target[prop];
|
|
1751
|
+
},
|
|
1752
|
+
});
|
|
1753
|
+
}
|
|
1754
|
+
/**
|
|
1755
|
+
* Creates a reactive resource that automatically tracks async state.
|
|
1756
|
+
* @param fetcher - Async function that returns the value. Reactive dependencies are tracked.
|
|
1757
|
+
* @param options - Resource options (initialValue)
|
|
1758
|
+
* @returns Reactive Resource object with value, loading, error, latest properties
|
|
1759
|
+
*/
|
|
1760
|
+
function resource(fetcher, options = {}) {
|
|
1761
|
+
const resource = proxy.reactive({
|
|
1762
|
+
value: options.initialValue,
|
|
1763
|
+
loading: true,
|
|
1764
|
+
error: undefined,
|
|
1765
|
+
latest: options.initialValue,
|
|
1766
|
+
reload() {
|
|
1767
|
+
reloadSignal.value++;
|
|
1768
|
+
},
|
|
1769
|
+
});
|
|
1770
|
+
const reloadSignal = proxy.reactive({ value: 0 });
|
|
1771
|
+
// Solve race conditions: make sure a new fast request is not overloaded by a slow old one
|
|
1772
|
+
let counter = 0;
|
|
1773
|
+
return lazyInit(resource, () => {
|
|
1774
|
+
proxy.link(resource, proxy.effect.named('watch:resource')((access) => {
|
|
1775
|
+
// Track reload signal to enable manual reloading
|
|
1776
|
+
void reloadSignal.value;
|
|
1777
|
+
const id = ++counter;
|
|
1778
|
+
resource.loading = true;
|
|
1779
|
+
resource.error = undefined;
|
|
1780
|
+
try {
|
|
1781
|
+
const result = fetcher(access);
|
|
1782
|
+
if (result instanceof Promise) {
|
|
1783
|
+
resource.promise = result
|
|
1784
|
+
.then((val) => {
|
|
1785
|
+
if (id === counter) {
|
|
1786
|
+
resource.value = val;
|
|
1787
|
+
resource.latest = val;
|
|
1788
|
+
resource.loading = false;
|
|
1789
|
+
}
|
|
1790
|
+
})
|
|
1791
|
+
.catch((err) => {
|
|
1792
|
+
if (id === counter) {
|
|
1793
|
+
resource.error = err;
|
|
1794
|
+
resource.loading = false;
|
|
1795
|
+
}
|
|
1796
|
+
});
|
|
1797
|
+
}
|
|
1798
|
+
else {
|
|
1799
|
+
resource.promise = Promise.resolve();
|
|
1800
|
+
resource.value = result;
|
|
1801
|
+
resource.latest = result;
|
|
1802
|
+
resource.loading = false;
|
|
1803
|
+
}
|
|
1804
|
+
}
|
|
1805
|
+
catch (err) {
|
|
1806
|
+
resource.promise = Promise.reject(err);
|
|
1807
|
+
resource.error = err;
|
|
1808
|
+
resource.loading = false;
|
|
1809
|
+
}
|
|
1810
|
+
}));
|
|
1811
|
+
});
|
|
1812
|
+
}
|
|
1813
|
+
//#endregion
|
|
1814
|
+
|
|
1815
|
+
/**
|
|
1816
|
+
* Converts an iterator to a generator that yields reactive values
|
|
1817
|
+
*/
|
|
1818
|
+
function* makeReactiveIterator(iterator) {
|
|
1819
|
+
let result = iterator.next();
|
|
1820
|
+
while (!result.done) {
|
|
1821
|
+
yield proxy.reactive(result.value);
|
|
1822
|
+
result = iterator.next();
|
|
1823
|
+
}
|
|
1824
|
+
}
|
|
1825
|
+
/**
|
|
1826
|
+
* Converts an iterator of key-value pairs to a generator that yields reactive key-value pairs
|
|
1827
|
+
*/
|
|
1828
|
+
function* makeReactiveEntriesIterator(iterator) {
|
|
1829
|
+
let result = iterator.next();
|
|
1830
|
+
while (!result.done) {
|
|
1831
|
+
const [key, value] = result.value;
|
|
1832
|
+
yield [proxy.reactive(key), proxy.reactive(value)];
|
|
1833
|
+
result = iterator.next();
|
|
1834
|
+
}
|
|
2083
1835
|
}
|
|
2084
1836
|
|
|
2085
1837
|
function* index(i, { length = true } = {}) {
|
|
@@ -2087,42 +1839,42 @@ function* index(i, { length = true } = {}) {
|
|
|
2087
1839
|
yield 'length';
|
|
2088
1840
|
yield i;
|
|
2089
1841
|
}
|
|
2090
|
-
function* range(a, b, { length = false } = {}) {
|
|
2091
|
-
const start = Math.min(a, b);
|
|
2092
|
-
const end = Math.max(a, b);
|
|
2093
|
-
if (length)
|
|
2094
|
-
yield 'length';
|
|
2095
|
-
for (let i = start; i <= end; i++)
|
|
2096
|
-
yield i;
|
|
2097
|
-
}
|
|
2098
1842
|
class Indexer extends Array {
|
|
2099
1843
|
get(i) {
|
|
2100
|
-
|
|
2101
|
-
return
|
|
1844
|
+
proxy.dependant(this, i);
|
|
1845
|
+
return proxy.reactive(this[i]);
|
|
2102
1846
|
}
|
|
2103
1847
|
// Returns undefined intentionally: signals the proxy handler that notifications
|
|
2104
1848
|
// were already dispatched via touched(), preventing double notification
|
|
2105
1849
|
set(i, value) {
|
|
2106
1850
|
const added = i >= this.length;
|
|
2107
1851
|
this[i] = value;
|
|
2108
|
-
|
|
1852
|
+
proxy.touched(this, { type: 'set', prop: i }, index(i, { length: added }));
|
|
2109
1853
|
}
|
|
2110
1854
|
}
|
|
2111
|
-
const indexLess = { get:
|
|
2112
|
-
|
|
1855
|
+
const indexLess = { get: proxy.FoolProof.get, set: proxy.FoolProof.set };
|
|
1856
|
+
// Fast numeric-string check: first char is a digit (0-9)
|
|
1857
|
+
function asIndex(prop) {
|
|
1858
|
+
const c = prop.charCodeAt(0);
|
|
1859
|
+
if (c < 48 || c > 57)
|
|
1860
|
+
return -1; // not 0-9
|
|
1861
|
+
const n = +prop; // coerce — faster than parseInt, handles "0", "12", etc.
|
|
1862
|
+
return n === (n | 0) && n >= 0 ? n : -1;
|
|
1863
|
+
}
|
|
1864
|
+
Object.assign(proxy.FoolProof, {
|
|
2113
1865
|
get(obj, prop, receiver) {
|
|
2114
|
-
if (obj
|
|
2115
|
-
const
|
|
2116
|
-
if (
|
|
2117
|
-
return Indexer.prototype.get.call(obj,
|
|
1866
|
+
if (Array.isArray(obj) && typeof prop === 'string') {
|
|
1867
|
+
const i = asIndex(prop);
|
|
1868
|
+
if (i >= 0)
|
|
1869
|
+
return Indexer.prototype.get.call(obj, i);
|
|
2118
1870
|
}
|
|
2119
1871
|
return indexLess.get(obj, prop, receiver);
|
|
2120
1872
|
},
|
|
2121
1873
|
set(obj, prop, value, receiver) {
|
|
2122
|
-
if (obj
|
|
2123
|
-
const
|
|
2124
|
-
if (
|
|
2125
|
-
return Indexer.prototype.set.call(obj,
|
|
1874
|
+
if (Array.isArray(obj) && typeof prop === 'string') {
|
|
1875
|
+
const i = asIndex(prop);
|
|
1876
|
+
if (i >= 0)
|
|
1877
|
+
return Indexer.prototype.set.call(obj, i, value);
|
|
2126
1878
|
}
|
|
2127
1879
|
return indexLess.set(obj, prop, value, receiver);
|
|
2128
1880
|
},
|
|
@@ -2131,374 +1883,190 @@ class ReactiveArray extends Array {
|
|
|
2131
1883
|
toJSON() {
|
|
2132
1884
|
return this;
|
|
2133
1885
|
}
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
if (actualIndex < 0 || actualIndex >= this.length)
|
|
2156
|
-
return undefined;
|
|
2157
|
-
return debug.reactive(this[actualIndex]);
|
|
2158
|
-
}
|
|
2159
|
-
// Immutable versions of mutator methods
|
|
2160
|
-
toReversed() {
|
|
2161
|
-
debug.dependant(this);
|
|
2162
|
-
return debug.reactive(this.toReversed());
|
|
2163
|
-
}
|
|
2164
|
-
toSorted(compareFn) {
|
|
2165
|
-
debug.dependant(this);
|
|
2166
|
-
return debug.reactive(this.toSorted(compareFn));
|
|
2167
|
-
}
|
|
2168
|
-
toSpliced(start, deleteCount, ...items) {
|
|
2169
|
-
debug.dependant(this);
|
|
2170
|
-
return deleteCount === undefined
|
|
2171
|
-
? this.toSpliced(start)
|
|
2172
|
-
: this.toSpliced(start, deleteCount, ...items);
|
|
2173
|
-
}
|
|
2174
|
-
with(index, value) {
|
|
2175
|
-
debug.dependant(this);
|
|
2176
|
-
return debug.reactive(this.with(index, value));
|
|
2177
|
-
}
|
|
2178
|
-
// Iterator methods with reactivity tracking
|
|
2179
|
-
entries() {
|
|
2180
|
-
debug.dependant(this);
|
|
2181
|
-
return makeReactiveEntriesIterator(this.entries());
|
|
2182
|
-
}
|
|
2183
|
-
keys() {
|
|
2184
|
-
debug.dependant(this, 'length');
|
|
2185
|
-
return this.keys();
|
|
2186
|
-
}
|
|
2187
|
-
values() {
|
|
2188
|
-
debug.dependant(this);
|
|
2189
|
-
return makeReactiveIterator(this.values());
|
|
2190
|
-
}
|
|
2191
|
-
[Symbol.iterator]() {
|
|
2192
|
-
debug.dependant(this);
|
|
2193
|
-
const nativeIterator = this[Symbol.iterator]();
|
|
2194
|
-
return {
|
|
2195
|
-
next() {
|
|
2196
|
-
const result = nativeIterator.next();
|
|
2197
|
-
if (result.done) {
|
|
2198
|
-
return result;
|
|
2199
|
-
}
|
|
2200
|
-
return { value: debug.reactive(result.value), done: false };
|
|
2201
|
-
},
|
|
2202
|
-
[Symbol.iterator]() {
|
|
2203
|
-
return this;
|
|
2204
|
-
},
|
|
2205
|
-
[Symbol.dispose]() { },
|
|
2206
|
-
};
|
|
2207
|
-
}
|
|
2208
|
-
indexOf(searchElement, fromIndex) {
|
|
2209
|
-
const length = this.length;
|
|
2210
|
-
let i = fromIndex === undefined ? 0 : fromIndex;
|
|
2211
|
-
if (i < 0)
|
|
2212
|
-
i = Math.max(length + i, 0);
|
|
2213
|
-
const unwrappedSearch = debug.unwrap(searchElement);
|
|
2214
|
-
for (; i < length; i++) {
|
|
2215
|
-
debug.dependant(this, i);
|
|
2216
|
-
const item = this[i];
|
|
2217
|
-
if (item === searchElement || item === unwrappedSearch || debug.unwrap(item) === unwrappedSearch) {
|
|
2218
|
-
return i;
|
|
1886
|
+
}
|
|
1887
|
+
/**
|
|
1888
|
+
* This is a wrapper class for Array that adds reactive behavior.
|
|
1889
|
+
* It extends Array and overrides methods to add reactive behavior, while making sure that the internal representation is not reactive.
|
|
1890
|
+
*/
|
|
1891
|
+
let ReactiveArrayWrapper = (() => {
|
|
1892
|
+
var _a;
|
|
1893
|
+
let _classSuper = Array;
|
|
1894
|
+
let _instanceExtraInitializers = [];
|
|
1895
|
+
let _fill_decorators;
|
|
1896
|
+
let _copyWithin_decorators;
|
|
1897
|
+
let _pop_decorators;
|
|
1898
|
+
let _push_decorators;
|
|
1899
|
+
let _reverse_decorators;
|
|
1900
|
+
let _shift_decorators;
|
|
1901
|
+
let _sort_decorators;
|
|
1902
|
+
let _splice_decorators;
|
|
1903
|
+
let _unshift_decorators;
|
|
1904
|
+
return _a = class ReactiveArrayWrapper extends _classSuper {
|
|
1905
|
+
at(index) {
|
|
1906
|
+
return proxy.reactive(super.at(index));
|
|
2219
1907
|
}
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
return -1;
|
|
2223
|
-
}
|
|
2224
|
-
lastIndexOf(searchElement, fromIndex) {
|
|
2225
|
-
const length = this.length;
|
|
2226
|
-
let i = fromIndex === undefined ? length - 1 : fromIndex;
|
|
2227
|
-
if (i >= length)
|
|
2228
|
-
i = length - 1;
|
|
2229
|
-
if (i < 0)
|
|
2230
|
-
i = Math.max(length + i, -1); // -1 ensures loop condition i >= 0 works correctly
|
|
2231
|
-
const unwrappedSearch = debug.unwrap(searchElement);
|
|
2232
|
-
for (; i >= 0; i--) {
|
|
2233
|
-
debug.dependant(this, i);
|
|
2234
|
-
const item = this[i];
|
|
2235
|
-
if (item === searchElement || item === unwrappedSearch || debug.unwrap(item) === unwrappedSearch) {
|
|
2236
|
-
return i;
|
|
1908
|
+
concat(...items) {
|
|
1909
|
+
return proxy.reactive(super.concat(...items.map(proxy.unwrap)));
|
|
2237
1910
|
}
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
1911
|
+
entries() {
|
|
1912
|
+
proxy.dependant(this, proxy.keysOf);
|
|
1913
|
+
return makeReactiveEntriesIterator(super.entries());
|
|
1914
|
+
}
|
|
1915
|
+
every(predicate, thisArg) {
|
|
1916
|
+
return super.every((v, i, a) => predicate.call(thisArg, proxy.reactive(v), i, a), thisArg);
|
|
1917
|
+
}
|
|
1918
|
+
fill(value, start, end) {
|
|
1919
|
+
return super.fill(proxy.unwrap(value), start, end);
|
|
1920
|
+
}
|
|
1921
|
+
copyWithin(target, start, end) {
|
|
1922
|
+
return super.copyWithin(target, start, end);
|
|
1923
|
+
}
|
|
1924
|
+
filter(predicate, thisArg) {
|
|
1925
|
+
return proxy.reactive(super.filter((v, i, a) => predicate.call(thisArg, proxy.reactive(v), i, a), thisArg));
|
|
1926
|
+
}
|
|
1927
|
+
find(predicate, thisArg) {
|
|
1928
|
+
return proxy.reactive(super.find((v, i, a) => predicate.call(thisArg, proxy.reactive(v), i, a), thisArg));
|
|
1929
|
+
}
|
|
1930
|
+
findIndex(predicate, thisArg) {
|
|
1931
|
+
return super.findIndex((v, i, a) => predicate.call(thisArg, proxy.reactive(v), i, a), thisArg);
|
|
1932
|
+
}
|
|
1933
|
+
findLast(predicate, thisArg) {
|
|
1934
|
+
return proxy.reactive(super.findLast((v, i, a) => predicate.call(thisArg, proxy.reactive(v), i, a), thisArg));
|
|
1935
|
+
}
|
|
1936
|
+
findLastIndex(predicate, thisArg) {
|
|
1937
|
+
return super.findLastIndex((v, i, a) => predicate.call(thisArg, proxy.reactive(v), i, a), thisArg);
|
|
1938
|
+
}
|
|
1939
|
+
flat(depth) {
|
|
1940
|
+
return proxy.reactive(super.flat(depth));
|
|
1941
|
+
}
|
|
1942
|
+
flatMap(callbackfn, thisArg) {
|
|
1943
|
+
return proxy.reactive(super.flatMap((v, i, a) => proxy.unwrap(callbackfn.call(thisArg, proxy.reactive(v), i, a)), thisArg));
|
|
1944
|
+
}
|
|
1945
|
+
forEach(callbackfn, thisArg) {
|
|
1946
|
+
super.forEach((v, i, a) => {
|
|
1947
|
+
callbackfn.call(thisArg, proxy.reactive(v), i, a);
|
|
1948
|
+
}, thisArg);
|
|
1949
|
+
}
|
|
1950
|
+
includes(searchElement, fromIndex) {
|
|
1951
|
+
return arguments.length > 1
|
|
1952
|
+
? super.includes(proxy.unwrap(searchElement), fromIndex)
|
|
1953
|
+
: super.includes(proxy.unwrap(searchElement));
|
|
1954
|
+
}
|
|
1955
|
+
indexOf(searchElement, fromIndex) {
|
|
1956
|
+
return arguments.length > 1
|
|
1957
|
+
? super.indexOf(proxy.unwrap(searchElement), fromIndex)
|
|
1958
|
+
: super.indexOf(proxy.unwrap(searchElement));
|
|
1959
|
+
}
|
|
1960
|
+
join(separator) {
|
|
1961
|
+
return super.join(separator);
|
|
1962
|
+
}
|
|
1963
|
+
keys() {
|
|
1964
|
+
proxy.dependant(this, 'length');
|
|
1965
|
+
return super.keys();
|
|
1966
|
+
}
|
|
1967
|
+
lastIndexOf(searchElement, fromIndex) {
|
|
1968
|
+
return arguments.length > 1
|
|
1969
|
+
? super.lastIndexOf(proxy.unwrap(searchElement), fromIndex)
|
|
1970
|
+
: super.lastIndexOf(proxy.unwrap(searchElement));
|
|
1971
|
+
}
|
|
1972
|
+
map(callbackfn, thisArg) {
|
|
1973
|
+
return proxy.reactive(super.map((v, i, a) => proxy.unwrap(callbackfn.call(thisArg, proxy.reactive(v), i, a)), thisArg));
|
|
1974
|
+
}
|
|
1975
|
+
pop() {
|
|
1976
|
+
return proxy.reactive(super.pop());
|
|
1977
|
+
}
|
|
1978
|
+
push(...items) {
|
|
1979
|
+
return super.push(...items.map(proxy.unwrap));
|
|
1980
|
+
}
|
|
1981
|
+
reduce(callbackfn, initialValue) {
|
|
1982
|
+
return proxy.reactive(arguments.length > 1
|
|
1983
|
+
? super.reduce((acc, v, i, a) => proxy.unwrap(callbackfn(acc, proxy.reactive(v), i, a)), initialValue)
|
|
1984
|
+
: super.reduce((acc, v, i, a) => proxy.unwrap(callbackfn(acc, proxy.reactive(v), i, a))));
|
|
1985
|
+
}
|
|
1986
|
+
reduceRight(callbackfn, initialValue) {
|
|
1987
|
+
return proxy.reactive(arguments.length > 1
|
|
1988
|
+
? super.reduceRight((acc, v, i, a) => proxy.unwrap(callbackfn(acc, proxy.reactive(v), i, a)), initialValue)
|
|
1989
|
+
: super.reduceRight((acc, v, i, a) => proxy.unwrap(callbackfn(acc, proxy.reactive(v), i, a))));
|
|
1990
|
+
}
|
|
1991
|
+
reverse() {
|
|
1992
|
+
return proxy.reactive(super.reverse());
|
|
1993
|
+
}
|
|
1994
|
+
shift() {
|
|
1995
|
+
return proxy.reactive(super.shift());
|
|
1996
|
+
}
|
|
1997
|
+
slice(start, end) {
|
|
1998
|
+
return proxy.reactive(super.slice(start, end));
|
|
2261
1999
|
}
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
}
|
|
2265
|
-
const fromIndex = typeof thisArg === 'number' ? thisArg : undefined;
|
|
2266
|
-
const index = this.indexOf(predicateOrElement, fromIndex);
|
|
2267
|
-
if (index === -1)
|
|
2268
|
-
return undefined;
|
|
2269
|
-
return debug.reactive(this[index]);
|
|
2270
|
-
}
|
|
2271
|
-
findIndex(predicateOrElement, thisArg) {
|
|
2272
|
-
if (typeof predicateOrElement === 'function') {
|
|
2273
|
-
const predicate = predicateOrElement;
|
|
2274
|
-
const length = this.length;
|
|
2275
|
-
for (let i = 0; i < length; i++) {
|
|
2276
|
-
debug.dependant(this, i);
|
|
2277
|
-
const val = debug.reactive(this[i]);
|
|
2278
|
-
if (predicate.call(thisArg, val, i, this)) {
|
|
2279
|
-
return i;
|
|
2280
|
-
}
|
|
2000
|
+
some(predicate, thisArg) {
|
|
2001
|
+
return super.some((v, i, a) => predicate.call(thisArg, proxy.reactive(v), i, a), thisArg);
|
|
2281
2002
|
}
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
}
|
|
2288
|
-
flat(depth) {
|
|
2289
|
-
debug.dependant(this);
|
|
2290
|
-
return debug.reactive(depth === undefined ? this.flat() : this.flat(depth));
|
|
2291
|
-
}
|
|
2292
|
-
flatMap(callbackfn, thisArg) {
|
|
2293
|
-
debug.dependant(this);
|
|
2294
|
-
return debug.reactive(this.flatMap((item, index, array) => callbackfn.call(thisArg, debug.reactive(item), index, array), thisArg));
|
|
2295
|
-
}
|
|
2296
|
-
filter(callbackfn, thisArg) {
|
|
2297
|
-
debug.dependant(this);
|
|
2298
|
-
return debug.reactive(this.filter((item, index, array) => callbackfn(debug.reactive(item), index, array), thisArg));
|
|
2299
|
-
}
|
|
2300
|
-
map(callbackfn, thisArg) {
|
|
2301
|
-
debug.dependant(this);
|
|
2302
|
-
return debug.reactive(this.map((item, index, array) => callbackfn(debug.reactive(item), index, array), thisArg));
|
|
2303
|
-
}
|
|
2304
|
-
reduce(callbackfn, initialValue) {
|
|
2305
|
-
debug.dependant(this);
|
|
2306
|
-
const result = initialValue === undefined
|
|
2307
|
-
? this.reduce(callbackfn)
|
|
2308
|
-
: this.reduce(callbackfn, initialValue);
|
|
2309
|
-
return debug.reactive(result);
|
|
2310
|
-
}
|
|
2311
|
-
reduceRight(callbackfn, initialValue) {
|
|
2312
|
-
debug.dependant(this);
|
|
2313
|
-
const result = initialValue !== undefined
|
|
2314
|
-
? this.reduceRight(callbackfn, initialValue)
|
|
2315
|
-
: this.reduceRight(callbackfn);
|
|
2316
|
-
return debug.reactive(result);
|
|
2317
|
-
}
|
|
2318
|
-
slice(start, end) {
|
|
2319
|
-
for (const i of range(start || 0, end || this.length - 1))
|
|
2320
|
-
debug.dependant(this, i);
|
|
2321
|
-
return start === undefined
|
|
2322
|
-
? this.slice()
|
|
2323
|
-
: end === undefined
|
|
2324
|
-
? this.slice(start)
|
|
2325
|
-
: this.slice(start, end);
|
|
2326
|
-
}
|
|
2327
|
-
concat(...items) {
|
|
2328
|
-
debug.dependant(this);
|
|
2329
|
-
return debug.reactive(this.concat(...items));
|
|
2330
|
-
}
|
|
2331
|
-
join(separator) {
|
|
2332
|
-
debug.dependant(this);
|
|
2333
|
-
return this.join(separator);
|
|
2334
|
-
}
|
|
2335
|
-
forEach(callbackfn, thisArg) {
|
|
2336
|
-
debug.dependant(this);
|
|
2337
|
-
this.forEach((value, index, array) => {
|
|
2338
|
-
callbackfn.call(thisArg, debug.reactive(value), index, array);
|
|
2339
|
-
});
|
|
2340
|
-
}
|
|
2341
|
-
every(callbackfn, thisArg) {
|
|
2342
|
-
const length = this.length;
|
|
2343
|
-
for (let i = 0; i < length; i++) {
|
|
2344
|
-
debug.dependant(this, i);
|
|
2345
|
-
if (!callbackfn.call(thisArg, debug.reactive(this[i]), i, this)) {
|
|
2346
|
-
return false;
|
|
2003
|
+
sort(compareFn) {
|
|
2004
|
+
const wrappedCompare = compareFn
|
|
2005
|
+
? (a, b) => compareFn(proxy.reactive(a), proxy.reactive(b))
|
|
2006
|
+
: undefined;
|
|
2007
|
+
return super.sort(wrappedCompare);
|
|
2347
2008
|
}
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
if (callbackfn.call(thisArg, debug.reactive(this[i]), i, this)) {
|
|
2357
|
-
return true;
|
|
2009
|
+
splice(start, deleteCount, ...items) {
|
|
2010
|
+
if (arguments.length > 2)
|
|
2011
|
+
return proxy.reactive(super.splice(start, deleteCount, ...items.map(proxy.unwrap)));
|
|
2012
|
+
if (arguments.length === 2)
|
|
2013
|
+
return proxy.reactive(super.splice(start, deleteCount));
|
|
2014
|
+
if (arguments.length === 1)
|
|
2015
|
+
return proxy.reactive(super.splice(start));
|
|
2016
|
+
return proxy.reactive([]);
|
|
2358
2017
|
}
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
return false;
|
|
2362
|
-
}
|
|
2363
|
-
// Side-effectful
|
|
2364
|
-
push(...items) {
|
|
2365
|
-
const oldLength = this.length;
|
|
2366
|
-
try {
|
|
2367
|
-
return this.push(...items);
|
|
2368
|
-
}
|
|
2369
|
-
finally {
|
|
2370
|
-
debug.touched(this, { type: 'bunch', method: 'push' }, range(oldLength, oldLength + items.length - 1, { length: true }));
|
|
2371
|
-
}
|
|
2372
|
-
}
|
|
2373
|
-
pop() {
|
|
2374
|
-
if (this.length === 0)
|
|
2375
|
-
return undefined;
|
|
2376
|
-
try {
|
|
2377
|
-
return debug.reactive(this.pop());
|
|
2378
|
-
}
|
|
2379
|
-
finally {
|
|
2380
|
-
debug.touched(this, { type: 'bunch', method: 'pop' }, index(this.length));
|
|
2381
|
-
}
|
|
2382
|
-
}
|
|
2383
|
-
shift() {
|
|
2384
|
-
if (this.length === 0)
|
|
2385
|
-
return undefined;
|
|
2386
|
-
try {
|
|
2387
|
-
return debug.reactive(this.shift());
|
|
2388
|
-
}
|
|
2389
|
-
finally {
|
|
2390
|
-
debug.touched(this, { type: 'bunch', method: 'shift' }, range(0, this.length + 1, { length: true }));
|
|
2391
|
-
}
|
|
2392
|
-
}
|
|
2393
|
-
unshift(...items) {
|
|
2394
|
-
try {
|
|
2395
|
-
return this.unshift(...items);
|
|
2396
|
-
}
|
|
2397
|
-
finally {
|
|
2398
|
-
debug.touched(this, { type: 'bunch', method: 'unshift' }, range(0, this.length - items.length, { length: true }));
|
|
2399
|
-
}
|
|
2400
|
-
}
|
|
2401
|
-
splice(start, deleteCount, ...items) {
|
|
2402
|
-
const oldLength = this.length;
|
|
2403
|
-
// Normalize start index
|
|
2404
|
-
let actualStart = start;
|
|
2405
|
-
if (actualStart < 0)
|
|
2406
|
-
actualStart = Math.max(oldLength + actualStart, 0);
|
|
2407
|
-
else
|
|
2408
|
-
actualStart = Math.min(actualStart, oldLength);
|
|
2409
|
-
// Normalize deleteCount
|
|
2410
|
-
let actualDeleteCount = deleteCount;
|
|
2411
|
-
if (actualDeleteCount === undefined) {
|
|
2412
|
-
actualDeleteCount = oldLength - actualStart;
|
|
2413
|
-
}
|
|
2414
|
-
else {
|
|
2415
|
-
actualDeleteCount = Math.max(0, Math.min(actualDeleteCount, oldLength - actualStart));
|
|
2416
|
-
}
|
|
2417
|
-
try {
|
|
2418
|
-
if (deleteCount === undefined)
|
|
2419
|
-
return debug.reactive(this.splice(start));
|
|
2420
|
-
return debug.reactive(this.splice(start, deleteCount, ...items));
|
|
2421
|
-
}
|
|
2422
|
-
finally {
|
|
2423
|
-
debug.touched(this, { type: 'bunch', method: 'splice' }, actualDeleteCount === items.length
|
|
2424
|
-
? range(actualStart, actualStart + actualDeleteCount - 1)
|
|
2425
|
-
: range(actualStart, oldLength + Math.max(items.length - actualDeleteCount, 0), {
|
|
2426
|
-
length: true,
|
|
2427
|
-
}));
|
|
2428
|
-
}
|
|
2429
|
-
}
|
|
2430
|
-
reverse() {
|
|
2431
|
-
try {
|
|
2432
|
-
return this.reverse();
|
|
2433
|
-
}
|
|
2434
|
-
finally {
|
|
2435
|
-
debug.touched(this, { type: 'bunch', method: 'reverse' }, range(0, this.length - 1));
|
|
2436
|
-
}
|
|
2437
|
-
}
|
|
2438
|
-
sort(compareFn) {
|
|
2439
|
-
compareFn = compareFn || ((a, b) => a.toString().localeCompare(b.toString()));
|
|
2440
|
-
try {
|
|
2441
|
-
return this.sort((a, b) => compareFn(debug.reactive(a), debug.reactive(b)));
|
|
2442
|
-
}
|
|
2443
|
-
finally {
|
|
2444
|
-
debug.touched(this, { type: 'bunch', method: 'sort' }, range(0, this.length - 1));
|
|
2445
|
-
}
|
|
2446
|
-
}
|
|
2447
|
-
fill(value, start, end) {
|
|
2448
|
-
const len = this.length;
|
|
2449
|
-
let k = start === undefined ? 0 : start;
|
|
2450
|
-
if (k < 0)
|
|
2451
|
-
k = Math.max(len + k, 0);
|
|
2452
|
-
else
|
|
2453
|
-
k = Math.min(k, len);
|
|
2454
|
-
let final = end === undefined ? len : end;
|
|
2455
|
-
if (final < 0)
|
|
2456
|
-
final = Math.max(len + final, 0);
|
|
2457
|
-
else
|
|
2458
|
-
final = Math.min(final, len);
|
|
2459
|
-
try {
|
|
2460
|
-
if (start === undefined)
|
|
2461
|
-
return this.fill(value);
|
|
2462
|
-
if (end === undefined)
|
|
2463
|
-
return this.fill(value, start);
|
|
2464
|
-
return this.fill(value, start, end);
|
|
2465
|
-
}
|
|
2466
|
-
finally {
|
|
2467
|
-
if (final > k) {
|
|
2468
|
-
debug.touched(this, { type: 'bunch', method: 'fill' }, range(k, final - 1));
|
|
2018
|
+
unshift(...items) {
|
|
2019
|
+
return super.unshift(...items.map(proxy.unwrap));
|
|
2469
2020
|
}
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
try {
|
|
2474
|
-
if (end === undefined)
|
|
2475
|
-
return this.copyWithin(target, start);
|
|
2476
|
-
return this.copyWithin(target, start, end);
|
|
2477
|
-
}
|
|
2478
|
-
finally {
|
|
2479
|
-
const len = this.length;
|
|
2480
|
-
let to = target;
|
|
2481
|
-
if (to < 0)
|
|
2482
|
-
to = Math.max(len + to, 0);
|
|
2483
|
-
else if (to >= len)
|
|
2484
|
-
to = len;
|
|
2485
|
-
let from = start;
|
|
2486
|
-
if (from < 0)
|
|
2487
|
-
from = Math.max(len + from, 0);
|
|
2488
|
-
else if (from >= len)
|
|
2489
|
-
from = len;
|
|
2490
|
-
let final = end === undefined ? len : end;
|
|
2491
|
-
if (final < 0)
|
|
2492
|
-
final = Math.max(len + final, 0);
|
|
2493
|
-
else if (final >= len)
|
|
2494
|
-
final = len;
|
|
2495
|
-
const count = Math.min(final - from, len - to);
|
|
2496
|
-
if (count > 0) {
|
|
2497
|
-
debug.touched(this, { type: 'bunch', method: 'copyWithin' }, range(to, to + count - 1));
|
|
2021
|
+
values() {
|
|
2022
|
+
proxy.dependant(this, proxy.keysOf);
|
|
2023
|
+
return makeReactiveIterator(super.values());
|
|
2498
2024
|
}
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2025
|
+
[(_fill_decorators = [proxy.atomic], _copyWithin_decorators = [proxy.atomic], _pop_decorators = [proxy.atomic], _push_decorators = [proxy.atomic], _reverse_decorators = [proxy.atomic], _shift_decorators = [proxy.atomic], _sort_decorators = [proxy.atomic], _splice_decorators = [proxy.atomic], _unshift_decorators = [proxy.atomic], Symbol.iterator)]() {
|
|
2026
|
+
proxy.dependant(this, proxy.keysOf);
|
|
2027
|
+
return makeReactiveIterator(super[Symbol.iterator]());
|
|
2028
|
+
}
|
|
2029
|
+
toReversed() {
|
|
2030
|
+
return proxy.reactive(super.toReversed());
|
|
2031
|
+
}
|
|
2032
|
+
toSorted(compareFn) {
|
|
2033
|
+
const wrappedCompare = compareFn
|
|
2034
|
+
? (a, b) => compareFn(proxy.reactive(a), proxy.reactive(b))
|
|
2035
|
+
: undefined;
|
|
2036
|
+
return proxy.reactive(super.toSorted(wrappedCompare));
|
|
2037
|
+
}
|
|
2038
|
+
toSpliced(start, deleteCount, ...items) {
|
|
2039
|
+
if (arguments.length > 2)
|
|
2040
|
+
return proxy.reactive(super.toSpliced(start, deleteCount, ...items.map(proxy.unwrap)));
|
|
2041
|
+
if (arguments.length === 2)
|
|
2042
|
+
return proxy.reactive(super.toSpliced(start, deleteCount));
|
|
2043
|
+
if (arguments.length === 1)
|
|
2044
|
+
return proxy.reactive(super.toSpliced(start));
|
|
2045
|
+
return proxy.reactive([...this]);
|
|
2046
|
+
}
|
|
2047
|
+
with(index, value) {
|
|
2048
|
+
return proxy.reactive(super.with(index, proxy.unwrap(value)));
|
|
2049
|
+
}
|
|
2050
|
+
constructor() {
|
|
2051
|
+
super(...arguments);
|
|
2052
|
+
proxy.__runInitializers(this, _instanceExtraInitializers);
|
|
2053
|
+
}
|
|
2054
|
+
},
|
|
2055
|
+
(() => {
|
|
2056
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
2057
|
+
proxy.__esDecorate(_a, null, _fill_decorators, { kind: "method", name: "fill", static: false, private: false, access: { has: obj => "fill" in obj, get: obj => obj.fill }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
2058
|
+
proxy.__esDecorate(_a, null, _copyWithin_decorators, { kind: "method", name: "copyWithin", static: false, private: false, access: { has: obj => "copyWithin" in obj, get: obj => obj.copyWithin }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
2059
|
+
proxy.__esDecorate(_a, null, _pop_decorators, { kind: "method", name: "pop", static: false, private: false, access: { has: obj => "pop" in obj, get: obj => obj.pop }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
2060
|
+
proxy.__esDecorate(_a, null, _push_decorators, { kind: "method", name: "push", static: false, private: false, access: { has: obj => "push" in obj, get: obj => obj.push }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
2061
|
+
proxy.__esDecorate(_a, null, _reverse_decorators, { kind: "method", name: "reverse", static: false, private: false, access: { has: obj => "reverse" in obj, get: obj => obj.reverse }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
2062
|
+
proxy.__esDecorate(_a, null, _shift_decorators, { kind: "method", name: "shift", static: false, private: false, access: { has: obj => "shift" in obj, get: obj => obj.shift }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
2063
|
+
proxy.__esDecorate(_a, null, _sort_decorators, { kind: "method", name: "sort", static: false, private: false, access: { has: obj => "sort" in obj, get: obj => obj.sort }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
2064
|
+
proxy.__esDecorate(_a, null, _splice_decorators, { kind: "method", name: "splice", static: false, private: false, access: { has: obj => "splice" in obj, get: obj => obj.splice }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
2065
|
+
proxy.__esDecorate(_a, null, _unshift_decorators, { kind: "method", name: "unshift", static: false, private: false, access: { has: obj => "unshift" in obj, get: obj => obj.unshift }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
2066
|
+
if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
2067
|
+
})(),
|
|
2068
|
+
_a;
|
|
2069
|
+
})();
|
|
2502
2070
|
|
|
2503
2071
|
/**
|
|
2504
2072
|
* Reactive wrapper around JavaScript's WeakMap class
|
|
@@ -2508,26 +2076,26 @@ class ReactiveWeakMap extends WeakMap {
|
|
|
2508
2076
|
// Implement WeakMap interface methods with reactivity
|
|
2509
2077
|
delete(key) {
|
|
2510
2078
|
const hadKey = this.has(key);
|
|
2511
|
-
const result =
|
|
2079
|
+
const result = super.delete(key);
|
|
2512
2080
|
if (hadKey)
|
|
2513
|
-
|
|
2081
|
+
proxy.touched1(proxy.contentRef(this), { type: 'del', prop: key }, key);
|
|
2514
2082
|
return result;
|
|
2515
2083
|
}
|
|
2516
2084
|
get(key) {
|
|
2517
|
-
|
|
2518
|
-
return
|
|
2085
|
+
proxy.dependant(proxy.contentRef(this), key);
|
|
2086
|
+
return proxy.reactive(super.get(key));
|
|
2519
2087
|
}
|
|
2520
2088
|
has(key) {
|
|
2521
|
-
|
|
2522
|
-
return
|
|
2089
|
+
proxy.dependant(proxy.contentRef(this), key);
|
|
2090
|
+
return super.has(key);
|
|
2523
2091
|
}
|
|
2524
2092
|
set(key, value) {
|
|
2525
2093
|
const hadKey = this.has(key);
|
|
2526
2094
|
const oldValue = this.get(key);
|
|
2527
|
-
const reactiveValue =
|
|
2095
|
+
const reactiveValue = proxy.reactive(value);
|
|
2528
2096
|
this.set(key, reactiveValue);
|
|
2529
2097
|
if (!hadKey || oldValue !== reactiveValue) {
|
|
2530
|
-
|
|
2098
|
+
proxy.notifyPropertyChange(proxy.contentRef(this), key, oldValue, reactiveValue, hadKey);
|
|
2531
2099
|
}
|
|
2532
2100
|
return this;
|
|
2533
2101
|
}
|
|
@@ -2539,37 +2107,39 @@ class ReactiveWeakMap extends WeakMap {
|
|
|
2539
2107
|
class ReactiveMap extends Map {
|
|
2540
2108
|
// Implement Map interface methods with reactivity
|
|
2541
2109
|
get size() {
|
|
2542
|
-
|
|
2543
|
-
return
|
|
2110
|
+
proxy.dependant(this, 'size'); // The ReactiveMap instance still goes through proxy
|
|
2111
|
+
return super.size;
|
|
2544
2112
|
}
|
|
2545
2113
|
clear() {
|
|
2546
2114
|
const hadEntries = this.size > 0;
|
|
2547
|
-
|
|
2115
|
+
super.clear();
|
|
2548
2116
|
if (hadEntries) {
|
|
2549
2117
|
const evolution = { type: 'bunch', method: 'clear' };
|
|
2550
2118
|
// Clear triggers all effects since all keys are affected
|
|
2551
|
-
|
|
2552
|
-
|
|
2119
|
+
proxy.batch(() => {
|
|
2120
|
+
proxy.touched1(this, evolution, 'size');
|
|
2121
|
+
proxy.touched(proxy.contentRef(this), evolution);
|
|
2122
|
+
});
|
|
2553
2123
|
}
|
|
2554
2124
|
}
|
|
2555
2125
|
entries() {
|
|
2556
|
-
|
|
2126
|
+
proxy.dependant(proxy.contentRef(this));
|
|
2557
2127
|
return makeReactiveEntriesIterator(this.entries());
|
|
2558
2128
|
}
|
|
2559
2129
|
forEach(callbackfn, thisArg) {
|
|
2560
|
-
|
|
2130
|
+
proxy.dependant(proxy.contentRef(this));
|
|
2561
2131
|
this.forEach(callbackfn, thisArg);
|
|
2562
2132
|
}
|
|
2563
2133
|
keys() {
|
|
2564
|
-
|
|
2134
|
+
proxy.dependant(proxy.contentRef(this), proxy.keysOf);
|
|
2565
2135
|
return this.keys();
|
|
2566
2136
|
}
|
|
2567
2137
|
values() {
|
|
2568
|
-
|
|
2138
|
+
proxy.dependant(proxy.contentRef(this));
|
|
2569
2139
|
return makeReactiveIterator(this.values());
|
|
2570
2140
|
}
|
|
2571
2141
|
[Symbol.iterator]() {
|
|
2572
|
-
|
|
2142
|
+
proxy.dependant(proxy.contentRef(this));
|
|
2573
2143
|
const it = Map.prototype[Symbol.iterator].call(this);
|
|
2574
2144
|
const nativeNext = it.next.bind(it);
|
|
2575
2145
|
it.next = () => {
|
|
@@ -2577,39 +2147,43 @@ class ReactiveMap extends Map {
|
|
|
2577
2147
|
if (result.done)
|
|
2578
2148
|
return result;
|
|
2579
2149
|
const [key, value] = result.value;
|
|
2580
|
-
return { value: [
|
|
2150
|
+
return { value: [proxy.reactive(key), proxy.reactive(value)], done: false };
|
|
2581
2151
|
};
|
|
2582
2152
|
return it;
|
|
2583
2153
|
}
|
|
2584
2154
|
// Implement Map methods with reactivity
|
|
2585
2155
|
delete(key) {
|
|
2586
2156
|
const hadKey = this.has(key);
|
|
2587
|
-
const result =
|
|
2157
|
+
const result = super.delete(key);
|
|
2588
2158
|
if (hadKey) {
|
|
2589
2159
|
const evolution = { type: 'del', prop: key };
|
|
2590
|
-
|
|
2591
|
-
|
|
2160
|
+
proxy.batch(() => {
|
|
2161
|
+
proxy.touched1(proxy.contentRef(this), evolution, key);
|
|
2162
|
+
proxy.touched1(this, evolution, 'size');
|
|
2163
|
+
});
|
|
2592
2164
|
}
|
|
2593
2165
|
return result;
|
|
2594
2166
|
}
|
|
2595
2167
|
get(key) {
|
|
2596
|
-
|
|
2597
|
-
return
|
|
2168
|
+
proxy.dependant(proxy.contentRef(this), key);
|
|
2169
|
+
return proxy.reactive(super.get(key));
|
|
2598
2170
|
}
|
|
2599
2171
|
has(key) {
|
|
2600
|
-
|
|
2601
|
-
return
|
|
2172
|
+
proxy.dependant(proxy.contentRef(this), key);
|
|
2173
|
+
return super.has(key);
|
|
2602
2174
|
}
|
|
2603
2175
|
set(key, value) {
|
|
2604
2176
|
const hadKey = this.has(key);
|
|
2605
2177
|
const oldValue = this.get(key);
|
|
2606
|
-
const reactiveValue =
|
|
2607
|
-
|
|
2178
|
+
const reactiveValue = proxy.reactive(value);
|
|
2179
|
+
super.set(key, reactiveValue);
|
|
2608
2180
|
if (!hadKey || oldValue !== reactiveValue) {
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2181
|
+
proxy.batch(() => {
|
|
2182
|
+
proxy.notifyPropertyChange(proxy.contentRef(this), key, oldValue, reactiveValue, hadKey);
|
|
2183
|
+
// Also notify size change for Map (WeakMap doesn't track size)
|
|
2184
|
+
const evolution = { type: hadKey ? 'set' : 'add', prop: key };
|
|
2185
|
+
proxy.touched1(this, evolution, 'size');
|
|
2186
|
+
});
|
|
2613
2187
|
}
|
|
2614
2188
|
return this;
|
|
2615
2189
|
}
|
|
@@ -2622,24 +2196,24 @@ class ReactiveMap extends Map {
|
|
|
2622
2196
|
class ReactiveWeakSet extends WeakSet {
|
|
2623
2197
|
add(value) {
|
|
2624
2198
|
const had = this.has(value);
|
|
2625
|
-
|
|
2199
|
+
super.add(value);
|
|
2626
2200
|
if (!had) {
|
|
2627
2201
|
// touch the specific value and the collection view
|
|
2628
|
-
|
|
2202
|
+
proxy.touched1(proxy.contentRef(this), { type: 'add', prop: value }, value);
|
|
2629
2203
|
// no size/allProps for WeakSet
|
|
2630
2204
|
}
|
|
2631
2205
|
return this;
|
|
2632
2206
|
}
|
|
2633
2207
|
delete(value) {
|
|
2634
2208
|
const had = this.has(value);
|
|
2635
|
-
const res =
|
|
2209
|
+
const res = super.delete(value);
|
|
2636
2210
|
if (had)
|
|
2637
|
-
|
|
2211
|
+
proxy.touched1(proxy.contentRef(this), { type: 'del', prop: value }, value);
|
|
2638
2212
|
return res;
|
|
2639
2213
|
}
|
|
2640
2214
|
has(value) {
|
|
2641
|
-
|
|
2642
|
-
return
|
|
2215
|
+
proxy.dependant(proxy.contentRef(this), value);
|
|
2216
|
+
return super.has(value);
|
|
2643
2217
|
}
|
|
2644
2218
|
}
|
|
2645
2219
|
/**
|
|
@@ -2649,93 +2223,99 @@ class ReactiveWeakSet extends WeakSet {
|
|
|
2649
2223
|
class ReactiveSet extends Set {
|
|
2650
2224
|
get size() {
|
|
2651
2225
|
// size depends on the wrapper instance, like Map counterpart
|
|
2652
|
-
|
|
2226
|
+
proxy.dependant(this, 'size');
|
|
2653
2227
|
return this.size;
|
|
2654
2228
|
}
|
|
2655
2229
|
add(value) {
|
|
2656
2230
|
const had = this.has(value);
|
|
2657
|
-
const reactiveValue =
|
|
2658
|
-
|
|
2231
|
+
const reactiveValue = proxy.reactive(value);
|
|
2232
|
+
super.add(reactiveValue);
|
|
2659
2233
|
if (!had) {
|
|
2660
2234
|
const evolution = { type: 'add', prop: reactiveValue };
|
|
2661
2235
|
// touch for value-specific and aggregate dependencies
|
|
2662
|
-
|
|
2663
|
-
|
|
2236
|
+
proxy.batch(() => {
|
|
2237
|
+
proxy.touched1(proxy.contentRef(this), evolution, reactiveValue);
|
|
2238
|
+
proxy.touched1(this, evolution, 'size');
|
|
2239
|
+
});
|
|
2664
2240
|
}
|
|
2665
2241
|
return this;
|
|
2666
2242
|
}
|
|
2667
2243
|
clear() {
|
|
2668
2244
|
const hadEntries = this.size > 0;
|
|
2669
|
-
|
|
2245
|
+
super.clear();
|
|
2670
2246
|
if (hadEntries) {
|
|
2671
2247
|
const evolution = { type: 'bunch', method: 'clear' };
|
|
2672
|
-
|
|
2673
|
-
|
|
2248
|
+
proxy.batch(() => {
|
|
2249
|
+
proxy.touched1(this, evolution, 'size');
|
|
2250
|
+
proxy.touched(proxy.contentRef(this), evolution);
|
|
2251
|
+
});
|
|
2674
2252
|
}
|
|
2675
2253
|
}
|
|
2676
2254
|
delete(value) {
|
|
2677
2255
|
const had = this.has(value);
|
|
2678
|
-
const res =
|
|
2256
|
+
const res = super.delete(value);
|
|
2679
2257
|
if (had) {
|
|
2680
2258
|
const evolution = { type: 'del', prop: value };
|
|
2681
|
-
|
|
2682
|
-
|
|
2259
|
+
proxy.batch(() => {
|
|
2260
|
+
proxy.touched1(proxy.contentRef(this), evolution, value);
|
|
2261
|
+
proxy.touched1(this, evolution, 'size');
|
|
2262
|
+
});
|
|
2683
2263
|
}
|
|
2684
2264
|
return res;
|
|
2685
2265
|
}
|
|
2686
2266
|
has(value) {
|
|
2687
|
-
|
|
2267
|
+
proxy.dependant(proxy.contentRef(this), value);
|
|
2688
2268
|
return this.has(value);
|
|
2689
2269
|
}
|
|
2690
2270
|
entries() {
|
|
2691
|
-
|
|
2271
|
+
proxy.dependant(proxy.contentRef(this));
|
|
2692
2272
|
return makeReactiveEntriesIterator(this.entries());
|
|
2693
2273
|
}
|
|
2694
2274
|
forEach(callbackfn, thisArg) {
|
|
2695
|
-
|
|
2275
|
+
proxy.dependant(proxy.contentRef(this));
|
|
2696
2276
|
this.forEach(callbackfn, thisArg);
|
|
2697
2277
|
}
|
|
2698
2278
|
keys() {
|
|
2699
|
-
|
|
2279
|
+
proxy.dependant(proxy.contentRef(this));
|
|
2700
2280
|
return makeReactiveIterator(this.keys());
|
|
2701
2281
|
}
|
|
2702
2282
|
values() {
|
|
2703
|
-
|
|
2283
|
+
proxy.dependant(proxy.contentRef(this));
|
|
2704
2284
|
return makeReactiveIterator(this.values());
|
|
2705
2285
|
}
|
|
2706
2286
|
[Symbol.iterator]() {
|
|
2707
|
-
|
|
2287
|
+
proxy.dependant(proxy.contentRef(this));
|
|
2708
2288
|
const it = Set.prototype[Symbol.iterator].call(this);
|
|
2709
2289
|
const nativeNext = it.next.bind(it);
|
|
2710
2290
|
it.next = () => {
|
|
2711
2291
|
const result = nativeNext();
|
|
2712
2292
|
if (result.done)
|
|
2713
2293
|
return result;
|
|
2714
|
-
return { value:
|
|
2294
|
+
return { value: proxy.reactive(result.value), done: false };
|
|
2715
2295
|
};
|
|
2716
2296
|
return it;
|
|
2717
2297
|
}
|
|
2718
2298
|
}
|
|
2719
2299
|
|
|
2720
2300
|
// Register native collection types to use specialized reactive wrappers
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2301
|
+
proxy.metaProtos.set(Array, ReactiveArray.prototype);
|
|
2302
|
+
proxy.metaProtos.set(Set, ReactiveSet.prototype);
|
|
2303
|
+
proxy.metaProtos.set(WeakSet, ReactiveWeakSet.prototype);
|
|
2304
|
+
proxy.metaProtos.set(Map, ReactiveMap.prototype);
|
|
2305
|
+
proxy.metaProtos.set(WeakMap, ReactiveWeakMap.prototype);
|
|
2306
|
+
proxy.wrapProtos.set(Array, ReactiveArrayWrapper.prototype);
|
|
2726
2307
|
/**
|
|
2727
2308
|
* Object containing internal reactive system state for debugging and profiling
|
|
2728
2309
|
*/
|
|
2729
2310
|
const profileInfo = {
|
|
2730
|
-
objectToProxy:
|
|
2731
|
-
proxyToObject:
|
|
2732
|
-
effectToReactiveObjects:
|
|
2733
|
-
watchers:
|
|
2734
|
-
objectParents:
|
|
2735
|
-
objectsWithDeepWatchers:
|
|
2736
|
-
deepWatchers:
|
|
2737
|
-
effectToDeepWatchedObjects:
|
|
2738
|
-
nonReactiveObjects: debug.nonReactiveObjects,
|
|
2311
|
+
objectToProxy: proxy.objectToProxy,
|
|
2312
|
+
proxyToObject: proxy.proxyToObject,
|
|
2313
|
+
effectToReactiveObjects: proxy.effectToReactiveObjects,
|
|
2314
|
+
watchers: proxy.watchers,
|
|
2315
|
+
objectParents: proxy.objectParents,
|
|
2316
|
+
objectsWithDeepWatchers: proxy.objectsWithDeepWatchers,
|
|
2317
|
+
deepWatchers: proxy.deepWatchers,
|
|
2318
|
+
effectToDeepWatchedObjects: proxy.effectToDeepWatchedObjects,
|
|
2739
2319
|
};
|
|
2740
2320
|
|
|
2741
2321
|
// In order to avoid async re-entrance, we could use zone.js or something like that.
|
|
@@ -2744,7 +2324,7 @@ const syncCalculating = [];
|
|
|
2744
2324
|
* Decorator that caches the result of a getter method and only recomputes when dependencies change
|
|
2745
2325
|
* Prevents circular dependencies and provides automatic cache invalidation
|
|
2746
2326
|
*/
|
|
2747
|
-
const cached =
|
|
2327
|
+
const cached = proxy.decorator({
|
|
2748
2328
|
getter(original, _target, propertyKey) {
|
|
2749
2329
|
return function () {
|
|
2750
2330
|
const alreadyCalculating = syncCalculating.findIndex((c) => c.object === this && c.prop === propertyKey);
|
|
@@ -2788,7 +2368,7 @@ function cache(object, propertyKey, value) {
|
|
|
2788
2368
|
* @param descriptor - The descriptor properties to apply
|
|
2789
2369
|
* @returns A class decorator that applies the descriptor to specified properties
|
|
2790
2370
|
*/
|
|
2791
|
-
const descriptor =
|
|
2371
|
+
const descriptor = proxy.flavored(function descriptor(descriptor) {
|
|
2792
2372
|
return (...properties) => (Base) => {
|
|
2793
2373
|
return class extends Base {
|
|
2794
2374
|
constructor(...args) {
|
|
@@ -2842,7 +2422,7 @@ const descriptor = debug.flavored(function descriptor(descriptor) {
|
|
|
2842
2422
|
* Decorator that marks methods, properties, or classes as deprecated
|
|
2843
2423
|
* Provides warning messages when deprecated items are used
|
|
2844
2424
|
*/
|
|
2845
|
-
const deprecated = Object.assign(
|
|
2425
|
+
const deprecated = Object.assign(proxy.decorator({
|
|
2846
2426
|
method(original, _target, propertyKey) {
|
|
2847
2427
|
return function (...args) {
|
|
2848
2428
|
deprecated.warn(this, propertyKey);
|
|
@@ -2870,7 +2450,7 @@ const deprecated = Object.assign(debug.decorator({
|
|
|
2870
2450
|
};
|
|
2871
2451
|
},
|
|
2872
2452
|
default(message) {
|
|
2873
|
-
return
|
|
2453
|
+
return proxy.decorator({
|
|
2874
2454
|
method(original, _target, propertyKey) {
|
|
2875
2455
|
return function (...args) {
|
|
2876
2456
|
deprecated.warn(this, propertyKey, message);
|
|
@@ -2901,8 +2481,7 @@ const deprecated = Object.assign(debug.decorator({
|
|
|
2901
2481
|
},
|
|
2902
2482
|
}), {
|
|
2903
2483
|
warn: (target, propertyKey, message) => {
|
|
2904
|
-
|
|
2905
|
-
console.warn(`${target.constructor.name}.${String(propertyKey)} is deprecated${message ? `: ${message}` : ''}`);
|
|
2484
|
+
proxy.options.warn(`${target.constructor.name}.${String(propertyKey)} is deprecated${message ? `: ${message}` : ''}`);
|
|
2906
2485
|
},
|
|
2907
2486
|
});
|
|
2908
2487
|
/**
|
|
@@ -2911,7 +2490,7 @@ const deprecated = Object.assign(debug.decorator({
|
|
|
2911
2490
|
* @returns A method decorator that debounces method calls
|
|
2912
2491
|
*/
|
|
2913
2492
|
function debounce(delay) {
|
|
2914
|
-
return
|
|
2493
|
+
return proxy.decorator({
|
|
2915
2494
|
method(original, _target, _propertyKey) {
|
|
2916
2495
|
let timeoutId = null;
|
|
2917
2496
|
return function (...args) {
|
|
@@ -2934,7 +2513,7 @@ function debounce(delay) {
|
|
|
2934
2513
|
* @returns A method decorator that throttles method calls
|
|
2935
2514
|
*/
|
|
2936
2515
|
function throttle(delay) {
|
|
2937
|
-
return
|
|
2516
|
+
return proxy.decorator({
|
|
2938
2517
|
method(original, _target, _propertyKey) {
|
|
2939
2518
|
let lastCallTime = 0;
|
|
2940
2519
|
let timeoutId = null;
|
|
@@ -2965,12 +2544,11 @@ function throttle(delay) {
|
|
|
2965
2544
|
});
|
|
2966
2545
|
}
|
|
2967
2546
|
|
|
2968
|
-
var version$1 = "1.0.
|
|
2547
|
+
var version$1 = "1.0.11";
|
|
2969
2548
|
var pkg = {
|
|
2970
2549
|
version: version$1};
|
|
2971
2550
|
|
|
2972
2551
|
const { version } = pkg;
|
|
2973
|
-
// Singleton verification
|
|
2974
2552
|
const GLOBAL_MUTTS_KEY = '__MUTTS_INSTANCE__';
|
|
2975
2553
|
const globalScope = (typeof globalThis !== 'undefined'
|
|
2976
2554
|
? globalThis
|
|
@@ -2980,27 +2558,16 @@ const globalScope = (typeof globalThis !== 'undefined'
|
|
|
2980
2558
|
? global
|
|
2981
2559
|
: false);
|
|
2982
2560
|
if (globalScope) {
|
|
2983
|
-
// Detect the source of this instance safely across different environments
|
|
2984
2561
|
let source = 'mutts/index';
|
|
2985
|
-
const viteEval = eval;
|
|
2986
2562
|
try {
|
|
2987
2563
|
if (typeof __filename !== 'undefined')
|
|
2988
2564
|
source = __filename;
|
|
2989
|
-
else {
|
|
2990
|
-
|
|
2991
|
-
const meta = viteEval('import.meta');
|
|
2992
|
-
if (meta && meta.url)
|
|
2993
|
-
source = meta.url;
|
|
2565
|
+
else if (typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('browser.cjs', document.baseURI).href)) }) !== 'undefined' && (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('browser.cjs', document.baseURI).href))) {
|
|
2566
|
+
source = (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('browser.cjs', document.baseURI).href));
|
|
2994
2567
|
}
|
|
2995
2568
|
}
|
|
2996
|
-
catch (
|
|
2997
|
-
|
|
2998
|
-
}
|
|
2999
|
-
const currentSourceInfo = {
|
|
3000
|
-
version,
|
|
3001
|
-
source,
|
|
3002
|
-
timestamp: Date.now(),
|
|
3003
|
-
};
|
|
2569
|
+
catch (_e) { }
|
|
2570
|
+
const currentSourceInfo = { version, source, timestamp: Date.now() };
|
|
3004
2571
|
if (globalScope[GLOBAL_MUTTS_KEY]) {
|
|
3005
2572
|
const existing = globalScope[GLOBAL_MUTTS_KEY];
|
|
3006
2573
|
throw new Error(`[Mutts] Multiple instances detected!\n` +
|
|
@@ -3013,63 +2580,70 @@ if (globalScope) {
|
|
|
3013
2580
|
globalScope[GLOBAL_MUTTS_KEY] = currentSourceInfo;
|
|
3014
2581
|
}
|
|
3015
2582
|
|
|
3016
|
-
exports.AZone =
|
|
3017
|
-
exports.DecoratorError =
|
|
3018
|
-
exports.
|
|
3019
|
-
exports.
|
|
3020
|
-
exports.
|
|
3021
|
-
exports.
|
|
3022
|
-
exports.ReactiveError = debug.ReactiveError;
|
|
2583
|
+
exports.AZone = proxy.AZone;
|
|
2584
|
+
exports.DecoratorError = proxy.DecoratorError;
|
|
2585
|
+
exports.IterableWeakMap = proxy.IterableWeakMap;
|
|
2586
|
+
exports.IterableWeakSet = proxy.IterableWeakSet;
|
|
2587
|
+
exports.ReactiveBase = proxy.ReactiveBase;
|
|
2588
|
+
exports.ReactiveError = proxy.ReactiveError;
|
|
3023
2589
|
Object.defineProperty(exports, "ReactiveErrorCode", {
|
|
3024
2590
|
enumerable: true,
|
|
3025
|
-
get: function () { return
|
|
2591
|
+
get: function () { return proxy.ReactiveErrorCode; }
|
|
3026
2592
|
});
|
|
3027
|
-
exports.Zone =
|
|
3028
|
-
exports.ZoneAggregator =
|
|
3029
|
-
exports.ZoneHistory =
|
|
3030
|
-
exports.addBatchCleanup =
|
|
3031
|
-
exports.
|
|
3032
|
-
exports.
|
|
3033
|
-
exports.
|
|
3034
|
-
exports.
|
|
3035
|
-
exports.
|
|
3036
|
-
exports.
|
|
3037
|
-
exports.
|
|
3038
|
-
exports.
|
|
3039
|
-
exports.
|
|
3040
|
-
exports.
|
|
3041
|
-
exports.
|
|
3042
|
-
exports.
|
|
3043
|
-
exports.
|
|
3044
|
-
exports.
|
|
3045
|
-
exports.
|
|
3046
|
-
exports.
|
|
3047
|
-
exports.
|
|
3048
|
-
exports.
|
|
3049
|
-
exports.
|
|
3050
|
-
exports.
|
|
3051
|
-
exports.
|
|
3052
|
-
exports.
|
|
3053
|
-
exports.
|
|
3054
|
-
exports.
|
|
3055
|
-
exports.
|
|
3056
|
-
exports.
|
|
3057
|
-
exports.
|
|
3058
|
-
exports.
|
|
3059
|
-
exports.
|
|
3060
|
-
exports.
|
|
3061
|
-
exports.
|
|
3062
|
-
exports.
|
|
3063
|
-
exports.
|
|
3064
|
-
exports.
|
|
3065
|
-
exports.
|
|
3066
|
-
exports.
|
|
3067
|
-
exports.
|
|
3068
|
-
exports.
|
|
3069
|
-
exports.
|
|
3070
|
-
exports.
|
|
3071
|
-
exports.
|
|
3072
|
-
exports.
|
|
2593
|
+
exports.Zone = proxy.Zone;
|
|
2594
|
+
exports.ZoneAggregator = proxy.ZoneAggregator;
|
|
2595
|
+
exports.ZoneHistory = proxy.ZoneHistory;
|
|
2596
|
+
exports.addBatchCleanup = proxy.addBatchCleanup;
|
|
2597
|
+
exports.addUnreactiveProps = proxy.addUnreactiveProps;
|
|
2598
|
+
exports.arrayEquals = proxy.arrayEquals;
|
|
2599
|
+
exports.assertUntracked = proxy.assertUntracked;
|
|
2600
|
+
exports.asyncZone = proxy.asyncZone;
|
|
2601
|
+
exports.atom = proxy.atom;
|
|
2602
|
+
exports.atomic = proxy.atomic;
|
|
2603
|
+
exports.biDi = proxy.biDi;
|
|
2604
|
+
exports.captured = proxy.captured;
|
|
2605
|
+
exports.caught = proxy.caught;
|
|
2606
|
+
exports.createFlavor = proxy.createFlavor;
|
|
2607
|
+
exports.debugPreset = proxy.debugPreset;
|
|
2608
|
+
exports.decorator = proxy.decorator;
|
|
2609
|
+
exports.deepCompare = proxy.deepCompare;
|
|
2610
|
+
exports.defer = proxy.defer;
|
|
2611
|
+
exports.devPreset = proxy.devPreset;
|
|
2612
|
+
exports.effect = proxy.effect;
|
|
2613
|
+
exports.effectAggregator = proxy.effectAggregator;
|
|
2614
|
+
exports.flavorOptions = proxy.flavorOptions;
|
|
2615
|
+
exports.flavored = proxy.flavored;
|
|
2616
|
+
exports.formatCleanupReason = proxy.formatCleanupReason;
|
|
2617
|
+
exports.getActivationLog = proxy.getActivationLog;
|
|
2618
|
+
exports.getActiveEffect = proxy.getActiveEffect;
|
|
2619
|
+
exports.getState = proxy.getState;
|
|
2620
|
+
exports.isConstructor = proxy.isConstructor;
|
|
2621
|
+
exports.isDev = proxy.isDev;
|
|
2622
|
+
exports.isNonReactive = proxy.isNonReactive;
|
|
2623
|
+
exports.isObject = proxy.isObject;
|
|
2624
|
+
exports.isProd = proxy.isProd;
|
|
2625
|
+
exports.isReactive = proxy.isReactive;
|
|
2626
|
+
exports.isTest = proxy.isTest;
|
|
2627
|
+
exports.legacyDecorator = proxy.legacyDecorator;
|
|
2628
|
+
exports.link = proxy.link;
|
|
2629
|
+
exports.mixin = proxy.mixin;
|
|
2630
|
+
exports.modernDecorator = proxy.modernDecorator;
|
|
2631
|
+
exports.named = proxy.named;
|
|
2632
|
+
exports.objectToProxy = proxy.objectToProxy;
|
|
2633
|
+
exports.onEffectThrow = proxy.onEffectThrow;
|
|
2634
|
+
exports.prodPreset = proxy.prodPreset;
|
|
2635
|
+
exports.proxyToObject = proxy.proxyToObject;
|
|
2636
|
+
exports.reactive = proxy.reactive;
|
|
2637
|
+
exports.reactiveOptions = proxy.options;
|
|
2638
|
+
exports.reset = proxy.reset;
|
|
2639
|
+
exports.root = proxy.root;
|
|
2640
|
+
exports.tag = proxy.tag;
|
|
2641
|
+
exports.touched = proxy.touched;
|
|
2642
|
+
exports.touched1 = proxy.touched1;
|
|
2643
|
+
exports.unlink = proxy.unlink;
|
|
2644
|
+
exports.untracked = proxy.untracked;
|
|
2645
|
+
exports.unwrap = proxy.unwrap;
|
|
2646
|
+
exports.zip = proxy.zip;
|
|
3073
2647
|
exports.asyncHook = asyncCore.asyncHook;
|
|
3074
2648
|
exports.asyncHooks = asyncCore.asyncHooks;
|
|
3075
2649
|
exports.hooks = asyncCore.hooks;
|
|
@@ -3078,9 +2652,9 @@ exports.Destroyable = Destroyable;
|
|
|
3078
2652
|
exports.DestructionError = DestructionError;
|
|
3079
2653
|
exports.Eventful = Eventful;
|
|
3080
2654
|
exports.Indexable = Indexable;
|
|
3081
|
-
exports.Register = Register;
|
|
3082
2655
|
exports.allocated = allocated;
|
|
3083
2656
|
exports.allocatedValues = allocatedValues;
|
|
2657
|
+
exports.arrayDiff = arrayDiff;
|
|
3084
2658
|
exports.attend = attend;
|
|
3085
2659
|
exports.cache = cache;
|
|
3086
2660
|
exports.cached = cached;
|
|
@@ -3089,23 +2663,22 @@ exports.chainPromise = chainPromise;
|
|
|
3089
2663
|
exports.debounce = debounce;
|
|
3090
2664
|
exports.deepWatch = deepWatch;
|
|
3091
2665
|
exports.deprecated = deprecated;
|
|
3092
|
-
exports.describe = describe;
|
|
3093
2666
|
exports.descriptor = descriptor;
|
|
3094
2667
|
exports.destructor = destructor;
|
|
3095
2668
|
exports.forwardArray = forwardArray;
|
|
3096
|
-
exports.getActiveProjection = getActiveProjection;
|
|
3097
2669
|
exports.getAt = getAt;
|
|
3098
2670
|
exports.isCached = isCached;
|
|
3099
2671
|
exports.lift = lift;
|
|
3100
2672
|
exports.memoize = memoize;
|
|
2673
|
+
exports.morph = morph;
|
|
3101
2674
|
exports.organize = organize;
|
|
3102
2675
|
exports.organized = organized;
|
|
3103
2676
|
exports.profileInfo = profileInfo;
|
|
3104
|
-
exports.project =
|
|
3105
|
-
exports.
|
|
3106
|
-
exports.scan = scan;
|
|
2677
|
+
exports.project = morph;
|
|
2678
|
+
exports.resource = resource;
|
|
3107
2679
|
exports.setAt = setAt;
|
|
3108
2680
|
exports.throttle = throttle;
|
|
3109
2681
|
exports.unreactive = unreactive;
|
|
3110
2682
|
exports.watch = watch;
|
|
2683
|
+
exports.when = when;
|
|
3111
2684
|
//# sourceMappingURL=browser.cjs.map
|