mutts 1.0.12 → 1.0.13

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 +5 -2
  2. package/dist/browser.cjs +7 -3
  3. package/dist/browser.cjs.map +1 -1
  4. package/dist/browser.d.ts +1407 -2
  5. package/dist/browser.dev.cjs +7 -3
  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 +3 -3
  10. package/dist/chunks/{index-yK0HVxHv.cjs → index-CAdnMJev.cjs} +202 -79
  11. package/dist/chunks/index-CAdnMJev.cjs.map +1 -0
  12. package/dist/chunks/{index-BUop6B2U.esm.js → index-XsYTUhHx.esm.js} +200 -77
  13. package/dist/chunks/index-XsYTUhHx.esm.js.map +1 -0
  14. package/dist/chunks/{node-Dd0esp5F.cjs → node-DrrphEPf.cjs} +2 -2
  15. package/dist/chunks/{node-Dd0esp5F.cjs.map → node-DrrphEPf.cjs.map} +1 -1
  16. package/dist/chunks/{node-Bo7WU5S2.esm.js → node-NEZvVo4M.esm.js} +2 -2
  17. package/dist/chunks/{node-Bo7WU5S2.esm.js.map → node-NEZvVo4M.esm.js.map} +1 -1
  18. package/dist/chunks/{proxy-D2C49sXH.esm.js → proxy-BtmPFjSr.esm.js} +307 -66
  19. package/dist/chunks/proxy-BtmPFjSr.esm.js.map +1 -0
  20. package/dist/chunks/{proxy-BvM4yewA.cjs → proxy-DBHj3kGK.cjs} +313 -66
  21. package/dist/chunks/proxy-DBHj3kGK.cjs.map +1 -0
  22. package/dist/debug.cjs +537 -166
  23. package/dist/debug.cjs.map +1 -1
  24. package/dist/debug.d.ts +96 -80
  25. package/dist/debug.esm.js +533 -166
  26. package/dist/debug.esm.js.map +1 -1
  27. package/dist/devtools/panel.js.map +1 -1
  28. package/dist/mutts.umd.js +508 -140
  29. package/dist/mutts.umd.js.map +1 -1
  30. package/dist/mutts.umd.min.js +1 -1
  31. package/dist/mutts.umd.min.js.map +1 -1
  32. package/dist/node.cjs +8 -4
  33. package/dist/node.cjs.map +1 -1
  34. package/dist/node.d.ts +2 -2
  35. package/dist/node.dev.cjs +8 -4
  36. package/dist/node.dev.cjs.map +1 -1
  37. package/dist/node.dev.d.ts +2 -2
  38. package/dist/node.dev.esm.js +3 -3
  39. package/dist/node.esm.js +3 -3
  40. package/dist/{types-Bx2PhORg.d.ts → types.d.ts} +12 -0
  41. package/docs/ai/api-reference.md +102 -12
  42. package/docs/ai/manual.md +60 -24
  43. package/docs/debug-getReason.md +161 -0
  44. package/docs/flavored.md +98 -1
  45. package/docs/reactive/advanced.md +15 -2
  46. package/docs/reactive/attend.md +32 -0
  47. package/docs/reactive/core.md +40 -6
  48. package/docs/reactive/debugging.md +25 -2
  49. package/docs/reactive.md +2 -0
  50. package/package.json +2 -3
  51. package/dist/chunks/index-BUop6B2U.esm.js.map +0 -1
  52. package/dist/chunks/index-yK0HVxHv.cjs.map +0 -1
  53. package/dist/chunks/proxy-BvM4yewA.cjs.map +0 -1
  54. package/dist/chunks/proxy-D2C49sXH.esm.js.map +0 -1
  55. package/dist/index.d.ts +0 -1322
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var proxy = require('./proxy-BvM4yewA.cjs');
3
+ var proxy = require('./proxy-DBHj3kGK.cjs');
4
4
 
5
5
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
6
6
  // Integrated with `using` statement via Symbol.dispose
