mobx 3.4.1 → 3.6.2

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.
@@ -31,7 +31,7 @@ function __extends(d, b) {
31
31
  * 1) detect when they are being _used_ and report this (using reportObserved). This allows mobx to make the connection between running functions and the data they used
32
32
  * 2) they should notify mobx whenever they have _changed_. This way mobx can re-run any functions (derivations) that are using this atom.
33
33
  */
34
- var BaseAtom = (function () {
34
+ var BaseAtom = /** @class */ (function () {
35
35
  /**
36
36
  * Create a new atom. For debugging purposes it is recommended to give it a name.
37
37
  * The onBecomeObserved and onBecomeUnobserved callbacks can be used for resource management.
@@ -68,7 +68,7 @@ var BaseAtom = (function () {
68
68
  };
69
69
  return BaseAtom;
70
70
  }());
71
- var Atom = (function (_super) {
71
+ var Atom = /** @class */ (function (_super) {
72
72
  __extends(Atom, _super);
73
73
  /**
74
74
  * Create a new atom. For debugging purposes it is recommended to give it a name.
@@ -234,7 +234,7 @@ var safariPrototypeSetterInheritanceBug = (function () {
234
234
  */
235
235
  var OBSERVABLE_ARRAY_BUFFER_SIZE = 0;
236
236
  // Typescript workaround to make sure ObservableArray extends Array
237
- var StubArray = (function () {
237
+ var StubArray = /** @class */ (function () {
238
238
  function StubArray() {
239
239
  }
240
240
  return StubArray;
@@ -277,7 +277,7 @@ if (Object.isFrozen(Array)) {
277
277
  });
278
278
  });
279
279
  }
280
- var ObservableArrayAdministration = (function () {
280
+ var ObservableArrayAdministration = /** @class */ (function () {
281
281
  function ObservableArrayAdministration(name, enhancer, array, owned) {
282
282
  this.array = array;
283
283
  this.owned = owned;
@@ -440,7 +440,7 @@ var ObservableArrayAdministration = (function () {
440
440
  };
441
441
  return ObservableArrayAdministration;
442
442
  }());
443
- var ObservableArray = (function (_super) {
443
+ var ObservableArray = /** @class */ (function (_super) {
444
444
  __extends(ObservableArray, _super);
445
445
  function ObservableArray(initialValues, enhancer, name, owned) {
446
446
  if (name === void 0) { name = "ObservableArray@" + getNextId(); }
@@ -753,7 +753,7 @@ function isObservableArray(thing) {
753
753
  }
754
754
 
755
755
  var UNCHANGED = {};
756
- var ObservableValue = (function (_super) {
756
+ var ObservableValue = /** @class */ (function (_super) {
757
757
  __extends(ObservableValue, _super);
758
758
  function ObservableValue(value, enhancer, name, notifySpy) {
759
759
  if (name === void 0) { name = "ObservableValue@" + getNextId(); }
@@ -994,18 +994,18 @@ function allowStateChangesEnd(prev) {
994
994
  * This means that these properties despite being enumerable might not show up in Object.keys() (but they will show up in for...in loops).
995
995
  */
996
996
  function createClassPropertyDecorator(
997
- /**
998
- * This function is invoked once, when the property is added to a new instance.
999
- * When this happens is not strictly determined due to differences in TS and Babel:
1000
- * Typescript: Usually when constructing the new instance
1001
- * Babel, sometimes Typescript: during the first get / set
1002
- * Both: when calling `runLazyInitializers(instance)`
1003
- */
1004
- onInitialize, get, set, enumerable,
1005
- /**
1006
- * Can this decorator invoked with arguments? e.g. @decorator(args)
1007
- */
1008
- allowCustomArguments) {
997
+ /**
998
+ * This function is invoked once, when the property is added to a new instance.
999
+ * When this happens is not strictly determined due to differences in TS and Babel:
1000
+ * Typescript: Usually when constructing the new instance
1001
+ * Babel, sometimes Typescript: during the first get / set
1002
+ * Both: when calling `runLazyInitializers(instance)`
1003
+ */
1004
+ onInitialize, get, set, enumerable,
1005
+ /**
1006
+ * Can this decorator invoked with arguments? e.g. @decorator(args)
1007
+ */
1008
+ allowCustomArguments) {
1009
1009
  function classPropertyDecorator(target, key, descriptor, customArgs, argLen) {
1010
1010
  if (argLen === void 0) { argLen = 0; }
1011
1011
  invariant(allowCustomArguments || quacksLikeADecorator(arguments), "This function is a decorator, but it wasn't invoked like a decorator");
@@ -1167,6 +1167,138 @@ function defineBoundAction(target, propertyName, fn) {
1167
1167
  addHiddenProp(target, propertyName, res);
1168
1168
  }
1169
1169
 
1170
+ var toString = Object.prototype.toString;
1171
+ function deepEqual(a, b) {
1172
+ return eq(a, b);
1173
+ }
1174
+ // Copied from https://github.com/jashkenas/underscore/blob/5c237a7c682fb68fd5378203f0bf22dce1624854/underscore.js#L1186-L1289
1175
+ // Internal recursive comparison function for `isEqual`.
1176
+ function eq(a, b, aStack, bStack) {
1177
+ // Identical objects are equal. `0 === -0`, but they aren't identical.
1178
+ // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
1179
+ if (a === b)
1180
+ return a !== 0 || 1 / a === 1 / b;
1181
+ // `null` or `undefined` only equal to itself (strict comparison).
1182
+ if (a == null || b == null)
1183
+ return false;
1184
+ // `NaN`s are equivalent, but non-reflexive.
1185
+ if (a !== a)
1186
+ return b !== b;
1187
+ // Exhaust primitive checks
1188
+ var type = typeof a;
1189
+ if (type !== "function" && type !== "object" && typeof b != "object")
1190
+ return false;
1191
+ return deepEq(a, b, aStack, bStack);
1192
+ }
1193
+ // Internal recursive comparison function for `isEqual`.
1194
+ function deepEq(a, b, aStack, bStack) {
1195
+ // Unwrap any wrapped objects.
1196
+ a = unwrap(a);
1197
+ b = unwrap(b);
1198
+ // Compare `[[Class]]` names.
1199
+ var className = toString.call(a);
1200
+ if (className !== toString.call(b))
1201
+ return false;
1202
+ switch (className) {
1203
+ // Strings, numbers, regular expressions, dates, and booleans are compared by value.
1204
+ case "[object RegExp]":
1205
+ // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
1206
+ case "[object String]":
1207
+ // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
1208
+ // equivalent to `new String("5")`.
1209
+ return "" + a === "" + b;
1210
+ case "[object Number]":
1211
+ // `NaN`s are equivalent, but non-reflexive.
1212
+ // Object(NaN) is equivalent to NaN.
1213
+ if (+a !== +a)
1214
+ return +b !== +b;
1215
+ // An `egal` comparison is performed for other numeric values.
1216
+ return +a === 0 ? 1 / +a === 1 / b : +a === +b;
1217
+ case "[object Date]":
1218
+ case "[object Boolean]":
1219
+ // Coerce dates and booleans to numeric primitive values. Dates are compared by their
1220
+ // millisecond representations. Note that invalid dates with millisecond representations
1221
+ // of `NaN` are not equivalent.
1222
+ return +a === +b;
1223
+ case "[object Symbol]":
1224
+ return (typeof Symbol !== "undefined" && Symbol.valueOf.call(a) === Symbol.valueOf.call(b));
1225
+ }
1226
+ var areArrays = className === "[object Array]";
1227
+ if (!areArrays) {
1228
+ if (typeof a != "object" || typeof b != "object")
1229
+ return false;
1230
+ // Objects with different constructors are not equivalent, but `Object`s or `Array`s
1231
+ // from different frames are.
1232
+ var aCtor = a.constructor, bCtor = b.constructor;
1233
+ if (aCtor !== bCtor &&
1234
+ !(typeof aCtor === "function" &&
1235
+ aCtor instanceof aCtor &&
1236
+ typeof bCtor === "function" &&
1237
+ bCtor instanceof bCtor) &&
1238
+ ("constructor" in a && "constructor" in b)) {
1239
+ return false;
1240
+ }
1241
+ }
1242
+ // Assume equality for cyclic structures. The algorithm for detecting cyclic
1243
+ // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
1244
+ // Initializing stack of traversed objects.
1245
+ // It's done here since we only need them for objects and arrays comparison.
1246
+ aStack = aStack || [];
1247
+ bStack = bStack || [];
1248
+ var length = aStack.length;
1249
+ while (length--) {
1250
+ // Linear search. Performance is inversely proportional to the number of
1251
+ // unique nested structures.
1252
+ if (aStack[length] === a)
1253
+ return bStack[length] === b;
1254
+ }
1255
+ // Add the first object to the stack of traversed objects.
1256
+ aStack.push(a);
1257
+ bStack.push(b);
1258
+ // Recursively compare objects and arrays.
1259
+ if (areArrays) {
1260
+ // Compare array lengths to determine if a deep comparison is necessary.
1261
+ length = a.length;
1262
+ if (length !== b.length)
1263
+ return false;
1264
+ // Deep compare the contents, ignoring non-numeric properties.
1265
+ while (length--) {
1266
+ if (!eq(a[length], b[length], aStack, bStack))
1267
+ return false;
1268
+ }
1269
+ }
1270
+ else {
1271
+ // Deep compare objects.
1272
+ var keys = Object.keys(a), key;
1273
+ length = keys.length;
1274
+ // Ensure that both objects contain the same number of properties before comparing deep equality.
1275
+ if (Object.keys(b).length !== length)
1276
+ return false;
1277
+ while (length--) {
1278
+ // Deep compare each member
1279
+ key = keys[length];
1280
+ if (!(has(b, key) && eq(a[key], b[key], aStack, bStack)))
1281
+ return false;
1282
+ }
1283
+ }
1284
+ // Remove the first object from the stack of traversed objects.
1285
+ aStack.pop();
1286
+ bStack.pop();
1287
+ return true;
1288
+ }
1289
+ function unwrap(a) {
1290
+ if (isObservableArray(a))
1291
+ return a.peek();
1292
+ if (isObservableMap(a))
1293
+ return a.entries();
1294
+ if (isES6Map(a))
1295
+ return iteratorToArray(a.entries());
1296
+ return a;
1297
+ }
1298
+ function has(a, key) {
1299
+ return Object.prototype.hasOwnProperty.call(a, key);
1300
+ }
1301
+
1170
1302
  function identityComparer(a, b) {
1171
1303
  return a === b;
1172
1304
  }
@@ -1348,7 +1480,7 @@ function reaction(expression, effect, arg3) {
1348
1480
  *
1349
1481
  * If at any point it's outside batch and it isn't observed: reset everything and go to 1.
1350
1482
  */
1351
- var ComputedValue = (function () {
1483
+ var ComputedValue = /** @class */ (function () {
1352
1484
  /**
1353
1485
  * Create a new computed value based on a function expression.
1354
1486
  *
@@ -1380,6 +1512,7 @@ var ComputedValue = (function () {
1380
1512
  this.value = new CaughtException(null);
1381
1513
  this.isComputing = false; // to check for cycles
1382
1514
  this.isRunningSetter = false;
1515
+ this.isTracing = TraceMode.NONE;
1383
1516
  this.name = name || "ComputedValue@" + getNextId();
1384
1517
  if (setter)
1385
1518
  this.setter = createAction(name + "-setter", setter);
@@ -1402,8 +1535,13 @@ var ComputedValue = (function () {
1402
1535
  // The computedValue is accessed outside of any mobx stuff. Batch observing should be enough and don't need
1403
1536
  // tracking as it will never be called again inside this batch.
1404
1537
  startBatch();
1405
- if (shouldCompute(this))
1538
+ if (shouldCompute(this)) {
1539
+ if (this.isTracing !== TraceMode.NONE) {
1540
+ console.log("[mobx.trace] '" + this
1541
+ .name + "' is being read outside a reactive context and doing a full recompute");
1542
+ }
1406
1543
  this.value = this.computeValue(false);
1544
+ }
1407
1545
  endBatch();
1408
1546
  }
1409
1547
  else {
@@ -1448,7 +1586,8 @@ var ComputedValue = (function () {
1448
1586
  });
1449
1587
  }
1450
1588
  var oldValue = this.value;
1451
- var wasSuspended = this.dependenciesState === IDerivationState.NOT_TRACKING;
1589
+ var wasSuspended =
1590
+ /* see #1208 */ this.dependenciesState === IDerivationState.NOT_TRACKING;
1452
1591
  var newValue = (this.value = this.computeValue(true));
1453
1592
  return (wasSuspended ||
1454
1593
  isCaughtException(oldValue) ||
@@ -1523,7 +1662,7 @@ var ComputedValue = (function () {
1523
1662
  ComputedValue.prototype[primitiveSymbol()] = ComputedValue.prototype.valueOf;
1524
1663
  var isComputedValue = createInstanceofPredicate("ComputedValue", ComputedValue);
1525
1664
 
1526
- var ObservableObjectAdministration = (function () {
1665
+ var ObservableObjectAdministration = /** @class */ (function () {
1527
1666
  function ObservableObjectAdministration(target, name) {
1528
1667
  this.target = target;
1529
1668
  this.name = name;
@@ -2023,7 +2162,7 @@ function transaction(action, thisArg) {
2023
2162
  }
2024
2163
 
2025
2164
  var ObservableMapMarker = {};
2026
- var ObservableMap = (function () {
2165
+ var ObservableMap = /** @class */ (function () {
2027
2166
  function ObservableMap(initialData, enhancer, name) {
2028
2167
  if (enhancer === void 0) { enhancer = deepEnhancer; }
2029
2168
  if (name === void 0) { name = "ObservableMap@" + getNextId(); }
@@ -2416,71 +2555,6 @@ function isPropertyConfigurable(object, prop) {
2416
2555
  function assertPropertyConfigurable(object, prop) {
2417
2556
  invariant(isPropertyConfigurable(object, prop), "Cannot make property '" + prop + "' observable, it is not configurable and writable in the target object");
2418
2557
  }
2419
- function getEnumerableKeys(obj) {
2420
- var res = [];
2421
- for (var key in obj)
2422
- res.push(key);
2423
- return res;
2424
- }
2425
- /**
2426
- * Naive deepEqual. Doesn't check for prototype, non-enumerable or out-of-range properties on arrays.
2427
- * If you have such a case, you probably should use this function but something fancier :).
2428
- */
2429
- function deepEqual(a, b) {
2430
- if (a === null && b === null)
2431
- return true;
2432
- if (a === undefined && b === undefined)
2433
- return true;
2434
- if (areBothNaN(a, b))
2435
- return true;
2436
- if (typeof a !== "object")
2437
- return a === b;
2438
- var aIsArray = isArrayLike(a);
2439
- var aIsMap = isMapLike(a);
2440
- if (aIsArray !== isArrayLike(b)) {
2441
- return false;
2442
- }
2443
- else if (aIsMap !== isMapLike(b)) {
2444
- return false;
2445
- }
2446
- else if (aIsArray) {
2447
- if (a.length !== b.length)
2448
- return false;
2449
- for (var i = a.length - 1; i >= 0; i--)
2450
- if (!deepEqual(a[i], b[i]))
2451
- return false;
2452
- return true;
2453
- }
2454
- else if (aIsMap) {
2455
- if (a.size !== b.size)
2456
- return false;
2457
- var equals_1 = true;
2458
- a.forEach(function (value, key) {
2459
- equals_1 = equals_1 && deepEqual(b.get(key), value);
2460
- });
2461
- return equals_1;
2462
- }
2463
- else if (typeof a === "object" && typeof b === "object") {
2464
- if (a === null || b === null)
2465
- return false;
2466
- if (isMapLike(a) && isMapLike(b)) {
2467
- if (a.size !== b.size)
2468
- return false;
2469
- // Freaking inefficient.... Create PR if you run into this :) Much appreciated!
2470
- return deepEqual(observable.shallowMap(a).entries(), observable.shallowMap(b).entries());
2471
- }
2472
- if (getEnumerableKeys(a).length !== getEnumerableKeys(b).length)
2473
- return false;
2474
- for (var prop in a) {
2475
- if (!(prop in b))
2476
- return false;
2477
- if (!deepEqual(a[prop], b[prop]))
2478
- return false;
2479
- }
2480
- return true;
2481
- }
2482
- return false;
2483
- }
2484
2558
  function createInstanceofPredicate(name, clazz) {
2485
2559
  var propName = "isMobX" + name;
2486
2560
  clazz.prototype[propName] = true;
@@ -2489,7 +2563,7 @@ function createInstanceofPredicate(name, clazz) {
2489
2563
  };
2490
2564
  }
2491
2565
  function areBothNaN(a, b) {
2492
- return (typeof a === "number" && typeof b === "number" && isNaN(a) && isNaN(b));
2566
+ return typeof a === "number" && typeof b === "number" && isNaN(a) && isNaN(b);
2493
2567
  }
2494
2568
  /**
2495
2569
  * Returns whether the argument is an array, disregarding observability.
@@ -2497,28 +2571,34 @@ function areBothNaN(a, b) {
2497
2571
  function isArrayLike(x) {
2498
2572
  return Array.isArray(x) || isObservableArray(x);
2499
2573
  }
2500
- function isMapLike(x) {
2501
- return isES6Map(x) || isObservableMap(x);
2502
- }
2503
2574
  function isES6Map(thing) {
2504
2575
  if (getGlobal().Map !== undefined && thing instanceof getGlobal().Map)
2505
2576
  return true;
2506
2577
  return false;
2507
2578
  }
2508
2579
  function getMapLikeKeys(map$$1) {
2509
- var keys;
2510
2580
  if (isPlainObject(map$$1))
2511
- keys = Object.keys(map$$1);
2512
- else if (Array.isArray(map$$1))
2513
- keys = map$$1.map(function (_a) {
2581
+ return Object.keys(map$$1);
2582
+ if (Array.isArray(map$$1))
2583
+ return map$$1.map(function (_a) {
2514
2584
  var key = _a[0];
2515
2585
  return key;
2516
2586
  });
2517
- else if (isMapLike(map$$1))
2518
- keys = Array.from(map$$1.keys());
2519
- else
2520
- fail("Cannot get keys from " + map$$1);
2521
- return keys;
2587
+ if (isES6Map(map$$1))
2588
+ return Array.from(map$$1.keys());
2589
+ if (isObservableMap(map$$1))
2590
+ return map$$1.keys();
2591
+ return fail("Cannot get keys from " + map$$1);
2592
+ }
2593
+ function iteratorToArray(it) {
2594
+ var res = [];
2595
+ while (true) {
2596
+ var r = it.next();
2597
+ if (r.done)
2598
+ break;
2599
+ res.push(r.value);
2600
+ }
2601
+ return res;
2522
2602
  }
2523
2603
  function primitiveSymbol() {
2524
2604
  return (typeof Symbol === "function" && Symbol.toPrimitive) || "@@toPrimitive";
@@ -2531,7 +2611,7 @@ function toPrimitive(value) {
2531
2611
  * These values will persist if global state is reset
2532
2612
  */
2533
2613
  var persistentKeys = ["mobxGuid", "resetId", "spyListeners", "strictMode", "runId"];
2534
- var MobXGlobals = (function () {
2614
+ var MobXGlobals = /** @class */ (function () {
2535
2615
  function MobXGlobals() {
2536
2616
  /**
2537
2617
  * MobXGlobals version.
@@ -2615,7 +2695,7 @@ var warnedAboutMultipleInstances = false;
2615
2695
  warnedAboutMultipleInstances = true;
2616
2696
  console.warn("[mobx] Warning: there are multiple mobx instances active. This might lead to unexpected results. See https://github.com/mobxjs/mobx/issues/1082 for details.");
2617
2697
  }
2618
- });
2698
+ }, 1);
2619
2699
  }
2620
2700
  }
2621
2701
  function isolateGlobalState() {
@@ -2657,6 +2737,91 @@ function resetGlobalState() {
2657
2737
  globalState.allowStateChanges = !globalState.strictMode;
2658
2738
  }
2659
2739
 
2740
+ function getAtom(thing, property) {
2741
+ if (typeof thing === "object" && thing !== null) {
2742
+ if (isObservableArray(thing)) {
2743
+ invariant(property === undefined, getMessage("m036"));
2744
+ return thing.$mobx.atom;
2745
+ }
2746
+ if (isObservableMap(thing)) {
2747
+ var anyThing = thing;
2748
+ if (property === undefined)
2749
+ return getAtom(anyThing._keys);
2750
+ var observable = anyThing._data[property] || anyThing._hasMap[property];
2751
+ invariant(!!observable, "the entry '" + property + "' does not exist in the observable map '" + getDebugName(thing) + "'");
2752
+ return observable;
2753
+ }
2754
+ // Initializers run lazily when transpiling to babel, so make sure they are run...
2755
+ runLazyInitializers(thing);
2756
+ if (property && !thing.$mobx)
2757
+ thing[property]; // See #1072 // TODO: remove in 4.0
2758
+ if (isObservableObject(thing)) {
2759
+ if (!property)
2760
+ return fail("please specify a property");
2761
+ var observable = thing.$mobx.values[property];
2762
+ invariant(!!observable, "no observable property '" + property + "' found on the observable object '" + getDebugName(thing) + "'");
2763
+ return observable;
2764
+ }
2765
+ if (isAtom(thing) || isComputedValue(thing) || isReaction(thing)) {
2766
+ return thing;
2767
+ }
2768
+ }
2769
+ else if (typeof thing === "function") {
2770
+ if (isReaction(thing.$mobx)) {
2771
+ // disposer function
2772
+ return thing.$mobx;
2773
+ }
2774
+ }
2775
+ return fail("Cannot obtain atom from " + thing);
2776
+ }
2777
+ function getAdministration(thing, property) {
2778
+ invariant(thing, "Expecting some object");
2779
+ if (property !== undefined)
2780
+ return getAdministration(getAtom(thing, property));
2781
+ if (isAtom(thing) || isComputedValue(thing) || isReaction(thing))
2782
+ return thing;
2783
+ if (isObservableMap(thing))
2784
+ return thing;
2785
+ // Initializers run lazily when transpiling to babel, so make sure they are run...
2786
+ runLazyInitializers(thing);
2787
+ if (thing.$mobx)
2788
+ return thing.$mobx;
2789
+ invariant(false, "Cannot obtain administration from " + thing);
2790
+ }
2791
+ function getDebugName(thing, property) {
2792
+ var named;
2793
+ if (property !== undefined)
2794
+ named = getAtom(thing, property);
2795
+ else if (isObservableObject(thing) || isObservableMap(thing))
2796
+ named = getAdministration(thing);
2797
+ else
2798
+ named = getAtom(thing); // valid for arrays as well
2799
+ return named.name;
2800
+ }
2801
+
2802
+ function getDependencyTree(thing, property) {
2803
+ return nodeToDependencyTree(getAtom(thing, property));
2804
+ }
2805
+ function nodeToDependencyTree(node) {
2806
+ var result = {
2807
+ name: node.name
2808
+ };
2809
+ if (node.observing && node.observing.length > 0)
2810
+ result.dependencies = unique(node.observing).map(nodeToDependencyTree);
2811
+ return result;
2812
+ }
2813
+ function getObserverTree(thing, property) {
2814
+ return nodeToObserverTree(getAtom(thing, property));
2815
+ }
2816
+ function nodeToObserverTree(node) {
2817
+ var result = {
2818
+ name: node.name
2819
+ };
2820
+ if (hasObservers(node))
2821
+ result.observers = getObservers(node).map(nodeToObserverTree);
2822
+ return result;
2823
+ }
2824
+
2660
2825
  function hasObservers(observable) {
2661
2826
  return observable.observers && observable.observers.length > 0;
2662
2827
  }
@@ -2775,8 +2940,12 @@ function propagateChanged(observable) {
2775
2940
  var i = observers.length;
2776
2941
  while (i--) {
2777
2942
  var d = observers[i];
2778
- if (d.dependenciesState === IDerivationState.UP_TO_DATE)
2943
+ if (d.dependenciesState === IDerivationState.UP_TO_DATE) {
2944
+ if (d.isTracing !== TraceMode.NONE) {
2945
+ logTraceInfo(d, observable);
2946
+ }
2779
2947
  d.onBecomeStale();
2948
+ }
2780
2949
  d.dependenciesState = IDerivationState.STALE;
2781
2950
  }
2782
2951
  // invariantLOS(observable, "changed end");
@@ -2811,11 +2980,32 @@ function propagateMaybeChanged(observable) {
2811
2980
  var d = observers[i];
2812
2981
  if (d.dependenciesState === IDerivationState.UP_TO_DATE) {
2813
2982
  d.dependenciesState = IDerivationState.POSSIBLY_STALE;
2983
+ if (d.isTracing !== TraceMode.NONE) {
2984
+ logTraceInfo(d, observable);
2985
+ }
2814
2986
  d.onBecomeStale();
2815
2987
  }
2816
2988
  }
2817
2989
  // invariantLOS(observable, "maybe end");
2818
2990
  }
2991
+ function logTraceInfo(derivation, observable) {
2992
+ console.log("[mobx.trace] '" + derivation.name + "' is invalidated due to a change in: '" + observable.name + "'");
2993
+ if (derivation.isTracing === TraceMode.BREAK) {
2994
+ var lines = [];
2995
+ printDepTree(getDependencyTree(derivation), lines, 1);
2996
+ // prettier-ignore
2997
+ new Function("debugger;\n/*\nTracing '" + derivation.name + "'\n\nYou are entering this break point because derivation '" + derivation.name + "' is being traced and '" + observable.name + "' is now forcing it to update.\nJust follow the stacktrace you should now see in the devtools to see precisely what piece of your code is causing this update\nThe stackframe you are looking for is at least ~6-8 stack-frames up.\n\n" + (derivation instanceof ComputedValue ? derivation.derivation.toString() : "") + "\n\nThe dependencies for this derivation are:\n\n" + lines.join("\n") + "\n*/\n ")();
2998
+ }
2999
+ }
3000
+ function printDepTree(tree, lines, depth) {
3001
+ if (lines.length >= 1000) {
3002
+ lines.push("(and many more)");
3003
+ return;
3004
+ }
3005
+ lines.push("" + new Array(depth).join("\t") + tree.name); // MWE: not the fastest, but the easiest way :)
3006
+ if (tree.dependencies)
3007
+ tree.dependencies.forEach(function (child) { return printDepTree(child, lines, depth + 1); });
3008
+ }
2819
3009
 
2820
3010
  var IDerivationState;
2821
3011
  (function (IDerivationState) {
@@ -2837,7 +3027,13 @@ var IDerivationState;
2837
3027
  // will need to recompute when it's needed next.
2838
3028
  IDerivationState[IDerivationState["STALE"] = 2] = "STALE";
2839
3029
  })(IDerivationState || (IDerivationState = {}));
2840
- var CaughtException = (function () {
3030
+ var TraceMode;
3031
+ (function (TraceMode) {
3032
+ TraceMode[TraceMode["NONE"] = 0] = "NONE";
3033
+ TraceMode[TraceMode["LOG"] = 1] = "LOG";
3034
+ TraceMode[TraceMode["BREAK"] = 2] = "BREAK";
3035
+ })(TraceMode || (TraceMode = {}));
3036
+ var CaughtException = /** @class */ (function () {
2841
3037
  function CaughtException(cause) {
2842
3038
  this.cause = cause;
2843
3039
  // Empty
@@ -3025,7 +3221,48 @@ function changeDependenciesStateTo0(derivation) {
3025
3221
  obs[i].lowestObserverState = IDerivationState.UP_TO_DATE;
3026
3222
  }
3027
3223
 
3028
- var Reaction = (function () {
3224
+ function log(msg) {
3225
+ console.log(msg);
3226
+ return msg;
3227
+ }
3228
+ function whyRun(thing, prop) {
3229
+ deprecated("`whyRun` is deprecated in favor of `trace`");
3230
+ thing = getAtomFromArgs(arguments);
3231
+ if (!thing)
3232
+ return log(getMessage("m024"));
3233
+ if (isComputedValue(thing) || isReaction(thing))
3234
+ return log(thing.whyRun());
3235
+ return fail(getMessage("m025"));
3236
+ }
3237
+ function trace() {
3238
+ var args = [];
3239
+ for (var _i = 0; _i < arguments.length; _i++) {
3240
+ args[_i] = arguments[_i];
3241
+ }
3242
+ var enterBreakPoint = false;
3243
+ if (typeof args[args.length - 1] === "boolean")
3244
+ enterBreakPoint = args.pop();
3245
+ var derivation = getAtomFromArgs(args);
3246
+ if (!derivation) {
3247
+ return fail("'trace(break?)' can only be used inside a tracked computed value or a Reaction. Consider passing in the computed value or reaction explicitly");
3248
+ }
3249
+ if (derivation.isTracing === TraceMode.NONE) {
3250
+ console.log("[mobx.trace] '" + derivation.name + "' tracing enabled");
3251
+ }
3252
+ derivation.isTracing = enterBreakPoint ? TraceMode.BREAK : TraceMode.LOG;
3253
+ }
3254
+ function getAtomFromArgs(args) {
3255
+ switch (args.length) {
3256
+ case 0:
3257
+ return globalState.trackingDerivation;
3258
+ case 1:
3259
+ return getAtom(args[0]);
3260
+ case 2:
3261
+ return getAtom(args[0], args[1]);
3262
+ }
3263
+ }
3264
+
3265
+ var Reaction = /** @class */ (function () {
3029
3266
  function Reaction(name, onInvalidate) {
3030
3267
  if (name === void 0) { name = "Reaction@" + getNextId(); }
3031
3268
  this.name = name;
@@ -3041,6 +3278,7 @@ var Reaction = (function () {
3041
3278
  this._isScheduled = false;
3042
3279
  this._isTrackPending = false;
3043
3280
  this._isRunning = false;
3281
+ this.isTracing = TraceMode.NONE;
3044
3282
  }
3045
3283
  Reaction.prototype.onBecomeStale = function () {
3046
3284
  this.schedule();
@@ -3153,6 +3391,10 @@ var Reaction = (function () {
3153
3391
  ? " (... or any observable accessed during the remainder of the current run)"
3154
3392
  : "") + "\n\t" + getMessage("m038") + "\n";
3155
3393
  };
3394
+ Reaction.prototype.trace = function (enterBreakPoint) {
3395
+ if (enterBreakPoint === void 0) { enterBreakPoint = false; }
3396
+ trace(this, enterBreakPoint);
3397
+ };
3156
3398
  return Reaction;
3157
3399
  }());
3158
3400
  function registerErrorHandler(handler) {
@@ -3261,68 +3503,6 @@ var computed = function computed(arg1, arg2, arg3) {
3261
3503
  computed.struct = computedStructDecorator;
3262
3504
  computed.equals = createComputedDecorator;
3263
3505
 
3264
- function getAtom(thing, property) {
3265
- if (typeof thing === "object" && thing !== null) {
3266
- if (isObservableArray(thing)) {
3267
- invariant(property === undefined, getMessage("m036"));
3268
- return thing.$mobx.atom;
3269
- }
3270
- if (isObservableMap(thing)) {
3271
- var anyThing = thing;
3272
- if (property === undefined)
3273
- return getAtom(anyThing._keys);
3274
- var observable = anyThing._data[property] || anyThing._hasMap[property];
3275
- invariant(!!observable, "the entry '" + property + "' does not exist in the observable map '" + getDebugName(thing) + "'");
3276
- return observable;
3277
- }
3278
- // Initializers run lazily when transpiling to babel, so make sure they are run...
3279
- runLazyInitializers(thing);
3280
- if (property && !thing.$mobx)
3281
- thing[property]; // See #1072 // TODO: remove in 4.0
3282
- if (isObservableObject(thing)) {
3283
- if (!property)
3284
- return fail("please specify a property");
3285
- var observable = thing.$mobx.values[property];
3286
- invariant(!!observable, "no observable property '" + property + "' found on the observable object '" + getDebugName(thing) + "'");
3287
- return observable;
3288
- }
3289
- if (isAtom(thing) || isComputedValue(thing) || isReaction(thing)) {
3290
- return thing;
3291
- }
3292
- }
3293
- else if (typeof thing === "function") {
3294
- if (isReaction(thing.$mobx)) {
3295
- // disposer function
3296
- return thing.$mobx;
3297
- }
3298
- }
3299
- return fail("Cannot obtain atom from " + thing);
3300
- }
3301
- function getAdministration(thing, property) {
3302
- invariant(thing, "Expecting some object");
3303
- if (property !== undefined)
3304
- return getAdministration(getAtom(thing, property));
3305
- if (isAtom(thing) || isComputedValue(thing) || isReaction(thing))
3306
- return thing;
3307
- if (isObservableMap(thing))
3308
- return thing;
3309
- // Initializers run lazily when transpiling to babel, so make sure they are run...
3310
- runLazyInitializers(thing);
3311
- if (thing.$mobx)
3312
- return thing.$mobx;
3313
- invariant(false, "Cannot obtain administration from " + thing);
3314
- }
3315
- function getDebugName(thing, property) {
3316
- var named;
3317
- if (property !== undefined)
3318
- named = getAtom(thing, property);
3319
- else if (isObservableObject(thing) || isObservableMap(thing))
3320
- named = getAdministration(thing);
3321
- else
3322
- named = getAtom(thing); // valid for arrays as well
3323
- return named.name;
3324
- }
3325
-
3326
3506
  function isComputed(value, property) {
3327
3507
  if (value === null || value === undefined)
3328
3508
  return false;
@@ -3435,7 +3615,7 @@ function createTransformer(transformer, onCleanup) {
3435
3615
  // This construction is used to avoid leaking refs to the objectCache directly
3436
3616
  var resetId = globalState.resetId;
3437
3617
  // Local transformer class specifically for this transformer
3438
- var Transformer = (function (_super) {
3618
+ var Transformer = /** @class */ (function (_super) {
3439
3619
  __extends(Transformer, _super);
3440
3620
  function Transformer(sourceIdentifier, sourceObject) {
3441
3621
  var _this = _super.call(this, function () { return transformer(sourceObject); }, undefined, comparer.default, "Transformer-" + transformer.name + "-" + sourceIdentifier, undefined) || this;
@@ -3479,52 +3659,6 @@ function getMemoizationId(object) {
3479
3659
  return tid;
3480
3660
  }
3481
3661
 
3482
- function log(msg) {
3483
- console.log(msg);
3484
- return msg;
3485
- }
3486
- function whyRun(thing, prop) {
3487
- switch (arguments.length) {
3488
- case 0:
3489
- thing = globalState.trackingDerivation;
3490
- if (!thing)
3491
- return log(getMessage("m024"));
3492
- break;
3493
- case 2:
3494
- thing = getAtom(thing, prop);
3495
- break;
3496
- }
3497
- thing = getAtom(thing);
3498
- if (isComputedValue(thing))
3499
- return log(thing.whyRun());
3500
- else if (isReaction(thing))
3501
- return log(thing.whyRun());
3502
- return fail(getMessage("m025"));
3503
- }
3504
-
3505
- function getDependencyTree(thing, property) {
3506
- return nodeToDependencyTree(getAtom(thing, property));
3507
- }
3508
- function nodeToDependencyTree(node) {
3509
- var result = {
3510
- name: node.name
3511
- };
3512
- if (node.observing && node.observing.length > 0)
3513
- result.dependencies = unique(node.observing).map(nodeToDependencyTree);
3514
- return result;
3515
- }
3516
- function getObserverTree(thing, property) {
3517
- return nodeToObserverTree(getAtom(thing, property));
3518
- }
3519
- function nodeToObserverTree(node) {
3520
- var result = {
3521
- name: node.name
3522
- };
3523
- if (hasObservers(node))
3524
- result.observers = getObservers(node).map(nodeToObserverTree);
3525
- return result;
3526
- }
3527
-
3528
3662
  function interceptReads(thing, propOrHandler, handler) {
3529
3663
  var target;
3530
3664
  if (isObservableMap(thing) || isObservableArray(thing) || isObservableValue(thing)) {
@@ -3650,4 +3784,4 @@ if (typeof __MOBX_DEVTOOLS_GLOBAL_HOOK__ === "object") {
3650
3784
  __MOBX_DEVTOOLS_GLOBAL_HOOK__.injectMobx({ spy: spy, extras: extras });
3651
3785
  }
3652
3786
 
3653
- export { extras, Reaction, untracked, IDerivationState, Atom, BaseAtom, useStrict, isStrictModeEnabled, spy, comparer, asReference, asFlat, asStructure, asMap, isModifierDescriptor, isObservableObject, isObservableValue as isBoxedObservable, isObservableArray, ObservableMap, isObservableMap, map, transaction, observable, computed, isObservable, isComputed, extendObservable, extendShallowObservable, observe, intercept, autorun, autorunAsync, when, reaction, action, isAction, runInAction, expr, toJS, createTransformer, whyRun, isArrayLike };export default everything;
3787
+ export { extras, Reaction, untracked, IDerivationState, Atom, BaseAtom, useStrict, isStrictModeEnabled, spy, comparer, asReference, asFlat, asStructure, asMap, isModifierDescriptor, isObservableObject, isObservableValue as isBoxedObservable, isObservableArray, ObservableMap, isObservableMap, map, transaction, observable, computed, isObservable, isComputed, extendObservable, extendShallowObservable, observe, intercept, autorun, autorunAsync, when, reaction, action, isAction, runInAction, expr, toJS, createTransformer, whyRun, trace, isArrayLike };export default everything;