mutts 1.0.10 → 1.0.12

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.
Files changed (61) hide show
  1. package/README.md +3 -3
  2. package/dist/browser.cjs +244 -3199
  3. package/dist/browser.cjs.map +1 -1
  4. package/dist/browser.d.ts +2 -2
  5. package/dist/browser.dev.cjs +51 -50
  6. package/dist/browser.dev.cjs.map +1 -1
  7. package/dist/browser.dev.d.ts +2 -2
  8. package/dist/browser.dev.esm.js +2 -2
  9. package/dist/browser.esm.js +15 -13
  10. package/dist/browser.esm.js.map +1 -1
  11. package/dist/chunks/{index-CaaQQlPJ.esm.js → index-BUop6B2U.esm.js} +384 -981
  12. package/dist/chunks/index-BUop6B2U.esm.js.map +1 -0
  13. package/dist/chunks/index-yK0HVxHv.cjs +2612 -0
  14. package/dist/chunks/index-yK0HVxHv.cjs.map +1 -0
  15. package/dist/chunks/{node-nKJBk8iJ.esm.js → node-Bo7WU5S2.esm.js} +2 -2
  16. package/dist/chunks/{node-nKJBk8iJ.esm.js.map → node-Bo7WU5S2.esm.js.map} +1 -1
  17. package/dist/chunks/{async-node-3PrbVAbB.cjs → node-Dd0esp5F.cjs} +4 -4
  18. package/dist/chunks/node-Dd0esp5F.cjs.map +1 -0
  19. package/dist/chunks/{proxy-Dtg-bJ3T.cjs → proxy-BvM4yewA.cjs} +441 -342
  20. package/dist/chunks/proxy-BvM4yewA.cjs.map +1 -0
  21. package/dist/chunks/{proxy-r7lARftl.esm.js → proxy-D2C49sXH.esm.js} +401 -330
  22. package/dist/chunks/proxy-D2C49sXH.esm.js.map +1 -0
  23. package/dist/debug.cjs +17 -4
  24. package/dist/debug.cjs.map +1 -1
  25. package/dist/debug.d.ts +2 -2
  26. package/dist/debug.esm.js +17 -3
  27. package/dist/debug.esm.js.map +1 -1
  28. package/dist/index.d.ts +84 -209
  29. package/dist/mutts.umd.js +842 -1362
  30. package/dist/mutts.umd.js.map +1 -1
  31. package/dist/mutts.umd.min.js +1 -1
  32. package/dist/mutts.umd.min.js.map +1 -1
  33. package/dist/node.cjs +51 -49
  34. package/dist/node.cjs.map +1 -1
  35. package/dist/node.d.ts +2 -2
  36. package/dist/node.dev.cjs +51 -49
  37. package/dist/node.dev.cjs.map +1 -1
  38. package/dist/node.dev.d.ts +2 -2
  39. package/dist/node.dev.esm.js +3 -3
  40. package/dist/node.esm.js +3 -3
  41. package/dist/{types-W5vD6m2n.d.ts → types-Bx2PhORg.d.ts} +38 -47
  42. package/docs/ai/api-reference.md +0 -14
  43. package/docs/ai/manual.md +2 -22
  44. package/docs/reactive/advanced.md +13 -14
  45. package/docs/reactive/attend.md +1 -2
  46. package/docs/reactive/collections.md +2 -149
  47. package/docs/reactive/core.md +218 -96
  48. package/docs/reactive/debugging.md +2 -2
  49. package/docs/reactive/resource.md +1 -1
  50. package/docs/reactive.md +1 -3
  51. package/docs/zone.md +1 -1
  52. package/package.json +18 -9
  53. package/dist/chunks/async-browser-BU_IfxYD.cjs +0 -216
  54. package/dist/chunks/async-browser-BU_IfxYD.cjs.map +0 -1
  55. package/dist/chunks/async-core-CRLKP3l-.cjs +0 -29
  56. package/dist/chunks/async-core-CRLKP3l-.cjs.map +0 -1
  57. package/dist/chunks/async-node-3PrbVAbB.cjs.map +0 -1
  58. package/dist/chunks/index-CaaQQlPJ.esm.js.map +0 -1
  59. package/dist/chunks/proxy-Dtg-bJ3T.cjs.map +0 -1
  60. package/dist/chunks/proxy-r7lARftl.esm.js.map +0 -1
  61. package/docs/reactive/scan.md +0 -324
package/dist/browser.cjs CHANGED
@@ -1,3179 +1,220 @@
1
1
  'use strict';
2
2
 
3
- require('./chunks/async-browser-BU_IfxYD.cjs');
4
- var proxy = require('./chunks/proxy-Dtg-bJ3T.cjs');
5
- var asyncCore = require('./chunks/async-core-CRLKP3l-.cjs');
6
- require('./chunks/async-node-3PrbVAbB.cjs');
7
- require('node:async_hooks');
3
+ var proxy = require('./chunks/proxy-BvM4yewA.cjs');
4
+ var index = require('./chunks/index-yK0HVxHv.cjs');
8
5
 
