mutts 1.0.1 → 1.0.3

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 (111) hide show
  1. package/README.md +36 -6
  2. package/dist/chunks/_tslib-BgjropY9.js +81 -0
  3. package/dist/chunks/_tslib-BgjropY9.js.map +1 -0
  4. package/dist/chunks/_tslib-Mzh1rNsX.esm.js +75 -0
  5. package/dist/chunks/_tslib-Mzh1rNsX.esm.js.map +1 -0
  6. package/dist/chunks/{decorator-8qjFb7dw.js → decorator-DLvrD0UF.js} +103 -14
  7. package/dist/chunks/decorator-DLvrD0UF.js.map +1 -0
  8. package/dist/chunks/{decorator-AbRkXM5O.esm.js → decorator-DqiszP7i.esm.js} +100 -15
  9. package/dist/chunks/decorator-DqiszP7i.esm.js.map +1 -0
  10. package/dist/chunks/index-DzUDtFc7.esm.js +4841 -0
  11. package/dist/chunks/index-DzUDtFc7.esm.js.map +1 -0
  12. package/dist/chunks/index-HNVqPzjz.js +4891 -0
  13. package/dist/chunks/index-HNVqPzjz.js.map +1 -0
  14. package/dist/decorator.d.ts +57 -0
  15. package/dist/decorator.esm.js +1 -1
  16. package/dist/decorator.js +1 -1
  17. package/dist/destroyable.d.ts +43 -1
  18. package/dist/destroyable.esm.js +19 -1
  19. package/dist/destroyable.esm.js.map +1 -1
  20. package/dist/destroyable.js +19 -1
  21. package/dist/destroyable.js.map +1 -1
  22. package/dist/devtools/devtools.html +9 -0
  23. package/dist/devtools/devtools.js +5 -0
  24. package/dist/devtools/devtools.js.map +1 -0
  25. package/dist/devtools/manifest.json +8 -0
  26. package/dist/devtools/panel.css +72 -0
  27. package/dist/devtools/panel.html +31 -0
  28. package/dist/devtools/panel.js +13048 -0
  29. package/dist/devtools/panel.js.map +1 -0
  30. package/dist/eventful.d.ts +10 -1
  31. package/dist/eventful.esm.js +5 -27
  32. package/dist/eventful.esm.js.map +1 -1
  33. package/dist/eventful.js +15 -37
  34. package/dist/eventful.js.map +1 -1
  35. package/dist/index.d.ts +18 -14
  36. package/dist/index.esm.js +4 -3
  37. package/dist/index.esm.js.map +1 -1
  38. package/dist/index.js +44 -5
  39. package/dist/index.js.map +1 -1
  40. package/dist/indexable.d.ts +213 -1
  41. package/dist/indexable.esm.js +203 -3
  42. package/dist/indexable.esm.js.map +1 -1
  43. package/dist/indexable.js +204 -2
  44. package/dist/indexable.js.map +1 -1
  45. package/dist/mutts.umd.js +1 -1
  46. package/dist/mutts.umd.js.map +1 -1
  47. package/dist/mutts.umd.min.js +1 -1
  48. package/dist/mutts.umd.min.js.map +1 -1
  49. package/dist/promiseChain.d.ts +10 -0
  50. package/dist/promiseChain.esm.js +6 -0
  51. package/dist/promiseChain.esm.js.map +1 -1
  52. package/dist/promiseChain.js +6 -0
  53. package/dist/promiseChain.js.map +1 -1
  54. package/dist/reactive.d.ts +774 -33
  55. package/dist/reactive.esm.js +4 -1458
  56. package/dist/reactive.esm.js.map +1 -1
  57. package/dist/reactive.js +53 -1474
  58. package/dist/reactive.js.map +1 -1
  59. package/dist/std-decorators.d.ts +35 -0
  60. package/dist/std-decorators.esm.js +36 -1
  61. package/dist/std-decorators.esm.js.map +1 -1
  62. package/dist/std-decorators.js +36 -1
  63. package/dist/std-decorators.js.map +1 -1
  64. package/docs/ai/api-reference.md +133 -0
  65. package/docs/ai/manual.md +105 -0
  66. package/docs/iterableWeak.md +646 -0
  67. package/docs/mixin.md +229 -0
  68. package/docs/reactive/advanced.md +1280 -0
  69. package/docs/reactive/collections.md +767 -0
  70. package/docs/reactive/core.md +973 -0
  71. package/docs/reactive.md +21 -2688
  72. package/package.json +18 -5
  73. package/src/decorator.ts +266 -0
  74. package/src/destroyable.ts +199 -0
  75. package/src/eventful.ts +77 -0
  76. package/src/index.d.ts +9 -0
  77. package/src/index.ts +9 -0
  78. package/src/indexable.ts +484 -0
  79. package/src/introspection.ts +59 -0
  80. package/src/iterableWeak.ts +233 -0
  81. package/src/mixins.ts +123 -0
  82. package/src/promiseChain.ts +110 -0
  83. package/src/reactive/array.ts +414 -0
  84. package/src/reactive/change.ts +134 -0
  85. package/src/reactive/debug.ts +517 -0
  86. package/src/reactive/deep-touch.ts +268 -0
  87. package/src/reactive/deep-watch-state.ts +82 -0
  88. package/src/reactive/deep-watch.ts +168 -0
  89. package/src/reactive/effect-context.ts +94 -0
  90. package/src/reactive/effects.ts +1333 -0
  91. package/src/reactive/index.ts +75 -0
  92. package/src/reactive/interface.ts +223 -0
  93. package/src/reactive/map.ts +171 -0
  94. package/src/reactive/mapped.ts +130 -0
  95. package/src/reactive/memoize.ts +107 -0
  96. package/src/reactive/non-reactive-state.ts +49 -0
  97. package/src/reactive/non-reactive.ts +43 -0
  98. package/src/reactive/project.project.md +93 -0
  99. package/src/reactive/project.ts +335 -0
  100. package/src/reactive/proxy-state.ts +27 -0
  101. package/src/reactive/proxy.ts +285 -0
  102. package/src/reactive/record.ts +196 -0
  103. package/src/reactive/register.ts +421 -0
  104. package/src/reactive/set.ts +144 -0
  105. package/src/reactive/tracking.ts +101 -0
  106. package/src/reactive/types.ts +358 -0
  107. package/src/reactive/zone.ts +208 -0
  108. package/src/std-decorators.ts +217 -0
  109. package/src/utils.ts +117 -0
  110. package/dist/chunks/decorator-8qjFb7dw.js.map +0 -1
  111. package/dist/chunks/decorator-AbRkXM5O.esm.js.map +0 -1