@@ -259,46 +259,57 @@ function buildPatches(history, A, B, offset, finalX, finalY, finalD, finalK, vOf
259
259
  var _a, _b;
260
260
  const events = Symbol('events');
261
261
  const hooks = Symbol('hooks');
262
+ function getEventMap(target) {
263
+ return target[events];
264
+ }
265
+ function getHookSet(target) {
266
+ return target[hooks];
267
+ }
262
268
  const eventBehavior = {
263
269
  on(eventOrEvents, cb) {
270
+ const self = this;
271
+ const eventMap = getEventMap(self);
264
272
  if (typeof eventOrEvents === 'object') {
265
273
  for (const e of Object.keys(eventOrEvents)) {
266
274
  this.on(e, eventOrEvents[e]);
267
275
  }
268
276
  }
269
277
  else if (cb !== undefined) {
270
- const callbacks = this[events].get(eventOrEvents) ?? new Set();
278
+ const callbacks = eventMap.get(eventOrEvents) ?? new Set();
271
279
  if (!callbacks.has(cb))
272
280
  callbacks.add(cb);
273
- this[events].set(eventOrEvents, callbacks);
281
+ eventMap.set(eventOrEvents, callbacks);
274
282
  }
275
283
  return () => this.off(eventOrEvents, cb);
276
284
  },
277
285
  off(eventOrEvents, cb) {
286
+ const self = this;
287
+ const eventMap = getEventMap(self);
278
288
  if (typeof eventOrEvents === 'object') {
279
289
  for (const e of Object.keys(eventOrEvents)) {
280
290
  this.off(e, eventOrEvents[e]);
281
291
  }
282
292
  }
283
293
  else if (cb !== null && cb !== undefined) {
284
- const callbacks = this[events].get(eventOrEvents);
294
+ const callbacks = eventMap.get(eventOrEvents);
285
295
  if (callbacks) {
286
296
  callbacks.delete(cb);
287
297
  if (!callbacks.size)
288
- this[events].delete(eventOrEvents);
298
+ eventMap.delete(eventOrEvents);
289
299
  }
290
300
  }
291
301
  else {
292
302
  // Remove all listeners for this event
293
- this[events].delete(eventOrEvents);
303
+ eventMap.delete(eventOrEvents);
294
304
  }
295
305
  },
296
306
  emit(event, ...args) {
297
- const callbacks = this[events].get(event);
307
+ const self = this;
308
+ const callbacks = getEventMap(self).get(event);
298
309
  if (callbacks)
299
310
  for (const cb of callbacks)
300
311
  cb.apply(this, args);
301
- for (const cb of this[hooks])
312
+ for (const cb of getHookSet(self))
302
313
  cb.call(this, event, ...args);
303
314
  },
304
315
  };
@@ -308,7 +319,7 @@ function perEvent(eventful, fct, use) {
308
319
  get(target, prop) {
309
320
  if (typeof prop !== 'string')
310
321
  return target[prop];
311
- if (use && !eventful[events].has(prop) && !eventful[hooks].size)
322
+ if (use && !getEventMap(eventful).has(prop) && !getHookSet(eventful).size)
312
323
  return () => { };
313
324
  // Return cached function or create and cache
314
325
  let cached = cache.get(prop);
@@ -747,7 +758,7 @@ function chainPromise(given) {
747
758
  return chained;
748
759
  }
749
760
 
750
- function attend(source, callback) {
761
+ const attend = proxy.captioned(function attend(source, callback) {
751
762
  const enumerate = typeof source === 'function'
752
763
  ? source
753
764
  : Array.isArray(source)
@@ -758,14 +769,16 @@ function attend(source, callback) {
758
769
  ? () => source.values()
759
770
  : () => Object.keys(source);
760
771
  const keyEffects = new Map();
761
- const outer = proxy.effect.named('attend')(({ ascend }) => {
772
+ const callbackLabel = callback.name ? callback.name : '';
773
+ const outer = proxy.effect `attend`(({ ascend }) => {
762
774
  const keys = new Set();
763
775
  for (const key of enumerate())
764
776
  keys.add(key);
765
777
  for (const key of keys) {
766
778
  if (keyEffects.has(key))
767
779
  continue;
768
- keyEffects.set(key, ascend(() => proxy.effect.named(`attend:${key}`)((access) => callback(key, access))));
780
+ const indexRef = { value: key };
781
+ keyEffects.set(key, ascend(() => proxy.effect `attend${callbackLabel ? `:${callbackLabel}` : ''}:${key}`((access) => callback(indexRef.value, access))));
769
782
  }
770
783
  for (const key of Array.from(keyEffects.keys())) {
771
784
  if (!keys.has(key)) {
@@ -780,17 +793,50 @@ function attend(source, callback) {
780
793
  stop(reason);
781
794
  keyEffects.clear();
782
795
  };
783
- }
784
- function lift(cb) {
796
+ }, {
797
+ name: 'attend',
798
+ callbackIndex: 1,
799
+ warn: (message) => proxy.options.warn(`[reactive] ${message}`),
800
+ });
801
+ /**
802
+ * Lifts a callback that returns an object into a reactive object that automatically
803
+ * synchronizes with the source object returned by the callback.
804
+ *
805
+ * The returned reactive object will update whenever the callback's dependencies change,
806
+ * efficiently syncing only the properties that differ from the previous result using
807
+ * Object.assign(). Properties that no longer exist in the source are automatically removed.
808
+ *
809
+ * @example
810
+ * ```typescript
811
+ * const user = reactive({ name: 'John', age: 30 })
812
+ * const profile = lift(() => ({
813
+ * displayName: user.name.toUpperCase(),
814
+ * isAdult: user.age >= 18,
815
+ * description: `${user.name} is ${user.age} years old`
816
+ * }))
817
+ *
818
+ * console.log(profile.displayName) // JOHN
819
+ * console.log(profile.isAdult) // true
820
+ *
821
+ * user.name = 'Jane'
822
+ * console.log(profile.displayName) // JANE
823
+ * console.log(profile.description) // Jane is 30 years old
824
+ * ```
825
+ *
826
+ * @param cb Callback function that returns an object
827
+ * @returns A reactive object synchronized with the callback's result, with a [cleanup] property to stop tracking
828
+ */
829
+ const lift = proxy.captioned(function lift(cb) {
785
830
  let result;
786
831
  let rawResult;
787
- const liftCleanup = proxy.effect.named(`lift:${cb.name}`)(proxy.markWithRoot((access) => {
832
+ const resultName = `lift:${cb.name || 'anonymous'}`;
833
+ const liftCleanup = proxy.effect `lift:${cb.name}`(proxy.markWithRoot((access) => {
788
834
  const source = cb(access);
789
835
  if (!source || typeof source !== 'object')
790
836
  throw new Error('lift callback must return an array or object');
791
837
  const sourceProto = Object.getPrototypeOf(source);
792
838
  if (!result) {
793
- rawResult = Array.isArray(source) ? [] : Object.create(sourceProto);
839
+ rawResult = proxy.tag(resultName, Array.isArray(source) ? [] : Object.create(sourceProto));
794
840
  result = proxy.reactive(rawResult);
795
841
  }
796
842
  if (sourceProto !== Object.getPrototypeOf(result))
@@ -801,6 +847,7 @@ function lift(cb) {
801
847
  res.splice(indexA, sliceA.length, ...sliceB);
802
848
  }
803
849
  else {
850
+ const recordResult = rawResult;
804
851
  for (const key of Object.keys(source)) {
805
852
  const had = key in rawResult;
806
853
  const newDesc = Object.getOwnPropertyDescriptor(source, key);
@@ -809,7 +856,7 @@ function lift(cb) {
809
856
  const sameAccessor = oldDesc && newDesc.get && oldDesc.get === newDesc.get;
810
857
  Object.defineProperty(rawResult, key, newDesc);
811
858
  if (!sameAccessor &&
812
- rawResult[key] !==
859
+ recordResult[key] !==
813
860
  (oldDesc ? (oldDesc.get ? oldDesc.get() : oldDesc.value) : undefined))
814
861
  proxy.touched1(rawResult, { type: 'set', prop: key }, key);
815
862
  }
@@ -820,13 +867,16 @@ function lift(cb) {
820
867
  }
821
868
  for (const key of Object.keys(rawResult))
822
869
  if (!(key in source)) {
823
- delete rawResult[key];
870
+ delete recordResult[key];
824
871
  proxy.touched1(rawResult, { type: 'del', prop: key }, key);
825
872
  }
826
873
  }
827
874
  }, cb));
828
875
  return proxy.link(result, liftCleanup);
829
- }
876
+ }, {
877
+ name: 'lift',
878
+ warn: (message) => proxy.options.warn(`[reactive] ${message}`),
879
+ });
830
880
  /**
831
881
  * Reactively maps an array source through `fn`, producing a lazy reactive output array.
832
882
  *
@@ -850,12 +900,18 @@ function morphArray(source, fn, options) {
850
900
  }
851
901
  let track;
852
902
  const itemEffects = new Map();
853
- const cache = [];
903
+ const cache = proxy.tag(`morph:${fn.name || 'anonymous'}`, []);
854
904
  let input = [];
855
905
  function stopItem(key) {
856
906
  const entry = itemEffects.get(key);
857
907
  if (entry) {
858
- entry.stop({ type: 'stopped' });
908
+ const activeEffect = proxy.getActiveEffect();
909
+ let chain;
910
+ if (activeEffect) {
911
+ const node = proxy.getEffectNode(activeEffect);
912
+ chain = node.currentReason;
913
+ }
914
+ entry.stop(proxy.chainExternalReason({ type: 'stopped', chain }));
859
915
  itemEffects.delete(key);
860
916
  }
861
917
  }
@@ -868,12 +924,22 @@ function morphArray(source, fn, options) {
868
924
  }
869
925
  else {
870
926
  const indexRef = { value: key };
871
- const stop = track(() => proxy.effect.named(`morph:${fn.name}:${key}`).opaque((access) => {
927
+ const stop = track(() => proxy.effect.opaque `morph:${fn.name}:${key}`((access) => {
872
928
  cache[indexRef.value] = fn(input, access);
873
929
  return (reason) => {
874
930
  delete cache[indexRef.value];
875
931
  proxy.touched1(cache, { type: 'invalidate', prop: 'morph' }, String(key));
876
- stop?.({ type: 'invalidate', cause: reason });
932
+ const activeEffect = proxy.getActiveEffect();
933
+ let chain;
934
+ if (activeEffect) {
935
+ const node = proxy.getEffectNode(activeEffect);
936
+ chain = node.currentReason;
937
+ }
938
+ stop?.({
939
+ type: 'invalidate',
940
+ cause: proxy.chainExternalReason(reason ?? { type: 'stopped', chain }),
941
+ chain: proxy.chainExternalReason(chain),
942
+ });
877
943
  };
878
944
  }));
879
945
  itemEffects.set(key, { stop, index: indexRef });
@@ -892,7 +958,7 @@ function morphArray(source, fn, options) {
892
958
  return Reflect.has(input, prop);
893
959
  },
894
960
  });
895
- const stopMain = proxy.effect.named(`morph:${fn.name}`)(({ ascend }) => {
961
+ const stopMain = proxy.effect `morph:${fn.name}`(({ ascend }) => {
896
962
  track = ascend;
897
963
  const newInput = [...(typeof source === 'function' ? source() : source)];
898
964
  const diffs = arrayDiff(input, newInput).toSorted((a, b) => b.indexA - a.indexA);
@@ -966,12 +1032,18 @@ function morphMap(source, fn, options) {
966
1032
  }
967
1033
  let track;
968
1034
  const itemEffects = new Map();
969
- const cache = new Map();
1035
+ const cache = proxy.tag(`morph:${fn.name || 'anonymous'}`, new Map());
970
1036
  Object.defineProperty(cache, 'constructor', { value: Object, enumerable: false });
971
1037
  function stopItem(key) {
972
1038
  const stop = itemEffects.get(key);
973
1039
  if (stop) {
974
- stop({ type: 'stopped' });
1040
+ const activeEffect = proxy.getActiveEffect();
1041
+ let chain;
1042
+ if (activeEffect) {
1043
+ const node = proxy.getEffectNode(activeEffect);
1044
+ chain = node.currentReason;
1045
+ }
1046
+ stop({ type: 'stopped', chain });
975
1047
  itemEffects.delete(key);
976
1048
  }
977
1049
  }
@@ -981,12 +1053,25 @@ function morphMap(source, fn, options) {
981
1053
  cache.set(key, track(() => fn(val, key)));
982
1054
  }
983
1055
  else {
984
- const stop = track(() => proxy.effect.named(`morph:${fn.name}:${key}`).opaque((access) => {
985
- cache.set(key, fn(source.get(key), key, access));
1056
+ const stop = track(() => proxy.effect.opaque `morph:${fn.name}:${key}`((access) => {
1057
+ const next = source.get(key);
1058
+ if (next === undefined && !source.has(key))
1059
+ return;
1060
+ cache.set(key, fn(next, key, access));
986
1061
  return (reason) => {
987
1062
  cache.delete(key);
988
1063
  proxy.touched1(cache, { type: 'invalidate', prop: 'morph' }, String(key));
989
- stop?.({ type: 'invalidate', cause: reason });
1064
+ const activeEffect = proxy.getActiveEffect();
1065
+ let chain;
1066
+ if (activeEffect) {
1067
+ const node = proxy.getEffectNode(activeEffect);
1068
+ chain = node.currentReason;
1069
+ }
1070
+ stop?.({
1071
+ type: 'invalidate',
1072
+ cause: proxy.chainExternalReason(reason ?? { type: 'stopped', chain }),
1073
+ chain: proxy.chainExternalReason(chain),
1074
+ });
990
1075
  };
991
1076
  }));
992
1077
  itemEffects.set(key, stop);
@@ -1030,7 +1115,7 @@ function morphMap(source, fn, options) {
1030
1115
  },
1031
1116
  });
1032
1117
  let stateSnapshot = proxy.getState(source);
1033
- const stopMain = proxy.effect.named(`morph:${fn.name}`)(({ ascend }) => {
1118
+ const stopMain = proxy.effect `morph:${fn.name}`(({ ascend }) => {
1034
1119
  track = ascend;
1035
1120
  proxy.dependant(source, proxy.keysOf);
1036
1121
  while ('evolution' in stateSnapshot) {
@@ -1077,7 +1162,13 @@ function morphRecord(source, fn, options) {
1077
1162
  function stopItem(key) {
1078
1163
  const stop = itemEffects.get(key);
1079
1164
  if (stop) {
1080
- stop({ type: 'stopped' });
1165
+ const activeEffect = proxy.getActiveEffect();
1166
+ let chain;
1167
+ if (activeEffect) {
1168
+ const node = proxy.getEffectNode(activeEffect);
1169
+ chain = node.currentReason;
1170
+ }
1171
+ stop({ type: 'stopped', chain });
1081
1172
  itemEffects.delete(key);
1082
1173
  }
1083
1174
  }
@@ -1087,12 +1178,22 @@ function morphRecord(source, fn, options) {
1087
1178
  cache[key] = track(() => fn(val, key));
1088
1179
  }
1089
1180
  else {
1090
- const stop = track(() => proxy.effect.named(`morph:${fn.name}:${key}`).opaque((access) => {
1181
+ const stop = track(() => proxy.effect.opaque `morph:${fn.name}:${key}`((access) => {
1091
1182
  cache[key] = fn(source[key], key, access);
1092
1183
  return (reason) => {
1093
1184
  delete cache[key];
1094
1185
  proxy.touched1(cache, { type: 'invalidate', prop: 'morph' }, String(key));
1095
- stop?.({ type: 'invalidate', cause: reason });
1186
+ const activeEffect = proxy.getActiveEffect();
1187
+ let chain;
1188
+ if (activeEffect) {
1189
+ const node = proxy.getEffectNode(activeEffect);
1190
+ chain = node.currentReason;
1191
+ }
1192
+ stop?.({
1193
+ type: 'invalidate',
1194
+ cause: proxy.chainExternalReason(reason ?? { type: 'stopped', chain }),
1195
+ chain: proxy.chainExternalReason(chain),
1196
+ });
1096
1197
  };
1097
1198
  }));
1098
1199
  itemEffects.set(key, stop);
@@ -1119,7 +1220,7 @@ function morphRecord(source, fn, options) {
1119
1220
  },
1120
1221
  });
1121
1222
  let stateSnapshot = proxy.getState(source);
1122
- const stopMain = proxy.effect.named(`morph:${fn.name}`)(({ ascend }) => {
1223
+ const stopMain = proxy.effect `morph:${fn.name}`(({ ascend }) => {
1123
1224
  track = ascend;
1124
1225
  // Track only structural changes on source
1125
1226
  proxy.dependant(source, proxy.keysOf);
@@ -1160,7 +1261,7 @@ function morphRecord(source, fn, options) {
1160
1261
  * // Changing users[0].name only recomputes names[0]
1161
1262
  * ```
1162
1263
  */
1163
- const morph = proxy.flavored(function morph(source, fn, options) {
1264
+ const morph = proxy.captioned(proxy.flavored(function morph(source, fn, options) {
1164
1265
  if (Array.isArray(source) || typeof source === 'function')
1165
1266
  return morphArray(source, fn, options);
1166
1267
  if (source instanceof Map)
@@ -1170,6 +1271,10 @@ const morph = proxy.flavored(function morph(source, fn, options) {
1170
1271
  get pure() {
1171
1272
  return (source, fn, _opt) => this(source, fn, { pure: true });
1172
1273
  },
1274
+ }), {
1275
+ name: 'morph',
1276
+ callbackIndex: 1,
1277
+ warn: (message) => proxy.options.warn(`[reactive] ${message}`),
1173
1278
  });
1174
1279
 
1175
1280
  /**
@@ -1195,7 +1300,7 @@ function deepWatch(target, callback, { immediate = false } = {}) {
1195
1300
  const wrappedCallback = proxy.markWithRoot((() => callback(target)), callback);
1196
1301
  proxy.registerDeepWatcher();
1197
1302
  // Use the existing effect system to register dependencies
1198
- return proxy.effect.named('deepWatch')(() => {
1303
+ return proxy.effect `deepWatch`(() => {
1199
1304
  // Mark the target object as having deep watchers
1200
1305
  proxy.objectsWithDeepWatchers.add(target);
1201
1306
  // Track which objects this effect is watching for cleanup
@@ -1259,7 +1364,7 @@ function deepWatch(target, callback, { immediate = false } = {}) {
1259
1364
  traverseAndTrack(target);
1260
1365
  // Only call the callback if immediate is true or if it's not the first run
1261
1366
  if (immediate) {
1262
- proxy.untracked(() => callback(target));
1367
+ proxy.untracked `deepWatch:callback`(() => callback(target));
1263
1368
  }
1264
1369
  immediate = true;
1265
1370
  // Return a cleanup function that properly removes deep watcher tracking
@@ -1326,7 +1431,7 @@ function memoizeFunction(fn, opts) {
1326
1431
  const wasVerification = proxy.options.isVerificationRun;
1327
1432
  proxy.options.isVerificationRun = true;
1328
1433
  try {
1329
- const fresh = proxy.untracked(() => fn.apply(this, args));
1434
+ const fresh = proxy.untracked `memoize:verify-calculation`(() => fn.apply(this, args));
1330
1435
  if (!proxy.deepCompare(node.result, fresh)) {
1331
1436
  proxy.optionCall('onMemoizationDiscrepancy', node.result, fresh, fn, args, 'calculation');
1332
1437
  }
@@ -1339,7 +1444,7 @@ function memoizeFunction(fn, opts) {
1339
1444
  }
1340
1445
  // Create memoize internal effect to track dependencies and invalidate cache
1341
1446
  // Use untracked to prevent the effect creation from being affected by parent effects
1342
- node.cleanup = proxy.root(() => proxy.effect.named('memoize')(() => {
1447
+ node.cleanup = proxy.root `memoize:root`(() => proxy.effect `memoize`(() => {
1343
1448
  // Execute the function and track its dependencies
1344
1449
  // The function execution will automatically track dependencies on reactive objects
1345
1450
  node.result = fn.apply(this, args);
@@ -1350,7 +1455,17 @@ function memoizeFunction(fn, opts) {
1350
1455
  // Lazy memoization: stop the effect so it doesn't re-run immediately.
1351
1456
  // It will be re-created on next access.
1352
1457
  if (node.cleanup) {
1353
- node.cleanup({ type: 'invalidate', cause: reason });
1458
+ const activeEffect = proxy.getActiveEffect();
1459
+ let chain;
1460
+ if (activeEffect) {
1461
+ const effectNode = proxy.getEffectNode(activeEffect);
1462
+ chain = effectNode.currentReason;
1463
+ }
1464
+ node.cleanup({
1465
+ type: 'invalidate',
1466
+ cause: proxy.chainExternalReason(reason ?? { type: 'stopped', chain }),
1467
+ chain: proxy.chainExternalReason(chain),
1468
+ });
1354
1469
  node.cleanup = undefined;
1355
1470
  }
1356
1471
  };
@@ -1359,7 +1474,7 @@ function memoizeFunction(fn, opts) {
1359
1474
  const wasVerification = proxy.options.isVerificationRun;
1360
1475
  proxy.options.isVerificationRun = true;
1361
1476
  try {
1362
- const fresh = proxy.untracked(() => fn.apply(this, args));
1477
+ const fresh = proxy.untracked `memoize:verify-comparison`(() => fn.apply(this, args));
1363
1478
  if (!proxy.deepCompare(node.result, fresh)) {
1364
1479
  proxy.optionCall('onMemoizationDiscrepancy', node.result, fresh, fn, args, 'comparison');
1365
1480
  }
@@ -1551,12 +1666,12 @@ const memoize = proxy.flavored(makeMemoizeDecorator(), {
1551
1666
  function organized(source, apply, baseTarget = {}) {
1552
1667
  const observedSource = proxy.reactive(source);
1553
1668
  const target = proxy.reactive(baseTarget);
1554
- const stop = attend(() => {
1669
+ const stop = attend `organized:entries`(function enumerateObservedSourceKeys() {
1555
1670
  const keys = [];
1556
1671
  for (const key in observedSource)
1557
1672
  keys.push(key);
1558
1673
  return keys;
1559
- }, (key) => {
1674
+ }, function applyObservedSourceKey(key) {
1560
1675
  const sourceKey = key;
1561
1676
  const accessBase = {
1562
1677
  key: sourceKey,
@@ -1594,7 +1709,7 @@ function organize(target, property, access) {
1594
1709
 
1595
1710
  //#region watch
1596
1711
  const unsetYet = Symbol('unset-yet');
1597
- const watch = proxy.flavored(function watch(value, //object | ((dep: DependencyAccess) => object),
1712
+ const watch = proxy.captioned(proxy.flavored(function watch(value, //object | ((dep: DependencyAccess) => object),
1598
1713
  changed, options = {}) {
1599
1714
  return typeof value === 'function'
1600
1715
  ? watchCallBack(value, changed, options)
@@ -1610,11 +1725,14 @@ changed, options = {}) {
1610
1725
  get immediate() {
1611
1726
  return proxy.flavorOptions(this, { immediate: true });
1612
1727
  },
1728
+ }), {
1729
+ name: 'watch',
1730
+ warn: (message) => proxy.options.warn(`[reactive] ${message}`),
1613
1731
  });
1614
1732
  function watchObject(value, changed, { immediate = false, deep = false } = {}) {
1615
1733
  if (deep)
1616
1734
  return deepWatch(value, changed, { immediate });
1617
- return proxy.effect.named('watch:object')(() => {
1735
+ return proxy.effect `watch:object`(() => {
1618
1736
  proxy.dependant(value);
1619
1737
  if (immediate)
1620
1738
  changed(value);
@@ -1624,16 +1742,16 @@ function watchObject(value, changed, { immediate = false, deep = false } = {}) {
1624
1742
  function watchCallBack(value, changed, { immediate = false, deep = false } = {}) {
1625
1743
  let oldValue = unsetYet;
1626
1744
  let deepCleanup;
1627
- const cbCleanup = proxy.effect.named('watch:callback')(proxy.markWithRoot((access) => {
1745
+ const cbCleanup = proxy.effect `watch:callback`(proxy.markWithRoot((access) => {
1628
1746
  const newValue = value(access);
1629
1747
  if (oldValue !== newValue) {
1630
1748
  const old = oldValue;
1631
1749
  if (old === unsetYet) {
1632
1750
  if (immediate)
1633
- proxy.untracked(() => changed(newValue));
1751
+ proxy.untracked `watch:changed`(() => changed(newValue));
1634
1752
  }
1635
1753
  else
1636
- proxy.untracked(() => changed(newValue, old));
1754
+ proxy.untracked `watch:changed`(() => changed(newValue, old));
1637
1755
  }
1638
1756
  oldValue = newValue;
1639
1757
  if (deep) {
@@ -1660,7 +1778,7 @@ function watchCallBack(value, changed, { immediate = false, deep = false } = {})
1660
1778
  function when(predicate, timeout) {
1661
1779
  return new Promise((resolve, reject) => {
1662
1780
  let timer;
1663
- const stop = proxy.effect.named('watch:when')((access) => {
1781
+ const stop = proxy.effect `watch:when`((access) => {
1664
1782
  try {
1665
1783
  const value = predicate(access);
1666
1784
  if (value) {
@@ -1767,7 +1885,7 @@ function resource(fetcher, options = {}) {
1767
1885
  // Solve race conditions: make sure a new fast request is not overloaded by a slow old one
1768
1886
  let counter = 0;
1769
1887
  return lazyInit(resource, () => {
1770
- proxy.link(resource, proxy.effect.named('watch:resource')((access) => {
1888
+ proxy.link(resource, proxy.effect `watch:resource`((access) => {
1771
1889
  // Track reload signal to enable manual reloading
1772
1890
  void reloadSignal.value;
1773
1891
  const id = ++counter;
@@ -1933,6 +2051,7 @@ let ReactiveArrayWrapper = (() => {
1933
2051
  return super.findLastIndex((v, i, a) => predicate.call(thisArg, proxy.reactive(v), i, a), thisArg);
1934
2052
  }
1935
2053
  flat(depth) {
2054
+ proxy.dependant(this, proxy.keysOf);
1936
2055
  return proxy.reactive(super.flat(depth));
1937
2056
  }
1938
2057
  flatMap(callbackfn, thisArg) {
@@ -2359,59 +2478,62 @@ function isCached(object, propertyKey) {
2359
2478
  function cache(object, propertyKey, value) {
2360
2479
  Object.defineProperty(object, propertyKey, { value });
2361
2480
  }
2481
+ function descriptorBase(descriptor) {
2482
+ return function descriptorDecorator(...properties) {
2483
+ return (Base) => {
2484
+ return class extends Base {
2485
+ constructor(...args) {
2486
+ super(...args);
2487
+ for (const key of properties) {
2488
+ const existing = Object.getOwnPropertyDescriptor(this, key);
2489
+ Object.defineProperty(this, key, Object.assign(existing || {}, descriptor));
2490
+ }
2491
+ }
2492
+ };
2493
+ };
2494
+ };
2495
+ }
2362
2496
  /**
2363
2497
  * Creates a decorator that modifies property descriptors for specified properties
2364
2498
  * @param descriptor - The descriptor properties to apply
2365
2499
  * @returns A class decorator that applies the descriptor to specified properties
2366
2500
  */
2367
- const descriptor = proxy.flavored(function descriptor(descriptor) {
2368
- return (...properties) => (Base) => {
2369
- return class extends Base {
2370
- constructor(...args) {
2371
- super(...args);
2372
- for (const key of properties) {
2373
- const existing = Object.getOwnPropertyDescriptor(this, key);
2374
- Object.defineProperty(this, key, Object.assign(existing || {}, descriptor));
2375
- }
2376
- }
2377
- };
2378
- };
2379
- }, {
2501
+ const descriptor = Object.assign(descriptorBase, {
2380
2502
  /**
2381
2503
  * enumerable: true
2382
2504
  */
2383
2505
  get enumerable() {
2384
- return descriptor({ enumerable: true });
2506
+ return descriptorBase({ enumerable: true });
2385
2507
  },
2386
2508
  /**
2387
2509
  * enumerable: false
2388
2510
  */
2389
2511
  get hidden() {
2390
- return descriptor({ enumerable: false });
2512
+ return descriptorBase({ enumerable: false });
2391
2513
  },
2392
2514
  /**
2393
2515
  * configurable: true
2394
2516
  */
2395
2517
  get configurable() {
2396
- return descriptor({ configurable: true });
2518
+ return descriptorBase({ configurable: true });
2397
2519
  },
2398
2520
  /**
2399
2521
  * configurable: false
2400
2522
  */
2401
2523
  get frozen() {
2402
- return descriptor({ configurable: false });
2524
+ return descriptorBase({ configurable: false });
2403
2525
  },
2404
2526
  /**
2405
2527
  * writable: true
2406
2528
  */
2407
2529
  get writable() {
2408
- return descriptor({ writable: true });
2530
+ return descriptorBase({ writable: true });
2409
2531
  },
2410
2532
  /**
2411
2533
  * writable: false
2412
2534
  */
2413
2535
  get readonly() {
2414
- return descriptor({ writable: false });
2536
+ return descriptorBase({ writable: false });
2415
2537
  },
2416
2538
  });
2417
2539
  /**
@@ -2540,26 +2662,27 @@ function throttle(delay) {
2540
2662
  });
2541
2663
  }
2542
2664
 
2543
- var version$1 = "1.0.12";
2665
+ var version$1 = "1.0.13";
2544
2666
  var pkg = {
2545
2667
  version: version$1};
2546
2668
 
2547
2669
  const { version } = pkg;
2548
2670
  const GLOBAL_MUTTS_KEY = '__MUTTS_INSTANCE__';
2671
+ const runtimeGlobals = globalThis;
2549
2672
  const globalScope = (typeof globalThis !== 'undefined'
2550
2673
  ? globalThis
2551
- : typeof window !== 'undefined'
2552
- ? window
2553
- : typeof global !== 'undefined'
2554
- ? global
2674
+ : runtimeGlobals.window
2675
+ ? runtimeGlobals.window
2676
+ : runtimeGlobals.global
2677
+ ? runtimeGlobals.global
2555
2678
  : false);
2556
2679
  if (globalScope) {
2557
2680
  let source = 'mutts/index';
2558
2681
  try {
2559
- if (typeof __filename !== 'undefined')
2560
- source = __filename;
2561
- else if (typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunks/index-yK0HVxHv.cjs', document.baseURI).href)) }) !== 'undefined' && (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunks/index-yK0HVxHv.cjs', document.baseURI).href))) {
2562
- source = (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunks/index-yK0HVxHv.cjs', document.baseURI).href));
2682
+ if (runtimeGlobals.__filename)
2683
+ source = runtimeGlobals.__filename;
2684
+ else if (typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunks/index-CAdnMJev.cjs', document.baseURI).href)) }) !== 'undefined' && (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunks/index-CAdnMJev.cjs', document.baseURI).href))) {
2685
+ source = (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunks/index-CAdnMJev.cjs', document.baseURI).href));
2563
2686
  }
2564
2687
  }
2565
2688
  catch (_e) { }
@@ -2609,4 +2732,4 @@ exports.throttle = throttle;
2609
2732
  exports.unreactive = unreactive;
2610
2733
  exports.watch = watch;
2611
2734
  exports.when = when;
2612
- //# sourceMappingURL=index-yK0HVxHv.cjs.map
2735
+ //# sourceMappingURL=index-CAdnMJev.cjs.map