9
- // Integrated with `using` statement via Symbol.dispose
10
- const fr = new FinalizationRegistry((f) => f());
11
- /**
12
- * Symbol for marking destructor methods
13
- */
14
- const destructor = Symbol('destructor');
15
- /**
16
- * Symbol for accessing allocated values in destroyable objects
17
- */
18
- const allocatedValues = Symbol('allocated');
19
- /**
20
- * Error thrown when attempting to access a destroyed object
21
- */
22
- class DestructionError extends Error {
23
- static throw(msg) {
24
- return () => {
25
- throw new DestructionError(msg);
26
- };
27
- }
28
- constructor(msg) {
29
- super(`Object is destroyed. ${msg}`);
30
- this.name = 'DestroyedAccessError';
6
+ const promiseContexts = new WeakMap();
7
+ // [HACK]: Sanitization
8
+ // If a Promise is created inside the zone, it carries the "Sticky" zone context.
9
+ // If returned to the outer scope, that context leaks. We wrap it in a new Promise
10
+ // created here (in the outer scope) to break the chain and sanitize the return value.
11
+ // See BROWSER_ASYNC_POLYFILL.md for full details.
12
+ proxy.asyncHooks.sanitizePromise = (res) => {
13
+ if (res && typeof res.then === 'function') {
14
+ return new Promise((resolve, reject) => {
15
+ setTimeout(() => {
16
+ res.then(resolve, reject);
17
+ }, 0);
18
+ });
31
19
  }
32
- }
33
- const destroyedHandler = {
34
- [Symbol.toStringTag]: 'MutTs Destroyable',
35
- get: DestructionError.throw('Cannot access destroyed object'),
36
- set: DestructionError.throw('Cannot access destroyed object'),
20
+ return res;
37
21
  };
38
- function Destroyable(base, destructorObj) {
39
- var _a;
40
- if (base && typeof base !== 'function') {
41
- destructorObj = base;
42
- base = undefined;
43
- }
44
- if (!base) {
45
- base = class {
46
- };
47
- }
48
- return _a = class Destroyable extends base {
49
- static destroy(obj) {
50
- const destructor = _a.destructors.get(obj);
51
- if (!destructor)
52
- return false;
53
- fr.unregister(obj[allocatedValues]);
54
- _a.destructors.delete(obj);
55
- Object.setPrototypeOf(obj, new Proxy({}, destroyedHandler));
56
- // Clear all own properties
57
- for (const key of Object.getOwnPropertyNames(obj)) {
58
- delete obj[key];
59
- }
60
- destructor();
61
- return true;
62
- }
63
- static isDestroyable(obj) {
64
- return _a.destructors.has(obj);
65
- }
66
- constructor(...args) {
67
- super(...args);
68
- const allocated = {};
69
- this[allocatedValues] = allocated;
70
- // @ts-expect-error `this` is an AbstractDestroyable
71
- const myDestructor = destructorObj?.destructor ?? this[destructor];
72
- if (!myDestructor) {
73
- throw new DestructionError('Destructor is not defined');
74
- }
75
- function destruction() {
76
- myDestructor(allocated);
77
- }
78
- _a.destructors.set(this, destruction);
79
- fr.register(this, destruction, allocated);
80
- }
81
- },
82
- _a.destructors = new WeakMap(),
83
- _a;
84
- }
85
- /**
86
- * Decorator that marks properties to be stored in the allocated object and passed to the destructor
87
- * Use with accessor properties or explicit get/set pairs
88
- */
89
- const allocated = proxy.decorator({
90
- setter(original, _target, propertyKey) {
91
- return function (value) {
92
- this[allocatedValues][propertyKey] = value;
93
- return original.call(this, value);
94
- };
95
- },
96
- });
97
- /**
98
- * Registers a callback to be called when an object is garbage collected
99
- * @param cb - The callback function to execute on garbage collection
100
- * @returns The object whose reference can be collected
101
- */
102
- function callOnGC(cb) {
103
- let called = false;
104
- const forward = () => {
105
- if (called)
106
- return;
107
- called = true;
108
- cb();
109
- };
110
- fr.register(forward, cb, cb);
111
- return forward;
112
- }
113
-
114
- /** Max edit distance before bailing out to a single "replace all" patch */
115
- const BAILOUT_D = 256;
116
- /**
117
- * Myers' diff producing grouped patches: `{indexA, indexB, sliceA, sliceB}[]`.
118
- * - O(N) for identical or prefix/suffix-only differences
119
- * - O(ND) for small D, with a hard bailout at D=BAILOUT_D → single replacement patch
120
- */
121
- function arrayDiff(A, B) {
122
- let start = 0;
123
- let endA = A.length;
124
- let endB = B.length;
125
- // Trim common prefix
126
- while (start < endA && start < endB && A[start] === B[start])
127
- start++;
128
- // Trim common suffix
129
- while (endA > start && endB > start && A[endA - 1] === B[endB - 1]) {
130
- endA--;
131
- endB--;
132
- }
133
- const lenA = endA - start;
134
- const lenB = endB - start;
135
- if (lenA === 0 && lenB === 0)
136
- return [];
137
- if (lenA === 0)
138
- return [{ indexA: start, indexB: start, sliceA: [], sliceB: B.slice(start, endB) }];
139
- if (lenB === 0)
140
- return [{ indexA: start, indexB: start, sliceA: A.slice(start, endA), sliceB: [] }];
141
- // Myers with bailout
142
- const maxD = Math.min(lenA + lenB, BAILOUT_D);
143
- const vSize = 2 * maxD + 1;
144
- const vOffset = maxD;
145
- const V = new Int32Array(vSize);
146
- V[vOffset + 1] = 0;
147
- const history = [];
148
- for (let d = 0; d <= maxD; d++) {
149
- for (let k = -d; k <= d; k += 2) {
150
- let x;
151
- if (k === -d || (k !== d && V[vOffset + k - 1] < V[vOffset + k + 1])) {
152
- x = V[vOffset + k + 1];
153
- }
154
- else {
155
- x = V[vOffset + k - 1] + 1;
156
- }
157
- let y = x - k;
158
- while (x < lenA && y < lenB && A[start + x] === B[start + y]) {
159
- x++;
160
- y++;
161
- }
162
- V[vOffset + k] = x;
163
- if (x >= lenA && y >= lenB)
164
- return buildPatches(history, A, B, start, x, y, d, k, vOffset);
165
- }
166
- history.push(new Int32Array(V));
167
- }
168
- // Bailout: too many differences
169
- return [
170
- { indexA: start, indexB: start, sliceA: A.slice(start, endA), sliceB: B.slice(start, endB) },
171
- ];
172
- }
173
- function buildPatches(history, A, B, offset, finalX, finalY, finalD, finalK, vOffset) {
174
- // Backtrack from (finalX, finalY) at step finalD to step 0, collecting ops in reverse
175
- const ops = []; // 0=eq, 1=ins, 2=del
176
- let x = finalX;
177
- let y = finalY;
178
- let k = finalK;
179
- for (let d = finalD; d > 0; d--) {
180
- const prev = history[d - 1];
181
- let prevK;
182
- let down;
183
- if (k === -d) {
184
- prevK = k + 1;
185
- down = true;
186
- }
187
- else if (k === d) {
188
- prevK = k - 1;
189
- down = false;
190
- }
191
- else if (prev[vOffset + k - 1] < prev[vOffset + k + 1]) {
192
- prevK = k + 1;
193
- down = true;
194
- }
195
- else {
196
- prevK = k - 1;
197
- down = false;
198
- }
199
- const prevXEnd = prev[vOffset + prevK];
200
- const prevYEnd = prevXEnd - prevK;
201
- const xStart = down ? prevXEnd : prevXEnd + 1;
202
- const yStart = down ? prevYEnd + 1 : prevXEnd + 1 - k;
203
- // Diagonal matches (pushed in reverse)
204
- while (x > xStart && y > yStart) {
205
- ops.push(0);
206
- x--;
207
- y--;
208
- }
209
- // The edit step
210
- if (down) {
211
- ops.push(1); // ins
212
- y--;
213
- }
214
- else {
215
- ops.push(2); // del
216
- x--;
217
- }
218
- k = prevK;
219
- }
220
- // Walk ops forward (they were pushed in reverse), grouping contiguous edits
221
- const patches = [];
222
- let currA = offset;
223
- let currB = offset;
224
- let sliceA = [];
225
- let sliceB = [];
226
- let patchA = -1;
227
- let patchB = -1;
228
- const flush = () => {
229
- if (patchA !== -1) {
230
- patches.push({ indexA: patchA, indexB: patchB, sliceA, sliceB });
231
- sliceA = [];
232
- sliceB = [];
233
- patchA = -1;
22
+ function captureRestorers() {
23
+ const restorers = new Set();
24
+ for (const hook of proxy.hooks) {
25
+ const restorer = hook();
26
+ if (restorer)
27
+ restorers.add(restorer);
28
+ }
29
+ return restorers;
30
+ }
31
+ function wrap(fn, capturedRestorers) {
32
+ if (typeof fn !== 'function')
33
+ return fn;
34
+ const restorers = capturedRestorers || captureRestorers();
35
+ return function (...args) {
36
+ const undoers = [];
37
+ for (const restore of restorers)
38
+ undoers.push(restore());
39
+ try {
40
+ return fn.apply(this, args);
41
+ }
42
+ finally {
43
+ /* cf BROWSER_ASYNC_POLYFILL.md
44
+ // Note: my fear about this code: in between 2~3~4 microtask waits, some other microtasks might have started, stopped, ...
45
+ // We might be in the middle of another promise hook trying to setup the zone
46
+ // TODO We might wish to have a flag :asyncZone.acquired - like a semaphore - that we falsify here and set back when we setup the zone
47
+ // - but this might perhaps be an overkill creating more problems than it solves
48
+ if (originals.queueMicrotask) {
49
+ // Double microtask ensures we run after the first await resumption microtask
50
+ originals.queueMicrotask.call(globalThis, () => {
51
+ originals.queueMicrotask.call(globalThis, () => {
52
+ originals.queueMicrotask.call(globalThis, () => {
53
+ for (let i = undoers.length - 1; i >= 0; i--) undoers[i]()
54
+ })
55
+ })
56
+ })
57
+ } else {
58
+ for (let i = undoers.length - 1; i >= 0; i--) undoers[i]()
59
+ }*/
234
60
  }
235
61
  };
236
- for (let i = ops.length - 1; i >= 0; i--) {
237
- const op = ops[i];
238
- if (op === 0) {
239
- flush();
240
- currA++;
241
- currB++;
242
- }
243
- else if (op === 1) {
244
- if (patchA === -1) {
245
- patchA = currA;
246
- patchB = currB;
247
- }
248
- sliceB.push(B[currB++]);
249
- }
250
- else {
251
- if (patchA === -1) {
252
- patchA = currA;
253
- patchB = currB;
254
- }
255
- sliceA.push(A[currA++]);
256
- }
257
- }
258
- flush();
259
- return patches;
260
- }
261
-
262
- var _a, _b;
263
- const events = Symbol('events');
264
- const hooks = Symbol('hooks');
265
- const eventBehavior = {
266
- on(eventOrEvents, cb) {
267
- if (typeof eventOrEvents === 'object') {
268
- for (const e of Object.keys(eventOrEvents)) {
269
- this.on(e, eventOrEvents[e]);
270
- }
271
- }
272
- else if (cb !== undefined) {
273
- const callbacks = this[events].get(eventOrEvents) ?? new Set();
274
- if (!callbacks.has(cb))
275
- callbacks.add(cb);
276
- this[events].set(eventOrEvents, callbacks);
277
- }
278
- return () => this.off(eventOrEvents, cb);
279
- },
280
- off(eventOrEvents, cb) {
281
- if (typeof eventOrEvents === 'object') {
282
- for (const e of Object.keys(eventOrEvents)) {
283
- this.off(e, eventOrEvents[e]);
284
- }
285
- }
286
- else if (cb !== null && cb !== undefined) {
287
- const callbacks = this[events].get(eventOrEvents);
288
- if (callbacks) {
289
- callbacks.delete(cb);
290
- if (!callbacks.size)
291
- this[events].delete(eventOrEvents);
292
- }
293
- }
294
- else {
295
- // Remove all listeners for this event
296
- this[events].delete(eventOrEvents);
297
- }
298
- },
299
- emit(event, ...args) {
300
- const callbacks = this[events].get(event);
301
- if (callbacks)
302
- for (const cb of callbacks)
303
- cb.apply(this, args);
304
- for (const cb of this[hooks])
305
- cb.call(this, event, ...args);
306
- },
307
- };
308
- function perEvent(eventful, fct, use) {
309
- const cache = new Map();
310
- return new Proxy(fct, {
311
- get(target, prop) {
312
- if (typeof prop !== 'string')
313
- return target[prop];
314
- if (use && !eventful[events].has(prop) && !eventful[hooks].size)
315
- return () => { };
316
- // Return cached function or create and cache
317
- let cached = cache.get(prop);
318
- if (!cached) {
319
- cached = (...args) => fct.apply(eventful, [prop, ...args]);
320
- cache.set(prop, cached);
321
- }
322
- return cached;
323
- },
324
- });
325
- }
326
- /**
327
- * A type-safe event system that provides a clean API for event handling
328
- * @template Events - The event map defining event names and their handler signatures
329
- */
330
- class Eventful {
331
- constructor() {
332
- this[_a] = new Map();
333
- this[_b] = new Set();
334
- this.on = perEvent(this, eventBehavior.on);
335
- this.off = perEvent(this, eventBehavior.off);
336
- this.emit = perEvent(this, eventBehavior.emit, 'use');
337
- }
338
- hook(cb) {
339
- this[hooks].add(cb);
340
- return () => {
341
- this[hooks].delete(cb);
342
- };
343
- }
344
- }
345
- _a = events, _b = hooks;
346
-
347
- /**
348
- * Symbol for defining custom getter logic for numeric index access
349
- */
350
- const getAt = Symbol('getAt');
351
- /**
352
- * Symbol for defining custom setter logic for numeric index access
353
- */
354
- const setAt = Symbol('setAt');
355
- function Indexable(base, accessor) {
356
- if (base && typeof base !== 'function') {
357
- accessor = base;
358
- base = undefined;
359
- }
360
- if (!base) {
361
- //@ts-expect-error
362
- base = class {
363
- };
364
- }
365
- if (!accessor) {
366
- accessor = {
367
- get(index) {
368
- if (typeof this[getAt] !== 'function') {
369
- throw new Error('Indexable class must have an [getAt] method');
370
- }
371
- return this[getAt](index);
372
- },
373
- set(index, value) {
374
- if (typeof this[setAt] !== 'function') {
375
- throw new Error('Indexable class has read-only numeric index access');
376
- }
377
- this[setAt](index, value);
378
- },
379
- };
380
- }
381
- class Indexable extends base {
382
- }
383
- Object.setPrototypeOf(Indexable.prototype, new Proxy(base.prototype, {
384
- //@ts-expect-error
385
- [Symbol.toStringTag]: 'MutTs Indexable',
386
- get(target, prop, receiver) {
387
- if (prop in target) {
388
- const getter = Object.getOwnPropertyDescriptor(target, prop)?.get;
389
- return getter ? getter.call(receiver) : target[prop];
390
- }
391
- if (typeof prop === 'string') {
392
- if (prop === 'length' && accessor.getLength)
393
- return accessor.getLength.call(receiver);
394
- const numProp = Number(prop);
395
- if (!Number.isNaN(numProp)) {
396
- return accessor.get.call(receiver, numProp);
397
- }
398
- }
399
- return undefined;
400
- },
401
- set(target, prop, value, receiver) {
402
- if (prop in target) {
403
- const setter = Object.getOwnPropertyDescriptor(target, prop)?.set;
404
- if (setter)
405
- setter.call(receiver, value);
406
- else
407
- target[prop] = value;
408
- return true;
409
- }
410
- if (typeof prop === 'string') {
411
- if (prop === 'length' && accessor.setLength) {
412
- accessor.setLength.call(receiver, value);
413
- return true;
414
- }
415
- const numProp = Number(prop);
416
- if (!Number.isNaN(numProp)) {
417
- if (!accessor.set)
418
- throw new Error('Indexable class has read-only numeric index access');
419
- accessor.set.call(receiver, numProp, value);
420
- return true;
421
- }
422
- }
423
- Object.defineProperty(receiver, prop, {
424
- value,
425
- writable: true,
426
- enumerable: true,
427
- configurable: true,
428
- });
429
- return true;
430
- },
431
- has(target, prop) {
432
- if (prop in target)
433
- return true;
434
- if (typeof prop === 'string') {
435
- if (prop === 'length' && accessor.getLength)
436
- return true;
437
- const numProp = Number(prop);
438
- if (!Number.isNaN(numProp))
439
- return true;
440
- }
441
- return false;
442
- },
443
- ownKeys(target) {
444
- const keys = Reflect.ownKeys(target);
445
- if (accessor.getLength) {
446
- keys.push('length');
447
- const len = accessor.getLength.call(this);
448
- for (let i = 0; i < len; i++)
449
- keys.push(String(i));
450
- }
451
- return keys;
452
- },
453
- getOwnPropertyDescriptor(target, prop) {
454
- if (prop in target)
455
- return Object.getOwnPropertyDescriptor(target, prop);
456
- if (typeof prop === 'string') {
457
- if (prop === 'length' && accessor.getLength) {
458
- return {
459
- enumerable: false,
460
- configurable: true,
461
- get: () => accessor.getLength.call(this),
462
- };
463
- }
464
- const numProp = Number(prop);
465
- if (!Number.isNaN(numProp)) {
466
- return {
467
- enumerable: true,
468
- configurable: true,
469
- get: () => accessor.get.call(this, numProp),
470
- set: accessor.set
471
- ? (v) => accessor.set.call(this, numProp, v)
472
- : undefined,
473
- };
474
- }
475
- }
476
- return undefined;
477
- },
478
- }));
479
- return Indexable;
480
- }
481
- /**
482
- * Symbol for accessing the forwarded array in ArrayReadForward
483
- */
484
- const forwardArray = Symbol('forwardArray');
485
- /**
486
- * A read-only array forwarder that implements all reading/iterating methods of Array
487
- * but does not implement modification methods.
488
- *
489
- * The constructor takes a callback that returns an array, and all methods forward
490
- * their behavior to the result of that callback.
491
- */
492
- class ArrayReadForward {
493
- get [forwardArray]() {
494
- throw new Error('ArrayReadForward is not implemented');
495
- }
496
- /**
497
- * Get the length of the array
498
- */
499
- get length() {
500
- return this[forwardArray].length;
501
- }
502
- /**
503
- * Iterator protocol support
504
- */
505
- [Symbol.iterator]() {
506
- return this[forwardArray][Symbol.iterator]();
507
- }
508
- // Reading/Iterating methods
509
- /**
510
- * Creates a new array with the results of calling a provided function on every element
511
- */
512
- map(callbackfn, thisArg) {
513
- return this[forwardArray].map(callbackfn, thisArg);
514
- }
515
- filter(predicate, thisArg) {
516
- return this[forwardArray].filter(predicate, thisArg);
517
- }
518
- reduce(callbackfn, initialValue) {
519
- return initialValue !== undefined
520
- ? this[forwardArray].reduce(callbackfn, initialValue)
521
- : this[forwardArray].reduce(callbackfn);
522
- }
523
- reduceRight(callbackfn, initialValue) {
524
- return initialValue !== undefined
525
- ? this[forwardArray].reduceRight(callbackfn, initialValue)
526
- : this[forwardArray].reduceRight(callbackfn);
527
- }
528
- /**
529
- * Executes a provided function once for each array element
530
- */
531
- forEach(callbackfn, thisArg) {
532
- this[forwardArray].forEach(callbackfn, thisArg);
533
- }
534
- find(predicate, thisArg) {
535
- return this[forwardArray].find(predicate, thisArg);
536
- }
537
- /**
538
- * Returns the index of the first element in the array that satisfies the provided testing function
539
- */
540
- findIndex(predicate, thisArg) {
541
- return this[forwardArray].findIndex(predicate, thisArg);
542
- }
543
- findLast(predicate, thisArg) {
544
- return this[forwardArray].findLast(predicate, thisArg);
545
- }
546
- /**
547
- * Returns the index of the last element in the array that satisfies the provided testing function
548
- */
549
- findLastIndex(predicate, thisArg) {
550
- return this[forwardArray].findLastIndex(predicate, thisArg);
551
- }
552
- /**
553
- * Determines whether an array includes a certain value among its entries
554
- */
555
- includes(searchElement, fromIndex) {
556
- return this[forwardArray].includes(searchElement, fromIndex);
557
- }
558
- /**
559
- * Returns the first index at which a given element can be found in the array
560
- */
561
- indexOf(searchElement, fromIndex) {
562
- return this[forwardArray].indexOf(searchElement, fromIndex);
563
- }
564
- /**
565
- * Returns the last index at which a given element can be found in the array
566
- */
567
- lastIndexOf(searchElement, fromIndex) {
568
- return this[forwardArray].lastIndexOf(searchElement, fromIndex);
569
- }
570
- /**
571
- * Returns a shallow copy of a portion of an array into a new array object
572
- */
573
- slice(start, end) {
574
- return this[forwardArray].slice(start, end);
575
- }
576
- concat(...items) {
577
- return this[forwardArray].concat(...items);
578
- }
579
- /**
580
- * Tests whether all elements in the array pass the test implemented by the provided function
581
- */
582
- every(predicate, thisArg) {
583
- return this[forwardArray].every(predicate, thisArg);
584
- }
585
- /**
586
- * Tests whether at least one element in the array passes the test implemented by the provided function
587
- */
588
- some(predicate, thisArg) {
589
- return this[forwardArray].some(predicate, thisArg);
590
- }
591
- /**
592
- * Joins all elements of an array into a string
593
- */
594
- join(separator) {
595
- return this[forwardArray].join(separator);
596
- }
597
- /**
598
- * Returns a new array iterator that contains the keys for each index in the array
599
- */
600
- keys() {
601
- return this[forwardArray].keys();
602
- }
603
- /**
604
- * Returns a new array iterator that contains the values for each index in the array
605
- */
606
- values() {
607
- return this[forwardArray].values();
608
- }
609
- /**
610
- * Returns a new array iterator that contains the key/value pairs for each index in the array
611
- */
612
- entries() {
613
- return this[forwardArray].entries();
614
- }
615
- /**
616
- * Returns a string representation of the array
617
- */
618
- toString() {
619
- return this[forwardArray].toString();
620
- }
621
- /**
622
- * Returns a localized string representing the array
623
- */
624
- toLocaleString(locales, options) {
625
- return this[forwardArray].toLocaleString(locales, options);
626
- }
627
- /**
628
- * Returns the element at the specified index, or undefined if the index is out of bounds
629
- */
630
- at(index) {
631
- return this[forwardArray].at(index);
632
- }
633
- /**
634
- * Returns a new array with all sub-array elements concatenated into it recursively up to the specified depth
635
- */
636
- flat(depth) {
637
- return this[forwardArray].flat(depth);
638
- }
639
- /**
640
- * Returns a new array formed by applying a given callback function to each element of the array,
641
- * and then flattening the result by one level
642
- */
643
- flatMap(callback, thisArg) {
644
- return this[forwardArray].flatMap(callback, thisArg);
645
- }
646
- /**
647
- * Returns a new array with elements in reversed order (ES2023)
648
- */
649
- toReversed() {
650
- return this[forwardArray].toReversed?.() ?? [...this[forwardArray]].reverse();
651
- }
652
- /**
653
- * Returns a new array with elements sorted (ES2023)
654
- */
655
- toSorted(compareFn) {
656
- return this[forwardArray].toSorted?.(compareFn) ?? [...this[forwardArray]].sort(compareFn);
657
- }
658
- /**
659
- * Returns a new array with some elements removed and/or replaced at a given index (ES2023)
660
- */
661
- toSpliced(start, deleteCount, ...items) {
662
- if (deleteCount === undefined)
663
- return this[forwardArray].toSpliced(start);
664
- return this[forwardArray].toSpliced(start, deleteCount, ...items);
665
- }
666
- /**
667
- * Returns a new array with the element at the given index replaced with the given value (ES2023)
668
- */
669
- with(index, value) {
670
- return this[forwardArray].with(index, value);
671
- }
672
- get [Symbol.unscopables]() {
673
- return this[forwardArray][Symbol.unscopables];
674
- }
675
- }
676
-
677
- const forward = (name, target) => (...args) => {
678
- return target[name](...args);
679
- };
680
- const alreadyChained = new WeakMap();
681
- const originals = new WeakMap();
682
- function cache$1(target, rv) {
683
- originals.set(rv, target);
684
- alreadyChained.set(target, rv);
685
- }
686
- const promiseProxyHandler = {
687
- //@ts-expect-error
688
- [Symbol.toStringTag]: 'MutTs PromiseChain function',
689
- get(target, prop) {
690
- if (prop === Symbol.toStringTag)
691
- return 'PromiseProxy';
692
- if (typeof prop === 'string' && ['then', 'catch', 'finally'].includes(prop))
693
- return target[prop];
694
- return chainPromise(target.then((r) => r[prop]));
695
- },
696
- };
697
- const promiseForward = (target) => ({
698
- // biome-ignore lint/suspicious/noThenProperty: This one is the whole point
699
- then: forward('then', target),
700
- catch: forward('catch', target),
701
- finally: forward('finally', target),
702
- });
703
- const objectProxyHandler = {
704
- //@ts-expect-error
705
- [Symbol.toStringTag]: 'MutTs PromiseChain object',
706
- get(target, prop, receiver) {
707
- const getter = Object.getOwnPropertyDescriptor(target, prop)?.get;
708
- const rv = getter ? getter.call(receiver) : target[prop];
709
- // Allows fct.call or fct.apply to bypass the chain system
710
- if (typeof target === 'function')
711
- return rv;
712
- return chainPromise(rv);
713
- },
714
- apply(target, thisArg, args) {
715
- return chainPromise(target.apply(thisArg, args));
716
- },
717
- };
718
- function chainObject(given) {
719
- const rv = new Proxy(given, objectProxyHandler);
720
- cache$1(given, rv);
721
- return rv;
722
- }
723
- function chainable(x) {
724
- return x && ['function', 'object'].includes(typeof x);
725
62
  }
726
- /**
727
- * Transforms a promise or value into a chainable object
728
- * Allows calling methods directly on promise results without awaiting them first
729
- * @param given - The promise or value to make chainable
730
- * @returns A chainable version of the input
731
- */
732
- function chainPromise(given) {
733
- if (!chainable(given))
734
- return given;
735
- if (alreadyChained.has(given))
736
- return alreadyChained.get(given);
737
- if (!(given instanceof Promise))
738
- return chainObject(given);
739
- // @ts-expect-error It's ok as we check if it's an object above
740
- given = given.then((r) => (chainable(r) ? chainObject(r) : r));
741
- const target = Object.assign(function (...args) {
742
- return chainPromise(given.then((r) => {
743
- return this?.then
744
- ? this.then((t) => r.apply(t, args))
745
- : r.apply(this, args);
746
- }));
747
- }, promiseForward(given));
748
- const chained = new Proxy(target, promiseProxyHandler);
749
- cache$1(given, chained);
750
- return chained;
751
- }
752
-
753
- const memoizedRegistry = new WeakMap();
754
- const wrapperRegistry = new WeakMap();
755
- function getBranch(tree, key) {
756
- tree.branches ?? (tree.branches = new WeakMap());
757
- let branch = tree.branches.get(key);
758
- if (!branch) {
759
- branch = {};
760
- tree.branches.set(key, branch);
761
- }
762
- return branch;
763
- }
764
- function memoizeFunction(fn, opts) {
765
- const fnRoot = proxy.getRoot(fn);
766
- const existing = memoizedRegistry.get(fnRoot);
767
- if (existing)
768
- return existing;
769
- const cacheRoot = {};
770
- const memoized = proxy.markWithRoot(function memoized(...args) {
771
- if (args.some((arg) => !(arg && ['object', 'symbol', 'function'].includes(typeof arg)))) {
772
- if (opts?.lenient)
773
- return fn.apply(this, args);
774
- throw new Error('memoize expects non-null object arguments');
775
- }
776
- let node = cacheRoot;
777
- // Note: decorators add `this` as first argument
778
- for (const arg of args) {
779
- node = getBranch(node, arg);
780
- }
781
- proxy.dependant(node, 'memoize');
782
- if ('result' in node) {
783
- if (proxy.options.onMemoizationDiscrepancy) {
784
- const wasVerification = proxy.options.isVerificationRun;
785
- proxy.options.isVerificationRun = true;
786
- try {
787
- const fresh = proxy.untracked(() => fn.apply(this, args));
788
- if (!proxy.deepCompare(node.result, fresh)) {
789
- proxy.optionCall('onMemoizationDiscrepancy', node.result, fresh, fn, args, 'calculation');
790
- }
791
- }
792
- finally {
793
- proxy.options.isVerificationRun = wasVerification;
794
- }
795
- }
796
- return node.result;
797
- }
798
- // Create memoize internal effect to track dependencies and invalidate cache
799
- // Use untracked to prevent the effect creation from being affected by parent effects
800
- node.cleanup = proxy.root(() => proxy.effect.named('memoize')(() => {
801
- // Execute the function and track its dependencies
802
- // The function execution will automatically track dependencies on reactive objects
803
- node.result = fn.apply(this, args);
804
- return (reason) => {
805
- // When dependencies change, clear the cache and notify consumers
806
- delete node.result;
807
- proxy.touched1(node, { type: 'invalidate', prop: args }, 'memoize');
808
- // Lazy memoization: stop the effect so it doesn't re-run immediately.
809
- // It will be re-created on next access.
810
- if (node.cleanup) {
811
- node.cleanup({ type: 'invalidate', cause: reason });
812
- node.cleanup = undefined;
813
- }
814
- };
815
- }, { opaque: true }));
816
- if (proxy.options.onMemoizationDiscrepancy) {
817
- const wasVerification = proxy.options.isVerificationRun;
818
- proxy.options.isVerificationRun = true;
819
- try {
820
- const fresh = proxy.untracked(() => fn.apply(this, args));
821
- if (!proxy.deepCompare(node.result, fresh)) {
822
- proxy.optionCall('onMemoizationDiscrepancy', node.result, fresh, fn, args, 'comparison');
823
- }
824
- }
825
- finally {
826
- proxy.options.isVerificationRun = wasVerification;
827
- }
828
- }
829
- return node.result;
830
- }, fn);
831
- memoizedRegistry.set(fnRoot, memoized);
832
- memoizedRegistry.set(memoized, memoized);
833
- return memoized;
834
- }
835
- function memoizeObject(target, opts) {
836
- const existing = memoizedRegistry.get(target);
837
- if (existing)
838
- return existing;
839
- const proxy$1 = new Proxy(target, {
840
- get(source, prop, receiver) {
841
- // 1. Walk prototype chain to find descriptor
842
- let current = source;
843
- let desc;
844
- while (current) {
845
- desc = Object.getOwnPropertyDescriptor(current, prop);
846
- if (desc)
847
- break;
848
- current = Object.getPrototypeOf(current);
849
- }
850
- if (!desc)
851
- return Reflect.get(source, prop, receiver);
852
- // 2. If getter, memoize
853
- if (desc.get) {
854
- const originalGetter = desc.get;
855
- let wrapper = wrapperRegistry.get(originalGetter);
856
- if (!wrapper) {
857
- wrapper = proxy.markWithRoot(proxy.named(`${String(source?.constructor?.name ?? 'Object')}.${String(prop)}`, (that) => {
858
- return originalGetter.call(that);
859
- }), {
860
- propertyKey: prop,
861
- });
862
- const origRoot = originalGetter[proxy.rootFunctionSymbol];
863
- if (origRoot)
864
- wrapper[proxy.rootFunctionSymbol] = origRoot;
865
- wrapperRegistry.set(originalGetter, wrapper);
866
- }
867
- const memoized = memoizeFunction(wrapper, opts);
868
- return memoized(receiver);
869
- }
870
- // 3. Otherwise forward
871
- return Reflect.get(source, prop, receiver);
872
- },
873
- // Forward set to the target (source) to ensure it acts as the receiver for reactivity notifications
874
- set(source, prop, value, _receiver) {
875
- // By strictly passing `source` as receiver, we ensure that if `source` is a reactive proxy,
876
- // it recognizes itself and triggers change notifications.
877
- return Reflect.set(source, prop, value, source);
878
- },
879
- });
880
- proxy.proxyToObject.set(proxy$1, target);
881
- memoizedRegistry.set(target, proxy$1);
882
- return proxy$1;
883
- }
884
- /**
885
- * Decorator and function wrapper for memoizing computed values based on reactive dependencies.
886
- *
887
- * When used as a decorator on getters or methods, it caches the result and automatically
888
- * invalidates the cache when reactive dependencies change.
889
- *
890
- * When used as a function wrapper, it memoizes based on object arguments (WeakMap-based cache).
891
- *
892
- * @example
893
- * ```typescript
894
- * class User {
895
- * @memoize
896
- * get fullName() {
897
- * return `${this.firstName} ${this.lastName}`
898
- * }
899
- * }
900
- *
901
- * // Or as a function wrapper
902
- * const expensive = memoize((obj: SomeObject) => {
903
- * return heavyComputation(obj)
904
- * })
905
- * ```
906
- */
907
- function makeMemoizeDecorator(memoizeOpts) {
908
- return proxy.decorator({
909
- getter(original, target, propertyKey) {
910
- return function () {
911
- let wrapper = wrapperRegistry.get(original);
912
- if (!wrapper) {
913
- wrapper = proxy.markWithRoot(proxy.named(`${String(target?.constructor?.name ?? target?.name ?? 'Object')}.${String(propertyKey)}`, (that) => {
914
- return original.call(that);
915
- }), {
916
- method: original,
917
- propertyKey,
918
- });
919
- const origRoot = original[proxy.rootFunctionSymbol];
920
- if (origRoot)
921
- wrapper[proxy.rootFunctionSymbol] = origRoot;
922
- wrapperRegistry.set(original, wrapper);
923
- }
924
- const memoized = memoizeFunction(wrapper, memoizeOpts);
925
- return memoized(this);
926
- };
927
- },
928
- method(original, target, name) {
929
- return function (...args) {
930
- let wrapper = wrapperRegistry.get(original);
931
- if (!wrapper) {
932
- wrapper = proxy.markWithRoot(proxy.named(`${String(target?.constructor?.name ?? target?.name ?? 'Object')}.${String(name)}`, (that, ...args) => {
933
- return original.call(that, ...args);
934
- }), {
935
- method: original,
936
- propertyKey: name,
937
- });
938
- const origRoot = original[proxy.rootFunctionSymbol];
939
- if (origRoot)
940
- wrapper[proxy.rootFunctionSymbol] = origRoot;
941
- wrapperRegistry.set(original, wrapper);
942
- }
943
- const memoized = memoizeFunction(wrapper, memoizeOpts);
944
- return memoized(this, ...args);
945
- };
946
- },
947
- default: (target) => typeof target === 'object'
948
- ? memoizeObject(target, memoizeOpts)
949
- : memoizeFunction(target, memoizeOpts),
950
- });
951
- }
952
- const memoize = proxy.flavored(makeMemoizeDecorator(), {
953
- get lenient() {
954
- return makeMemoizeDecorator({ lenient: true });
955
- },
956
- });
957
-
958
- function attend(source, callback) {
959
- const enumerate = typeof source === 'function'
960
- ? source
961
- : Array.isArray(source)
962
- ? () => Array.from({ length: source.length }, (_, i) => i)
963
- : source instanceof Map
964
- ? () => source.keys()
965
- : source instanceof Set
966
- ? () => source.values()
967
- : () => Object.keys(source);
968
- const keyEffects = new Map();
969
- const outer = proxy.effect(({ ascend }) => {
970
- const keys = new Set();
971
- for (const key of enumerate())
972
- keys.add(key);
973
- for (const key of keys) {
974
- if (keyEffects.has(key))
975
- continue;
976
- keyEffects.set(key, ascend(() => proxy.effect(() => callback(key))));
977
- }
978
- for (const key of Array.from(keyEffects.keys())) {
979
- if (!keys.has(key)) {
980
- keyEffects.get(key)();
981
- keyEffects.delete(key);
982
- }
983
- }
984
- });
985
- return (reason) => {
986
- outer(reason);
987
- for (const stop of keyEffects.values())
988
- stop(reason);
989
- keyEffects.clear();
63
+ const GLOBAL_ORIGINALS = Symbol.for('mutts.originals');
64
+ const GLOBAL_PROMISE = Symbol.for('mutts.OriginalPromise');
65
+ let originals;
66
+ let OriginalPromise;
67
+ if (globalThis[GLOBAL_ORIGINALS]) {
68
+ originals = globalThis[GLOBAL_ORIGINALS];
69
+ OriginalPromise = globalThis[GLOBAL_PROMISE];
70
+ }
71
+ else {
72
+ OriginalPromise = globalThis.Promise;
73
+ originals = {
74
+ // biome-ignore lint/suspicious/noThenProperty: Intentional Promise.prototype patching
75
+ then: OriginalPromise.prototype.then,
76
+ catch: OriginalPromise.prototype.catch,
77
+ finally: OriginalPromise.prototype.finally,
78
+ resolve: OriginalPromise.resolve,
79
+ reject: OriginalPromise.reject,
80
+ all: OriginalPromise.all,
81
+ allSettled: OriginalPromise.allSettled,
82
+ race: OriginalPromise.race,
83
+ any: OriginalPromise.any,
84
+ setTimeout: globalThis.setTimeout,
85
+ setInterval: globalThis.setInterval,
86
+ setImmediate: globalThis.setImmediate,
87
+ requestAnimationFrame: globalThis.requestAnimationFrame,
88
+ queueMicrotask: globalThis.queueMicrotask,
990
89
  };
991
- }
992
- /**
993
- * Perform a reactive scan over an array of items.
994
- *
995
- * This implementation is highly optimized for performance and fine-grained reactivity:
996
- * - **Incremental Updates**: Changes to an item only trigger re-computation from that
997
- * point onwards in the result chain.
998
- * - **Move Optimization**: If items are moved within the array, their accumulated
999
- * values are reused as long as their predecessor remains the same.
1000
- * - **Duplicate Support**: Correctly handles multiple occurrences of the same object
1001
- * instance using an internal occurrence tracking mechanism.
1002
- * - **Memory Efficient**: Uses `WeakMap` for caching intermediates, which are
1003
- * automatically cleared when source items are garbage collected.
1004
- *
1005
- * @example
1006
- * ```typescript
1007
- * const source = reactive([{ val: 1 }, { val: 2 }, { val: 3 }])
1008
- * const sum = scan(source, (acc, item) => acc + item.val, 0)
1009
- *
1010
- * expect([...sum]).toEqual([1, 3, 6])
1011
- *
1012
- * // Modifying an item only re-computes subsequent sums
1013
- * source[1].val = 10
1014
- * expect([...sum]).toEqual([1, 11, 14])
1015
- * ```
1016
- *
1017
- * @param source The source array of objects (will be made reactive)
1018
- * @param callback The accumulator function called with (accumulator, currentItem)
1019
- * @param initialValue The starting value for the accumulation
1020
- * @returns A reactive array of accumulated values, with a [cleanup] property to stop the tracking
1021
- */
1022
- function scan(source, callback, initialValue) {
1023
- const observedSource = proxy.reactive(source);
1024
- const rawResult = [];
1025
- const result = proxy.reactive(rawResult);
1026
- // Track effects for each index to dispose them when the array shrinks
1027
- const indexEffects = new Map();
1028
- // Mapping from index to its current intermediate object
1029
- const indexToIntermediate = proxy.reactive([]);
1030
- const intermediaries = new WeakMap();
1031
- let Intermediate = (() => {
1032
- var _a;
1033
- let _instanceExtraInitializers = [];
1034
- let _get_acc_decorators;
1035
- return _a = class Intermediate {
1036
- constructor(val, prev) {
1037
- this.val = (proxy.__runInitializers(this, _instanceExtraInitializers), val);
1038
- this.prev = prev;
1039
- }
1040
- get acc() {
1041
- const prevAcc = this.prev ? this.prev.acc : initialValue;
1042
- return callback(prevAcc, this.val);
1043
- }
1044
- },
1045
- (() => {
1046
- const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
1047
- _get_acc_decorators = [memoize];
1048
- proxy.__esDecorate(_a, null, _get_acc_decorators, { kind: "getter", name: "acc", static: false, private: false, access: { has: obj => "acc" in obj, get: obj => obj.acc }, metadata: _metadata }, null, _instanceExtraInitializers);
1049
- if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
1050
- })(),
1051
- _a;
1052
- })();
1053
- function disposeIndex(index) {
1054
- const stop = indexEffects.get(index);
1055
- if (stop) {
1056
- stop();
1057
- indexEffects.delete(index);
1058
- Reflect.deleteProperty(indexToIntermediate, index);
1059
- Reflect.deleteProperty(result, index);
1060
- }
1061
- }
1062
- const mainEffect = proxy.effect(function scanMainEffect({ ascend }) {
1063
- const length = observedSource.length;
1064
- const occurrenceCount = new Map();
1065
- let prev;
1066
- for (let i = 0; i < length; i++)
1067
- if (i in observedSource) {
1068
- const val = observedSource[i];
1069
- if (!(val &&
1070
- (typeof val === 'object' || typeof val === 'function' || typeof val === 'symbol'))) {
1071
- throw new Error('scan: items must be objects (WeakKey) for intermediate caching');
1072
- }
1073
- const count = occurrenceCount.get(val) ?? 0;
1074
- occurrenceCount.set(val, count + 1);
1075
- let list = intermediaries.get(val);
1076
- if (!list) {
1077
- list = [];
1078
- intermediaries.set(val, list);
1079
- }
1080
- let intermediate = list[count];
1081
- if (!intermediate) {
1082
- intermediate = proxy.reactive(new Intermediate(val, prev));
1083
- list[count] = intermediate;
1084
- }
1085
- else {
1086
- // Update the link.
1087
- if (proxy.untracked(() => intermediate.prev) !== prev) {
1088
- intermediate.prev = prev;
1089
- }
1090
- }
1091
- // Update the reactive mapping for this index
1092
- if (indexToIntermediate[i] !== intermediate) {
1093
- indexToIntermediate[i] = intermediate;
1094
- }
1095
- // If we don't have an effect for this index yet, create one
1096
- if (!indexEffects.has(i)) {
1097
- ascend(() => {
1098
- const index = i;
1099
- const stop = proxy.effect(function scanIndexSyncEffect() {
1100
- const inter = indexToIntermediate[index];
1101
- if (inter) {
1102
- const accValue = inter.acc;
1103
- result[index] = accValue;
1104
- }
1105
- });
1106
- indexEffects.set(index, stop);
1107
- });
1108
- }
1109
- prev = intermediate;
1110
- }
1111
- // Cleanup trailing indices
1112
- for (const index of Array.from(indexEffects.keys())) {
1113
- if (index >= length)
1114
- disposeIndex(index);
1115
- }
1116
- // Ensure result length matches source length
1117
- if (rawResult.length !== length) {
1118
- proxy.FoolProof.set(result, 'length', length, result);
1119
- }
1120
- });
1121
- return proxy.cleanedBy(result, ((reason) => {
1122
- mainEffect(reason);
1123
- for (const stop of indexEffects.values())
1124
- stop(reason);
1125
- indexEffects.clear();
1126
- }));
1127
- }
1128
- function lift(cb) {
1129
- let result;
1130
- let rawResult;
1131
- const liftCleanup = proxy.effect.named('lift')(proxy.markWithRoot((access) => {
1132
- const source = cb(access);
1133
- if (!source || typeof source !== 'object')
1134
- throw new Error('lift callback must return an array or object');
1135
- const sourceProto = Object.getPrototypeOf(source);
1136
- if (!result) {
1137
- rawResult = Array.isArray(source) ? [] : Object.create(sourceProto);
1138
- result = proxy.reactive(rawResult);
1139
- }
1140
- if (sourceProto !== Object.getPrototypeOf(result))
1141
- throw new Error('lift callback must return the same type as the previous result');
1142
- if (Array.isArray(source)) {
1143
- const res = result;
1144
- const patches = arrayDiff(res, source);
1145
- for (let i = patches.length - 1; i >= 0; i--) {
1146
- const { indexA, sliceA, sliceB } = patches[i];
1147
- res.splice(indexA, sliceA.length, ...sliceB);
1148
- }
1149
- }
1150
- else {
1151
- for (const key of Object.keys(source)) {
1152
- const had = key in rawResult;
1153
- const newDesc = Object.getOwnPropertyDescriptor(source, key);
1154
- if (had) {
1155
- const oldDesc = Object.getOwnPropertyDescriptor(rawResult, key);
1156
- const sameAccessor = oldDesc && newDesc.get && oldDesc.get === newDesc.get;
1157
- Object.defineProperty(rawResult, key, newDesc);
1158
- if (!sameAccessor &&
1159
- rawResult[key] !==
1160
- (oldDesc ? (oldDesc.get ? oldDesc.get() : oldDesc.value) : undefined))
1161
- proxy.touched1(rawResult, { type: 'set', prop: key }, key);
1162
- }
1163
- else {
1164
- Object.defineProperty(rawResult, key, newDesc);
1165
- proxy.touched1(rawResult, { type: 'add', prop: key }, key);
1166
- }
1167
- }
1168
- for (const key of Object.keys(rawResult))
1169
- if (!(key in source)) {
1170
- delete rawResult[key];
1171
- proxy.touched1(rawResult, { type: 'del', prop: key }, key);
1172
- }
1173
- }
1174
- }, cb));
1175
- return proxy.cleanedBy(result, liftCleanup);
1176
- }
1177
- /**
1178
- * Reactively maps an array source through `fn`, producing a lazy reactive output array.
1179
- *
1180
- * Each source item gets its own isolated effect (via `root()`) so that changes to one item
1181
- * only recompute that item's projection. Structural changes (push, splice, reorder) are detected
1182
- * via `arrayDiff` and surgically applied to the output cache.
1183
- *
1184
- * The source can be a reactive array or a function returning an array. When a function is provided,
1185
- * the function is re-evaluated inside an effect whenever its dependencies change.
1186
- *
1187
- * Output elements are computed lazily — accessing `result[i]` triggers computation if not yet cached.
1188
- *
1189
- * @param source - A reactive array or a function returning an array
1190
- * @param fn - Mapping function applied to each element
1191
- * @param options - Optional purity hints to skip per-item effects
1192
- * @returns A readonly reactive array with a `[cleanup]` method to dispose all effects
1193
- */
1194
- function morphArray(source, fn, options) {
1195
- if (typeof source !== 'function' && !proxy.isReactive(source) && options?.pure === true) {
1196
- return source.map(fn);
1197
- }
1198
- let track;
1199
- const itemEffects = new Map();
1200
- const cache = [];
1201
- let input = [];
1202
- function stopItem(key) {
1203
- const entry = itemEffects.get(key);
1204
- if (entry) {
1205
- entry.stop({ type: 'stopped' });
1206
- itemEffects.delete(key);
1207
- }
1208
- }
1209
- function computeItem(key, input) {
1210
- const isPure = options?.pure === true || (typeof options?.pure === 'function' && options.pure(input));
1211
- if (isPure) {
1212
- track(() => {
1213
- cache[key] = fn(input);
1214
- });
1215
- }
1216
- else {
1217
- const indexRef = { value: key };
1218
- let stop;
1219
- track(() => {
1220
- stop = proxy.effect.opaque(() => {
1221
- cache[indexRef.value] = fn(input);
1222
- return (reason) => {
1223
- delete cache[indexRef.value];
1224
- proxy.touched1(cache, { type: 'invalidate', prop: 'morph' }, String(key));
1225
- stop({ type: 'invalidate', cause: reason });
1226
- };
1227
- });
1228
- });
1229
- itemEffects.set(key, { stop, index: indexRef });
1230
- }
1231
- }
1232
- const proxy$1 = proxy.reactive(cache, {
1233
- get(cache, prop) {
1234
- const n = typeof prop === 'string' ? Number(prop) : NaN;
1235
- if (Number.isNaN(n))
1236
- return cache[prop];
1237
- if (!(n in cache))
1238
- computeItem(n, input[n]);
1239
- return cache[n];
1240
- },
1241
- has(_cache, prop) {
1242
- return Reflect.has(input, prop);
1243
- },
1244
- });
1245
- const stopMain = proxy.effect.named('morph:array')(({ ascend }) => {
1246
- track = ascend;
1247
- const newInput = [...(typeof source === 'function' ? source() : source)];
1248
- const diffs = arrayDiff(input, newInput).toSorted((a, b) => b.indexA - a.indexA);
1249
- if (diffs.length > 0) {
1250
- for (const diff of diffs) {
1251
- // Stop items in removed range
1252
- for (let i = diff.indexA; i < diff.indexA + diff.sliceA.length; i++)
1253
- stopItem(i);
1254
- // Shift existing itemEffects in the Map to match the new indices
1255
- const shift = diff.sliceB.length - diff.sliceA.length;
1256
- if (shift !== 0) {
1257
- // We need to move entries in the Map.
1258
- const entries = Array.from(itemEffects.entries()).sort((a, b) => a[0] - b[0]);
1259
- // Remove entries that will be shifted
1260
- for (const [idx, entry] of entries) {
1261
- if (idx >= diff.indexA + diff.sliceA.length) {
1262
- itemEffects.delete(idx);
1263
- }
1264
- }
1265
- // Re-add them with shifted indices
1266
- for (const [idx, entry] of entries) {
1267
- if (idx >= diff.indexA + diff.sliceA.length) {
1268
- const newIdx = idx + shift;
1269
- entry.index.value = newIdx;
1270
- itemEffects.set(newIdx, entry);
1271
- }
1272
- }
1273
- }
1274
- // Splice the cache
1275
- cache.splice(diff.indexA, diff.sliceA.length, ...new Array(diff.sliceB.length).fill(undefined));
1276
- // Make holes for lazy computation
1277
- for (let i = diff.indexA; i < diff.indexA + diff.sliceB.length; i++)
1278
- delete cache[i];
1279
- }
1280
- const invalidates = new Set([proxy.keysOf]);
1281
- if (input.length !== newInput.length)
1282
- invalidates.add('length');
1283
- for (const diff of diffs) {
1284
- const max = Math.max(diff.sliceA.length, diff.sliceB.length);
1285
- for (let i = 0; i < max; i++)
1286
- invalidates.add(String(diff.indexA + i));
1287
- }
1288
- proxy.touched(cache, { type: 'bunch', method: 'morph-input' }, invalidates);
1289
- }
1290
- input = newInput;
1291
- });
1292
- return proxy.cleanedBy(proxy$1, (reason) => {
1293
- stopMain(reason);
1294
- for (const entry of itemEffects.values())
1295
- entry.stop(reason);
1296
- itemEffects.clear();
1297
- });
1298
- }
1299
- /**
1300
- * Reactively maps a `Map` source through `fn`, producing a reactive output Map.
1301
- *
1302
- * Each key gets its own isolated effect so that value changes for one key only recompute
1303
- * that key's projection. Key additions and removals are tracked via `keysOf` dependency.
1304
- *
1305
- * @param source - A reactive Map
1306
- * @param fn - Mapping function applied to each value
1307
- * @param options - Optional purity hints to skip per-key effects
1308
- * @returns A reactive Map with a `[cleanup]` method to dispose all effects
1309
- */
1310
- function morphMap(source, fn, options) {
1311
- if (!proxy.isReactive(source) && options?.pure === true) {
1312
- const res = new Map();
1313
- for (const [k, v] of source)
1314
- res.set(k, fn(v));
1315
- return res;
1316
- }
1317
- let track;
1318
- const itemEffects = new Map();
1319
- const cache = new Map();
1320
- Object.defineProperty(cache, 'constructor', { value: Object, enumerable: false });
1321
- function stopItem(key) {
1322
- const stop = itemEffects.get(key);
1323
- if (stop) {
1324
- stop({ type: 'stopped' });
1325
- itemEffects.delete(key);
1326
- }
1327
- }
1328
- function computeItem(key, val) {
1329
- const isPure = options?.pure === true || (typeof options?.pure === 'function' && options.pure(val));
1330
- if (isPure) {
1331
- cache.set(key, track(() => fn(val)));
1332
- }
1333
- else {
1334
- const stop = track(() => proxy.effect.opaque(() => {
1335
- cache.set(key, fn(source.get(key)));
1336
- return (reason) => {
1337
- cache.delete(key);
1338
- proxy.touched1(cache, { type: 'invalidate', prop: 'morph' }, String(key));
1339
- stop({ type: 'invalidate', cause: reason });
1340
- };
1341
- }));
1342
- itemEffects.set(key, stop);
1343
- }
1344
- }
1345
- const proxy$1 = proxy.reactive(cache, {
1346
- get(cache, prop) {
1347
- if (prop === 'get')
1348
- return (key) => {
1349
- if (!cache.has(key) && source.has(key))
1350
- computeItem(key, source.get(key));
1351
- return cache.get(key);
1352
- };
1353
- if (prop === 'has')
1354
- return (key) => {
1355
- return source.has(key);
1356
- };
1357
- if (prop === 'keys')
1358
- return () => {
1359
- return source.keys();
1360
- };
1361
- if (prop === 'values')
1362
- return function* () {
1363
- for (const key of source.keys()) {
1364
- yield proxy$1.get(key);
1365
- }
1366
- };
1367
- if (prop === 'entries')
1368
- return function* () {
1369
- for (const key of source.keys()) {
1370
- yield [key, proxy$1.get(key)];
1371
- }
1372
- };
1373
- if (prop === Symbol.iterator)
1374
- return function* () {
1375
- for (const key of source.keys()) {
1376
- yield [key, proxy$1.get(key)];
1377
- }
1378
- };
1379
- return cache[prop];
1380
- },
1381
- });
1382
- let stateSnapshot = proxy.getState(source);
1383
- const stopMain = proxy.effect.named('morph:map')(({ ascend }) => {
1384
- track = ascend;
1385
- proxy.dependant(source, proxy.keysOf);
1386
- while ('evolution' in stateSnapshot) {
1387
- const { evolution } = stateSnapshot;
1388
- stateSnapshot = stateSnapshot.next;
1389
- if (evolution.type === 'add') {
1390
- proxy.touched1(cache, evolution, evolution.prop);
1391
- }
1392
- else if (evolution.type === 'del') {
1393
- stopItem(evolution.prop);
1394
- cache.delete(evolution.prop);
1395
- proxy.touched1(cache, evolution, evolution.prop);
1396
- }
1397
- }
1398
- });
1399
- return proxy.cleanedBy(proxy$1, (reason) => {
1400
- stopMain(reason);
1401
- for (const stop of itemEffects.values())
1402
- stop(reason);
1403
- itemEffects.clear();
1404
- });
1405
- }
1406
- /**
1407
- * Reactively maps a record/object source through `fn`, producing a reactive output record.
1408
- *
1409
- * Each key gets its own isolated effect so that value changes for one key only recompute
1410
- * that key's projection. Key additions and removals are tracked automatically.
1411
- *
1412
- * @param source - A reactive record
1413
- * @param fn - Mapping function applied to each value
1414
- * @param options - Optional purity hints to skip per-key effects
1415
- * @returns A reactive record with a `[cleanup]` method to dispose all effects
1416
- */
1417
- function morphRecord(source, fn, options) {
1418
- if (!proxy.isReactive(source) && options?.pure === true) {
1419
- const res = {};
1420
- for (const k of Object.keys(source))
1421
- res[k] = fn(source[k]);
1422
- return res;
1423
- }
1424
- let track;
1425
- const itemEffects = new Map();
1426
- const cache = {};
1427
- function stopItem(key) {
1428
- const stop = itemEffects.get(key);
1429
- if (stop) {
1430
- stop({ type: 'stopped' });
1431
- itemEffects.delete(key);
1432
- }
1433
- }
1434
- function computeItem(key, val) {
1435
- const isPure = options?.pure === true || (typeof options?.pure === 'function' && options.pure(val));
1436
- if (isPure) {
1437
- cache[key] = track(() => fn(val));
1438
- }
1439
- else {
1440
- const stop = track(() => proxy.effect.opaque(() => {
1441
- cache[key] = fn(source[key]);
1442
- return (reason) => {
1443
- delete cache[key];
1444
- proxy.touched1(cache, { type: 'invalidate', prop: 'morph' }, String(key));
1445
- stop({ type: 'invalidate', cause: reason });
1446
- };
1447
- }));
1448
- itemEffects.set(key, stop);
1449
- }
1450
- }
1451
- function get(prop) {
1452
- if (!(prop in cache) && prop in source)
1453
- computeItem(prop, source[prop]);
1454
- return cache[prop];
1455
- }
1456
- const proxy$1 = proxy.reactive(cache, {
1457
- get(_, prop) {
1458
- return get(prop);
1459
- },
1460
- has(_, prop) {
1461
- return prop in source;
1462
- },
1463
- ownKeys() {
1464
- return Reflect.ownKeys(source);
1465
- },
1466
- getOwnPropertyDescriptor(_cache, prop) {
1467
- if (prop in source)
1468
- return { configurable: true, enumerable: true, get: () => get(prop) };
1469
- },
1470
- });
1471
- let stateSnapshot = proxy.getState(source);
1472
- const stopMain = proxy.effect.named('morph:record')(({ ascend }) => {
1473
- track = ascend;
1474
- // Track only structural changes on source
1475
- proxy.dependant(source, proxy.keysOf);
1476
- while ('evolution' in stateSnapshot) {
1477
- const { evolution } = stateSnapshot;
1478
- stateSnapshot = stateSnapshot.next;
1479
- if (evolution.type === 'add') {
1480
- proxy.touched1(cache, evolution, evolution.prop);
1481
- }
1482
- else if (evolution.type === 'del') {
1483
- stopItem(evolution.prop);
1484
- delete cache[evolution.prop];
1485
- proxy.touched1(cache, evolution, evolution.prop);
1486
- }
1487
- }
1488
- });
1489
- return proxy.cleanedBy(proxy$1, (reason) => {
1490
- stopMain(reason);
1491
- for (const stop of itemEffects.values())
1492
- stop(reason);
1493
- itemEffects.clear();
1494
- });
1495
- }
1496
- /**
1497
- * Reactively maps a collection (array, Map, or record) through a per-entry function.
1498
- *
1499
- * Each entry in the source gets its own reactive context — when only one entry's dependencies
1500
- * change, only that entry's projection recomputes. Structural changes (additions, removals,
1501
- * reorders) are detected via diffing and applied surgically.
1502
- *
1503
- * Use `morph.pure(source, fn)` when `fn` has no reactive reads (skips per-item effects).
1504
- *
1505
- * @example
1506
- * ```ts
1507
- * const users = reactive([{ name: 'John' }, { name: 'Jane' }])
1508
- * const names = morph(users, u => u.name.toUpperCase())
1509
- * // names[0] = 'JOHN', names[1] = 'JANE'
1510
- * // Changing users[0].name only recomputes names[0]
1511
- * ```
1512
- */
1513
- const morph = proxy.flavored(function morph(source, fn, options) {
1514
- if (Array.isArray(source) || typeof source === 'function')
1515
- return morphArray(source, fn, options);
1516
- if (source instanceof Map)
1517
- return morphMap(source, fn, options);
1518
- return morphRecord(source, fn, options);
1519
- }, {
1520
- get pure() {
1521
- return (source, fn, _opt) => this(source, fn, { pure: true });
1522
- },
1523
- });
1524
-
1525
- /**
1526
- * Deep watch an object and all its nested properties
1527
- * @param target - The object to watch deeply
1528
- * @param callback - The callback to call when any nested property changes
1529
- * @param options - Options for the deep watch
1530
- * @returns A cleanup function to stop watching
1531
- */
1532
- /**
1533
- * Sets up deep watching for an object, tracking all nested property changes
1534
- * @param target - The object to watch
1535
- * @param callback - The callback to call when changes occur
1536
- * @param options - Options for deep watching
1537
- * @returns A cleanup function to stop deep watching
1538
- */
1539
- function deepWatch(target, callback, { immediate = false } = {}) {
1540
- if (target === null || target === undefined)
1541
- return undefined;
1542
- if (typeof target !== 'object')
1543
- throw new Error('Target of deep watching must be an object');
1544
- // Create a wrapper callback that matches EffectTrigger signature
1545
- const wrappedCallback = proxy.markWithRoot((() => callback(target)), callback);
1546
- proxy.registerDeepWatcher();
1547
- // Use the existing effect system to register dependencies
1548
- return proxy.effect(() => {
1549
- // Mark the target object as having deep watchers
1550
- proxy.objectsWithDeepWatchers.add(target);
1551
- // Track which objects this effect is watching for cleanup
1552
- let effectObjects = proxy.effectToDeepWatchedObjects.get(wrappedCallback);
1553
- if (!effectObjects) {
1554
- effectObjects = new Set();
1555
- proxy.effectToDeepWatchedObjects.set(wrappedCallback, effectObjects);
1556
- }
1557
- effectObjects.add(target);
1558
- // Traverse the object graph and register dependencies
1559
- // This will re-run every time the effect runs, ensuring we catch all changes
1560
- const visited = new WeakSet();
1561
- function traverseAndTrack(obj, depth = 0) {
1562
- // Prevent infinite recursion and excessive depth
1563
- if (!obj || visited.has(obj) || typeof obj !== 'object' || depth > proxy.options.maxDeepWatchDepth)
1564
- return;
1565
- // Do not traverse into unreactive objects
1566
- if (proxy.isNonReactive(obj))
1567
- return;
1568
- visited.add(obj);
1569
- // Mark this object as having deep watchers
1570
- proxy.objectsWithDeepWatchers.add(obj);
1571
- effectObjects.add(obj);
1572
- // Traverse all properties to register dependencies
1573
- // unwrap to avoid kicking dependency
1574
- for (const key in proxy.unwrap(obj)) {
1575
- if (Object.hasOwn(obj, key)) {
1576
- // Access the property to register dependency
1577
- const value = obj[key];
1578
- // Make the value reactive if it's an object
1579
- const reactiveValue = typeof value === 'object' && value !== null ? proxy.reactive(value) : value;
1580
- traverseAndTrack(reactiveValue, depth + 1);
1581
- }
1582
- }
1583
- // Also handle array indices and length
1584
- // biome-ignore lint/suspicious/useIsArray: Check for both native arrays and reactive arrays
1585
- if (Array.isArray(obj) || obj instanceof Array) {
1586
- // Access array length to register dependency on length changes
1587
- const length = obj.length;
1588
- // Access all current array elements to register dependencies
1589
- for (let i = 0; i < length; i++) {
1590
- // Access the array element to register dependency
1591
- const value = obj[i];
1592
- // Make the value reactive if it's an object
1593
- const reactiveValue = typeof value === 'object' && value !== null ? proxy.reactive(value) : value;
1594
- traverseAndTrack(reactiveValue, depth + 1);
1595
- }
1596
- }
1597
- // Handle Set values (deep watch values only, not keys since Sets don't have separate keys)
1598
- else if (obj instanceof Set) {
1599
- // Access all Set values to register dependencies
1600
- for (const value of obj) {
1601
- // Make the value reactive if it's an object
1602
- const reactiveValue = typeof value === 'object' && value !== null ? proxy.reactive(value) : value;
1603
- traverseAndTrack(reactiveValue, depth + 1);
1604
- }
1605
- }
1606
- // Handle Map values (deep watch values only, not keys)
1607
- else if (obj instanceof Map) {
1608
- // Access all Map values to register dependencies
1609
- for (const [_key, value] of obj) {
1610
- // Make the value reactive if it's an object
1611
- const reactiveValue = typeof value === 'object' && value !== null ? proxy.reactive(value) : value;
1612
- traverseAndTrack(reactiveValue, depth + 1);
1613
- }
1614
- }
1615
- // Note: WeakSet and WeakMap cannot be iterated, so we can't deep watch their contents
1616
- // They will only trigger when the collection itself is replaced
1617
- }
1618
- // Traverse the target object to register all dependencies
1619
- // This will register dependencies on all current properties and array elements
1620
- traverseAndTrack(target);
1621
- // Only call the callback if immediate is true or if it's not the first run
1622
- if (immediate) {
1623
- proxy.untracked(() => callback(target));
1624
- }
1625
- immediate = true;
1626
- // Return a cleanup function that properly removes deep watcher tracking
1627
- return () => {
1628
- // Get the objects this effect was watching
1629
- const effectObjects = proxy.effectToDeepWatchedObjects.get(wrappedCallback);
1630
- if (effectObjects) {
1631
- // Remove deep watcher tracking from all objects this effect was watching
1632
- for (const obj of effectObjects) {
1633
- // Check if this object still has other deep watchers
1634
- const watchers = proxy.deepWatchers.get(obj);
1635
- if (watchers) {
1636
- // Remove this effect's callback from the watchers
1637
- watchers.delete(wrappedCallback);
1638
- // If no more watchers, remove the object from deep watchers tracking
1639
- if (watchers.size === 0) {
1640
- proxy.deepWatchers.delete(obj);
1641
- proxy.objectsWithDeepWatchers.delete(obj);
1642
- }
1643
- }
1644
- else {
1645
- // No watchers found, remove from deep watchers tracking
1646
- proxy.objectsWithDeepWatchers.delete(obj);
1647
- }
1648
- }
1649
- // Clean up the tracking data
1650
- proxy.effectToDeepWatchedObjects.delete(wrappedCallback);
1651
- }
1652
- };
1653
- });
1654
- }
1655
-
1656
- /**
1657
- * Organizes a source object's properties into a target object using a callback function.
1658
- * This creates a reactive mapping between source properties and a target object,
1659
- * automatically handling property additions, updates, and removals.
1660
- *
1661
- * @template Source - The type of the source object
1662
- * @template Target - The type of the target object (defaults to Record<PropertyKey, any>)
1663
- *
1664
- * @param {Source} source - The source object to organize
1665
- * @param {OrganizedCallback<Source, Target>} apply - Callback function that defines how each source property is mapped to the target
1666
- * @param {Target} [baseTarget={}] - Optional base target object to use (will be made reactive if not already)
1667
- *
1668
- * @returns {OrganizedResult<Target>} The target object with cleanup capability
1669
- *
1670
- * @example
1671
- * // Organize user permissions into role-based access
1672
- * const user = reactive({ isAdmin: true, canEdit: false });
1673
- * const permissions = organized(
1674
- * user,
1675
- * (access, target) => {
1676
- * if (access.key === 'isAdmin') {
1677
- * target.hasFullAccess = access.value;
1678
- * }
1679
- * target[`can${access.key.charAt(0).toUpperCase() + access.key.slice(1)}`] = access.value;
1680
- * }
1681
- * );
1682
- *
1683
- * @example
1684
- * // Transform object structure with cleanup
1685
- * const source = reactive({ firstName: 'John', lastName: 'Doe' });
1686
- * const formatted = organized(
1687
- * source,
1688
- * (access, target) => {
1689
- * if (access.key === 'firstName' || access.key === 'lastName') {
1690
- * target.fullName = `${source.firstName} ${source.lastName}`.trim();
1691
- * }
1692
- * }
1693
- * );
1694
- *
1695
- * @example
1696
- * // Using with cleanup in a component
1697
- * effect(() => {
1698
- * const data = fetchData();
1699
- * const organizedData = organized(data, (access, target) => {
1700
- * // Transform data
1701
- * });
1702
- *
1703
- * // The cleanup will be called automatically when the effect is disposed
1704
- * return () => organizedData[cleanup]();
1705
- * });
1706
- */
1707
- function organized(source, apply, baseTarget = {}) {
1708
- const observedSource = proxy.reactive(source);
1709
- const target = proxy.reactive(baseTarget);
1710
- const stop = attend(() => {
1711
- const keys = [];
1712
- for (const key in observedSource)
1713
- keys.push(key);
1714
- return keys;
1715
- }, (key) => {
1716
- const sourceKey = key;
1717
- const accessBase = {
1718
- key: sourceKey,
1719
- get: () => proxy.FoolProof.get(observedSource, sourceKey, observedSource),
1720
- set: (value) => proxy.FoolProof.set(observedSource, sourceKey, value, observedSource),
1721
- };
1722
- Object.defineProperty(accessBase, 'value', {
1723
- get: accessBase.get,
1724
- set: accessBase.set,
1725
- configurable: true,
1726
- enumerable: true,
90
+ globalThis[GLOBAL_ORIGINALS] = originals;
91
+ globalThis[GLOBAL_PROMISE] = OriginalPromise;
92
+ }
93
+ // Ensure modern statics are captured even if originals was cached from an older version
94
+ if (!originals.allSettled)
95
+ originals.allSettled = OriginalPromise.allSettled;
96
+ if (!originals.any)
97
+ originals.any = OriginalPromise.any;
98
+ if (!originals.race)
99
+ originals.race = OriginalPromise.race;
100
+ function patchedThen(onFulfilled, onRejected) {
101
+ const context = promiseContexts.get(this) || captureRestorers();
102
+ const nextPromise = originals.then.call(this, wrap(onFulfilled, context), wrap(onRejected, context));
103
+ if (context.size > 0)
104
+ promiseContexts.set(nextPromise, context);
105
+ return nextPromise;
106
+ }
107
+ function patchedCatch(onRejected) {
108
+ const context = promiseContexts.get(this) || captureRestorers();
109
+ const nextPromise = originals.catch.call(this, wrap(onRejected, context));
110
+ if (context.size > 0)
111
+ promiseContexts.set(nextPromise, context);
112
+ return nextPromise;
113
+ }
114
+ function patchedFinally(onFinally) {
115
+ const context = promiseContexts.get(this) || captureRestorers();
116
+ const nextPromise = originals.finally.call(this, wrap(onFinally, context));
117
+ if (context.size > 0)
118
+ promiseContexts.set(nextPromise, context);
119
+ return nextPromise;
120
+ }
121
+ function PatchedPromise(executor) {
122
+ if (typeof executor === 'function') {
123
+ const p = new OriginalPromise((resolve, reject) => {
124
+ const wrappedResolve = wrap(resolve);
125
+ const wrappedReject = wrap(reject);
126
+ executor(wrappedResolve, wrappedReject);
1727
127
  });
1728
- return apply(accessBase, target);
1729
- });
1730
- return proxy.cleanedBy(target, (reason) => stop(reason));
1731
- }
1732
- /**
1733
- * Organizes a property on a target object
1734
- * Shortcut for defineProperty/delete with touched signal
1735
- * @param target - The target object
1736
- * @param property - The property to organize
1737
- * @param access - The access object
1738
- * @returns The property descriptor
1739
- */
1740
- function organize(target, property, access) {
1741
- Object.defineProperty(target, property, {
1742
- get: access.get,
1743
- set: access.set,
1744
- configurable: true,
1745
- enumerable: true,
1746
- });
1747
- proxy.touched1(target, { type: 'set', prop: property }, property);
1748
- return () => delete target[property];
1749
- }
1750
-
1751
- //#region watch
1752
- const unsetYet = Symbol('unset-yet');
1753
- const watch = proxy.flavored(function watch(value, //object | ((dep: DependencyAccess) => object),
1754
- changed, options = {}) {
1755
- return typeof value === 'function'
1756
- ? watchCallBack(value, changed, options)
1757
- : typeof value === 'object' && value !== null
1758
- ? watchObject(value, changed, options)
1759
- : (() => {
1760
- throw new Error('watch: value must be a function or an object');
1761
- })();
1762
- }, {
1763
- get deep() {
1764
- return proxy.flavorOptions(this, { deep: true });
1765
- },
1766
- get immediate() {
1767
- return proxy.flavorOptions(this, { immediate: true });
1768
- },
128
+ const context = captureRestorers();
129
+ promiseContexts.set(p, context); // Always set, even if empty (Sticky Root)
130
+ return p;
131
+ }
132
+ return new OriginalPromise(executor);
133
+ }
134
+ // Copy statics
135
+ Object.assign(PatchedPromise, OriginalPromise);
136
+ // Inherit prototype for instanceof checks
137
+ PatchedPromise.prototype = OriginalPromise.prototype;
138
+ PatchedPromise.resolve = ((value) => {
139
+ const p = originals.resolve.call(OriginalPromise, value);
140
+ const context = captureRestorers();
141
+ // Ensure we don't overwrite if it already has context (e.g. from constructor)
142
+ if (context.size > 0 && !promiseContexts.has(p))
143
+ promiseContexts.set(p, context);
144
+ return p;
1769
145
  });
1770
- function watchObject(value, changed, { immediate = false, deep = false } = {}) {
1771
- if (deep)
1772
- return deepWatch(value, changed, { immediate });
1773
- return proxy.effect(function watchObjectEffect() {
1774
- proxy.dependant(value);
1775
- if (immediate)
1776
- changed(value);
1777
- immediate = true;
1778
- });
1779
- }
1780
- function watchCallBack(value, changed, { immediate = false, deep = false } = {}) {
1781
- let oldValue = unsetYet;
1782
- let deepCleanup;
1783
- const cbCleanup = proxy.effect(proxy.markWithRoot(function watchCallBackEffect(access) {
1784
- const newValue = value(access);
1785
- if (oldValue !== newValue) {
1786
- const old = oldValue;
1787
- if (old === unsetYet) {
1788
- if (immediate)
1789
- proxy.untracked(() => changed(newValue));
1790
- }
1791
- else
1792
- proxy.untracked(() => changed(newValue, old));
1793
- }
1794
- oldValue = newValue;
1795
- if (deep) {
1796
- if (deepCleanup)
1797
- deepCleanup();
1798
- deepCleanup = deepWatch(newValue, (value) => changed(value, value));
1799
- }
1800
- }, value));
1801
- return Object.defineProperties(() => {
1802
- cbCleanup();
1803
- if (deepCleanup)
1804
- deepCleanup();
1805
- }, {
1806
- [proxy.stopped]: { get: () => cbCleanup[proxy.stopped] },
1807
- });
1808
- }
1809
- //#endregion
1810
- //#region when
1811
- /**
1812
- * Returns a promise that resolves when the predicate returns a truthy value.
1813
- * The predicate is evaluated reactively — it re-runs whenever its dependencies change.
1814
- * @param predicate - Reactive function that returns a value; resolves when truthy
1815
- * @param timeout - Optional timeout in milliseconds — rejects if condition is not met within this duration
1816
- * @returns Promise that resolves with the first truthy return value
1817
- */
1818
- function when(predicate, timeout) {
1819
- return new Promise((resolve, reject) => {
1820
- let timer;
1821
- const stop = proxy.effect(function whenEffect(access) {
1822
- try {
1823
- const value = predicate(access);
1824
- if (value) {
1825
- if (timer !== undefined)
1826
- clearTimeout(timer);
1827
- timer = undefined;
1828
- queueMicrotask(() => stop());
1829
- resolve(value);
1830
- }
1831
- }
1832
- catch (error) {
1833
- if (timer !== undefined)
1834
- clearTimeout(timer);
1835
- timer = undefined;
1836
- reject(error);
1837
- }
1838
- });
1839
- if (timeout !== undefined) {
1840
- timer = setTimeout(() => {
1841
- stop();
1842
- timer = undefined;
1843
- reject(new Error(`when: timed out after ${timeout}ms`));
1844
- }, timeout);
1845
- }
1846
- });
1847
- }
1848
- //#endregion
1849
- //#region nonReactive
1850
- /**
1851
- * Mark an object as non-reactive. This object and all its properties will never be made reactive.
1852
- * @param obj - The object to mark as non-reactive
1853
- */
1854
- function shallowNonReactive(obj) {
1855
- obj = proxy.unwrap(obj);
1856
- if (proxy.isNonReactive(obj))
1857
- return obj;
1858
- proxy.nonReactiveObjects.add(obj);
1859
- return obj;
1860
- }
1861
- function unreactiveApplication(arg1, ...args) {
1862
- return typeof arg1 === 'object'
1863
- ? shallowNonReactive(arg1)
1864
- : ((original) => {
1865
- // Copy the parent's unreactive properties if they exist
1866
- const parentSet = proxy.unreactiveProps.get(original.prototype);
1867
- const set = new Set(parentSet || []);
1868
- // Add all arguments (including the first one)
1869
- set.add(arg1);
1870
- for (const arg of args)
1871
- set.add(arg);
1872
- proxy.addUnreactiveProps(original.prototype, set);
1873
- return original; // Return the class
1874
- });
1875
- }
1876
- /**
1877
- * Decorator that marks classes or properties as non-reactive
1878
- * Prevents objects from being made reactive
1879
- */
1880
- const unreactive = proxy.decorator({
1881
- class(original) {
1882
- // Called without arguments, mark entire class as non-reactive
1883
- proxy.nonReactiveClass(original);
1884
- },
1885
- default: unreactiveApplication,
146
+ PatchedPromise.reject = ((reason) => {
147
+ const p = originals.reject.call(OriginalPromise, reason);
148
+ const context = captureRestorers();
149
+ if (context.size > 0)
150
+ promiseContexts.set(p, context);
151
+ return p;
1886
152
  });
1887
- /**
1888
- * Creates a reactive resource that automatically tracks async state.
1889
- * @param fetcher - Async function that returns the value. Reactive dependencies are tracked.
1890
- * @param options - Resource options (initialValue)
1891
- * @returns Reactive Resource object with value, loading, error, latest properties
1892
- */
1893
- function resource(fetcher, options = {}) {
1894
- const state = proxy.reactive({
1895
- value: options.initialValue,
1896
- loading: true,
1897
- error: undefined,
1898
- latest: options.initialValue,
1899
- reload: () => {
1900
- reloadSignal.value++;
1901
- },
1902
- });
1903
- const reloadSignal = proxy.reactive({ value: 0 });
1904
- let counter = 0;
1905
- const stop = proxy.effect(function resourceEffect(access) {
1906
- // Track reload signal to enable manual reloading
1907
- if (reloadSignal.value) ;
1908
- const id = ++counter;
1909
- state.loading = true;
1910
- state.error = undefined;
1911
- try {
1912
- const result = fetcher(access);
1913
- if (result instanceof Promise) {
1914
- result.then((val) => {
1915
- if (id === counter) {
1916
- state.value = val;
1917
- state.latest = val;
1918
- state.loading = false;
1919
- }
1920
- }, (err) => {
1921
- if (id === counter) {
1922
- state.error = err;
1923
- state.loading = false;
1924
- }
1925
- });
1926
- }
1927
- else {
1928
- state.value = result;
1929
- state.latest = result;
1930
- state.loading = false;
1931
- }
1932
- }
1933
- catch (err) {
1934
- state.error = err;
1935
- state.loading = false;
1936
- }
1937
- });
1938
- state.stop = stop;
1939
- return state;
1940
- }
1941
- //#endregion
1942
-
1943
- // Helper to work around TypeScript limitation: base class expressions cannot reference class type parameters
1944
- function getRegisterBase() {
1945
- class RegisterBase extends Indexable(ArrayReadForward, {
1946
- get(index) {
1947
- return this[getAt](index);
1948
- },
1949
- set(index, value) {
1950
- this[setAt](index, value);
1951
- },
1952
- getLength() {
1953
- return this.length;
1954
- },
1955
- setLength(value) {
1956
- this.length = value;
1957
- },
1958
- }) {
1959
- toArray() {
1960
- return Array.from(this);
1961
- }
1962
- }
1963
- return RegisterBase;
1964
- }
1965
- let RegisterClass = (() => {
1966
- var _RegisterClass_instances, _RegisterClass_keyFn, _RegisterClass_keys, _RegisterClass_values, _RegisterClass_usage, _RegisterClass_valueInfo, _RegisterClass_keyEffects, _RegisterClass_ascend, _RegisterClass_events, _RegisterClass_rekeyValue;
1967
- let _classDecorators = [unreactive];
1968
- let _classDescriptor;
1969
- let _classExtraInitializers = [];
1970
- let _classThis;
1971
- let _classSuper = getRegisterBase();
1972
- _classThis = class extends _classSuper {
1973
- 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)]() {
1974
- return this.toArray();
1975
- }
1976
- on(eventOrEvents, cb) {
1977
- // @ts-expect-error Delegate to Eventful
1978
- return proxy.__classPrivateFieldGet(this, _RegisterClass_events, "f").on(eventOrEvents, cb);
1979
- }
1980
- off(eventOrEvents, cb) {
1981
- // @ts-expect-error Delegate to Eventful
1982
- proxy.__classPrivateFieldGet(this, _RegisterClass_events, "f").off(eventOrEvents, cb);
1983
- }
1984
- /**
1985
- * Register a global hook that receives all events
1986
- */
1987
- hook(cb) {
1988
- return proxy.__classPrivateFieldGet(this, _RegisterClass_events, "f").hook(cb);
1989
- }
1990
- constructor(keyFn, initial) {
1991
- super();
1992
- _RegisterClass_instances.add(this);
1993
- _RegisterClass_keyFn.set(this, void 0);
1994
- _RegisterClass_keys.set(this, void 0);
1995
- _RegisterClass_values.set(this, void 0);
1996
- _RegisterClass_usage.set(this, new Map());
1997
- _RegisterClass_valueInfo.set(this, new Map());
1998
- _RegisterClass_keyEffects.set(this, new Set());
1999
- _RegisterClass_ascend.set(this, void 0);
2000
- _RegisterClass_events.set(this, new Eventful()
2001
- /**
2002
- * Register event listeners for CRUD operations
2003
- */
2004
- );
2005
- /* Moved below initialization */
2006
- let ascendGet;
2007
- proxy.effect(({ ascend }) => {
2008
- ascendGet = ascend;
2009
- });
2010
- proxy.__classPrivateFieldSet(this, _RegisterClass_ascend, ascendGet, "f");
2011
- if (typeof keyFn !== 'function')
2012
- throw new Error('Register requires a key function');
2013
- proxy.__classPrivateFieldSet(this, _RegisterClass_keyFn, keyFn, "f");
2014
- proxy.__classPrivateFieldSet(this, _RegisterClass_keys, proxy.reactive([]), "f");
2015
- proxy.__classPrivateFieldSet(this, _RegisterClass_values, proxy.reactive(new Map()), "f");
2016
- if (initial)
2017
- this.push(...initial);
2018
- }
2019
- ensureKey(value) {
2020
- let info = proxy.__classPrivateFieldGet(this, _RegisterClass_valueInfo, "f").get(value);
2021
- if (info)
2022
- return info.key;
2023
- info = { key: undefined };
2024
- proxy.__classPrivateFieldGet(this, _RegisterClass_valueInfo, "f").set(value, info);
2025
- proxy.__classPrivateFieldGet(this, _RegisterClass_ascend, "f").call(this, () => {
2026
- const stop = proxy.effect(({ reaction }) => {
2027
- const nextKey = proxy.__classPrivateFieldGet(this, _RegisterClass_keyFn, "f").call(this, value);
2028
- this.assertValidKey(nextKey);
2029
- const previousKey = info.key;
2030
- if (reaction && previousKey !== undefined && !Object.is(nextKey, previousKey))
2031
- proxy.__classPrivateFieldGet(this, _RegisterClass_instances, "m", _RegisterClass_rekeyValue).call(this, value, previousKey, nextKey);
2032
- info.key = nextKey;
2033
- });
2034
- info.stop = stop;
2035
- proxy.__classPrivateFieldGet(this, _RegisterClass_keyEffects, "f").add(stop);
2036
- });
2037
- if (info.key === undefined)
2038
- throw new Error('Register key function must return a property key');
2039
- return info.key;
2040
- }
2041
- assertValidKey(key) {
2042
- const type = typeof key;
2043
- if (type !== 'string' && type !== 'number' && type !== 'symbol')
2044
- throw new Error('Register key function must return a property key');
2045
- }
2046
- setKeyValue(key, value, index) {
2047
- const existing = proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(key);
2048
- if (existing !== undefined && existing !== value) {
2049
- this.cleanupValue(existing);
2050
- proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").set(key, value);
2051
- if (index !== undefined) {
2052
- proxy.__classPrivateFieldGet(this, _RegisterClass_events, "f").emit('update', existing, value, key, index);
2053
- }
2054
- }
2055
- else {
2056
- proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").set(key, value);
2057
- }
2058
- }
2059
- cleanupValue(value) {
2060
- const info = proxy.__classPrivateFieldGet(this, _RegisterClass_valueInfo, "f").get(value);
2061
- if (!info)
2062
- return;
2063
- const stop = info.stop;
2064
- if (stop) {
2065
- info.stop = undefined;
2066
- proxy.__classPrivateFieldGet(this, _RegisterClass_keyEffects, "f").delete(stop);
2067
- stop();
2068
- }
2069
- proxy.__classPrivateFieldGet(this, _RegisterClass_valueInfo, "f").delete(value);
2070
- }
2071
- disposeKeyEffects() {
2072
- for (const value of Array.from(proxy.__classPrivateFieldGet(this, _RegisterClass_valueInfo, "f").keys()))
2073
- this.cleanupValue(value);
2074
- proxy.__classPrivateFieldGet(this, _RegisterClass_keyEffects, "f").clear();
2075
- }
2076
- incrementUsage(key) {
2077
- const count = proxy.__classPrivateFieldGet(this, _RegisterClass_usage, "f").get(key) ?? 0;
2078
- proxy.__classPrivateFieldGet(this, _RegisterClass_usage, "f").set(key, count + 1);
2079
- }
2080
- decrementUsage(key, index) {
2081
- const count = proxy.__classPrivateFieldGet(this, _RegisterClass_usage, "f").get(key);
2082
- if (!count)
2083
- return;
2084
- if (count <= 1) {
2085
- const value = proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(key);
2086
- proxy.__classPrivateFieldGet(this, _RegisterClass_usage, "f").delete(key);
2087
- proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").delete(key);
2088
- if (value !== undefined) {
2089
- this.cleanupValue(value);
2090
- const idx = index ?? proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").indexOf(key);
2091
- proxy.__classPrivateFieldGet(this, _RegisterClass_events, "f").emit('delete', value, key, idx);
2092
- }
2093
- }
2094
- else {
2095
- proxy.__classPrivateFieldGet(this, _RegisterClass_usage, "f").set(key, count - 1);
2096
- }
2097
- }
2098
- normalizeIndex(index, allowEnd = false) {
2099
- const length = this.length;
2100
- let resolved = index;
2101
- if (resolved < 0)
2102
- resolved = Math.max(length + resolved, 0);
2103
- if (resolved > length) {
2104
- if (allowEnd)
2105
- resolved = length;
2106
- else
2107
- throw new RangeError('Index out of bounds');
2108
- }
2109
- if (!allowEnd && resolved === length)
2110
- throw new RangeError('Index out of bounds');
2111
- return resolved;
2112
- }
2113
- assignAt(index, key, value) {
2114
- const oldKey = proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f")[index];
2115
- if (oldKey !== undefined && Object.is(oldKey, key)) {
2116
- const oldValue = proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(key);
2117
- this.setKeyValue(key, value);
2118
- if (oldValue !== undefined && oldValue !== value) {
2119
- proxy.__classPrivateFieldGet(this, _RegisterClass_events, "f").emit('update', oldValue, value, key, index);
2120
- }
2121
- return;
2122
- }
2123
- if (oldKey !== undefined)
2124
- this.decrementUsage(oldKey);
2125
- proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f")[index] = key;
2126
- this.incrementUsage(key);
2127
- this.setKeyValue(key, value);
2128
- proxy.__classPrivateFieldGet(this, _RegisterClass_events, "f").emit('add', value, key, index);
2129
- }
2130
- insertKeyValue(index, key, value) {
2131
- proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").splice(index, 0, key);
2132
- this.incrementUsage(key);
2133
- this.setKeyValue(key, value);
2134
- proxy.__classPrivateFieldGet(this, _RegisterClass_events, "f").emit('add', value, key, index);
2135
- }
2136
- rebuildFrom(values) {
2137
- this.disposeKeyEffects();
2138
- proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").splice(0, proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").length);
2139
- proxy.__classPrivateFieldGet(this, _RegisterClass_usage, "f").clear();
2140
- proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").clear();
2141
- for (const value of values) {
2142
- const key = this.ensureKey(value);
2143
- proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").push(key);
2144
- this.incrementUsage(key);
2145
- proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").set(key, value);
2146
- }
2147
- }
2148
- get length() {
2149
- return proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").length;
2150
- }
2151
- [(_RegisterClass_rekeyValue = function _RegisterClass_rekeyValue(value, oldKey, newKey) {
2152
- if (Object.is(oldKey, newKey))
2153
- return;
2154
- const existingValue = proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(newKey);
2155
- if (existingValue !== undefined && existingValue !== value)
2156
- throw new Error(`Register key collision for key ${String(newKey)}`);
2157
- const count = proxy.__classPrivateFieldGet(this, _RegisterClass_usage, "f").get(oldKey);
2158
- if (!count)
2159
- return;
2160
- const existingCount = proxy.__classPrivateFieldGet(this, _RegisterClass_usage, "f").get(newKey) ?? 0;
2161
- this.setKeyValue(newKey, value);
2162
- let index = -1;
2163
- for (let i = 0; i < proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").length; i++)
2164
- if (Object.is(proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f")[i], oldKey)) {
2165
- proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f")[i] = newKey;
2166
- if (index === -1)
2167
- index = i;
2168
- }
2169
- proxy.__classPrivateFieldGet(this, _RegisterClass_usage, "f").set(newKey, existingCount + count);
2170
- proxy.__classPrivateFieldGet(this, _RegisterClass_usage, "f").delete(oldKey);
2171
- proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").delete(oldKey);
2172
- const updatedInfo = proxy.__classPrivateFieldGet(this, _RegisterClass_valueInfo, "f").get(value);
2173
- if (updatedInfo)
2174
- updatedInfo.key = newKey;
2175
- if (index !== -1) {
2176
- proxy.__classPrivateFieldGet(this, _RegisterClass_events, "f").emit('rekey', value, oldKey, newKey, index);
2177
- }
2178
- }, getAt)](index) {
2179
- const key = proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f")[index];
2180
- return key === undefined ? undefined : proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(key);
2181
- }
2182
- [setAt](index, value) {
2183
- const key = this.ensureKey(value);
2184
- if (index === this.length) {
2185
- this.insertKeyValue(index, key, value);
2186
- return;
2187
- }
2188
- const normalized = this.normalizeIndex(index);
2189
- this.assignAt(normalized, key, value);
2190
- }
2191
- push(...items) {
2192
- for (const item of items) {
2193
- const key = this.ensureKey(item);
2194
- this.insertKeyValue(this.length, key, item);
2195
- }
2196
- return this.length;
2197
- }
2198
- pop() {
2199
- if (!this.length)
2200
- return undefined;
2201
- return this.removeAt(this.length - 1);
2202
- }
2203
- shift() {
2204
- if (!this.length)
2205
- return undefined;
2206
- return this.removeAt(0);
2207
- }
2208
- unshift(...items) {
2209
- let index = 0;
2210
- for (const item of items) {
2211
- const key = this.ensureKey(item);
2212
- this.insertKeyValue(index++, key, item);
2213
- }
2214
- return this.length;
2215
- }
2216
- splice(start, deleteCount, ...items) {
2217
- const normalizedStart = this.normalizeIndex(start, true);
2218
- const maxDeletions = this.length - normalizedStart;
2219
- const actualDelete = Math.min(deleteCount === undefined ? maxDeletions : Math.max(deleteCount, 0), maxDeletions);
2220
- const keysToInsert = [];
2221
- for (const item of items)
2222
- keysToInsert.push(this.ensureKey(item));
2223
- const removedKeys = proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").splice(normalizedStart, actualDelete, ...keysToInsert);
2224
- const removedValues = [];
2225
- for (let i = 0; i < removedKeys.length; i++) {
2226
- const key = removedKeys[i];
2227
- if (key === undefined)
2228
- continue;
2229
- const value = proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(key);
2230
- this.decrementUsage(key, normalizedStart + i);
2231
- removedValues.push(value);
2232
- }
2233
- for (let i = 0; i < keysToInsert.length; i++) {
2234
- const key = keysToInsert[i];
2235
- const value = items[i];
2236
- this.incrementUsage(key);
2237
- this.setKeyValue(key, value);
2238
- }
2239
- return removedValues;
2240
- }
2241
- clear() {
2242
- proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").length = 0;
2243
- proxy.__classPrivateFieldGet(this, _RegisterClass_usage, "f").clear();
2244
- proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").clear();
2245
- this.disposeKeyEffects();
2246
- }
2247
- get(key) {
2248
- return proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(key);
2249
- }
2250
- set(key, value) {
2251
- if (proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").has(key))
2252
- this.setKeyValue(key, value);
2253
- }
2254
- remove(key) {
2255
- let index = this.indexOfKey(key);
2256
- while (index !== -1) {
2257
- this.removeAt(index);
2258
- index = this.indexOfKey(key);
2259
- }
2260
- }
2261
- removeAt(index) {
2262
- const [key] = proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").splice(index, 1);
2263
- if (key === undefined)
2264
- return undefined;
2265
- const value = proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(key);
2266
- this.decrementUsage(key, index);
2267
- return value;
2268
- }
2269
- /**
2270
- * Keep only the items for which the predicate returns true.
2271
- * Items for which the predicate returns false are removed.
2272
- *
2273
- * The predicate is evaluated once per distinct key; duplicate keys
2274
- * will follow the same keep/remove decision.
2275
- */
2276
- keep(predicate) {
2277
- const decisions = new Map();
2278
- for (const [index, key] of proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").entries()) {
2279
- if (decisions.has(key)) {
2280
- if (!decisions.get(key))
2281
- this.removeAt(index);
2282
- continue;
2283
- }
2284
- const value = proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(key);
2285
- const shouldKeep = predicate(value);
2286
- decisions.set(key, shouldKeep);
2287
- if (!shouldKeep)
2288
- this.removeAt(index);
2289
- }
2290
- }
2291
- hasKey(key) {
2292
- return proxy.__classPrivateFieldGet(this, _RegisterClass_usage, "f").has(key);
2293
- }
2294
- indexOfKey(key) {
2295
- return proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").indexOf(key);
2296
- }
2297
- mapKeys() {
2298
- return proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").keys();
2299
- }
2300
- update(...values) {
2301
- for (const value of values) {
2302
- const key = this.ensureKey(value);
2303
- if (proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").has(key)) {
2304
- const index = proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").indexOf(key);
2305
- this.setKeyValue(key, value, index);
2306
- }
2307
- }
2308
- }
2309
- upsert(insert, ...values) {
2310
- for (const value of values) {
2311
- const key = this.ensureKey(value);
2312
- if (proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").has(key))
2313
- this.setKeyValue(key, value);
2314
- else
2315
- insert(value);
2316
- }
2317
- }
2318
- entries() {
2319
- const self = this;
2320
- function* iterator() {
2321
- for (let i = 0; i < proxy.__classPrivateFieldGet(self, _RegisterClass_keys, "f").length; i++) {
2322
- const val = proxy.__classPrivateFieldGet(self, _RegisterClass_values, "f").get(proxy.__classPrivateFieldGet(self, _RegisterClass_keys, "f")[i]);
2323
- if (val !== undefined)
2324
- yield [i, val];
2325
- }
2326
- }
2327
- return iterator();
2328
- }
2329
- [Symbol.iterator]() {
2330
- const self = this;
2331
- function* iterator() {
2332
- for (const key of proxy.__classPrivateFieldGet(self, _RegisterClass_keys, "f")) {
2333
- const value = proxy.__classPrivateFieldGet(self, _RegisterClass_values, "f").get(key);
2334
- if (value !== undefined)
2335
- yield value;
2336
- }
2337
- }
2338
- return iterator();
2339
- }
2340
- toString() {
2341
- return `[Register length=${this.length}]`;
2342
- }
2343
- at(index) {
2344
- const resolved = index < 0 ? this.length + index : index;
2345
- if (resolved < 0 || resolved >= this.length)
2346
- return undefined;
2347
- return this[getAt](resolved);
2348
- }
2349
- reverse() {
2350
- proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").reverse();
2351
- return this;
2352
- }
2353
- sort(compareFn) {
2354
- const fwdCompareFn = compareFn
2355
- ? (a, b) => compareFn(proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(a), proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(b))
2356
- : undefined;
2357
- proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").sort(fwdCompareFn);
2358
- return this;
2359
- }
2360
- fill(value, start = 0, end = this.length) {
2361
- const values = this.toArray();
2362
- values.fill(value, start, end);
2363
- this.rebuildFrom(values);
2364
- return this;
2365
- }
2366
- copyWithin(target, start, end) {
2367
- const values = this.toArray();
2368
- values.copyWithin(target, start, end);
2369
- this.rebuildFrom(values);
2370
- return this;
2371
- }
2372
- };
2373
- proxy.__setFunctionName(_classThis, "RegisterClass");
2374
- (() => {
2375
- const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
2376
- proxy.__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
2377
- _classThis = _classDescriptor.value;
2378
- if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
2379
- proxy.__runInitializers(_classThis, _classExtraInitializers);
2380
- })();
2381
- return _classThis;
2382
- })();
2383
- const Register = RegisterClass;
2384
- /**
2385
- * Creates a reactive Register - an ordered, array-like collection with stable key-based identity.
2386
- *
2387
- * Register combines array semantics (indexable access, ordering, iteration) with Map-like
2388
- * key-based lookups. Items with the same key share the same value instance, making it ideal
2389
- * for UI lists keyed by IDs or when you need to preserve identity across reorders.
2390
- *
2391
- * @param keyFn - Function that extracts the key from each item
2392
- * @param initial - Optional initial items to populate the register
2393
- * @returns A reactive Register instance
2394
- *
2395
- * @example
2396
- * ```typescript
2397
- * const users = register(
2398
- * (user: User) => user.id,
2399
- * [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]
2400
- * )
2401
- *
2402
- * users.push({ id: 3, name: 'Charlie' })
2403
- * const bob = users.get(2) // Get by key
2404
- * ```
2405
- */
2406
- function register(keyFn, initial) {
2407
- return new RegisterClass(keyFn, initial);
2408
- }
2409
-
2410
- /**
2411
- * Converts an iterator to a generator that yields reactive values
2412
- */
2413
- function* makeReactiveIterator(iterator) {
2414
- let result = iterator.next();
2415
- while (!result.done) {
2416
- yield proxy.reactive(result.value);
2417
- result = iterator.next();
2418
- }
2419
- }
2420
- /**
2421
- * Converts an iterator of key-value pairs to a generator that yields reactive key-value pairs
2422
- */
2423
- function* makeReactiveEntriesIterator(iterator) {
2424
- let result = iterator.next();
2425
- while (!result.done) {
2426
- const [key, value] = result.value;
2427
- yield [proxy.reactive(key), proxy.reactive(value)];
2428
- result = iterator.next();
2429
- }
2430
- }
2431
-
2432
- function* index(i, { length = true } = {}) {
2433
- if (length)
2434
- yield 'length';
2435
- yield i;
2436
- }
2437
- class Indexer extends Array {
2438
- get(i) {
2439
- proxy.dependant(this, i);
2440
- return proxy.reactive(this[i]);
2441
- }
2442
- // Returns undefined intentionally: signals the proxy handler that notifications
2443
- // were already dispatched via touched(), preventing double notification
2444
- set(i, value) {
2445
- const added = i >= this.length;
2446
- this[i] = value;
2447
- proxy.touched(this, { type: 'set', prop: i }, index(i, { length: added }));
2448
- }
2449
- }
2450
- const indexLess = { get: proxy.FoolProof.get, set: proxy.FoolProof.set };
2451
- // Fast numeric-string check: first char is a digit (0-9)
2452
- function asIndex(prop) {
2453
- const c = prop.charCodeAt(0);
2454
- if (c < 48 || c > 57)
2455
- return -1; // not 0-9
2456
- const n = +prop; // coerce — faster than parseInt, handles "0", "12", etc.
2457
- return n === (n | 0) && n >= 0 ? n : -1;
2458
- }
2459
- Object.assign(proxy.FoolProof, {
2460
- get(obj, prop, receiver) {
2461
- if (Array.isArray(obj) && typeof prop === 'string') {
2462
- const i = asIndex(prop);
2463
- if (i >= 0)
2464
- return Indexer.prototype.get.call(obj, i);
2465
- }
2466
- return indexLess.get(obj, prop, receiver);
2467
- },
2468
- set(obj, prop, value, receiver) {
2469
- if (Array.isArray(obj) && typeof prop === 'string') {
2470
- const i = asIndex(prop);
2471
- if (i >= 0)
2472
- return Indexer.prototype.set.call(obj, i, value);
2473
- }
2474
- return indexLess.set(obj, prop, value, receiver);
2475
- },
153
+ PatchedPromise.all = ((values) => {
154
+ const p = originals.all.call(OriginalPromise, values);
155
+ const context = captureRestorers();
156
+ if (context.size > 0)
157
+ promiseContexts.set(p, context);
158
+ return p;
2476
159
  });
2477
- class ReactiveArray extends Array {
2478
- toJSON() {
2479
- return this;
2480
- }
2481
- }
2482
- /**
2483
- * This is a wrapper class for Array that adds reactive behavior.
2484
- * It extends Array and overrides methods to add reactive behavior, while making sure that the internal representation is not reactive.
2485
- */
2486
- let ReactiveArrayWrapper = (() => {
2487
- var _a;
2488
- let _classSuper = Array;
2489
- let _instanceExtraInitializers = [];
2490
- let _fill_decorators;
2491
- let _pop_decorators;
2492
- let _push_decorators;
2493
- let _reverse_decorators;
2494
- let _shift_decorators;
2495
- let _sort_decorators;
2496
- let _splice_decorators;
2497
- let _unshift_decorators;
2498
- return _a = class ReactiveArrayWrapper extends _classSuper {
2499
- at(index) {
2500
- return proxy.reactive(super.at(index));
2501
- }
2502
- concat(...items) {
2503
- return proxy.reactive(super.concat(...items.map(proxy.unwrap)));
2504
- }
2505
- entries() {
2506
- proxy.dependant(this, proxy.keysOf);
2507
- return makeReactiveEntriesIterator(super.entries());
2508
- }
2509
- every(predicate, thisArg) {
2510
- return super.every((v, i, a) => predicate.call(thisArg, proxy.reactive(v), i, a), thisArg);
2511
- }
2512
- fill(value, start, end) {
2513
- return super.fill(proxy.unwrap(value), start, end);
2514
- }
2515
- filter(predicate, thisArg) {
2516
- return proxy.reactive(super.filter((v, i, a) => predicate.call(thisArg, proxy.reactive(v), i, a), thisArg));
2517
- }
2518
- find(predicate, thisArg) {
2519
- return proxy.reactive(super.find((v, i, a) => predicate.call(thisArg, proxy.reactive(v), i, a), thisArg));
2520
- }
2521
- findIndex(predicate, thisArg) {
2522
- return super.findIndex((v, i, a) => predicate.call(thisArg, proxy.reactive(v), i, a), thisArg);
2523
- }
2524
- findLast(predicate, thisArg) {
2525
- return proxy.reactive(super.findLast((v, i, a) => predicate.call(thisArg, proxy.reactive(v), i, a), thisArg));
2526
- }
2527
- findLastIndex(predicate, thisArg) {
2528
- return super.findLastIndex((v, i, a) => predicate.call(thisArg, proxy.reactive(v), i, a), thisArg);
2529
- }
2530
- flat(depth) {
2531
- return proxy.reactive(super.flat(depth));
2532
- }
2533
- flatMap(callbackfn, thisArg) {
2534
- return proxy.reactive(super.flatMap((v, i, a) => proxy.unwrap(callbackfn.call(thisArg, proxy.reactive(v), i, a)), thisArg));
2535
- }
2536
- forEach(callbackfn, thisArg) {
2537
- super.forEach((v, i, a) => {
2538
- callbackfn.call(thisArg, proxy.reactive(v), i, a);
2539
- }, thisArg);
2540
- }
2541
- includes(searchElement, fromIndex) {
2542
- return arguments.length > 1
2543
- ? super.includes(proxy.unwrap(searchElement), fromIndex)
2544
- : super.includes(proxy.unwrap(searchElement));
2545
- }
2546
- indexOf(searchElement, fromIndex) {
2547
- return arguments.length > 1
2548
- ? super.indexOf(proxy.unwrap(searchElement), fromIndex)
2549
- : super.indexOf(proxy.unwrap(searchElement));
2550
- }
2551
- join(separator) {
2552
- return super.join(separator);
2553
- }
2554
- keys() {
2555
- proxy.dependant(this, 'length');
2556
- return super.keys();
2557
- }
2558
- lastIndexOf(searchElement, fromIndex) {
2559
- return arguments.length > 1
2560
- ? super.lastIndexOf(proxy.unwrap(searchElement), fromIndex)
2561
- : super.lastIndexOf(proxy.unwrap(searchElement));
2562
- }
2563
- map(callbackfn, thisArg) {
2564
- return proxy.reactive(super.map((v, i, a) => proxy.unwrap(callbackfn.call(thisArg, proxy.reactive(v), i, a)), thisArg));
2565
- }
2566
- pop() {
2567
- return proxy.reactive(super.pop());
2568
- }
2569
- push(...items) {
2570
- return super.push(...items.map(proxy.unwrap));
2571
- }
2572
- reduce(callbackfn, initialValue) {
2573
- return proxy.reactive(arguments.length > 1
2574
- ? super.reduce((acc, v, i, a) => proxy.unwrap(callbackfn(acc, proxy.reactive(v), i, a)), initialValue)
2575
- : super.reduce((acc, v, i, a) => proxy.unwrap(callbackfn(acc, proxy.reactive(v), i, a))));
2576
- }
2577
- reduceRight(callbackfn, initialValue) {
2578
- return proxy.reactive(arguments.length > 1
2579
- ? super.reduceRight((acc, v, i, a) => proxy.unwrap(callbackfn(acc, proxy.reactive(v), i, a)), initialValue)
2580
- : super.reduceRight((acc, v, i, a) => proxy.unwrap(callbackfn(acc, proxy.reactive(v), i, a))));
2581
- }
2582
- reverse() {
2583
- return proxy.reactive(super.reverse());
2584
- }
2585
- shift() {
2586
- return proxy.reactive(super.shift());
2587
- }
2588
- slice(start, end) {
2589
- return proxy.reactive(super.slice(start, end));
2590
- }
2591
- some(predicate, thisArg) {
2592
- return super.some((v, i, a) => predicate.call(thisArg, proxy.reactive(v), i, a), thisArg);
2593
- }
2594
- sort(compareFn) {
2595
- const wrappedCompare = compareFn
2596
- ? (a, b) => compareFn(proxy.reactive(a), proxy.reactive(b))
2597
- : undefined;
2598
- return super.sort(wrappedCompare);
2599
- }
2600
- splice(start, deleteCount, ...items) {
2601
- if (arguments.length > 2)
2602
- return proxy.reactive(super.splice(start, deleteCount, ...items.map(proxy.unwrap)));
2603
- if (arguments.length === 2)
2604
- return proxy.reactive(super.splice(start, deleteCount));
2605
- if (arguments.length === 1)
2606
- return proxy.reactive(super.splice(start));
2607
- return proxy.reactive([]);
2608
- }
2609
- unshift(...items) {
2610
- return super.unshift(...items.map(proxy.unwrap));
2611
- }
2612
- values() {
2613
- proxy.dependant(this, proxy.keysOf);
2614
- return makeReactiveIterator(super.values());
2615
- }
2616
- [(_fill_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)]() {
2617
- proxy.dependant(this, proxy.keysOf);
2618
- return makeReactiveIterator(super[Symbol.iterator]());
2619
- }
2620
- toReversed() {
2621
- return proxy.reactive(super.toReversed());
2622
- }
2623
- toSorted(compareFn) {
2624
- const wrappedCompare = compareFn
2625
- ? (a, b) => compareFn(proxy.reactive(a), proxy.reactive(b))
2626
- : undefined;
2627
- return proxy.reactive(super.toSorted(wrappedCompare));
2628
- }
2629
- // biome-ignore lint/complexity/noArguments: Needed to distinguish fn() from fn(undefined)
2630
- toSpliced(start, deleteCount, ...items) {
2631
- if (arguments.length > 2)
2632
- return proxy.reactive(super.toSpliced(start, deleteCount, ...items.map(proxy.unwrap)));
2633
- if (arguments.length === 2)
2634
- return proxy.reactive(super.toSpliced(start, deleteCount));
2635
- if (arguments.length === 1)
2636
- return proxy.reactive(super.toSpliced(start));
2637
- return proxy.reactive([...this]);
2638
- }
2639
- with(index, value) {
2640
- return proxy.reactive(super.with(index, proxy.unwrap(value)));
2641
- }
2642
- constructor() {
2643
- super(...arguments);
2644
- proxy.__runInitializers(this, _instanceExtraInitializers);
2645
- }
2646
- },
2647
- (() => {
2648
- const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
2649
- 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);
2650
- 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);
2651
- 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);
2652
- 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);
2653
- 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);
2654
- 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);
2655
- 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);
2656
- 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);
2657
- if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
2658
- })(),
2659
- _a;
2660
- })();
2661
-
2662
- /**
2663
- * Reactive wrapper around JavaScript's WeakMap class
2664
- * Only tracks individual key operations, no size tracking (WeakMap limitation)
2665
- */
2666
- class ReactiveWeakMap extends WeakMap {
2667
- // Implement WeakMap interface methods with reactivity
2668
- delete(key) {
2669
- const hadKey = this.has(key);
2670
- const result = this.delete(key);
2671
- if (hadKey)
2672
- proxy.touched1(proxy.contentRef(this), { type: 'del', prop: key }, key);
2673
- return result;
2674
- }
2675
- get(key) {
2676
- proxy.dependant(proxy.contentRef(this), key);
2677
- return proxy.reactive(this.get(key));
2678
- }
2679
- has(key) {
2680
- proxy.dependant(proxy.contentRef(this), key);
2681
- return this.has(key);
2682
- }
2683
- set(key, value) {
2684
- const hadKey = this.has(key);
2685
- const oldValue = this.get(key);
2686
- const reactiveValue = proxy.reactive(value);
2687
- this.set(key, reactiveValue);
2688
- if (!hadKey || oldValue !== reactiveValue) {
2689
- proxy.notifyPropertyChange(proxy.contentRef(this), key, oldValue, reactiveValue, hadKey);
2690
- }
2691
- return this;
2692
- }
2693
- }
2694
- /**
2695
- * Reactive wrapper around JavaScript's Map class
2696
- * Tracks size changes, individual key operations, and collection-wide operations
2697
- */
2698
- class ReactiveMap extends Map {
2699
- // Implement Map interface methods with reactivity
2700
- get size() {
2701
- proxy.dependant(this, 'size'); // The ReactiveMap instance still goes through proxy
2702
- return this.size;
2703
- }
2704
- clear() {
2705
- const hadEntries = this.size > 0;
2706
- this.clear();
2707
- if (hadEntries) {
2708
- const evolution = { type: 'bunch', method: 'clear' };
2709
- // Clear triggers all effects since all keys are affected
2710
- proxy.touched1(this, evolution, 'size');
2711
- proxy.touched(proxy.contentRef(this), evolution);
2712
- }
2713
- }
2714
- entries() {
2715
- proxy.dependant(proxy.contentRef(this));
2716
- return makeReactiveEntriesIterator(this.entries());
2717
- }
2718
- forEach(callbackfn, thisArg) {
2719
- proxy.dependant(proxy.contentRef(this));
2720
- this.forEach(callbackfn, thisArg);
2721
- }
2722
- keys() {
2723
- proxy.dependant(proxy.contentRef(this), proxy.keysOf);
2724
- return this.keys();
2725
- }
2726
- values() {
2727
- proxy.dependant(proxy.contentRef(this));
2728
- return makeReactiveIterator(this.values());
2729
- }
2730
- [Symbol.iterator]() {
2731
- proxy.dependant(proxy.contentRef(this));
2732
- const it = Map.prototype[Symbol.iterator].call(this);
2733
- const nativeNext = it.next.bind(it);
2734
- it.next = () => {
2735
- const result = nativeNext();
2736
- if (result.done)
2737
- return result;
2738
- const [key, value] = result.value;
2739
- return { value: [proxy.reactive(key), proxy.reactive(value)], done: false };
2740
- };
2741
- return it;
2742
- }
2743
- // Implement Map methods with reactivity
2744
- delete(key) {
2745
- const hadKey = this.has(key);
2746
- const result = this.delete(key);
2747
- if (hadKey) {
2748
- const evolution = { type: 'del', prop: key };
2749
- proxy.touched1(proxy.contentRef(this), evolution, key);
2750
- proxy.touched1(this, evolution, 'size');
2751
- }
2752
- return result;
2753
- }
2754
- get(key) {
2755
- proxy.dependant(proxy.contentRef(this), key);
2756
- return proxy.reactive(this.get(key));
2757
- }
2758
- has(key) {
2759
- proxy.dependant(proxy.contentRef(this), key);
2760
- return this.has(key);
2761
- }
2762
- set(key, value) {
2763
- const hadKey = this.has(key);
2764
- const oldValue = this.get(key);
2765
- const reactiveValue = proxy.reactive(value);
2766
- this.set(key, reactiveValue);
2767
- if (!hadKey || oldValue !== reactiveValue) {
2768
- proxy.notifyPropertyChange(proxy.contentRef(this), key, oldValue, reactiveValue, hadKey);
2769
- // Also notify size change for Map (WeakMap doesn't track size)
2770
- const evolution = { type: hadKey ? 'set' : 'add', prop: key };
2771
- proxy.touched1(this, evolution, 'size');
2772
- }
2773
- return this;
2774
- }
2775
- }
2776
-
2777
- /**
2778
- * Reactive wrapper around JavaScript's WeakSet class
2779
- * Only tracks individual value operations, no size tracking (WeakSet limitation)
2780
- */
2781
- class ReactiveWeakSet extends WeakSet {
2782
- add(value) {
2783
- const had = this.has(value);
2784
- this.add(value);
2785
- if (!had) {
2786
- // touch the specific value and the collection view
2787
- proxy.touched1(proxy.contentRef(this), { type: 'add', prop: value }, value);
2788
- // no size/allProps for WeakSet
2789
- }
2790
- return this;
2791
- }
2792
- delete(value) {
2793
- const had = this.has(value);
2794
- const res = this.delete(value);
2795
- if (had)
2796
- proxy.touched1(proxy.contentRef(this), { type: 'del', prop: value }, value);
2797
- return res;
2798
- }
2799
- has(value) {
2800
- proxy.dependant(proxy.contentRef(this), value);
2801
- return this.has(value);
2802
- }
2803
- }
2804
- /**
2805
- * Reactive wrapper around JavaScript's Set class
2806
- * Tracks size changes, individual value operations, and collection-wide operations
2807
- */
2808
- class ReactiveSet extends Set {
2809
- get size() {
2810
- // size depends on the wrapper instance, like Map counterpart
2811
- proxy.dependant(this, 'size');
2812
- return this.size;
2813
- }
2814
- add(value) {
2815
- const had = this.has(value);
2816
- const reactiveValue = proxy.reactive(value);
2817
- this.add(reactiveValue);
2818
- if (!had) {
2819
- const evolution = { type: 'add', prop: reactiveValue };
2820
- // touch for value-specific and aggregate dependencies
2821
- proxy.touched1(proxy.contentRef(this), evolution, reactiveValue);
2822
- proxy.touched1(this, evolution, 'size');
2823
- }
2824
- return this;
2825
- }
2826
- clear() {
2827
- const hadEntries = this.size > 0;
2828
- this.clear();
2829
- if (hadEntries) {
2830
- const evolution = { type: 'bunch', method: 'clear' };
2831
- proxy.touched1(this, evolution, 'size');
2832
- proxy.touched(proxy.contentRef(this), evolution);
2833
- }
2834
- }
2835
- delete(value) {
2836
- const had = this.has(value);
2837
- const res = this.delete(value);
2838
- if (had) {
2839
- const evolution = { type: 'del', prop: value };
2840
- proxy.touched1(proxy.contentRef(this), evolution, value);
2841
- proxy.touched1(this, evolution, 'size');
2842
- }
2843
- return res;
2844
- }
2845
- has(value) {
2846
- proxy.dependant(proxy.contentRef(this), value);
2847
- return this.has(value);
2848
- }
2849
- entries() {
2850
- proxy.dependant(proxy.contentRef(this));
2851
- return makeReactiveEntriesIterator(this.entries());
2852
- }
2853
- forEach(callbackfn, thisArg) {
2854
- proxy.dependant(proxy.contentRef(this));
2855
- this.forEach(callbackfn, thisArg);
2856
- }
2857
- keys() {
2858
- proxy.dependant(proxy.contentRef(this));
2859
- return makeReactiveIterator(this.keys());
2860
- }
2861
- values() {
2862
- proxy.dependant(proxy.contentRef(this));
2863
- return makeReactiveIterator(this.values());
2864
- }
2865
- [Symbol.iterator]() {
2866
- proxy.dependant(proxy.contentRef(this));
2867
- const it = Set.prototype[Symbol.iterator].call(this);
2868
- const nativeNext = it.next.bind(it);
2869
- it.next = () => {
2870
- const result = nativeNext();
2871
- if (result.done)
2872
- return result;
2873
- return { value: proxy.reactive(result.value), done: false };
2874
- };
2875
- return it;
2876
- }
2877
- }
2878
-
2879
- // Register native collection types to use specialized reactive wrappers
2880
- console.time('mutts-reactive-init');
2881
- proxy.metaProtos.set(Array, ReactiveArray.prototype);
2882
- proxy.metaProtos.set(Set, ReactiveSet.prototype);
2883
- proxy.metaProtos.set(WeakSet, ReactiveWeakSet.prototype);
2884
- proxy.metaProtos.set(Map, ReactiveMap.prototype);
2885
- proxy.metaProtos.set(WeakMap, ReactiveWeakMap.prototype);
2886
- proxy.wrapProtos.set(Array, ReactiveArrayWrapper.prototype);
2887
- console.timeEnd('mutts-reactive-init');
2888
- /**
2889
- * Object containing internal reactive system state for debugging and profiling
2890
- */
2891
- const profileInfo = {
2892
- objectToProxy: proxy.objectToProxy,
2893
- proxyToObject: proxy.proxyToObject,
2894
- effectToReactiveObjects: proxy.effectToReactiveObjects,
2895
- watchers: proxy.watchers,
2896
- objectParents: proxy.objectParents,
2897
- objectsWithDeepWatchers: proxy.objectsWithDeepWatchers,
2898
- deepWatchers: proxy.deepWatchers,
2899
- effectToDeepWatchedObjects: proxy.effectToDeepWatchedObjects,
2900
- nonReactiveObjects: proxy.nonReactiveObjects,
2901
- };
2902
-
2903
- // In order to avoid async re-entrance, we could use zone.js or something like that.
2904
- const syncCalculating = [];
2905
- /**
2906
- * Decorator that caches the result of a getter method and only recomputes when dependencies change
2907
- * Prevents circular dependencies and provides automatic cache invalidation
2908
- */
2909
- const cached = proxy.decorator({
2910
- getter(original, _target, propertyKey) {
2911
- return function () {
2912
- const alreadyCalculating = syncCalculating.findIndex((c) => c.object === this && c.prop === propertyKey);
2913
- if (alreadyCalculating > -1)
2914
- throw new Error(`Circular dependency detected: ${syncCalculating
2915
- .slice(alreadyCalculating)
2916
- .map((c) => `${c.object.constructor.name}.${String(c.prop)}`)
2917
- .join(' -> ')} -> again`);
2918
- syncCalculating.push({ object: this, prop: propertyKey });
2919
- try {
2920
- const rv = original.call(this);
2921
- cache(this, propertyKey, rv);
2922
- return rv;
2923
- }
2924
- finally {
2925
- syncCalculating.pop();
2926
- }
2927
- };
2928
- },
160
+ PatchedPromise.allSettled = ((values) => {
161
+ const p = originals.allSettled.call(OriginalPromise, values);
162
+ const context = captureRestorers();
163
+ if (context.size > 0)
164
+ promiseContexts.set(p, context);
165
+ return p;
2929
166
  });
2930
- /**
2931
- * Checks if a property is cached (has a cached value)
2932
- * @param object - The object to check
2933
- * @param propertyKey - The property key to check
2934
- * @returns True if the property has a cached value
2935
- */
2936
- function isCached(object, propertyKey) {
2937
- return !!Object.getOwnPropertyDescriptor(object, propertyKey);
2938
- }
2939
- /**
2940
- * Caches a value for a property on an object
2941
- * @param object - The object to cache the value on
2942
- * @param propertyKey - The property key to cache
2943
- * @param value - The value to cache
2944
- */
2945
- function cache(object, propertyKey, value) {
2946
- Object.defineProperty(object, propertyKey, { value });
2947
- }
2948
- /**
2949
- * Creates a decorator that modifies property descriptors for specified properties
2950
- * @param descriptor - The descriptor properties to apply
2951
- * @returns A class decorator that applies the descriptor to specified properties
2952
- */
2953
- const descriptor = proxy.flavored(function descriptor(descriptor) {
2954
- return (...properties) => (Base) => {
2955
- return class extends Base {
2956
- constructor(...args) {
2957
- super(...args);
2958
- for (const key of properties) {
2959
- const existing = Object.getOwnPropertyDescriptor(this, key);
2960
- Object.defineProperty(this, key, Object.assign(existing || {}, descriptor));
2961
- }
2962
- }
2963
- };
2964
- };
2965
- }, {
2966
- /**
2967
- * enumerable: true
2968
- */
2969
- get enumerable() {
2970
- return descriptor({ enumerable: true });
2971
- },
2972
- /**
2973
- * enumerable: false
2974
- */
2975
- get hidden() {
2976
- return descriptor({ enumerable: false });
2977
- },
2978
- /**
2979
- * configurable: true
2980
- */
2981
- get configurable() {
2982
- return descriptor({ configurable: true });
2983
- },
2984
- /**
2985
- * configurable: false
2986
- */
2987
- get frozen() {
2988
- return descriptor({ configurable: false });
2989
- },
2990
- /**
2991
- * writable: true
2992
- */
2993
- get writable() {
2994
- return descriptor({ writable: true });
2995
- },
2996
- /**
2997
- * writable: false
2998
- */
2999
- get readonly() {
3000
- return descriptor({ writable: false });
3001
- },
167
+ PatchedPromise.race = ((values) => {
168
+ const p = originals.race.call(OriginalPromise, values);
169
+ const context = captureRestorers();
170
+ if (context.size > 0)
171
+ promiseContexts.set(p, context);
172
+ return p;
3002
173
  });
3003
- /**
3004
- * Decorator that marks methods, properties, or classes as deprecated
3005
- * Provides warning messages when deprecated items are used
3006
- */
3007
- const deprecated = Object.assign(proxy.decorator({
3008
- method(original, _target, propertyKey) {
3009
- return function (...args) {
3010
- deprecated.warn(this, propertyKey);
3011
- return original.apply(this, args);
3012
- };
3013
- },
3014
- getter(original, _target, propertyKey) {
3015
- return function () {
3016
- deprecated.warn(this, propertyKey);
3017
- return original.call(this);
3018
- };
3019
- },
3020
- setter(original, _target, propertyKey) {
3021
- return function (value) {
3022
- deprecated.warn(this, propertyKey);
3023
- return original.call(this, value);
3024
- };
3025
- },
3026
- class(original) {
3027
- return class extends original {
3028
- constructor(...args) {
3029
- super(...args);
3030
- deprecated.warn(this, 'constructor');
3031
- }
3032
- };
3033
- },
3034
- default(message) {
3035
- return proxy.decorator({
3036
- method(original, _target, propertyKey) {
3037
- return function (...args) {
3038
- deprecated.warn(this, propertyKey, message);
3039
- return original.apply(this, args);
3040
- };
3041
- },
3042
- getter(original, _target, propertyKey) {
3043
- return function () {
3044
- deprecated.warn(this, propertyKey, message);
3045
- return original.call(this);
3046
- };
3047
- },
3048
- setter(original, _target, propertyKey) {
3049
- return function (value) {
3050
- deprecated.warn(this, propertyKey, message);
3051
- return original.call(this, value);
3052
- };
3053
- },
3054
- class(original) {
3055
- return class extends original {
3056
- constructor(...args) {
3057
- super(...args);
3058
- deprecated.warn(this, 'constructor', message);
3059
- }
3060
- };
3061
- },
3062
- });
3063
- },
3064
- }), {
3065
- warn: (target, propertyKey, message) => {
3066
- // biome-ignore lint/suspicious/noConsole: To be overridden
3067
- console.warn(`${target.constructor.name}.${String(propertyKey)} is deprecated${message ? `: ${message}` : ''}`);
3068
- },
174
+ PatchedPromise.any = ((values) => {
175
+ const p = originals.any.call(OriginalPromise, values);
176
+ const context = captureRestorers();
177
+ if (context.size > 0)
178
+ promiseContexts.set(p, context);
179
+ return p;
3069
180
  });
3070
- /**
3071
- * Creates a debounced method decorator that delays execution until after the delay period has passed
3072
- * @param delay - The delay in milliseconds
3073
- * @returns A method decorator that debounces method calls
3074
- */
3075
- function debounce(delay) {
3076
- return proxy.decorator({
3077
- method(original, _target, _propertyKey) {
3078
- let timeoutId = null;
3079
- return function (...args) {
3080
- // Clear existing timeout
3081
- if (timeoutId) {
3082
- clearTimeout(timeoutId);
3083
- }
3084
- // Set new timeout
3085
- timeoutId = setTimeout(() => {
3086
- original.apply(this, args);
3087
- timeoutId = null;
3088
- }, delay);
3089
- };
3090
- },
181
+ // Only apply patches if not already applied (or re-apply safely)
182
+ // Note: OriginalPromise.prototype might be shared if we used the global one.
183
+ // We must ensure we don't patch it twice if it's the SAME object.
184
+ if (OriginalPromise.prototype.then !== patchedThen) {
185
+ // biome-ignore lint/suspicious/noThenProperty: Intentional Promise.prototype patching
186
+ OriginalPromise.prototype.then = patchedThen;
187
+ OriginalPromise.prototype.catch = patchedCatch;
188
+ OriginalPromise.prototype.finally = patchedFinally;
189
+ }
190
+ try {
191
+ Object.defineProperty(OriginalPromise, Symbol.species, {
192
+ get: () => PatchedPromise,
193
+ configurable: true,
3091
194
  });
3092
195
  }
3093
- /**
3094
- * Creates a throttled method decorator that limits execution to once per delay period
3095
- * @param delay - The delay in milliseconds
3096
- * @returns A method decorator that throttles method calls
3097
- */
3098
- function throttle(delay) {
3099
- return proxy.decorator({
3100
- method(original, _target, _propertyKey) {
3101
- let lastCallTime = 0;
3102
- let timeoutId = null;
3103
- return function (...args) {
3104
- const now = Date.now();
3105
- // If enough time has passed since last call, execute immediately
3106
- if (now - lastCallTime >= delay) {
3107
- // Clear any pending timeout since we're executing now
3108
- if (timeoutId) {
3109
- clearTimeout(timeoutId);
3110
- timeoutId = null;
3111
- }
3112
- lastCallTime = now;
3113
- return original.apply(this, args);
3114
- }
3115
- // Otherwise, schedule execution for when the delay period ends
3116
- if (!timeoutId) {
3117
- const remainingTime = delay - (now - lastCallTime);
3118
- const scheduledArgs = [...args]; // Capture args at scheduling time
3119
- timeoutId = setTimeout(() => {
3120
- lastCallTime = Date.now();
3121
- original.apply(this, scheduledArgs);
3122
- timeoutId = null;
3123
- }, remainingTime);
3124
- }
3125
- };
3126
- },
196
+ catch (_e) { }
197
+ globalThis.Promise = PatchedPromise;
198
+ globalThis.setTimeout = ((callback, ...args) => {
199
+ return originals.setTimeout.call(globalThis, wrap(callback), ...args);
200
+ });
201
+ globalThis.setInterval = ((callback, ...args) => {
202
+ return originals.setInterval.call(globalThis, wrap(callback), ...args);
203
+ });
204
+ if (originals.setImmediate) {
205
+ globalThis.setImmediate = ((callback, ...args) => {
206
+ return originals.setImmediate.call(globalThis, wrap(callback), ...args);
3127
207
  });
3128
208
  }
3129
-
3130
- var version$1 = "1.0.10";
3131
- var pkg = {
3132
- version: version$1};
3133
-
3134
- const { version } = pkg;
3135
- // Singleton verification
3136
- const GLOBAL_MUTTS_KEY = '__MUTTS_INSTANCE__';
3137
- const globalScope = (typeof globalThis !== 'undefined'
3138
- ? globalThis
3139
- : typeof window !== 'undefined'
3140
- ? window
3141
- : typeof global !== 'undefined'
3142
- ? global
3143
- : false);
3144
- if (globalScope) {
3145
- // Detect the source of this instance safely across different environments
3146
- let source = 'mutts/index';
3147
- // biome-ignore lint/security/noGlobalEval: Intentional eval for cross-env import.meta detection
3148
- const viteEval = eval;
3149
- try {
3150
- if (typeof __filename !== 'undefined')
3151
- source = __filename;
3152
- else {
3153
- // Using eval to avoid SyntaxError in CJS environments where import.meta is not allowed
3154
- const meta = viteEval('import.meta');
3155
- if (meta && meta.url)
3156
- source = meta.url;
3157
- }
3158
- }
3159
- catch (e) {
3160
- // Fallback for environments where neither is available or accessible
3161
- }
3162
- const currentSourceInfo = {
3163
- version,
3164
- source,
3165
- timestamp: Date.now(),
209
+ if (originals.requestAnimationFrame) {
210
+ globalThis.requestAnimationFrame = (callback) => {
211
+ return originals.requestAnimationFrame.call(globalThis, wrap(callback));
212
+ };
213
+ }
214
+ if (originals.queueMicrotask) {
215
+ globalThis.queueMicrotask = (callback) => {
216
+ originals.queueMicrotask.call(globalThis, wrap(callback));
3166
217
  };
3167
- if (globalScope[GLOBAL_MUTTS_KEY]) {
3168
- const existing = globalScope[GLOBAL_MUTTS_KEY];
3169
- throw new Error(`[Mutts] Multiple instances detected!\n` +
3170
- `Existing instance: ${JSON.stringify(existing, null, 2)}\n` +
3171
- `New instance: ${JSON.stringify(currentSourceInfo, null, 2)}\n` +
3172
- `This usually happens when 'mutts' is both installed as a dependency and bundled, ` +
3173
- `or when different versions are loaded. ` +
3174
- `Please check your build configuration (aliases, externals) to ensure a single source of truth.`);
3175
- }
3176
- globalScope[GLOBAL_MUTTS_KEY] = currentSourceInfo;
3177
218
  }
3178
219
 
3179
220
  exports.AZone = proxy.AZone;
@@ -3190,18 +231,23 @@ exports.Zone = proxy.Zone;
3190
231
  exports.ZoneAggregator = proxy.ZoneAggregator;
3191
232
  exports.ZoneHistory = proxy.ZoneHistory;
3192
233
  exports.addBatchCleanup = proxy.addBatchCleanup;
234
+ exports.addUnreactiveProps = proxy.addUnreactiveProps;
3193
235
  exports.arrayEquals = proxy.arrayEquals;
236
+ exports.assertUntracked = proxy.assertUntracked;
237
+ exports.asyncHook = proxy.asyncHook;
238
+ exports.asyncHooks = proxy.asyncHooks;
3194
239
  exports.asyncZone = proxy.asyncZone;
3195
240
  exports.atom = proxy.atom;
3196
241
  exports.atomic = proxy.atomic;
3197
242
  exports.biDi = proxy.biDi;
243
+ exports.captured = proxy.captured;
3198
244
  exports.caught = proxy.caught;
3199
- exports.cleanedBy = proxy.cleanedBy;
3200
- exports.cleanup = proxy.cleanup;
3201
245
  exports.createFlavor = proxy.createFlavor;
246
+ exports.debugPreset = proxy.debugPreset;
3202
247
  exports.decorator = proxy.decorator;
3203
248
  exports.deepCompare = proxy.deepCompare;
3204
249
  exports.defer = proxy.defer;
250
+ exports.devPreset = proxy.devPreset;
3205
251
  exports.effect = proxy.effect;
3206
252
  exports.effectAggregator = proxy.effectAggregator;
3207
253
  exports.flavorOptions = proxy.flavorOptions;
@@ -3210,67 +256,66 @@ exports.formatCleanupReason = proxy.formatCleanupReason;
3210
256
  exports.getActivationLog = proxy.getActivationLog;
3211
257
  exports.getActiveEffect = proxy.getActiveEffect;
3212
258
  exports.getState = proxy.getState;
3213
- exports.immutables = proxy.immutables;
259
+ exports.hooks = proxy.hooks;
3214
260
  exports.isConstructor = proxy.isConstructor;
261
+ exports.isDev = proxy.isDev;
3215
262
  exports.isNonReactive = proxy.isNonReactive;
3216
263
  exports.isObject = proxy.isObject;
264
+ exports.isProd = proxy.isProd;
3217
265
  exports.isReactive = proxy.isReactive;
266
+ exports.isTest = proxy.isTest;
3218
267
  exports.legacyDecorator = proxy.legacyDecorator;
268
+ exports.link = proxy.link;
3219
269
  exports.mixin = proxy.mixin;
3220
270
  exports.modernDecorator = proxy.modernDecorator;
3221
271
  exports.named = proxy.named;
3222
272
  exports.objectToProxy = proxy.objectToProxy;
3223
273
  exports.onEffectThrow = proxy.onEffectThrow;
274
+ exports.prodPreset = proxy.prodPreset;
3224
275
  exports.proxyToObject = proxy.proxyToObject;
3225
276
  exports.reactive = proxy.reactive;
3226
277
  exports.reactiveOptions = proxy.options;
3227
278
  exports.reset = proxy.reset;
3228
279
  exports.root = proxy.root;
3229
- exports.stopped = proxy.stopped;
3230
280
  exports.tag = proxy.tag;
3231
281
  exports.touched = proxy.touched;
3232
282
  exports.touched1 = proxy.touched1;
283
+ exports.unlink = proxy.unlink;
3233
284
  exports.untracked = proxy.untracked;
3234
285
  exports.unwrap = proxy.unwrap;
3235
286
  exports.zip = proxy.zip;
3236
- exports.asyncHook = asyncCore.asyncHook;
3237
- exports.asyncHooks = asyncCore.asyncHooks;
3238
- exports.hooks = asyncCore.hooks;
3239
- exports.ArrayReadForward = ArrayReadForward;
3240
- exports.Destroyable = Destroyable;
3241
- exports.DestructionError = DestructionError;
3242
- exports.Eventful = Eventful;
3243
- exports.Indexable = Indexable;
3244
- exports.Register = Register;
3245
- exports.allocated = allocated;
3246
- exports.allocatedValues = allocatedValues;
3247
- exports.arrayDiff = arrayDiff;
3248
- exports.attend = attend;
3249
- exports.cache = cache;
3250
- exports.cached = cached;
3251
- exports.callOnGC = callOnGC;
3252
- exports.chainPromise = chainPromise;
3253
- exports.debounce = debounce;
3254
- exports.deepWatch = deepWatch;
3255
- exports.deprecated = deprecated;
3256
- exports.descriptor = descriptor;
3257
- exports.destructor = destructor;
3258
- exports.forwardArray = forwardArray;
3259
- exports.getAt = getAt;
3260
- exports.isCached = isCached;
3261
- exports.lift = lift;
3262
- exports.memoize = memoize;
3263
- exports.morph = morph;
3264
- exports.organize = organize;
3265
- exports.organized = organized;
3266
- exports.profileInfo = profileInfo;
3267
- exports.project = morph;
3268
- exports.register = register;
3269
- exports.resource = resource;
3270
- exports.scan = scan;
3271
- exports.setAt = setAt;
3272
- exports.throttle = throttle;
3273
- exports.unreactive = unreactive;
3274
- exports.watch = watch;
3275
- exports.when = when;
287
+ exports.ArrayReadForward = index.ArrayReadForward;
288
+ exports.Destroyable = index.Destroyable;
289
+ exports.DestructionError = index.DestructionError;
290
+ exports.Eventful = index.Eventful;
291
+ exports.Indexable = index.Indexable;
292
+ exports.allocated = index.allocated;
293
+ exports.allocatedValues = index.allocatedValues;
294
+ exports.arrayDiff = index.arrayDiff;
295
+ exports.attend = index.attend;
296
+ exports.cache = index.cache;
297
+ exports.cached = index.cached;
298
+ exports.callOnGC = index.callOnGC;
299
+ exports.chainPromise = index.chainPromise;
300
+ exports.debounce = index.debounce;
301
+ exports.deepWatch = index.deepWatch;
302
+ exports.deprecated = index.deprecated;
303
+ exports.descriptor = index.descriptor;
304
+ exports.destructor = index.destructor;
305
+ exports.forwardArray = index.forwardArray;
306
+ exports.getAt = index.getAt;
307
+ exports.isCached = index.isCached;
308
+ exports.lift = index.lift;
309
+ exports.memoize = index.memoize;
310
+ exports.morph = index.morph;
311
+ exports.organize = index.organize;
312
+ exports.organized = index.organized;
313
+ exports.profileInfo = index.profileInfo;
314
+ exports.project = index.morph;
315
+ exports.resource = index.resource;
316
+ exports.setAt = index.setAt;
317
+ exports.throttle = index.throttle;
318
+ exports.unreactive = index.unreactive;
319
+ exports.watch = index.watch;
320
+ exports.when = index.when;
3276
321
  //# sourceMappingURL=browser.cjs.map