mutts 1.0.10 → 1.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +3 -3
  2. package/dist/browser.cjs +395 -987
  3. package/dist/browser.cjs.map +1 -1
  4. package/dist/browser.d.ts +2 -2
  5. package/dist/browser.dev.cjs +13 -9
  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/{async-browser-BU_IfxYD.cjs → async-browser-Dgr5CreQ.cjs} +13 -11
  12. package/dist/chunks/async-browser-Dgr5CreQ.cjs.map +1 -0
  13. package/dist/chunks/{index-CaaQQlPJ.esm.js → index-Sf74wXTV.esm.js} +384 -981
  14. package/dist/chunks/index-Sf74wXTV.esm.js.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/{proxy-Dtg-bJ3T.cjs → proxy-Cc79Lrzj.cjs} +414 -339
  18. package/dist/chunks/proxy-Cc79Lrzj.cjs.map +1 -0
  19. package/dist/chunks/{proxy-r7lARftl.esm.js → proxy-D2C49sXH.esm.js} +401 -330
  20. package/dist/chunks/proxy-D2C49sXH.esm.js.map +1 -0
  21. package/dist/debug.cjs +17 -3
  22. package/dist/debug.cjs.map +1 -1
  23. package/dist/debug.d.ts +2 -2
  24. package/dist/debug.esm.js +17 -3
  25. package/dist/debug.esm.js.map +1 -1
  26. package/dist/index.d.ts +84 -209
  27. package/dist/mutts.umd.js +842 -1362
  28. package/dist/mutts.umd.js.map +1 -1
  29. package/dist/mutts.umd.min.js +1 -1
  30. package/dist/mutts.umd.min.js.map +1 -1
  31. package/dist/node.cjs +13 -9
  32. package/dist/node.cjs.map +1 -1
  33. package/dist/node.d.ts +2 -2
  34. package/dist/node.dev.cjs +13 -9
  35. package/dist/node.dev.cjs.map +1 -1
  36. package/dist/node.dev.d.ts +2 -2
  37. package/dist/node.dev.esm.js +3 -3
  38. package/dist/node.esm.js +3 -3
  39. package/dist/{types-W5vD6m2n.d.ts → types-Bx2PhORg.d.ts} +38 -47
  40. package/docs/ai/api-reference.md +0 -14
  41. package/docs/ai/manual.md +2 -22
  42. package/docs/reactive/advanced.md +13 -14
  43. package/docs/reactive/attend.md +1 -2
  44. package/docs/reactive/collections.md +2 -149
  45. package/docs/reactive/core.md +218 -96
  46. package/docs/reactive/debugging.md +2 -2
  47. package/docs/reactive/resource.md +1 -1
  48. package/docs/reactive.md +1 -3
  49. package/docs/zone.md +1 -1
  50. package/package.json +18 -9
  51. package/dist/chunks/async-browser-BU_IfxYD.cjs.map +0 -1
  52. package/dist/chunks/index-CaaQQlPJ.esm.js.map +0 -1
  53. package/dist/chunks/proxy-Dtg-bJ3T.cjs.map +0 -1
  54. package/dist/chunks/proxy-r7lARftl.esm.js.map +0 -1
  55. package/docs/reactive/scan.md +0 -324
package/dist/browser.cjs CHANGED
@@ -1,11 +1,12 @@
1
1
  'use strict';
2
2
 
3
- require('./chunks/async-browser-BU_IfxYD.cjs');
4
- var proxy = require('./chunks/proxy-Dtg-bJ3T.cjs');
3
+ require('./chunks/async-browser-Dgr5CreQ.cjs');
4
+ var proxy = require('./chunks/proxy-Cc79Lrzj.cjs');
5
5
  var asyncCore = require('./chunks/async-core-CRLKP3l-.cjs');
6
6
  require('./chunks/async-node-3PrbVAbB.cjs');
7
7
  require('node:async_hooks');
8
8
 
9
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
9
10
  // Integrated with `using` statement via Symbol.dispose
10
11
  const fr = new FinalizationRegistry((f) => f());
11
12
  /**
@@ -750,211 +751,6 @@ function chainPromise(given) {
750
751
  return chained;
751
752
  }
752
753
 
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
754
  function attend(source, callback) {
959
755
  const enumerate = typeof source === 'function'
960
756
  ? source
@@ -966,14 +762,14 @@ function attend(source, callback) {
966
762
  ? () => source.values()
967
763
  : () => Object.keys(source);
968
764
  const keyEffects = new Map();
969
- const outer = proxy.effect(({ ascend }) => {
765
+ const outer = proxy.effect.named('attend')(({ ascend }) => {
970
766
  const keys = new Set();
971
767
  for (const key of enumerate())
972
768
  keys.add(key);
973
769
  for (const key of keys) {
974
770
  if (keyEffects.has(key))
975
771
  continue;
976
- keyEffects.set(key, ascend(() => proxy.effect(() => callback(key))));
772
+ keyEffects.set(key, ascend(() => proxy.effect.named(`attend:${key}`)((access) => callback(key, access))));
977
773
  }
978
774
  for (const key of Array.from(keyEffects.keys())) {
979
775
  if (!keys.has(key)) {
@@ -989,146 +785,10 @@ function attend(source, callback) {
989
785
  keyEffects.clear();
990
786
  };
991
787
  }
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
788
  function lift(cb) {
1129
789
  let result;
1130
790
  let rawResult;
1131
- const liftCleanup = proxy.effect.named('lift')(proxy.markWithRoot((access) => {
791
+ const liftCleanup = proxy.effect.named(`lift:${cb.name}`)(proxy.markWithRoot((access) => {
1132
792
  const source = cb(access);
1133
793
  if (!source || typeof source !== 'object')
1134
794
  throw new Error('lift callback must return an array or object');
@@ -1141,11 +801,8 @@ function lift(cb) {
1141
801
  throw new Error('lift callback must return the same type as the previous result');
1142
802
  if (Array.isArray(source)) {
1143
803
  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];
804
+ for (const { indexA, sliceA, sliceB } of arrayDiff(res, source).sort((a, b) => a.indexA - b.indexA))
1147
805
  res.splice(indexA, sliceA.length, ...sliceB);
1148
- }
1149
806
  }
1150
807
  else {
1151
808
  for (const key of Object.keys(source)) {
@@ -1172,7 +829,7 @@ function lift(cb) {
1172
829
  }
1173
830
  }
1174
831
  }, cb));
1175
- return proxy.cleanedBy(result, liftCleanup);
832
+ return proxy.link(result, liftCleanup);
1176
833
  }
1177
834
  /**
1178
835
  * Reactively maps an array source through `fn`, producing a lazy reactive output array.
@@ -1193,7 +850,7 @@ function lift(cb) {
1193
850
  */