@@ -1,1459 +1,5 @@
1
- import { d as decorator, r as renamed } from './chunks/decorator-AbRkXM5O.esm.js';
2
- import { Indexable } from './indexable.esm.js';
3
-
4
- // biome-ignore-all lint/suspicious/noConfusingVoidType: Type 'void' is not assignable to type 'ScopedCallback | undefined'.
5
- // Argument of type '() => void' is not assignable to parameter of type '(dep: DependencyFunction) => ScopedCallback | undefined'.
6
- // Track which effects are watching which reactive objects for cleanup
7
- const effectToReactiveObjects = new WeakMap();
8
- // Track object -> proxy and proxy -> object relationships
9
- const objectToProxy = new WeakMap();
10
- const proxyToObject = new WeakMap();
11
- // Deep watching data structures
12
- // Track which objects contain which other objects (back-references)
13
- const objectParents = new WeakMap();
14
- // Track which objects have deep watchers
15
- const objectsWithDeepWatchers = new WeakSet();
16
- // Track deep watchers per object
17
- const deepWatchers = new WeakMap();
18
- // Track which effects are doing deep watching
19
- const effectToDeepWatchedObjects = new WeakMap();
20
- // Track objects that should never be reactive and cannot be modified
21
- const nonReactiveObjects = new WeakSet();
22
- const absent = Symbol('absent');
23
- /**
24
- * Converts an iterator to a generator that yields reactive values
25
- */
26
- function* makeReactiveIterator(iterator) {
27
- let result = iterator.next();
28
- while (!result.done) {
29
- yield reactive(result.value);
30
- result = iterator.next();
31
- }
32
- }
33
- /**
34
- * Converts an iterator of key-value pairs to a generator that yields reactive key-value pairs
35
- */
36
- function* makeReactiveEntriesIterator(iterator) {
37
- let result = iterator.next();
38
- while (!result.done) {
39
- const [key, value] = result.value;
40
- yield [reactive(key), reactive(value)];
41
- result = iterator.next();
42
- }
43
- }
44
- // Track effects per reactive object and property
45
- const watchers = new WeakMap();
46
- const profileInfo = {
47
- objectToProxy,
48
- proxyToObject,
49
- effectToReactiveObjects,
50
- watchers,
51
- objectParents,
52
- objectsWithDeepWatchers,
53
- deepWatchers,
54
- effectToDeepWatchedObjects,
55
- nonReactiveObjects,
56
- };
57
- // Track native reactivity
58
- const nativeReactive = Symbol('native-reactive');
59
- // Symbol to mark individual objects as non-reactive
60
- const nonReactiveMark = Symbol('non-reactive');
61
- // Symbol to mark class properties as non-reactive
62
- const unreactiveProperties = Symbol('unreactive-properties');
63
- const prototypeForwarding = Symbol('prototype-forwarding');
64
- const allProps = Symbol('all-props');
65
- // Symbol to mark functions with their root function
66
- const rootFunction = Symbol('root-function');
67
- /**
68
- * Mark a function with its root function. If the function already has a root,
69
- * the root becomes the root of the new root (transitive root tracking).
70
- * @param fn - The function to mark
71
- * @param root - The root function to associate with fn
72
- */
73
- function markWithRoot(fn, root) {
74
- // Mark fn with the new root
75
- return Object.defineProperty(fn, rootFunction, {
76
- value: getRoot(root),
77
- writable: false,
78
- });
79
- }
80
- /**
81
- * Retrieve the root function from a callback. Returns the function itself if it has no root.
82
- * @param fn - The function to get the root from
83
- * @returns The root function, or the function itself if no root exists
84
- */
85
- function getRoot(fn) {
86
- return fn?.[rootFunction] || fn;
87
- }
88
- class ReactiveError extends Error {
89
- constructor(message) {
90
- super(message);
91
- this.name = 'ReactiveError';
92
- }
93
- }
94
- // biome-ignore-start lint/correctness/noUnusedFunctionParameters: Interface declaration with empty defaults
95
- /**
96
- * Options for the reactive system, can be configured at runtime
97
- */
98
- const options = {
99
- /**
100
- * Debug purpose: called when an effect is entered
101
- * @param effect - The effect that is entered
102
- */
103
- enter: (effect) => { },
104
- /**
105
- * Debug purpose: called when an effect is left
106
- * @param effect - The effect that is left
107
- */
108
- leave: (effect) => { },
109
- /**
110
- * Debug purpose: called when an effect is chained
111
- * @param target - The effect that is being triggered
112
- * @param caller - The effect that is calling the target
113
- */
114
- chain: (target, caller) => { },
115
- /**
116
- * Debug purpose: maximum effect chain (like call stack max depth)
117
- * Used to prevent infinite loops
118
- * @default 100
119
- */
120
- maxEffectChain: 100,
121
- /**
122
- * Maximum depth for deep watching traversal
123
- * Used to prevent infinite recursion in circular references
124
- * @default 100
125
- */
126
- maxDeepWatchDepth: 100,
127
- /**
128
- * Only react on instance members modification (not inherited properties)
129
- * For instance, do not track class methods
130
- * @default true
131
- */
132
- instanceMembers: true,
133
- // biome-ignore lint/suspicious/noConsole: This is the whole point here
134
- warn: (...args) => console.warn(...args),
135
- };
136
- // biome-ignore-end lint/correctness/noUnusedFunctionParameters: Interface declaration with empty defaults
137
- //#region evolution
138
- function raiseDeps(objectWatchers, ...keyChains) {
139
- for (const keys of keyChains)
140
- for (const key of keys) {
141
- const deps = objectWatchers.get(key);
142
- if (deps)
143
- for (const effect of Array.from(deps))
144
- atomicEffect(effect);
145
- }
146
- }
147
- function touched1(obj, evolution, prop) {
148
- touched(obj, evolution, [prop]);
149
- }
150
- function touched(obj, evolution, props) {
151
- obj = unwrap(obj);
152
- addState(obj, evolution);
153
- const objectWatchers = watchers.get(obj);
154
- if (objectWatchers) {
155
- if (props)
156
- raiseDeps(objectWatchers, [allProps], props);
157
- else
158
- raiseDeps(objectWatchers, objectWatchers.keys());
159
- }
160
- // Bubble up changes if this object has deep watchers
161
- if (objectsWithDeepWatchers.has(obj)) {
162
- bubbleUpChange(obj);
163
- }
164
- }
165
- const states = new WeakMap();
166
- function addState(obj, evolution) {
167
- obj = unwrap(obj);
168
- const next = {};
169
- const state = getState(obj);
170
- if (state)
171
- Object.assign(state, { evolution, next });
172
- states.set(obj, next);
173
- }
174
- function getState(obj) {
175
- obj = unwrap(obj);
176
- let state = states.get(obj);
177
- if (!state) {
178
- state = {};
179
- states.set(obj, state);
180
- }
181
- return state;
182
- }
183
- function dependant(obj, prop = allProps) {
184
- obj = unwrap(obj);
185
- if (activeEffect && (typeof prop !== 'symbol' || prop === allProps)) {
186
- let objectWatchers = watchers.get(obj);
187
- if (!objectWatchers) {
188
- objectWatchers = new Map();
189
- watchers.set(obj, objectWatchers);
190
- }
191
- let deps = objectWatchers.get(prop);
192
- if (!deps) {
193
- deps = new Set();
194
- objectWatchers.set(prop, deps);
195
- }
196
- deps.add(activeEffect);
197
- // Track which reactive objects this effect is watching
198
- let effectObjects = effectToReactiveObjects.get(activeEffect);
199
- if (!effectObjects) {
200
- effectObjects = new Set();
201
- effectToReactiveObjects.set(activeEffect, effectObjects);
202
- }
203
- effectObjects.add(obj);
204
- }
205
- }
206
- // Stack of active effects to handle nested effects
207
- let activeEffect;
208
- // Parent effect used for lifecycle/cleanup relationships (can diverge later)
209
- let parentEffect;
210
- // Track currently executing effects to prevent re-execution
211
- // These are all the effects triggered under `activeEffect`
212
- let batchedEffects;
213
- // Track which sub-effects have been executed to prevent infinite loops
214
- // These are all the effects triggered under `activeEffect` and all their sub-effects
215
- function atomicEffect(effect, immediate) {
216
- const root = getRoot(effect);
217
- options?.chain(getRoot(effect), getRoot(activeEffect));
218
- if (batchedEffects) {
219
- batchedEffects.set(root, effect);
220
- if (immediate)
221
- try {
222
- return effect();
223
- }
224
- finally {
225
- batchedEffects.delete(root);
226
- }
227
- }
228
- else {
229
- const runEffects = [];
230
- batchedEffects = new Map([[root, effect]]);
231
- const firstReturn = {};
232
- try {
233
- while (batchedEffects.size) {
234
- if (runEffects.length > options.maxEffectChain)
235
- throw new ReactiveError('[reactive] Max effect chain reached');
236
- const [root, effect] = batchedEffects.entries().next().value;
237
- runEffects.push(root);
238
- const rv = effect();
239
- if (!('value' in firstReturn))
240
- firstReturn.value = rv;
241
- batchedEffects.delete(root);
242
- }
243
- return firstReturn.value;
244
- }
245
- finally {
246
- batchedEffects = undefined;
247
- }
248
- }
249
- }
250
- const atomic = decorator({
251
- method(original) {
252
- return function (...args) {
253
- return atomicEffect(markWithRoot(() => original.apply(this, args), original), 'immediate');
254
- };
255
- },
256
- default(original) {
257
- return function (...args) {
258
- return atomicEffect(markWithRoot(() => original.apply(this, args), original), 'immediate');
259
- };
260
- },
261
- });
262
- function withEffect(effect, fn, keepParent) {
263
- if (getRoot(effect) === getRoot(activeEffect))
264
- return fn();
265
- const oldActiveEffect = activeEffect;
266
- const oldParentEffect = parentEffect;
267
- activeEffect = effect;
268
- if (!keepParent)
269
- parentEffect = effect;
270
- try {
271
- return fn();
272
- }
273
- finally {
274
- activeEffect = oldActiveEffect;
275
- parentEffect = oldParentEffect;
276
- }
277
- }
278
- //#endregion
279
- //#region deep watching
280
- /**
281
- * Add a back-reference from child to parent
282
- */
283
- function addBackReference(child, parent, prop) {
284
- let parents = objectParents.get(child);
285
- if (!parents) {
286
- parents = new Set();
287
- objectParents.set(child, parents);
288
- }
289
- parents.add({ parent, prop });
290
- }
291
- /**
292
- * Remove a back-reference from child to parent
293
- */
294
- function removeBackReference(child, parent, prop) {
295
- const parents = objectParents.get(child);
296
- if (parents) {
297
- parents.delete({ parent, prop });
298
- if (parents.size === 0) {
299
- objectParents.delete(child);
300
- }
301
- }
302
- }
303
- /**
304
- * Check if an object needs back-references (has deep watchers or parents with deep watchers)
305
- */
306
- function needsBackReferences(obj) {
307
- return objectsWithDeepWatchers.has(obj) || hasParentWithDeepWatchers(obj);
308
- }
309
- /**
310
- * Check if an object has any parent with deep watchers
311
- */
312
- function hasParentWithDeepWatchers(obj) {
313
- const parents = objectParents.get(obj);
314
- if (!parents)
315
- return false;
316
- for (const { parent } of parents) {
317
- if (objectsWithDeepWatchers.has(parent))
318
- return true;
319
- if (hasParentWithDeepWatchers(parent))
320
- return true;
321
- }
322
- return false;
323
- }
324
- /**
325
- * Bubble up changes through the back-reference chain
326
- */
327
- function bubbleUpChange(changedObject, evolution) {
328
- const parents = objectParents.get(changedObject);
329
- if (!parents)
330
- return;
331
- for (const { parent } of parents) {
332
- // Trigger deep watchers on parent
333
- const parentDeepWatchers = deepWatchers.get(parent);
334
- if (parentDeepWatchers)
335
- for (const watcher of parentDeepWatchers)
336
- atomicEffect(watcher);
337
- // Continue bubbling up
338
- bubbleUpChange(parent);
339
- }
340
- }
341
- function track1(obj, prop, oldVal, newValue) {
342
- // Manage back-references if this object has deep watchers
343
- if (objectsWithDeepWatchers.has(obj)) {
344
- // Remove old back-references
345
- if (typeof oldVal === 'object' && oldVal !== null) {
346
- removeBackReference(oldVal, obj, prop);
347
- }
348
- // Add new back-references
349
- if (typeof newValue === 'object' && newValue !== null) {
350
- const reactiveValue = reactive(newValue);
351
- addBackReference(reactiveValue, obj, prop);
352
- }
353
- }
354
- return newValue;
355
- }
356
- //#endregion
357
- const reactiveHandlers = {
358
- [Symbol.toStringTag]: 'MutTs Reactive',
359
- get(obj, prop, receiver) {
360
- if (prop === nonReactiveMark)
361
- return false;
362
- // Check if this property is marked as unreactive
363
- if (obj[unreactiveProperties]?.has(prop) || typeof prop === 'symbol')
364
- return Reflect.get(obj, prop, receiver);
365
- // Depend if...
366
- if (!options.instanceMembers || Object.hasOwn(receiver, prop) || !Reflect.has(receiver, prop))
367
- dependant(obj, prop);
368
- const value = Reflect.get(obj, prop, receiver);
369
- if (typeof value === 'object' && value !== null) {
370
- const reactiveValue = reactive(value);
371
- // Only create back-references if this object needs them
372
- if (needsBackReferences(obj)) {
373
- addBackReference(reactiveValue, obj, prop);
374
- }
375
- return reactiveValue;
376
- }
377
- return value;
378
- },
379
- set(obj, prop, value, receiver) {
380
- // Check if this property is marked as unreactive
381
- if (obj[unreactiveProperties]?.has(prop))
382
- return Reflect.set(obj, prop, value, receiver);
383
- // Really specific case for when Array is forwarder, in order to let it manage the reactivity
384
- const isArrayCase = prototypeForwarding in obj &&
385
- // biome-ignore lint/suspicious/useIsArray: This is the whole point here
386
- obj[prototypeForwarding] instanceof Array &&
387
- (!Number.isNaN(Number(prop)) || prop === 'length');
388
- const newValue = unwrap(value);
389
- if (isArrayCase) {
390
- obj[prop] = newValue;
391
- return true;
392
- }
393
- const oldVal = Reflect.has(receiver, prop) ? Reflect.get(obj, prop, receiver) : absent;
394
- track1(obj, prop, oldVal, newValue);
395
- if (oldVal !== newValue) {
396
- Reflect.set(obj, prop, newValue, receiver);
397
- // try to find a "generic" way to express that
398
- touched1(obj, { type: oldVal !== absent ? 'set' : 'add', prop }, prop);
399
- }
400
- return true;
401
- },
402
- deleteProperty(obj, prop) {
403
- if (!Object.hasOwn(obj, prop))
404
- return false;
405
- const oldVal = obj[prop];
406
- // Remove back-references if this object has deep watchers
407
- if (objectsWithDeepWatchers.has(obj) && typeof oldVal === 'object' && oldVal !== null) {
408
- removeBackReference(oldVal, obj, prop);
409
- }
410
- delete obj[prop];
411
- touched1(obj, { type: 'del', prop }, prop);
412
- // Bubble up changes if this object has deep watchers
413
- if (objectsWithDeepWatchers.has(obj)) {
414
- bubbleUpChange(obj);
415
- }
416
- return true;
417
- },
418
- getPrototypeOf(obj) {
419
- if (prototypeForwarding in obj)
420
- return obj[prototypeForwarding];
421
- return Object.getPrototypeOf(obj);
422
- },
423
- setPrototypeOf(obj, proto) {
424
- if (prototypeForwarding in obj)
425
- return false;
426
- Object.setPrototypeOf(obj, proto);
427
- return true;
428
- },
429
- ownKeys(obj) {
430
- dependant(obj, allProps);
431
- return Reflect.ownKeys(obj);
432
- },
433
- };
434
- const reactiveClasses = new WeakSet();
435
- class ReactiveBase {
436
- constructor() {
437
- // biome-ignore lint/correctness/noConstructorReturn: This is the whole point here
438
- return reactiveClasses.has(new.target) ? reactive(this) : this;
439
- }
440
- }
441
- function reactiveObject(anyTarget) {
442
- if (!anyTarget || typeof anyTarget !== 'object')
443
- return anyTarget;
444
- const target = anyTarget;
445
- // If target is already a proxy, return it
446
- if (proxyToObject.has(target) || isNonReactive(target))
447
- return target;
448
- // If we already have a proxy for this object, return it
449
- if (objectToProxy.has(target))
450
- return objectToProxy.get(target);
451
- const proxied = nativeReactive in target && !(target instanceof target[nativeReactive])
452
- ? new target[nativeReactive](target)
453
- : target;
454
- if (proxied !== target)
455
- proxyToObject.set(proxied, target);
456
- const proxy = new Proxy(proxied, reactiveHandlers);
457
- // Store the relationships
458
- objectToProxy.set(target, proxy);
459
- proxyToObject.set(proxy, target);
460
- return proxy;
461
- }
462
- const reactive = decorator({
463
- class(original) {
464
- if (original.prototype instanceof ReactiveBase) {
465
- reactiveClasses.add(original);
466
- return original;
467
- }
468
- class Reactive extends original {
469
- constructor(...args) {
470
- super(...args);
471
- if (new.target !== Reactive && !reactiveClasses.has(new.target))
472
- options.warn(`${original.name} has been inherited by ${this.constructor.name} that is not reactive.
473
- @reactive decorator must be applied to the leaf class OR classes have to extend ReactiveBase.`);
474
- // biome-ignore lint/correctness/noConstructorReturn: This is the whole point here
475
- return reactive(this);
476
- }
477
- }
478
- Object.defineProperty(Reactive, 'name', {
479
- value: `Reactive<${original.name}>`,
480
- });
481
- return Reactive;
482
- },
483
- get(original) {
484
- return reactiveObject(original);
485
- },
486
- default: reactiveObject,
487
- });
488
- function unwrap(proxy) {
489
- // Return the original object
490
- return proxyToObject.get(proxy) ?? proxy;
491
- }
492
- function isReactive(obj) {
493
- return proxyToObject.has(obj);
494
- }
495
- function untracked(fn) {
496
- withEffect(undefined, fn, true);
497
- }
498
- // runEffect -> set<cleanup>
499
- const effectChildren = new WeakMap();
500
- const fr = new FinalizationRegistry((f) => f());
501
- /**
502
- * @param fn - The effect function to run - provides the cleaner
503
- * @returns The cleanup function
504
- */
505
- function effect(fn, ...args) {
506
- let cleanup = null;
507
- const dep = markWithRoot((cb) => withEffect(runEffect, cb), fn);
508
- let effectStopped = false;
509
- function runEffect() {
510
- // Clear previous dependencies
511
- cleanup?.();
512
- options.enter(fn);
513
- const reactionCleanup = withEffect(effectStopped ? undefined : runEffect, () => fn(dep, ...args));
514
- options.leave(fn);
515
- // Create cleanup function for next run
516
- cleanup = () => {
517
- cleanup = null;
518
- reactionCleanup?.();
519
- // Remove this effect from all reactive objects it's watching
520
- const effectObjects = effectToReactiveObjects.get(runEffect);
521
- if (effectObjects) {
522
- for (const reactiveObj of effectObjects) {
523
- const objectWatchers = watchers.get(reactiveObj);
524
- if (objectWatchers) {
525
- for (const [prop, deps] of objectWatchers.entries()) {
526
- deps.delete(runEffect);
527
- if (deps.size === 0) {
528
- objectWatchers.delete(prop);
529
- }
530
- }
531
- if (objectWatchers.size === 0) {
532
- watchers.delete(reactiveObj);
533
- }
534
- }
535
- }
536
- effectToReactiveObjects.delete(runEffect);
537
- }
538
- };
539
- }
540
- // Mark the runEffect callback with the original function as its root
541
- markWithRoot(runEffect, fn);
542
- atomicEffect(runEffect, 'immediate');
543
- const mainCleanup = () => {
544
- if (effectStopped)
545
- return;
546
- effectStopped = true;
547
- cleanup?.();
548
- // Invoke all child cleanups (recursive via subEffectCleanup calling its own mainCleanup)
549
- const children = effectChildren.get(runEffect);
550
- if (children) {
551
- for (const childCleanup of children)
552
- childCleanup();
553
- effectChildren.delete(runEffect);
554
- }
555
- fr.unregister(mainCleanup);
556
- };
557
- // Only ROOT effects are registered for GC cleanup
558
- if (!parentEffect) {
559
- const callIfCollected = () => mainCleanup();
560
- fr.register(callIfCollected, mainCleanup, callIfCollected);
561
- return callIfCollected;
562
- }
563
- // Register this effect to be cleaned up with the parent effect
564
- let children = effectChildren.get(parentEffect);
565
- if (!children) {
566
- children = new Set();
567
- effectChildren.set(parentEffect, children);
568
- }
569
- const parent = parentEffect;
570
- const subEffectCleanup = () => {
571
- children.delete(subEffectCleanup);
572
- if (children.size === 0) {
573
- effectChildren.delete(parent);
574
- }
575
- // Execute this child effect cleanup (which triggers its own mainCleanup)
576
- mainCleanup();
577
- };
578
- children.add(subEffectCleanup);
579
- return subEffectCleanup;
580
- }
581
- /**
582
- * Mark an object as non-reactive. This object and all its properties will never be made reactive.
583
- * @param obj - The object to mark as non-reactive
584
- */
585
- function nonReactive(...obj) {
586
- for (const o of obj) {
587
- try {
588
- Object.defineProperty(o, nonReactiveMark, {
589
- value: true,
590
- writable: false,
591
- enumerable: false,
592
- configurable: false,
593
- });
594
- }
595
- catch { }
596
- if (!(nonReactiveMark in o))
597
- nonReactiveObjects.add(o);
598
- }
599
- return obj[0];
600
- }
601
- /**
602
- * Set of functions to test if an object is immutable
603
- */
604
- const immutables = new Set();
605
- /**
606
- * Check if an object is marked as non-reactive (for testing purposes)
607
- * @param obj - The object to check
608
- * @returns true if the object is marked as non-reactive
609
- */
610
- function isNonReactive(obj) {
611
- // Don't make primitives reactive
612
- if (obj === null || typeof obj !== 'object')
613
- return true;
614
- // Check if the object itself is marked as non-reactive
615
- if (nonReactiveObjects.has(obj))
616
- return true;
617
- // Check if the object has the non-reactive symbol
618
- if (obj[nonReactiveMark])
619
- return true;
620
- // Check if the object is immutable
621
- if (Array.from(immutables).some((fn) => fn(obj)))
622
- return true;
623
- return false;
624
- }
625
- /**
626
- * Mark a class as non-reactive. All instances of this class will automatically be non-reactive.
627
- * @param cls - The class constructor to mark as non-reactive
628
- */
629
- function nonReactiveClass(...cls) {
630
- for (const c of cls)
631
- if (c)
632
- c.prototype[nonReactiveMark] = true;
633
- return cls[0];
634
- }
635
- nonReactiveClass(Date, RegExp, Error, Promise, Function);
636
- if (typeof window !== 'undefined')
637
- nonReactive(window, document);
638
- if (typeof Element !== 'undefined')
639
- nonReactiveClass(Element, Node);
640
- function registerNativeReactivity(originalClass, reactiveClass) {
641
- originalClass.prototype[nativeReactive] = reactiveClass;
642
- nonReactiveClass(reactiveClass);
643
- }
644
- /**
645
- * Deep watch an object and all its nested properties
646
- * @param target - The object to watch deeply
647
- * @param callback - The callback to call when any nested property changes
648
- * @param options - Options for the deep watch
649
- * @returns A cleanup function to stop watching
650
- */
651
- function deepWatch(target, callback, { immediate = false } = {}) {
652
- if (target === null || target === undefined)
653
- return undefined;
654
- if (typeof target !== 'object')
655
- throw new Error('Target of deep watching must be an object');
656
- // Create a wrapper callback that matches ScopedCallback signature
657
- const wrappedCallback = markWithRoot(() => callback(target), callback);
658
- // Use the existing effect system to register dependencies
659
- return effect(() => {
660
- // Mark the target object as having deep watchers
661
- objectsWithDeepWatchers.add(target);
662
- // Track which objects this effect is watching for cleanup
663
- let effectObjects = effectToDeepWatchedObjects.get(wrappedCallback);
664
- if (!effectObjects) {
665
- effectObjects = new Set();
666
- effectToDeepWatchedObjects.set(wrappedCallback, effectObjects);
667
- }
668
- effectObjects.add(target);
669
- // Traverse the object graph and register dependencies
670
- // This will re-run every time the effect runs, ensuring we catch all changes
671
- const visited = new WeakSet();
672
- function traverseAndTrack(obj, depth = 0) {
673
- // Prevent infinite recursion and excessive depth
674
- if (visited.has(obj) || !isObject(obj) || depth > options.maxDeepWatchDepth)
675
- return;
676
- // Do not traverse into unreactive objects
677
- if (isNonReactive(obj))
678
- return;
679
- visited.add(obj);
680
- // Mark this object as having deep watchers
681
- objectsWithDeepWatchers.add(obj);
682
- effectObjects.add(obj);
683
- // Traverse all properties to register dependencies
684
- // unwrap to avoid kicking dependency
685
- for (const key in unwrap(obj)) {
686
- if (Object.hasOwn(obj, key)) {
687
- // Access the property to register dependency
688
- const value = obj[key];
689
- // Make the value reactive if it's an object
690
- const reactiveValue = typeof value === 'object' && value !== null ? reactive(value) : value;
691
- traverseAndTrack(reactiveValue, depth + 1);
692
- }
693
- }
694
- // Also handle array indices and length
695
- // biome-ignore lint/suspicious/useIsArray: Check for both native arrays and reactive arrays
696
- if (Array.isArray(obj) || obj instanceof Array) {
697
- // Access array length to register dependency on length changes
698
- const length = obj.length;
699
- // Access all current array elements to register dependencies
700
- for (let i = 0; i < length; i++) {
701
- // Access the array element to register dependency
702
- const value = obj[i];
703
- // Make the value reactive if it's an object
704
- const reactiveValue = typeof value === 'object' && value !== null ? reactive(value) : value;
705
- traverseAndTrack(reactiveValue, depth + 1);
706
- }
707
- }
708
- // Handle Set values (deep watch values only, not keys since Sets don't have separate keys)
709
- else if (obj instanceof Set) {
710
- // Access all Set values to register dependencies
711
- for (const value of obj) {
712
- // Make the value reactive if it's an object
713
- const reactiveValue = typeof value === 'object' && value !== null ? reactive(value) : value;
714
- traverseAndTrack(reactiveValue, depth + 1);
715
- }
716
- }
717
- // Handle Map values (deep watch values only, not keys)
718
- else if (obj instanceof Map) {
719
- // Access all Map values to register dependencies
720
- for (const [_key, value] of obj) {
721
- // Make the value reactive if it's an object
722
- const reactiveValue = typeof value === 'object' && value !== null ? reactive(value) : value;
723
- traverseAndTrack(reactiveValue, depth + 1);
724
- }
725
- }
726
- // Note: WeakSet and WeakMap cannot be iterated, so we can't deep watch their contents
727
- // They will only trigger when the collection itself is replaced
728
- }
729
- // Traverse the target object to register all dependencies
730
- // This will register dependencies on all current properties and array elements
731
- traverseAndTrack(target);
732
- // Only call the callback if immediate is true or if it's not the first run
733
- if (immediate)
734
- callback(target);
735
- immediate = true;
736
- // Return a cleanup function that properly removes deep watcher tracking
737
- return () => {
738
- // Get the objects this effect was watching
739
- const effectObjects = effectToDeepWatchedObjects.get(wrappedCallback);
740
- if (effectObjects) {
741
- // Remove deep watcher tracking from all objects this effect was watching
742
- for (const obj of effectObjects) {
743
- // Check if this object still has other deep watchers
744
- const watchers = deepWatchers.get(obj);
745
- if (watchers) {
746
- // Remove this effect's callback from the watchers
747
- watchers.delete(wrappedCallback);
748
- // If no more watchers, remove the object from deep watchers tracking
749
- if (watchers.size === 0) {
750
- deepWatchers.delete(obj);
751
- objectsWithDeepWatchers.delete(obj);
752
- }
753
- }
754
- else {
755
- // No watchers found, remove from deep watchers tracking
756
- objectsWithDeepWatchers.delete(obj);
757
- }
758
- }
759
- // Clean up the tracking data
760
- effectToDeepWatchedObjects.delete(wrappedCallback);
761
- }
762
- };
763
- });
764
- }
765
- /**
766
- * Check if an object is an object (not null, not primitive)
767
- */
768
- function isObject(obj) {
769
- return obj !== null && typeof obj === 'object';
770
- }
771
-
772
- //#region computed
773
- let computedInvalidations;
774
- /**
775
- * When used in a computed property computation, it will register the callback to be called when the computed property is invalidated
776
- * @param cb - The callback to register
777
- * @param warn - Whether to warn if used outside of a computed property
778
- */
779
- function invalidateComputed(cb, warn = true) {
780
- if (computedInvalidations)
781
- computedInvalidations.push(cb);
782
- else if (warn)
783
- options.warn('Using `invalidateComputed` outside of a computed property');
784
- }
785
- const computedCache = new WeakMap();
786
- function computedFunction(getter) {
787
- const key = getRoot(getter);
788
- let invalidations = [];
789
- dependant(computedCache, key);
790
- if (computedCache.has(key))
791
- return computedCache.get(key);
792
- let stopped = false;
793
- const stop = effect(markWithRoot((dep) => {
794
- if (stopped)
795
- return;
796
- const oldCI = computedInvalidations;
797
- if (computedCache.has(key)) {
798
- // This should *not* be called in the cleanup chain, as its effects would be lost and cleaned-up
799
- for (const cb of invalidations)
800
- cb();
801
- invalidations = [];
802
- computedCache.delete(key);
803
- touched1(computedCache, { type: 'invalidate', prop: key }, key);
804
- stop();
805
- stopped = true;
806
- }
807
- else
808
- try {
809
- computedInvalidations = invalidations;
810
- computedCache.set(key, getter(dep));
811
- }
812
- finally {
813
- computedInvalidations = oldCI;
814
- }
815
- }, getter));
816
- return computedCache.get(key);
817
- }
818
- /**
819
- * Get the cached value of a computed function - cache is invalidated when the dependencies change
820
- */
821
- const computed = decorator({
822
- getter(original, propertyKey) {
823
- const computers = new WeakMap();
824
- return function () {
825
- if (!computers.has(this)) {
826
- computers.set(this, renamed(() => original.call(this), `${String(this.constructor.name)}.${String(propertyKey)}`));
827
- }
828
- return computedFunction(computers.get(this));
829
- };
830
- },
831
- default(getter) {
832
- return computedFunction(getter);
833
- },
834
- });
835
- //#endregion
836
- //#region watch
837
- const unsetYet = Symbol('unset-yet');
838
- function watch(value, //object | ((dep: DependencyFunction) => object),
839
- changed, options = {}) {
840
- return typeof value === 'function'
841
- ? watchCallBack(value, changed, options)
842
- : typeof value === 'object'
843
- ? watchObject(value, changed, options)
844
- : (() => {
845
- throw new Error('watch: value must be a function or an object');
846
- })();
847
- }
848
- function watchObject(value, changed, { immediate = false, deep = false } = {}) {
849
- if (deep)
850
- return deepWatch(value, changed, { immediate });
851
- return effect(markWithRoot(() => {
852
- dependant(value);
853
- if (immediate)
854
- untracked(() => changed(value));
855
- immediate = true;
856
- }, changed));
857
- }
858
- function watchCallBack(value, changed, { immediate = false, deep = false } = {}) {
859
- let oldValue = unsetYet;
860
- let deepCleanup;
861
- const cbCleanup = effect(markWithRoot((dep) => {
862
- const newValue = value(dep);
863
- if (oldValue !== newValue)
864
- untracked(markWithRoot(() => {
865
- if (oldValue === unsetYet) {
866
- if (immediate)
867
- changed(newValue);
868
- }
869
- else
870
- changed(newValue, oldValue);
871
- oldValue = newValue;
872
- if (deep) {
873
- if (deepCleanup)
874
- deepCleanup();
875
- deepCleanup = deepWatch(newValue, markWithRoot((value) => changed(value, value), changed));
876
- }
877
- }, changed));
878
- }, value));
879
- return () => {
880
- cbCleanup();
881
- if (deepCleanup)
882
- deepCleanup();
883
- };
884
- }
885
- //#endregion
886
- //#region nonReactive
887
- /**
888
- * Mark an object as non-reactive. This object and all its properties will never be made reactive.
889
- * @param obj - The object to mark as non-reactive
890
- */
891
- function deepNonReactive(obj) {
892
- obj = unwrap(obj);
893
- if (isNonReactive(obj))
894
- return obj;
895
- try {
896
- Object.defineProperty(obj, nonReactiveMark, {
897
- value: true,
898
- writable: false,
899
- enumerable: false,
900
- configurable: true,
901
- });
902
- }
903
- catch { }
904
- if (!(nonReactiveMark in obj))
905
- nonReactiveObjects.add(obj);
906
- for (const key in obj)
907
- deepNonReactive(obj[key]);
908
- return obj;
909
- }
910
- function unreactiveApplication(arg1, ...args) {
911
- return typeof arg1 === 'object'
912
- ? deepNonReactive(arg1)
913
- : ((original) => {
914
- // Copy the parent's unreactive properties if they exist
915
- original.prototype[unreactiveProperties] = new Set(original.prototype[unreactiveProperties] || []);
916
- // Add all arguments (including the first one)
917
- original.prototype[unreactiveProperties].add(arg1);
918
- for (const arg of args)
919
- original.prototype[unreactiveProperties].add(arg);
920
- return original; // Return the class
921
- });
922
- }
923
- const unreactive = decorator({
924
- class(original) {
925
- // Called without arguments, mark entire class as non-reactive
926
- nonReactiveClass(original);
927
- },
928
- default: unreactiveApplication,
929
- });
930
- Object.assign(profileInfo, { computedCache });
931
-
932
- const native$2 = Symbol('native');
933
- const isArray = Array.isArray;
934
- Array.isArray = ((value) =>
935
- // biome-ignore lint/suspicious/useIsArray: We are defining it
936
- isArray(value) || (value instanceof Array && native$2 in value));
937
- class ReactiveBaseArray {
938
- }
939
- function* index(i, { length = true } = {}) {
940
- yield i;
941
- if (length)
942
- yield 'length';
943
- }
944
- function* range(a, b, { length = false } = {}) {
945
- const start = Math.min(a, b);
946
- const end = Math.max(a, b);
947
- for (let i = start; i <= end; i++)
948
- yield i;
949
- if (length)
950
- yield 'length';
951
- }
952
- class ReactiveArray extends Indexable(ReactiveBaseArray, {
953
- get(i) {
954
- dependant(this[native$2], i);
955
- return reactive(this[native$2][i]);
956
- },
957
- set(i, value) {
958
- const added = i >= this[native$2].length;
959
- this[native$2][i] = value;
960
- touched(this[native$2], { type: 'bunch', method: 'set' }, index(i, { length: added }));
961
- },
962
- getLength() {
963
- dependant(this[native$2], 'length');
964
- return this[native$2].length;
965
- },
966
- setLength(value) {
967
- const oldLength = this[native$2].length;
968
- try {
969
- this[native$2].length = value;
970
- }
971
- finally {
972
- touched(this[native$2], { type: 'set', prop: 'length' }, range(oldLength, value, { length: true }));
973
- }
974
- },
975
- }) {
976
- constructor(original) {
977
- super();
978
- Object.defineProperties(this, {
979
- // We have to make it double, as [native] must be `unique symbol` - impossible through import
980
- [native$2]: { value: original },
981
- [prototypeForwarding]: { value: original },
982
- });
983
- }
984
- // Safe array access with negative indices
985
- at(index) {
986
- const actualIndex = index < 0 ? this[native$2].length + index : index;
987
- dependant(this, actualIndex);
988
- if (actualIndex < 0 || actualIndex >= this[native$2].length)
989
- return undefined;
990
- return reactive(this[native$2][actualIndex]);
991
- }
992
- push(...items) {
993
- const oldLength = this[native$2].length;
994
- try {
995
- return this[native$2].push(...items);
996
- }
997
- finally {
998
- touched(this, { type: 'bunch', method: 'push' }, range(oldLength, oldLength + items.length - 1, { length: true }));
999
- }
1000
- }
1001
- pop() {
1002
- if (this[native$2].length === 0)
1003
- return undefined;
1004
- try {
1005
- return reactive(this[native$2].pop());
1006
- }
1007
- finally {
1008
- touched(this, { type: 'bunch', method: 'pop' }, index(this[native$2].length));
1009
- }
1010
- }
1011
- shift() {
1012
- if (this[native$2].length === 0)
1013
- return undefined;
1014
- try {
1015
- return reactive(this[native$2].shift());
1016
- }
1017
- finally {
1018
- touched(this, { type: 'bunch', method: 'shift' }, range(0, this[native$2].length + 1, { length: true }));
1019
- }
1020
- }
1021
- unshift(...items) {
1022
- try {
1023
- return this[native$2].unshift(...items);
1024
- }
1025
- finally {
1026
- touched(this, { type: 'bunch', method: 'unshift' }, range(0, this[native$2].length - items.length, { length: true }));
1027
- }
1028
- }
1029
- splice(start, deleteCount, ...items) {
1030
- const oldLength = this[native$2].length;
1031
- if (deleteCount === undefined)
1032
- deleteCount = oldLength - start;
1033
- try {
1034
- if (deleteCount === undefined)
1035
- return reactive(this[native$2].splice(start));
1036
- return reactive(this[native$2].splice(start, deleteCount, ...items));
1037
- }
1038
- finally {
1039
- touched(this, { type: 'bunch', method: 'splice' },
1040
- // TODO: edge cases
1041
- deleteCount === items.length
1042
- ? range(start, start + deleteCount)
1043
- : range(start, oldLength + Math.max(items.length - deleteCount, 0), {
1044
- length: true,
1045
- }));
1046
- }
1047
- }
1048
- reverse() {
1049
- try {
1050
- return this[native$2].reverse();
1051
- }
1052
- finally {
1053
- touched(this, { type: 'bunch', method: 'reverse' }, range(0, this[native$2].length - 1));
1054
- }
1055
- }
1056
- sort(compareFn) {
1057
- try {
1058
- return this[native$2].sort(compareFn);
1059
- }
1060
- finally {
1061
- touched(this, { type: 'bunch', method: 'sort' }, range(0, this[native$2].length - 1));
1062
- }
1063
- }
1064
- fill(value, start, end) {
1065
- try {
1066
- if (start === undefined)
1067
- return this[native$2].fill(value);
1068
- if (end === undefined)
1069
- return this[native$2].fill(value, start);
1070
- return this[native$2].fill(value, start, end);
1071
- }
1072
- finally {
1073
- touched(this, { type: 'bunch', method: 'fill' }, range(0, this[native$2].length - 1));
1074
- }
1075
- }
1076
- copyWithin(target, start, end) {
1077
- try {
1078
- if (end === undefined)
1079
- return this[native$2].copyWithin(target, start);
1080
- return this[native$2].copyWithin(target, start, end);
1081
- }
1082
- finally {
1083
- touched(this, { type: 'bunch', method: 'copyWithin' },
1084
- // TODO: calculate the range properly
1085
- range(0, this[native$2].length - 1));
1086
- }
1087
- // Touch all affected indices with a single allProps call
1088
- }
1089
- // Immutable versions of mutator methods
1090
- toReversed() {
1091
- dependant(this);
1092
- return reactive(this[native$2].toReversed());
1093
- }
1094
- toSorted(compareFn) {
1095
- dependant(this);
1096
- return reactive(this[native$2].toSorted(compareFn));
1097
- }
1098
- toSpliced(start, deleteCount, ...items) {
1099
- dependant(this);
1100
- return deleteCount === undefined
1101
- ? this[native$2].toSpliced(start)
1102
- : this[native$2].toSpliced(start, deleteCount, ...items);
1103
- }
1104
- with(index, value) {
1105
- dependant(this);
1106
- return reactive(this[native$2].with(index, value));
1107
- }
1108
- // Iterator methods with reactivity tracking
1109
- entries() {
1110
- dependant(this);
1111
- return makeReactiveEntriesIterator(this[native$2].entries());
1112
- }
1113
- keys() {
1114
- dependant(this);
1115
- return this[native$2].keys();
1116
- }
1117
- values() {
1118
- dependant(this);
1119
- return makeReactiveIterator(this[native$2].values());
1120
- }
1121
- [Symbol.iterator]() {
1122
- dependant(this);
1123
- const nativeIterator = this[native$2][Symbol.iterator]();
1124
- return {
1125
- next() {
1126
- const result = nativeIterator.next();
1127
- if (result.done) {
1128
- return result;
1129
- }
1130
- return { value: reactive(result.value), done: false };
1131
- },
1132
- };
1133
- }
1134
- indexOf(searchElement, fromIndex) {
1135
- dependant(this);
1136
- return this[native$2].indexOf(searchElement, fromIndex);
1137
- }
1138
- lastIndexOf(searchElement, fromIndex) {
1139
- dependant(this);
1140
- return this[native$2].lastIndexOf(searchElement, fromIndex);
1141
- }
1142
- includes(searchElement, fromIndex) {
1143
- dependant(this);
1144
- return this[native$2].includes(searchElement, fromIndex);
1145
- }
1146
- find(predicate, thisArg) {
1147
- dependant(this);
1148
- return reactive(this[native$2].find(predicate, thisArg));
1149
- }
1150
- findIndex(predicate, thisArg) {
1151
- dependant(this);
1152
- return this[native$2].findIndex(predicate, thisArg);
1153
- }
1154
- flat() {
1155
- dependant(this);
1156
- return reactive(this[native$2].flat());
1157
- }
1158
- flatMap(callbackfn, thisArg) {
1159
- dependant(this);
1160
- return reactive(this[native$2].flatMap(callbackfn, thisArg));
1161
- }
1162
- filter(callbackfn, thisArg) {
1163
- dependant(this);
1164
- return reactive(this[native$2].filter(callbackfn, thisArg));
1165
- }
1166
- map(callbackfn, thisArg) {
1167
- dependant(this);
1168
- return reactive(this[native$2].map(callbackfn, thisArg));
1169
- }
1170
- reduce(callbackfn, initialValue) {
1171
- dependant(this);
1172
- const result = initialValue === undefined
1173
- ? this[native$2].reduce(callbackfn)
1174
- : this[native$2].reduce(callbackfn, initialValue);
1175
- return reactive(result);
1176
- }
1177
- reduceRight(callbackfn, initialValue) {
1178
- dependant(this);
1179
- const result = initialValue !== undefined
1180
- ? this[native$2].reduceRight(callbackfn, initialValue)
1181
- : this[native$2].reduceRight(callbackfn);
1182
- return reactive(result);
1183
- }
1184
- slice(start, end) {
1185
- for (const i of range(start || 0, end || this[native$2].length - 1))
1186
- dependant(this, i);
1187
- return start === undefined
1188
- ? this[native$2].slice()
1189
- : end === undefined
1190
- ? this[native$2].slice(start)
1191
- : this[native$2].slice(start, end);
1192
- }
1193
- concat(...items) {
1194
- dependant(this);
1195
- return reactive(this[native$2].concat(...items));
1196
- }
1197
- join(separator) {
1198
- dependant(this);
1199
- return this[native$2].join(separator);
1200
- }
1201
- forEach(callbackfn, thisArg) {
1202
- dependant(this);
1203
- this[native$2].forEach(callbackfn, thisArg);
1204
- }
1205
- // TODO: re-implement for fun dependencies? (eg - every only check the first ones until it find some),
1206
- // no need to make it dependant on indexes after the found one
1207
- every(callbackfn, thisArg) {
1208
- dependant(this);
1209
- return this[native$2].every(callbackfn, thisArg);
1210
- }
1211
- some(callbackfn, thisArg) {
1212
- dependant(this);
1213
- return this[native$2].some(callbackfn, thisArg);
1214
- }
1215
- }
1216
-
1217
- const native$1 = Symbol('native');
1218
- class ReactiveWeakMap {
1219
- constructor(original) {
1220
- Object.defineProperties(this, {
1221
- [native$1]: { value: original },
1222
- [prototypeForwarding]: { value: original },
1223
- content: { value: Symbol('content') },
1224
- [Symbol.toStringTag]: { value: 'ReactiveWeakMap' },
1225
- });
1226
- }
1227
- // Implement WeakMap interface methods with reactivity
1228
- delete(key) {
1229
- const hadKey = this[native$1].has(key);
1230
- const result = this[native$1].delete(key);
1231
- if (hadKey)
1232
- touched1(this.content, { type: 'del', prop: key }, key);
1233
- return result;
1234
- }
1235
- get(key) {
1236
- dependant(this.content, key);
1237
- return reactive(this[native$1].get(key));
1238
- }
1239
- has(key) {
1240
- dependant(this.content, key);
1241
- return this[native$1].has(key);
1242
- }
1243
- set(key, value) {
1244
- // Trigger effects for the specific key
1245
- touched1(this.content, { type: this[native$1].has(key) ? 'set' : 'add', prop: key }, key);
1246
- this[native$1].set(key, value);
1247
- return this;
1248
- }
1249
- }
1250
- class ReactiveMap {
1251
- constructor(original) {
1252
- Object.defineProperties(this, {
1253
- [native$1]: { value: original },
1254
- [prototypeForwarding]: { value: original },
1255
- content: { value: Symbol('content') },
1256
- [Symbol.toStringTag]: { value: 'ReactiveMap' },
1257
- });
1258
- }
1259
- // Implement Map interface methods with reactivity
1260
- get size() {
1261
- dependant(this, 'size'); // The ReactiveMap instance still goes through proxy
1262
- return this[native$1].size;
1263
- }
1264
- clear() {
1265
- const hadEntries = this[native$1].size > 0;
1266
- this[native$1].clear();
1267
- if (hadEntries) {
1268
- const evolution = { type: 'bunch', method: 'clear' };
1269
- // Clear triggers all effects since all keys are affected
1270
- touched1(this, evolution, 'size');
1271
- touched(this.content, evolution);
1272
- }
1273
- }
1274
- entries() {
1275
- dependant(this.content);
1276
- return makeReactiveEntriesIterator(this[native$1].entries());
1277
- }
1278
- forEach(callbackfn, thisArg) {
1279
- dependant(this.content);
1280
- this[native$1].forEach(callbackfn, thisArg);
1281
- }
1282
- keys() {
1283
- dependant(this.content);
1284
- return this[native$1].keys();
1285
- }
1286
- values() {
1287
- dependant(this.content);
1288
- return makeReactiveIterator(this[native$1].values());
1289
- }
1290
- [Symbol.iterator]() {
1291
- dependant(this.content);
1292
- const nativeIterator = this[native$1][Symbol.iterator]();
1293
- return {
1294
- next() {
1295
- const result = nativeIterator.next();
1296
- if (result.done) {
1297
- return result;
1298
- }
1299
- return {
1300
- value: [result.value[0], reactive(result.value[1])],
1301
- done: false,
1302
- };
1303
- },
1304
- };
1305
- }
1306
- // Implement Map methods with reactivity
1307
- delete(key) {
1308
- const hadKey = this[native$1].has(key);
1309
- const result = this[native$1].delete(key);
1310
- if (hadKey) {
1311
- const evolution = { type: 'del', prop: key };
1312
- touched1(this.content, evolution, key);
1313
- touched1(this, evolution, 'size');
1314
- }
1315
- return result;
1316
- }
1317
- get(key) {
1318
- dependant(this.content, key);
1319
- return reactive(this[native$1].get(key));
1320
- }
1321
- has(key) {
1322
- dependant(this.content, key);
1323
- return this[native$1].has(key);
1324
- }
1325
- set(key, value) {
1326
- const hadKey = this[native$1].has(key);
1327
- const oldValue = this[native$1].get(key);
1328
- const reactiveValue = reactive(value);
1329
- this[native$1].set(key, reactiveValue);
1330
- if (!hadKey || oldValue !== reactiveValue) {
1331
- const evolution = { type: hadKey ? 'set' : 'add', prop: key };
1332
- touched1(this.content, evolution, key);
1333
- touched1(this, evolution, 'size');
1334
- }
1335
- return this;
1336
- }
1337
- }
1338
-
1339
- const native = Symbol('native');
1340
- class ReactiveWeakSet {
1341
- constructor(original) {
1342
- Object.defineProperties(this, {
1343
- [native]: { value: original },
1344
- [prototypeForwarding]: { value: original },
1345
- content: { value: Symbol('content') },
1346
- [Symbol.toStringTag]: { value: 'ReactiveWeakSet' },
1347
- });
1348
- }
1349
- add(value) {
1350
- const had = this[native].has(value);
1351
- this[native].add(value);
1352
- if (!had) {
1353
- // touch the specific value and the collection view
1354
- touched1(this.content, { type: 'add', prop: value }, value);
1355
- // no size/allProps for WeakSet
1356
- }
1357
- return this;
1358
- }
1359
- delete(value) {
1360
- const had = this[native].has(value);
1361
- const res = this[native].delete(value);
1362
- if (had)
1363
- touched1(this.content, { type: 'del', prop: value }, value);
1364
- return res;
1365
- }
1366
- has(value) {
1367
- dependant(this.content, value);
1368
- return this[native].has(value);
1369
- }
1370
- }
1371
- class ReactiveSet {
1372
- constructor(original) {
1373
- Object.defineProperties(this, {
1374
- [native]: { value: original },
1375
- [prototypeForwarding]: { value: original },
1376
- content: { value: Symbol('content') },
1377
- [Symbol.toStringTag]: { value: 'ReactiveSet' },
1378
- });
1379
- }
1380
- get size() {
1381
- // size depends on the wrapper instance, like Map counterpart
1382
- dependant(this, 'size');
1383
- return this[native].size;
1384
- }
1385
- add(value) {
1386
- const had = this[native].has(value);
1387
- const reactiveValue = reactive(value);
1388
- this[native].add(reactiveValue);
1389
- if (!had) {
1390
- const evolution = { type: 'add', prop: reactiveValue };
1391
- // touch for value-specific and aggregate dependencies
1392
- touched1(this.content, evolution, reactiveValue);
1393
- touched1(this, evolution, 'size');
1394
- }
1395
- return this;
1396
- }
1397
- clear() {
1398
- const hadEntries = this[native].size > 0;
1399
- this[native].clear();
1400
- if (hadEntries) {
1401
- const evolution = { type: 'bunch', method: 'clear' };
1402
- touched1(this, evolution, 'size');
1403
- touched(this.content, evolution);
1404
- }
1405
- }
1406
- delete(value) {
1407
- const had = this[native].has(value);
1408
- const res = this[native].delete(value);
1409
- if (had) {
1410
- const evolution = { type: 'del', prop: value };
1411
- touched1(this.content, evolution, value);
1412
- touched1(this, evolution, 'size');
1413
- }
1414
- return res;
1415
- }
1416
- has(value) {
1417
- dependant(this.content, value);
1418
- return this[native].has(value);
1419
- }
1420
- entries() {
1421
- dependant(this.content);
1422
- return makeReactiveEntriesIterator(this[native].entries());
1423
- }
1424
- forEach(callbackfn, thisArg) {
1425
- dependant(this.content);
1426
- this[native].forEach(callbackfn, thisArg);
1427
- }
1428
- keys() {
1429
- dependant(this.content);
1430
- return makeReactiveIterator(this[native].keys());
1431
- }
1432
- values() {
1433
- dependant(this.content);
1434
- return makeReactiveIterator(this[native].values());
1435
- }
1436
- [Symbol.iterator]() {
1437
- dependant(this.content);
1438
- const nativeIterator = this[native][Symbol.iterator]();
1439
- return {
1440
- next() {
1441
- const result = nativeIterator.next();
1442
- if (result.done) {
1443
- return result;
1444
- }
1445
- return { value: reactive(result.value), done: false };
1446
- },
1447
- };
1448
- }
1449
- }
1450
-
1451
- // Register native collection types to use specialized reactive wrappers
1452
- registerNativeReactivity(WeakMap, ReactiveWeakMap);
1453
- registerNativeReactivity(Map, ReactiveMap);
1454
- registerNativeReactivity(WeakSet, ReactiveWeakSet);
1455
- registerNativeReactivity(Set, ReactiveSet);
1456
- registerNativeReactivity(Array, ReactiveArray);
1457
-
1458
- export { ReactiveBase, ReactiveError, atomic, computed, effect, getState, immutables, invalidateComputed, isNonReactive, isReactive, profileInfo, reactive, options as reactiveOptions, unreactive, untracked, unwrap, watch };
1
+ export { L as ReactiveBase, U as ReactiveError, R as ReadOnlyError, Q as Register, j as addBatchCleanup, k as atomic, l as biDi, c as buildReactivityGraph, x as cleanedBy, y as cleanup, h as deepWatch, n as defer, z as derived, o as effect, e as enableDevTools, q as getActiveEffect, g as getState, F as immutables, i as isDevtoolsEnabled, G as isNonReactive, K as isReactive, V as isZoneEnabled, C as mapped, E as memoize, O as organize, P as organized, p as profileInfo, J as project, M as reactive, T as reactiveOptions, D as reduced, S as register, r as registerEffectForDebug, H as registerNativeReactivity, d as registerObjectForDebug, u as root, s as setEffectName, f as setObjectName, W as setZoneEnabled, t as touched, b as touched1, v as trackEffect, A as unreactive, w as untracked, N as unwrap, B as watch } from './chunks/index-DzUDtFc7.esm.js';
2
+ import './chunks/decorator-DqiszP7i.esm.js';
3
+ import './indexable.esm.js';
4
+ import './chunks/_tslib-Mzh1rNsX.esm.js';
1459
5
  //# sourceMappingURL=reactive.esm.js.map