1194
851
  function morphArray(source, fn, options) {
1195
852
  if (typeof source !== 'function' && !proxy.isReactive(source) && options?.pure === true) {
1196
- return source.map(fn);
853
+ return source.map((i) => fn(i));
1197
854
  }
1198
855
  let track;
1199
856
  const itemEffects = new Map();
@@ -1215,17 +872,14 @@ function morphArray(source, fn, options) {
1215
872
  }
1216
873
  else {
1217
874
  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
- });
875
+ const stop = track(() => proxy.effect.named(`morph:${fn.name}:${key}`).opaque((access) => {
876
+ cache[indexRef.value] = fn(input, access);
877
+ return (reason) => {
878
+ delete cache[indexRef.value];
879
+ proxy.touched1(cache, { type: 'invalidate', prop: 'morph' }, String(key));
880
+ stop?.({ type: 'invalidate', cause: reason });
881
+ };
882
+ }));
1229
883
  itemEffects.set(key, { stop, index: indexRef });
1230
884
  }
1231
885
  }
@@ -1242,7 +896,7 @@ function morphArray(source, fn, options) {
1242
896
  return Reflect.has(input, prop);
1243
897
  },
1244
898
  });
1245
- const stopMain = proxy.effect.named('morph:array')(({ ascend }) => {
899
+ const stopMain = proxy.effect.named(`morph:${fn.name}`)(({ ascend }) => {
1246
900
  track = ascend;
1247
901
  const newInput = [...(typeof source === 'function' ? source() : source)];
1248
902
  const diffs = arrayDiff(input, newInput).toSorted((a, b) => b.indexA - a.indexA);
@@ -1257,7 +911,7 @@ function morphArray(source, fn, options) {
1257
911
  // We need to move entries in the Map.
1258
912
  const entries = Array.from(itemEffects.entries()).sort((a, b) => a[0] - b[0]);
1259
913
  // Remove entries that will be shifted
1260
- for (const [idx, entry] of entries) {
914
+ for (const [idx, _entry] of entries) {
1261
915
  if (idx >= diff.indexA + diff.sliceA.length) {
1262
916
  itemEffects.delete(idx);
1263
917
  }
@@ -1289,7 +943,7 @@ function morphArray(source, fn, options) {
1289
943
  }
1290
944
  input = newInput;
1291
945
  });
1292
- return proxy.cleanedBy(proxy$1, (reason) => {
946
+ return proxy.link(proxy$1, (reason) => {
1293
947
  stopMain(reason);
1294
948
  for (const entry of itemEffects.values())
1295
949
  entry.stop(reason);
@@ -1311,7 +965,7 @@ function morphMap(source, fn, options) {
1311
965
  if (!proxy.isReactive(source) && options?.pure === true) {
1312
966
  const res = new Map();
1313
967
  for (const [k, v] of source)
1314
- res.set(k, fn(v));
968
+ res.set(k, fn(v, k));
1315
969
  return res;
1316
970
  }
1317
971
  let track;
@@ -1328,15 +982,15 @@ function morphMap(source, fn, options) {
1328
982
  function computeItem(key, val) {
1329
983
  const isPure = options?.pure === true || (typeof options?.pure === 'function' && options.pure(val));
1330
984
  if (isPure) {
1331
- cache.set(key, track(() => fn(val)));
985
+ cache.set(key, track(() => fn(val, key)));
1332
986
  }
1333
987
  else {
1334
- const stop = track(() => proxy.effect.opaque(() => {
1335
- cache.set(key, fn(source.get(key)));
988
+ const stop = track(() => proxy.effect.named(`morph:${fn.name}:${key}`).opaque((access) => {
989
+ cache.set(key, fn(source.get(key), key, access));
1336
990
  return (reason) => {
1337
991
  cache.delete(key);
1338
992
  proxy.touched1(cache, { type: 'invalidate', prop: 'morph' }, String(key));
1339
- stop({ type: 'invalidate', cause: reason });
993
+ stop?.({ type: 'invalidate', cause: reason });
1340
994
  };
1341
995
  }));
1342
996
  itemEffects.set(key, stop);
@@ -1380,7 +1034,7 @@ function morphMap(source, fn, options) {
1380
1034
  },
1381
1035
  });
1382
1036
  let stateSnapshot = proxy.getState(source);
1383
- const stopMain = proxy.effect.named('morph:map')(({ ascend }) => {
1037
+ const stopMain = proxy.effect.named(`morph:${fn.name}`)(({ ascend }) => {
1384
1038
  track = ascend;
1385
1039
  proxy.dependant(source, proxy.keysOf);
1386
1040
  while ('evolution' in stateSnapshot) {
@@ -1396,7 +1050,7 @@ function morphMap(source, fn, options) {
1396
1050
  }
1397
1051
  }
1398
1052
  });
1399
- return proxy.cleanedBy(proxy$1, (reason) => {
1053
+ return proxy.link(proxy$1, (reason) => {
1400
1054
  stopMain(reason);
1401
1055
  for (const stop of itemEffects.values())
1402
1056
  stop(reason);
@@ -1418,7 +1072,7 @@ function morphRecord(source, fn, options) {
1418
1072
  if (!proxy.isReactive(source) && options?.pure === true) {
1419
1073
  const res = {};
1420
1074
  for (const k of Object.keys(source))
1421
- res[k] = fn(source[k]);
1075
+ res[k] = fn(source[k], k);
1422
1076
  return res;
1423
1077
  }
1424
1078
  let track;
@@ -1434,15 +1088,15 @@ function morphRecord(source, fn, options) {
1434
1088
  function computeItem(key, val) {
1435
1089
  const isPure = options?.pure === true || (typeof options?.pure === 'function' && options.pure(val));
1436
1090
  if (isPure) {
1437
- cache[key] = track(() => fn(val));
1091
+ cache[key] = track(() => fn(val, key));
1438
1092
  }
1439
1093
  else {
1440
- const stop = track(() => proxy.effect.opaque(() => {
1441
- cache[key] = fn(source[key]);
1094
+ const stop = track(() => proxy.effect.named(`morph:${fn.name}:${key}`).opaque((access) => {
1095
+ cache[key] = fn(source[key], key, access);
1442
1096
  return (reason) => {
1443
1097
  delete cache[key];
1444
1098
  proxy.touched1(cache, { type: 'invalidate', prop: 'morph' }, String(key));
1445
- stop({ type: 'invalidate', cause: reason });
1099
+ stop?.({ type: 'invalidate', cause: reason });
1446
1100
  };
1447
1101
  }));
1448
1102
  itemEffects.set(key, stop);
@@ -1469,7 +1123,7 @@ function morphRecord(source, fn, options) {
1469
1123
  },
1470
1124
  });
1471
1125
  let stateSnapshot = proxy.getState(source);
1472
- const stopMain = proxy.effect.named('morph:record')(({ ascend }) => {
1126
+ const stopMain = proxy.effect.named(`morph:${fn.name}`)(({ ascend }) => {
1473
1127
  track = ascend;
1474
1128
  // Track only structural changes on source
1475
1129
  proxy.dependant(source, proxy.keysOf);
@@ -1486,7 +1140,7 @@ function morphRecord(source, fn, options) {
1486
1140
  }
1487
1141
  }
1488
1142
  });
1489
- return proxy.cleanedBy(proxy$1, (reason) => {
1143
+ return proxy.link(proxy$1, (reason) => {
1490
1144
  stopMain(reason);
1491
1145
  for (const stop of itemEffects.values())
1492
1146
  stop(reason);
@@ -1545,7 +1199,7 @@ function deepWatch(target, callback, { immediate = false } = {}) {
1545
1199
  const wrappedCallback = proxy.markWithRoot((() => callback(target)), callback);
1546
1200
  proxy.registerDeepWatcher();
1547
1201
  // Use the existing effect system to register dependencies
1548
- return proxy.effect(() => {
1202
+ return proxy.effect.named('deepWatch')(() => {
1549
1203
  // Mark the target object as having deep watchers
1550
1204
  proxy.objectsWithDeepWatchers.add(target);
1551
1205
  // Track which objects this effect is watching for cleanup
@@ -1581,35 +1235,24 @@ function deepWatch(target, callback, { immediate = false } = {}) {
1581
1235
  }
1582
1236
  }
1583
1237
  // 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
1238
+ // Handle arrays and collections using iterators to ensure proxy tracking is triggered
1239
+ if (typeof obj[Symbol.iterator] === 'function') {
1240
+ // Access the iterator to track additions/removals/collection changes
1600
1241
  for (const value of obj) {
1601
1242
  // Make the value reactive if it's an object
1602
1243
  const reactiveValue = typeof value === 'object' && value !== null ? proxy.reactive(value) : value;
1603
1244
  traverseAndTrack(reactiveValue, depth + 1);
1604
1245
  }
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);
1246
+ // Explicitly depend on length so array mutations changing count trigger re-evaluation
1247
+ if ('length' in obj) {
1248
+ proxy.dependant(obj, 'length');
1249
+ }
1250
+ // For Maps, also ensure we track values explicitly if the iterator yields entries
1251
+ if (obj instanceof Map) {
1252
+ for (const value of obj.values()) {
1253
+ const reactiveValue = typeof value === 'object' && value !== null ? proxy.reactive(value) : value;
1254
+ traverseAndTrack(reactiveValue, depth + 1);
1255
+ }
1613
1256
  }
1614
1257
  }
1615
1258
  // Note: WeakSet and WeakMap cannot be iterated, so we can't deep watch their contents
@@ -1646,12 +1289,217 @@ function deepWatch(target, callback, { immediate = false } = {}) {
1646
1289
  proxy.objectsWithDeepWatchers.delete(obj);
1647
1290
  }
1648
1291
  }
1649
- // Clean up the tracking data
1650
- proxy.effectToDeepWatchedObjects.delete(wrappedCallback);
1292
+ // Clean up the tracking data
1293
+ proxy.effectToDeepWatchedObjects.delete(wrappedCallback);
1294
+ }
1295
+ };
1296
+ });
1297
+ }
1298
+
1299
+ const memoizedRegistry = new WeakMap();
1300
+ const wrapperRegistry = new WeakMap();
1301
+ function getBranch(tree, key) {
1302
+ tree.branches ?? (tree.branches = new WeakMap());
1303
+ let branch = tree.branches.get(key);
1304
+ if (!branch) {
1305
+ branch = {};
1306
+ tree.branches.set(key, branch);
1307
+ }
1308
+ return branch;
1309
+ }
1310
+ function memoizeFunction(fn, opts) {
1311
+ const fnRoot = proxy.getRoot(fn);
1312
+ const existing = memoizedRegistry.get(fnRoot);
1313
+ if (existing)
1314
+ return existing;
1315
+ const cacheRoot = {};
1316
+ const memoized = proxy.markWithRoot(function memoized(...args) {
1317
+ if (args.some((arg) => !(arg && ['object', 'symbol', 'function'].includes(typeof arg)))) {
1318
+ if (opts?.lenient)
1319
+ return fn.apply(this, args);
1320
+ throw new Error('memoize expects non-null object arguments');
1321
+ }
1322
+ let node = cacheRoot;
1323
+ // Note: decorators add `this` as first argument
1324
+ for (const arg of args) {
1325
+ node = getBranch(node, arg);
1326
+ }
1327
+ proxy.dependant(node, 'memoize');
1328
+ if ('result' in node) {
1329
+ if (proxy.options.onMemoizationDiscrepancy) {
1330
+ const wasVerification = proxy.options.isVerificationRun;
1331
+ proxy.options.isVerificationRun = true;
1332
+ try {
1333
+ const fresh = proxy.untracked(() => fn.apply(this, args));
1334
+ if (!proxy.deepCompare(node.result, fresh)) {
1335
+ proxy.optionCall('onMemoizationDiscrepancy', node.result, fresh, fn, args, 'calculation');
1336
+ }
1337
+ }
1338
+ finally {
1339
+ proxy.options.isVerificationRun = wasVerification;
1340
+ }
1341
+ }
1342
+ return node.result;
1343
+ }
1344
+ // Create memoize internal effect to track dependencies and invalidate cache
1345
+ // Use untracked to prevent the effect creation from being affected by parent effects
1346
+ node.cleanup = proxy.root(() => proxy.effect.named('memoize')(() => {
1347
+ // Execute the function and track its dependencies
1348
+ // The function execution will automatically track dependencies on reactive objects
1349
+ node.result = fn.apply(this, args);
1350
+ return (reason) => {
1351
+ // When dependencies change, clear the cache and notify consumers
1352
+ delete node.result;
1353
+ proxy.touched1(node, { type: 'invalidate', prop: args }, 'memoize');
1354
+ // Lazy memoization: stop the effect so it doesn't re-run immediately.
1355
+ // It will be re-created on next access.
1356
+ if (node.cleanup) {
1357
+ node.cleanup({ type: 'invalidate', cause: reason });
1358
+ node.cleanup = undefined;
1359
+ }
1360
+ };
1361
+ }, { opaque: true }));
1362
+ if (proxy.options.onMemoizationDiscrepancy) {
1363
+ const wasVerification = proxy.options.isVerificationRun;
1364
+ proxy.options.isVerificationRun = true;
1365
+ try {
1366
+ const fresh = proxy.untracked(() => fn.apply(this, args));
1367
+ if (!proxy.deepCompare(node.result, fresh)) {
1368
+ proxy.optionCall('onMemoizationDiscrepancy', node.result, fresh, fn, args, 'comparison');
1369
+ }
1370
+ }
1371
+ finally {
1372
+ proxy.options.isVerificationRun = wasVerification;
1373
+ }
1374
+ }
1375
+ return node.result;
1376
+ }, fn);
1377
+ memoizedRegistry.set(fnRoot, memoized);
1378
+ memoizedRegistry.set(memoized, memoized);
1379
+ return memoized;
1380
+ }
1381
+ function memoizeObject(target, opts) {
1382
+ const existing = memoizedRegistry.get(target);
1383
+ if (existing)
1384
+ return existing;
1385
+ const proxy$1 = new Proxy(target, {
1386
+ get(source, prop, receiver) {
1387
+ // 1. Walk prototype chain to find descriptor
1388
+ let current = source;
1389
+ let desc;
1390
+ while (current) {
1391
+ desc = Object.getOwnPropertyDescriptor(current, prop);
1392
+ if (desc)
1393
+ break;
1394
+ current = Object.getPrototypeOf(current);
1395
+ }
1396
+ if (!desc)
1397
+ return Reflect.get(source, prop, receiver);
1398
+ // 2. If getter, memoize
1399
+ if (desc.get) {
1400
+ const originalGetter = desc.get;
1401
+ let wrapper = wrapperRegistry.get(originalGetter);
1402
+ if (!wrapper) {
1403
+ wrapper = proxy.markWithRoot(proxy.named(`${String(source?.constructor?.name ?? 'Object')}.${String(prop)}`, (that) => {
1404
+ return originalGetter.call(that);
1405
+ }), {
1406
+ propertyKey: prop,
1407
+ });
1408
+ const origRoot = originalGetter[proxy.rootFunctionSymbol];
1409
+ if (origRoot)
1410
+ wrapper[proxy.rootFunctionSymbol] = origRoot;
1411
+ wrapperRegistry.set(originalGetter, wrapper);
1412
+ }
1413
+ const memoized = memoizeFunction(wrapper, opts);
1414
+ return memoized(receiver);
1651
1415
  }
1652
- };
1416
+ // 3. Otherwise forward
1417
+ return Reflect.get(source, prop, receiver);
1418
+ },
1419
+ // Forward set to the target (source) to ensure it acts as the receiver for reactivity notifications
1420
+ set(source, prop, value, _receiver) {
1421
+ // By strictly passing `source` as receiver, we ensure that if `source` is a reactive proxy,
1422
+ // it recognizes itself and triggers change notifications.
1423
+ return Reflect.set(source, prop, value, source);
1424
+ },
1425
+ });
1426
+ proxy.proxyToObject.set(proxy$1, target);
1427
+ memoizedRegistry.set(target, proxy$1);
1428
+ return proxy$1;
1429
+ }
1430
+ /**
1431
+ * Decorator and function wrapper for memoizing computed values based on reactive dependencies.
1432
+ *
1433
+ * When used as a decorator on getters or methods, it caches the result and automatically
1434
+ * invalidates the cache when reactive dependencies change.
1435
+ *
1436
+ * When used as a function wrapper, it memoizes based on object arguments (WeakMap-based cache).
1437
+ *
1438
+ * @example
1439
+ * ```typescript
1440
+ * class User {
1441
+ * @memoize
1442
+ * get fullName() {
1443
+ * return `${this.firstName} ${this.lastName}`
1444
+ * }
1445
+ * }
1446
+ *
1447
+ * // Or as a function wrapper
1448
+ * const expensive = memoize((obj: SomeObject) => {
1449
+ * return heavyComputation(obj)
1450
+ * })
1451
+ * ```
1452
+ */
1453
+ function makeMemoizeDecorator(memoizeOpts) {
1454
+ return proxy.decorator({
1455
+ getter(original, target, propertyKey) {
1456
+ return function () {
1457
+ let wrapper = wrapperRegistry.get(original);
1458
+ if (!wrapper) {
1459
+ wrapper = proxy.markWithRoot(proxy.named(`${String(target?.constructor?.name ?? target?.name ?? 'Object')}.${String(propertyKey)}`, (that) => {
1460
+ return original.call(that);
1461
+ }), {
1462
+ method: original,
1463
+ propertyKey,
1464
+ });
1465
+ const origRoot = original[proxy.rootFunctionSymbol];
1466
+ if (origRoot)
1467
+ wrapper[proxy.rootFunctionSymbol] = origRoot;
1468
+ wrapperRegistry.set(original, wrapper);
1469
+ }
1470
+ const memoized = memoizeFunction(wrapper, memoizeOpts);
1471
+ return memoized(this);
1472
+ };
1473
+ },
1474
+ method(original, target, name) {
1475
+ return function (...args) {
1476
+ let wrapper = wrapperRegistry.get(original);
1477
+ if (!wrapper) {
1478
+ wrapper = proxy.markWithRoot(proxy.named(`${String(target?.constructor?.name ?? target?.name ?? 'Object')}.${String(name)}`, (that, ...args) => {
1479
+ return original.call(that, ...args);
1480
+ }), {
1481
+ method: original,
1482
+ propertyKey: name,
1483
+ });
1484
+ const origRoot = original[proxy.rootFunctionSymbol];
1485
+ if (origRoot)
1486
+ wrapper[proxy.rootFunctionSymbol] = origRoot;
1487
+ wrapperRegistry.set(original, wrapper);
1488
+ }
1489
+ const memoized = memoizeFunction(wrapper, memoizeOpts);
1490
+ return memoized(this, ...args);
1491
+ };
1492
+ },
1493
+ default: (target) => typeof target === 'object'
1494
+ ? memoizeObject(target, memoizeOpts)
1495
+ : memoizeFunction(target, memoizeOpts),
1653
1496
  });
1654
1497
  }
1498
+ const memoize = proxy.flavored(makeMemoizeDecorator(), {
1499
+ get lenient() {
1500
+ return makeMemoizeDecorator({ lenient: true });
1501
+ },
1502
+ });
1655
1503
 
1656
1504
  /**
1657
1505
  * Organizes a source object's properties into a target object using a callback function.
@@ -1727,7 +1575,7 @@ function organized(source, apply, baseTarget = {}) {
1727
1575
  });
1728
1576
  return apply(accessBase, target);
1729
1577
  });
1730
- return proxy.cleanedBy(target, (reason) => stop(reason));
1578
+ return proxy.link(target, (reason) => stop(reason));
1731
1579
  }
1732
1580
  /**
1733
1581
  * Organizes a property on a target object
@@ -1770,7 +1618,7 @@ changed, options = {}) {
1770
1618
  function watchObject(value, changed, { immediate = false, deep = false } = {}) {
1771
1619
  if (deep)
1772
1620
  return deepWatch(value, changed, { immediate });
1773
- return proxy.effect(function watchObjectEffect() {
1621
+ return proxy.effect.named('watch:object')(() => {
1774
1622
  proxy.dependant(value);
1775
1623
  if (immediate)
1776
1624
  changed(value);
@@ -1780,7 +1628,7 @@ function watchObject(value, changed, { immediate = false, deep = false } = {}) {
1780
1628
  function watchCallBack(value, changed, { immediate = false, deep = false } = {}) {
1781
1629
  let oldValue = unsetYet;
1782
1630
  let deepCleanup;
1783
- const cbCleanup = proxy.effect(proxy.markWithRoot(function watchCallBackEffect(access) {
1631
+ const cbCleanup = proxy.effect.named('watch:callback')(proxy.markWithRoot((access) => {
1784
1632
  const newValue = value(access);
1785
1633
  if (oldValue !== newValue) {
1786
1634
  const old = oldValue;
@@ -1798,12 +1646,10 @@ function watchCallBack(value, changed, { immediate = false, deep = false } = {})
1798
1646
  deepCleanup = deepWatch(newValue, (value) => changed(value, value));
1799
1647
  }
1800
1648
  }, value));
1801
- return Object.defineProperties(() => {
1649
+ return (() => {
1802
1650
  cbCleanup();
1803
1651
  if (deepCleanup)
1804
1652
  deepCleanup();
1805
- }, {
1806
- [proxy.stopped]: { get: () => cbCleanup[proxy.stopped] },
1807
1653
  });
1808
1654
  }
1809
1655
  //#endregion
@@ -1818,7 +1664,7 @@ function watchCallBack(value, changed, { immediate = false, deep = false } = {})
1818
1664
  function when(predicate, timeout) {
1819
1665
  return new Promise((resolve, reject) => {
1820
1666
  let timer;
1821
- const stop = proxy.effect(function whenEffect(access) {
1667
+ const stop = proxy.effect.named('watch:when')((access) => {
1822
1668
  try {
1823
1669
  const value = predicate(access);
1824
1670
  if (value) {
@@ -1855,7 +1701,7 @@ function shallowNonReactive(obj) {
1855
1701
  obj = proxy.unwrap(obj);
1856
1702
  if (proxy.isNonReactive(obj))
1857
1703
  return obj;
1858
- proxy.nonReactiveObjects.add(obj);
1704
+ obj[proxy.unreactiveProperties] = true;
1859
1705
  return obj;
1860
1706
  }
1861
1707
  function unreactiveApplication(arg1, ...args) {
@@ -1863,13 +1709,19 @@ function unreactiveApplication(arg1, ...args) {
1863
1709
  ? shallowNonReactive(arg1)
1864
1710
  : ((original) => {
1865
1711
  // 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);
1712
+ const parentMarker = original.prototype[proxy.unreactiveProperties];
1713
+ // If parent is fully unreactive, child is too
1714
+ if (parentMarker === true) {
1715
+ original.prototype[proxy.unreactiveProperties] = true;
1716
+ }
1717
+ else {
1718
+ const set = new Set(parentMarker || []);
1719
+ // Add all arguments (including the first one)
1720
+ set.add(arg1);
1721
+ for (const arg of args)
1722
+ set.add(arg);
1723
+ proxy.addUnreactiveProps(original.prototype, set);
1724
+ }
1873
1725
  return original; // Return the class
1874
1726
  });
1875
1727
  }
@@ -1879,11 +1731,26 @@ function unreactiveApplication(arg1, ...args) {
1879
1731
  */
1880
1732
  const unreactive = proxy.decorator({
1881
1733
  class(original) {
1882
- // Called without arguments, mark entire class as non-reactive
1883
- proxy.nonReactiveClass(original);
1734
+ original.prototype[proxy.unreactiveProperties] = true;
1884
1735
  },
1885
1736
  default: unreactiveApplication,
1886
1737
  });
1738
+ //#endregion
1739
+ //#region resource
1740
+ function lazyInit(resource, load) {
1741
+ const creation = proxy.effectHistory.active;
1742
+ let fresh = true;
1743
+ return new Proxy(resource, {
1744
+ [Symbol.toStringTag]: 'LazyInit',
1745
+ get(target, prop) {
1746
+ if (fresh) {
1747
+ proxy.captured(creation, load)();
1748
+ fresh = false;
1749
+ }
1750
+ return target[prop];
1751
+ },
1752
+ });
1753
+ }
1887
1754
  /**
1888
1755
  * Creates a reactive resource that automatically tracks async state.
1889
1756
  * @param fetcher - Async function that returns the value. Reactive dependencies are tracked.
@@ -1891,521 +1758,59 @@ const unreactive = proxy.decorator({
1891
1758
  * @returns Reactive Resource object with value, loading, error, latest properties
1892
1759
  */
1893
1760
  function resource(fetcher, options = {}) {
1894
- const state = proxy.reactive({
1761
+ const resource = proxy.reactive({
1895
1762
  value: options.initialValue,
1896
1763
  loading: true,
1897
1764
  error: undefined,
1898
1765
  latest: options.initialValue,
1899
- reload: () => {
1766
+ reload() {
1900
1767
  reloadSignal.value++;
1901
1768
  },
1902
1769
  });
1903
1770
  const reloadSignal = proxy.reactive({ value: 0 });
1771
+ // Solve race conditions: make sure a new fast request is not overloaded by a slow old one
1904
1772
  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);
1773
+ return lazyInit(resource, () => {
1774
+ proxy.link(resource, proxy.effect.named('watch:resource')((access) => {
1775
+ // Track reload signal to enable manual reloading
1776
+ void reloadSignal.value;
1777
+ const id = ++counter;
1778
+ resource.loading = true;
1779
+ resource.error = undefined;
1780
+ try {
1781
+ const result = fetcher(access);
1782
+ if (result instanceof Promise) {
1783
+ resource.promise = result
1784
+ .then((val) => {
1785
+ if (id === counter) {
1786
+ resource.value = val;
1787
+ resource.latest = val;
1788
+ resource.loading = false;
1789
+ }
1790
+ })
1791
+ .catch((err) => {
1792
+ if (id === counter) {
1793
+ resource.error = err;
1794
+ resource.loading = false;
1795
+ }
1796
+ });
2306
1797
  }
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];
1798
+ else {
1799
+ resource.promise = Promise.resolve();
1800
+ resource.value = result;
1801
+ resource.latest = result;
1802
+ resource.loading = false;
2325
1803
  }
2326
1804
  }
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
- }
1805
+ catch (err) {
1806
+ resource.promise = Promise.reject(err);
1807
+ resource.error = err;
1808
+ resource.loading = false;
2337
1809
  }
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);
1810
+ }));
1811
+ });
2408
1812
  }
1813
+ //#endregion
2409
1814
 
2410
1815
  /**
2411
1816
  * Converts an iterator to a generator that yields reactive values
@@ -2488,6 +1893,7 @@ let ReactiveArrayWrapper = (() => {
2488
1893
  let _classSuper = Array;
2489
1894
  let _instanceExtraInitializers = [];
2490
1895
  let _fill_decorators;
1896
+ let _copyWithin_decorators;
2491
1897
  let _pop_decorators;
2492
1898
  let _push_decorators;
2493
1899
  let _reverse_decorators;
@@ -2512,6 +1918,9 @@ let ReactiveArrayWrapper = (() => {
2512
1918
  fill(value, start, end) {
2513
1919
  return super.fill(proxy.unwrap(value), start, end);
2514
1920
  }
1921
+ copyWithin(target, start, end) {
1922
+ return super.copyWithin(target, start, end);
1923
+ }
2515
1924
  filter(predicate, thisArg) {
2516
1925
  return proxy.reactive(super.filter((v, i, a) => predicate.call(thisArg, proxy.reactive(v), i, a), thisArg));
2517
1926
  }
@@ -2613,7 +2022,7 @@ let ReactiveArrayWrapper = (() => {
2613
2022
  proxy.dependant(this, proxy.keysOf);
2614
2023
  return makeReactiveIterator(super.values());
2615
2024
  }
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)]() {
2025
+ [(_fill_decorators = [proxy.atomic], _copyWithin_decorators = [proxy.atomic], _pop_decorators = [proxy.atomic], _push_decorators = [proxy.atomic], _reverse_decorators = [proxy.atomic], _shift_decorators = [proxy.atomic], _sort_decorators = [proxy.atomic], _splice_decorators = [proxy.atomic], _unshift_decorators = [proxy.atomic], Symbol.iterator)]() {
2617
2026
  proxy.dependant(this, proxy.keysOf);
2618
2027
  return makeReactiveIterator(super[Symbol.iterator]());
2619
2028
  }
@@ -2626,7 +2035,6 @@ let ReactiveArrayWrapper = (() => {
2626
2035
  : undefined;
2627
2036
  return proxy.reactive(super.toSorted(wrappedCompare));
2628
2037
  }
2629
- // biome-ignore lint/complexity/noArguments: Needed to distinguish fn() from fn(undefined)
2630
2038
  toSpliced(start, deleteCount, ...items) {
2631
2039
  if (arguments.length > 2)
2632
2040
  return proxy.reactive(super.toSpliced(start, deleteCount, ...items.map(proxy.unwrap)));
@@ -2647,6 +2055,7 @@ let ReactiveArrayWrapper = (() => {
2647
2055
  (() => {
2648
2056
  const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
2649
2057
  proxy.__esDecorate(_a, null, _fill_decorators, { kind: "method", name: "fill", static: false, private: false, access: { has: obj => "fill" in obj, get: obj => obj.fill }, metadata: _metadata }, null, _instanceExtraInitializers);
2058
+ proxy.__esDecorate(_a, null, _copyWithin_decorators, { kind: "method", name: "copyWithin", static: false, private: false, access: { has: obj => "copyWithin" in obj, get: obj => obj.copyWithin }, metadata: _metadata }, null, _instanceExtraInitializers);
2650
2059
  proxy.__esDecorate(_a, null, _pop_decorators, { kind: "method", name: "pop", static: false, private: false, access: { has: obj => "pop" in obj, get: obj => obj.pop }, metadata: _metadata }, null, _instanceExtraInitializers);
2651
2060
  proxy.__esDecorate(_a, null, _push_decorators, { kind: "method", name: "push", static: false, private: false, access: { has: obj => "push" in obj, get: obj => obj.push }, metadata: _metadata }, null, _instanceExtraInitializers);
2652
2061
  proxy.__esDecorate(_a, null, _reverse_decorators, { kind: "method", name: "reverse", static: false, private: false, access: { has: obj => "reverse" in obj, get: obj => obj.reverse }, metadata: _metadata }, null, _instanceExtraInitializers);
@@ -2667,18 +2076,18 @@ class ReactiveWeakMap extends WeakMap {
2667
2076
  // Implement WeakMap interface methods with reactivity
2668
2077
  delete(key) {
2669
2078
  const hadKey = this.has(key);
2670
- const result = this.delete(key);
2079
+ const result = super.delete(key);
2671
2080
  if (hadKey)
2672
2081
  proxy.touched1(proxy.contentRef(this), { type: 'del', prop: key }, key);
2673
2082
  return result;
2674
2083
  }
2675
2084
  get(key) {
2676
2085
  proxy.dependant(proxy.contentRef(this), key);
2677
- return proxy.reactive(this.get(key));
2086
+ return proxy.reactive(super.get(key));
2678
2087
  }
2679
2088
  has(key) {
2680
2089
  proxy.dependant(proxy.contentRef(this), key);
2681
- return this.has(key);
2090
+ return super.has(key);
2682
2091
  }
2683
2092
  set(key, value) {
2684
2093
  const hadKey = this.has(key);
@@ -2699,16 +2108,18 @@ class ReactiveMap extends Map {
2699
2108
  // Implement Map interface methods with reactivity
2700
2109
  get size() {
2701
2110
  proxy.dependant(this, 'size'); // The ReactiveMap instance still goes through proxy
2702
- return this.size;
2111
+ return super.size;
2703
2112
  }
2704
2113
  clear() {
2705
2114
  const hadEntries = this.size > 0;
2706
- this.clear();
2115
+ super.clear();
2707
2116
  if (hadEntries) {
2708
2117
  const evolution = { type: 'bunch', method: 'clear' };
2709
2118
  // Clear triggers all effects since all keys are affected
2710
- proxy.touched1(this, evolution, 'size');
2711
- proxy.touched(proxy.contentRef(this), evolution);
2119
+ proxy.batch(() => {
2120
+ proxy.touched1(this, evolution, 'size');
2121
+ proxy.touched(proxy.contentRef(this), evolution);
2122
+ });
2712
2123
  }
2713
2124
  }
2714
2125
  entries() {
@@ -2743,32 +2154,36 @@ class ReactiveMap extends Map {
2743
2154
  // Implement Map methods with reactivity
2744
2155
  delete(key) {
2745
2156
  const hadKey = this.has(key);
2746
- const result = this.delete(key);
2157
+ const result = super.delete(key);
2747
2158
  if (hadKey) {
2748
2159
  const evolution = { type: 'del', prop: key };
2749
- proxy.touched1(proxy.contentRef(this), evolution, key);
2750
- proxy.touched1(this, evolution, 'size');
2160
+ proxy.batch(() => {
2161
+ proxy.touched1(proxy.contentRef(this), evolution, key);
2162
+ proxy.touched1(this, evolution, 'size');
2163
+ });
2751
2164
  }
2752
2165
  return result;
2753
2166
  }
2754
2167
  get(key) {
2755
2168
  proxy.dependant(proxy.contentRef(this), key);
2756
- return proxy.reactive(this.get(key));
2169
+ return proxy.reactive(super.get(key));
2757
2170
  }
2758
2171
  has(key) {
2759
2172
  proxy.dependant(proxy.contentRef(this), key);
2760
- return this.has(key);
2173
+ return super.has(key);
2761
2174
  }
2762
2175
  set(key, value) {
2763
2176
  const hadKey = this.has(key);
2764
2177
  const oldValue = this.get(key);
2765
2178
  const reactiveValue = proxy.reactive(value);
2766
- this.set(key, reactiveValue);
2179
+ super.set(key, reactiveValue);
2767
2180
  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');
2181
+ proxy.batch(() => {
2182
+ proxy.notifyPropertyChange(proxy.contentRef(this), key, oldValue, reactiveValue, hadKey);
2183
+ // Also notify size change for Map (WeakMap doesn't track size)
2184
+ const evolution = { type: hadKey ? 'set' : 'add', prop: key };
2185
+ proxy.touched1(this, evolution, 'size');
2186
+ });
2772
2187
  }
2773
2188
  return this;
2774
2189
  }
@@ -2781,7 +2196,7 @@ class ReactiveMap extends Map {
2781
2196
  class ReactiveWeakSet extends WeakSet {
2782
2197
  add(value) {
2783
2198
  const had = this.has(value);
2784
- this.add(value);
2199
+ super.add(value);
2785
2200
  if (!had) {
2786
2201
  // touch the specific value and the collection view
2787
2202
  proxy.touched1(proxy.contentRef(this), { type: 'add', prop: value }, value);
@@ -2791,14 +2206,14 @@ class ReactiveWeakSet extends WeakSet {
2791
2206
  }
2792
2207
  delete(value) {
2793
2208
  const had = this.has(value);
2794
- const res = this.delete(value);
2209
+ const res = super.delete(value);
2795
2210
  if (had)
2796
2211
  proxy.touched1(proxy.contentRef(this), { type: 'del', prop: value }, value);
2797
2212
  return res;
2798
2213
  }
2799
2214
  has(value) {
2800
2215
  proxy.dependant(proxy.contentRef(this), value);
2801
- return this.has(value);
2216
+ return super.has(value);
2802
2217
  }
2803
2218
  }
2804
2219
  /**
@@ -2814,31 +2229,37 @@ class ReactiveSet extends Set {
2814
2229
  add(value) {
2815
2230
  const had = this.has(value);
2816
2231
  const reactiveValue = proxy.reactive(value);
2817
- this.add(reactiveValue);
2232
+ super.add(reactiveValue);
2818
2233
  if (!had) {
2819
2234
  const evolution = { type: 'add', prop: reactiveValue };
2820
2235
  // touch for value-specific and aggregate dependencies
2821
- proxy.touched1(proxy.contentRef(this), evolution, reactiveValue);
2822
- proxy.touched1(this, evolution, 'size');
2236
+ proxy.batch(() => {
2237
+ proxy.touched1(proxy.contentRef(this), evolution, reactiveValue);
2238
+ proxy.touched1(this, evolution, 'size');
2239
+ });
2823
2240
  }
2824
2241
  return this;
2825
2242
  }
2826
2243
  clear() {
2827
2244
  const hadEntries = this.size > 0;
2828
- this.clear();
2245
+ super.clear();
2829
2246
  if (hadEntries) {
2830
2247
  const evolution = { type: 'bunch', method: 'clear' };
2831
- proxy.touched1(this, evolution, 'size');
2832
- proxy.touched(proxy.contentRef(this), evolution);
2248
+ proxy.batch(() => {
2249
+ proxy.touched1(this, evolution, 'size');
2250
+ proxy.touched(proxy.contentRef(this), evolution);
2251
+ });
2833
2252
  }
2834
2253
  }
2835
2254
  delete(value) {
2836
2255
  const had = this.has(value);
2837
- const res = this.delete(value);
2256
+ const res = super.delete(value);
2838
2257
  if (had) {
2839
2258
  const evolution = { type: 'del', prop: value };
2840
- proxy.touched1(proxy.contentRef(this), evolution, value);
2841
- proxy.touched1(this, evolution, 'size');
2259
+ proxy.batch(() => {
2260
+ proxy.touched1(proxy.contentRef(this), evolution, value);
2261
+ proxy.touched1(this, evolution, 'size');
2262
+ });
2842
2263
  }
2843
2264
  return res;
2844
2265
  }
@@ -2877,14 +2298,12 @@ class ReactiveSet extends Set {
2877
2298
  }
2878
2299
 
2879
2300
  // Register native collection types to use specialized reactive wrappers
2880
- console.time('mutts-reactive-init');
2881
2301
  proxy.metaProtos.set(Array, ReactiveArray.prototype);
2882
2302
  proxy.metaProtos.set(Set, ReactiveSet.prototype);
2883
2303
  proxy.metaProtos.set(WeakSet, ReactiveWeakSet.prototype);
2884
2304
  proxy.metaProtos.set(Map, ReactiveMap.prototype);
2885
2305
  proxy.metaProtos.set(WeakMap, ReactiveWeakMap.prototype);
2886
2306
  proxy.wrapProtos.set(Array, ReactiveArrayWrapper.prototype);
2887
- console.timeEnd('mutts-reactive-init');
2888
2307
  /**
2889
2308
  * Object containing internal reactive system state for debugging and profiling
2890
2309
  */
@@ -2897,7 +2316,6 @@ const profileInfo = {
2897
2316
  objectsWithDeepWatchers: proxy.objectsWithDeepWatchers,
2898
2317
  deepWatchers: proxy.deepWatchers,
2899
2318
  effectToDeepWatchedObjects: proxy.effectToDeepWatchedObjects,
2900
- nonReactiveObjects: proxy.nonReactiveObjects,
2901
2319
  };
2902
2320
 
2903
2321
  // In order to avoid async re-entrance, we could use zone.js or something like that.
@@ -3063,8 +2481,7 @@ const deprecated = Object.assign(proxy.decorator({
3063
2481
  },
3064
2482
  }), {
3065
2483
  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}` : ''}`);
2484
+ proxy.options.warn(`${target.constructor.name}.${String(propertyKey)} is deprecated${message ? `: ${message}` : ''}`);
3068
2485
  },
3069
2486
  });
3070
2487
  /**
@@ -3127,12 +2544,11 @@ function throttle(delay) {
3127
2544
  });
3128
2545
  }
3129
2546
 
3130
- var version$1 = "1.0.10";
2547
+ var version$1 = "1.0.11";
3131
2548
  var pkg = {
3132
2549
  version: version$1};
3133
2550
 
3134
2551
  const { version } = pkg;
3135
- // Singleton verification
3136
2552
  const GLOBAL_MUTTS_KEY = '__MUTTS_INSTANCE__';
3137
2553
  const globalScope = (typeof globalThis !== 'undefined'
3138
2554
  ? globalThis
@@ -3142,28 +2558,16 @@ const globalScope = (typeof globalThis !== 'undefined'
3142
2558
  ? global
3143
2559
  : false);
3144
2560
  if (globalScope) {
3145
- // Detect the source of this instance safely across different environments
3146
2561
  let source = 'mutts/index';
3147
- // biome-ignore lint/security/noGlobalEval: Intentional eval for cross-env import.meta detection
3148
- const viteEval = eval;
3149
2562
  try {
3150
2563
  if (typeof __filename !== 'undefined')
3151
2564
  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;
2565
+ else if (typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('browser.cjs', document.baseURI).href)) }) !== 'undefined' && (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('browser.cjs', document.baseURI).href))) {
2566
+ source = (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('browser.cjs', document.baseURI).href));
3157
2567
  }
3158
2568
  }
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(),
3166
- };
2569
+ catch (_e) { }
2570
+ const currentSourceInfo = { version, source, timestamp: Date.now() };
3167
2571
  if (globalScope[GLOBAL_MUTTS_KEY]) {
3168
2572
  const existing = globalScope[GLOBAL_MUTTS_KEY];
3169
2573
  throw new Error(`[Mutts] Multiple instances detected!\n` +
@@ -3190,18 +2594,21 @@ exports.Zone = proxy.Zone;
3190
2594
  exports.ZoneAggregator = proxy.ZoneAggregator;
3191
2595
  exports.ZoneHistory = proxy.ZoneHistory;
3192
2596
  exports.addBatchCleanup = proxy.addBatchCleanup;
2597
+ exports.addUnreactiveProps = proxy.addUnreactiveProps;
3193
2598
  exports.arrayEquals = proxy.arrayEquals;
2599
+ exports.assertUntracked = proxy.assertUntracked;
3194
2600
  exports.asyncZone = proxy.asyncZone;
3195
2601
  exports.atom = proxy.atom;
3196
2602
  exports.atomic = proxy.atomic;
3197
2603
  exports.biDi = proxy.biDi;
2604
+ exports.captured = proxy.captured;
3198
2605
  exports.caught = proxy.caught;
3199
- exports.cleanedBy = proxy.cleanedBy;
3200
- exports.cleanup = proxy.cleanup;
3201
2606
  exports.createFlavor = proxy.createFlavor;
2607
+ exports.debugPreset = proxy.debugPreset;
3202
2608
  exports.decorator = proxy.decorator;
3203
2609
  exports.deepCompare = proxy.deepCompare;
3204
2610
  exports.defer = proxy.defer;
2611
+ exports.devPreset = proxy.devPreset;
3205
2612
  exports.effect = proxy.effect;
3206
2613
  exports.effectAggregator = proxy.effectAggregator;
3207
2614
  exports.flavorOptions = proxy.flavorOptions;
@@ -3210,26 +2617,30 @@ exports.formatCleanupReason = proxy.formatCleanupReason;
3210
2617
  exports.getActivationLog = proxy.getActivationLog;
3211
2618
  exports.getActiveEffect = proxy.getActiveEffect;
3212
2619
  exports.getState = proxy.getState;
3213
- exports.immutables = proxy.immutables;
3214
2620
  exports.isConstructor = proxy.isConstructor;
2621
+ exports.isDev = proxy.isDev;
3215
2622
  exports.isNonReactive = proxy.isNonReactive;
3216
2623
  exports.isObject = proxy.isObject;
2624
+ exports.isProd = proxy.isProd;
3217
2625
  exports.isReactive = proxy.isReactive;
2626
+ exports.isTest = proxy.isTest;
3218
2627
  exports.legacyDecorator = proxy.legacyDecorator;
2628
+ exports.link = proxy.link;
3219
2629
  exports.mixin = proxy.mixin;
3220
2630
  exports.modernDecorator = proxy.modernDecorator;
3221
2631
  exports.named = proxy.named;
3222
2632
  exports.objectToProxy = proxy.objectToProxy;
3223
2633
  exports.onEffectThrow = proxy.onEffectThrow;
2634
+ exports.prodPreset = proxy.prodPreset;
3224
2635
  exports.proxyToObject = proxy.proxyToObject;
3225
2636
  exports.reactive = proxy.reactive;
3226
2637
  exports.reactiveOptions = proxy.options;
3227
2638
  exports.reset = proxy.reset;
3228
2639
  exports.root = proxy.root;
3229
- exports.stopped = proxy.stopped;
3230
2640
  exports.tag = proxy.tag;
3231
2641
  exports.touched = proxy.touched;
3232
2642
  exports.touched1 = proxy.touched1;
2643
+ exports.unlink = proxy.unlink;
3233
2644
  exports.untracked = proxy.untracked;
3234
2645
  exports.unwrap = proxy.unwrap;
3235
2646
  exports.zip = proxy.zip;
@@ -3241,7 +2652,6 @@ exports.Destroyable = Destroyable;
3241
2652
  exports.DestructionError = DestructionError;
3242
2653
  exports.Eventful = Eventful;
3243
2654
  exports.Indexable = Indexable;
3244
- exports.Register = Register;
3245
2655
  exports.allocated = allocated;
3246
2656
  exports.allocatedValues = allocatedValues;
3247
2657
  exports.arrayDiff = arrayDiff;
@@ -3265,9 +2675,7 @@ exports.organize = organize;
3265
2675
  exports.organized = organized;
3266
2676
  exports.profileInfo = profileInfo;
3267
2677
  exports.project = morph;
3268
- exports.register = register;
3269
2678
  exports.resource = resource;
3270
- exports.scan = scan;
3271
2679
  exports.setAt = setAt;
3272
2680
  exports.throttle = throttle;
3273
2681
  exports.unreactive = unreactive;