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.
package/lib/mobx.umd.js CHANGED
@@ -37,7 +37,7 @@ function __extends(d, b) {
37
37
  * 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
38
38
  * 2) they should notify mobx whenever they have _changed_. This way mobx can re-run any functions (derivations) that are using this atom.
39
39
  */
40
- var BaseAtom = (function () {
40
+ var BaseAtom = /** @class */ (function () {
41
41
  /**
42
42
  * Create a new atom. For debugging purposes it is recommended to give it a name.
43
43
  * The onBecomeObserved and onBecomeUnobserved callbacks can be used for resource management.
@@ -74,7 +74,7 @@ var BaseAtom = (function () {
74
74
  };
75
75
  return BaseAtom;
76
76
  }());
77
- var Atom = (function (_super) {
77
+ var Atom = /** @class */ (function (_super) {
78
78
  __extends(Atom, _super);
79
79
  /**
80
80
  * Create a new atom. For debugging purposes it is recommended to give it a name.
@@ -240,7 +240,7 @@ var safariPrototypeSetterInheritanceBug = (function () {
240
240
  */
241
241
  var OBSERVABLE_ARRAY_BUFFER_SIZE = 0;
242
242
  // Typescript workaround to make sure ObservableArray extends Array
243
- var StubArray = (function () {
243
+ var StubArray = /** @class */ (function () {
244
244
  function StubArray() {
245
245
  }
246
246
  return StubArray;
@@ -283,7 +283,7 @@ if (Object.isFrozen(Array)) {
283
283
  });
284
284
  });
285
285
  }
286
- var ObservableArrayAdministration = (function () {
286
+ var ObservableArrayAdministration = /** @class */ (function () {
287
287
  function ObservableArrayAdministration(name, enhancer, array, owned) {
288
288
  this.array = array;
289
289
  this.owned = owned;
@@ -446,7 +446,7 @@ var ObservableArrayAdministration = (function () {
446
446
  };
447
447
  return ObservableArrayAdministration;
448
448
  }());
449
- var ObservableArray = (function (_super) {
449
+ var ObservableArray = /** @class */ (function (_super) {
450
450
  __extends(ObservableArray, _super);
451
451
  function ObservableArray(initialValues, enhancer, name, owned) {
452
452
  if (name === void 0) { name = "ObservableArray@" + getNextId(); }
@@ -759,7 +759,7 @@ function isObservableArray(thing) {
759
759
  }
760
760
 
761
761
  var UNCHANGED = {};
762
- var ObservableValue = (function (_super) {
762
+ var ObservableValue = /** @class */ (function (_super) {
763
763
  __extends(ObservableValue, _super);
764
764
  function ObservableValue(value, enhancer, name, notifySpy) {
765
765
  if (name === void 0) { name = "ObservableValue@" + getNextId(); }
@@ -1000,18 +1000,18 @@ function allowStateChangesEnd(prev) {
1000
1000
  * This means that these properties despite being enumerable might not show up in Object.keys() (but they will show up in for...in loops).
1001
1001
  */
1002
1002
  function createClassPropertyDecorator(
1003
- /**
1004
- * This function is invoked once, when the property is added to a new instance.
1005
- * When this happens is not strictly determined due to differences in TS and Babel:
1006
- * Typescript: Usually when constructing the new instance
1007
- * Babel, sometimes Typescript: during the first get / set
1008
- * Both: when calling `runLazyInitializers(instance)`
1009
- */
1010
- onInitialize, get, set, enumerable,
1011
- /**
1012
- * Can this decorator invoked with arguments? e.g. @decorator(args)
1013
- */
1014
- allowCustomArguments) {
1003
+ /**
1004
+ * This function is invoked once, when the property is added to a new instance.
1005
+ * When this happens is not strictly determined due to differences in TS and Babel:
1006
+ * Typescript: Usually when constructing the new instance
1007
+ * Babel, sometimes Typescript: during the first get / set
1008
+ * Both: when calling `runLazyInitializers(instance)`
1009
+ */
1010
+ onInitialize, get, set, enumerable,
1011
+ /**
1012
+ * Can this decorator invoked with arguments? e.g. @decorator(args)
1013
+ */
1014
+ allowCustomArguments) {
1015
1015
  function classPropertyDecorator(target, key, descriptor, customArgs, argLen) {
1016
1016
  if (argLen === void 0) { argLen = 0; }
1017
1017
  invariant(allowCustomArguments || quacksLikeADecorator(arguments), "This function is a decorator, but it wasn't invoked like a decorator");
@@ -1173,6 +1173,138 @@ function defineBoundAction(target, propertyName, fn) {
1173
1173
  addHiddenProp(target, propertyName, res);
1174
1174
  }
1175
1175
 
1176
+ var toString = Object.prototype.toString;
1177
+ function deepEqual(a, b) {
1178
+ return eq(a, b);
1179
+ }
1180
+ // Copied from https://github.com/jashkenas/underscore/blob/5c237a7c682fb68fd5378203f0bf22dce1624854/underscore.js#L1186-L1289
1181
+ // Internal recursive comparison function for `isEqual`.
1182
+ function eq(a, b, aStack, bStack) {
1183
+ // Identical objects are equal. `0 === -0`, but they aren't identical.
1184
+ // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
1185
+ if (a === b)
1186
+ return a !== 0 || 1 / a === 1 / b;
1187
+ // `null` or `undefined` only equal to itself (strict comparison).
1188
+ if (a == null || b == null)
1189
+ return false;
1190
+ // `NaN`s are equivalent, but non-reflexive.
1191
+ if (a !== a)
1192
+ return b !== b;
1193
+ // Exhaust primitive checks
1194
+ var type = typeof a;
1195
+ if (type !== "function" && type !== "object" && typeof b != "object")
1196
+ return false;
1197
+ return deepEq(a, b, aStack, bStack);
1198
+ }
1199
+ // Internal recursive comparison function for `isEqual`.
1200
+ function deepEq(a, b, aStack, bStack) {
1201
+ // Unwrap any wrapped objects.
1202
+ a = unwrap(a);
1203
+ b = unwrap(b);
1204
+ // Compare `[[Class]]` names.
1205
+ var className = toString.call(a);
1206
+ if (className !== toString.call(b))
1207
+ return false;
1208
+ switch (className) {
1209
+ // Strings, numbers, regular expressions, dates, and booleans are compared by value.
1210
+ case "[object RegExp]":
1211
+ // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
1212
+ case "[object String]":
1213
+ // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
1214
+ // equivalent to `new String("5")`.
1215
+ return "" + a === "" + b;
1216
+ case "[object Number]":
1217
+ // `NaN`s are equivalent, but non-reflexive.
1218
+ // Object(NaN) is equivalent to NaN.
1219
+ if (+a !== +a)
1220
+ return +b !== +b;
1221
+ // An `egal` comparison is performed for other numeric values.
1222
+ return +a === 0 ? 1 / +a === 1 / b : +a === +b;
1223
+ case "[object Date]":
1224
+ case "[object Boolean]":
1225
+ // Coerce dates and booleans to numeric primitive values. Dates are compared by their
1226
+ // millisecond representations. Note that invalid dates with millisecond representations
1227
+ // of `NaN` are not equivalent.
1228
+ return +a === +b;
1229
+ case "[object Symbol]":
1230
+ return (typeof Symbol !== "undefined" && Symbol.valueOf.call(a) === Symbol.valueOf.call(b));
1231
+ }
1232
+ var areArrays = className === "[object Array]";
1233
+ if (!areArrays) {
1234
+ if (typeof a != "object" || typeof b != "object")
1235
+ return false;
1236
+ // Objects with different constructors are not equivalent, but `Object`s or `Array`s
1237
+ // from different frames are.
1238
+ var aCtor = a.constructor, bCtor = b.constructor;
1239
+ if (aCtor !== bCtor &&
1240
+ !(typeof aCtor === "function" &&
1241
+ aCtor instanceof aCtor &&
1242
+ typeof bCtor === "function" &&
1243
+ bCtor instanceof bCtor) &&
1244
+ ("constructor" in a && "constructor" in b)) {
1245
+ return false;
1246
+ }
1247
+ }
1248
+ // Assume equality for cyclic structures. The algorithm for detecting cyclic
1249
+ // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
1250
+ // Initializing stack of traversed objects.
1251
+ // It's done here since we only need them for objects and arrays comparison.
1252
+ aStack = aStack || [];
1253
+ bStack = bStack || [];
1254
+ var length = aStack.length;
1255
+ while (length--) {
1256
+ // Linear search. Performance is inversely proportional to the number of
1257
+ // unique nested structures.
1258
+ if (aStack[length] === a)
1259
+ return bStack[length] === b;
1260
+ }
1261
+ // Add the first object to the stack of traversed objects.
1262
+ aStack.push(a);
1263
+ bStack.push(b);
1264
+ // Recursively compare objects and arrays.
1265
+ if (areArrays) {
1266
+ // Compare array lengths to determine if a deep comparison is necessary.
1267
+ length = a.length;
1268
+ if (length !== b.length)
1269
+ return false;
1270
+ // Deep compare the contents, ignoring non-numeric properties.
1271
+ while (length--) {
1272
+ if (!eq(a[length], b[length], aStack, bStack))
1273
+ return false;
1274
+ }
1275
+ }
1276
+ else {
1277
+ // Deep compare objects.
1278
+ var keys = Object.keys(a), key;
1279
+ length = keys.length;
1280
+ // Ensure that both objects contain the same number of properties before comparing deep equality.
1281
+ if (Object.keys(b).length !== length)
1282
+ return false;
1283
+ while (length--) {
1284
+ // Deep compare each member
1285
+ key = keys[length];
1286
+ if (!(has(b, key) && eq(a[key], b[key], aStack, bStack)))
1287
+ return false;
1288
+ }
1289
+ }
1290
+ // Remove the first object from the stack of traversed objects.
1291
+ aStack.pop();
1292
+ bStack.pop();
1293
+ return true;
1294
+ }
1295
+ function unwrap(a) {
1296
+ if (isObservableArray(a))
1297
+ return a.peek();
1298
+ if (isObservableMap(a))
1299
+ return a.entries();
1300
+ if (isES6Map(a))
1301
+ return iteratorToArray(a.entries());
1302
+ return a;
1303
+ }
1304
+ function has(a, key) {
1305
+ return Object.prototype.hasOwnProperty.call(a, key);
1306
+ }
1307
+
1176
1308
  function identityComparer(a, b) {
1177
1309
  return a === b;
1178
1310
  }
@@ -1354,7 +1486,7 @@ function reaction(expression, effect, arg3) {
1354
1486
  *
1355
1487
  * If at any point it's outside batch and it isn't observed: reset everything and go to 1.
1356
1488
  */
1357
- var ComputedValue = (function () {
1489
+ var ComputedValue = /** @class */ (function () {
1358
1490
  /**
1359
1491
  * Create a new computed value based on a function expression.
1360
1492
  *
@@ -1386,6 +1518,7 @@ var ComputedValue = (function () {
1386
1518
  this.value = new CaughtException(null);
1387
1519
  this.isComputing = false; // to check for cycles
1388
1520
  this.isRunningSetter = false;
1521
+ this.isTracing = TraceMode.NONE;
1389
1522
  this.name = name || "ComputedValue@" + getNextId();
1390
1523
  if (setter)
1391
1524
  this.setter = createAction(name + "-setter", setter);
@@ -1408,8 +1541,13 @@ var ComputedValue = (function () {
1408
1541
  // The computedValue is accessed outside of any mobx stuff. Batch observing should be enough and don't need
1409
1542
  // tracking as it will never be called again inside this batch.
1410
1543
  startBatch();
1411
- if (shouldCompute(this))
1544
+ if (shouldCompute(this)) {
1545
+ if (this.isTracing !== TraceMode.NONE) {
1546
+ console.log("[mobx.trace] '" + this
1547
+ .name + "' is being read outside a reactive context and doing a full recompute");
1548
+ }
1412
1549
  this.value = this.computeValue(false);
1550
+ }
1413
1551
  endBatch();
1414
1552
  }
1415
1553
  else {
@@ -1454,7 +1592,8 @@ var ComputedValue = (function () {
1454
1592
  });
1455
1593
  }
1456
1594
  var oldValue = this.value;
1457
- var wasSuspended = this.dependenciesState === exports.IDerivationState.NOT_TRACKING;
1595
+ var wasSuspended =
1596
+ /* see #1208 */ this.dependenciesState === exports.IDerivationState.NOT_TRACKING;
1458
1597
  var newValue = (this.value = this.computeValue(true));
1459
1598
  return (wasSuspended ||
1460
1599
  isCaughtException(oldValue) ||
@@ -1529,7 +1668,7 @@ var ComputedValue = (function () {
1529
1668
  ComputedValue.prototype[primitiveSymbol()] = ComputedValue.prototype.valueOf;
1530
1669
  var isComputedValue = createInstanceofPredicate("ComputedValue", ComputedValue);
1531
1670
 
1532
- var ObservableObjectAdministration = (function () {
1671
+ var ObservableObjectAdministration = /** @class */ (function () {
1533
1672
  function ObservableObjectAdministration(target, name) {
1534
1673
  this.target = target;
1535
1674
  this.name = name;
@@ -2029,7 +2168,7 @@ function transaction(action, thisArg) {
2029
2168
  }
2030
2169
 
2031
2170
  var ObservableMapMarker = {};
2032
- var ObservableMap = (function () {
2171
+ var ObservableMap = /** @class */ (function () {
2033
2172
  function ObservableMap(initialData, enhancer, name) {
2034
2173
  if (enhancer === void 0) { enhancer = deepEnhancer; }
2035
2174
  if (name === void 0) { name = "ObservableMap@" + getNextId(); }
@@ -2422,71 +2561,6 @@ function isPropertyConfigurable(object, prop) {
2422
2561
  function assertPropertyConfigurable(object, prop) {
2423
2562
  invariant(isPropertyConfigurable(object, prop), "Cannot make property '" + prop + "' observable, it is not configurable and writable in the target object");
2424
2563
  }
2425
- function getEnumerableKeys(obj) {
2426
- var res = [];
2427
- for (var key in obj)
2428
- res.push(key);
2429
- return res;
2430
- }
2431
- /**
2432
- * Naive deepEqual. Doesn't check for prototype, non-enumerable or out-of-range properties on arrays.
2433
- * If you have such a case, you probably should use this function but something fancier :).
2434
- */
2435
- function deepEqual(a, b) {
2436
- if (a === null && b === null)
2437
- return true;
2438
- if (a === undefined && b === undefined)
2439
- return true;
2440
- if (areBothNaN(a, b))
2441
- return true;
2442
- if (typeof a !== "object")
2443
- return a === b;
2444
- var aIsArray = isArrayLike(a);
2445
- var aIsMap = isMapLike(a);
2446
- if (aIsArray !== isArrayLike(b)) {
2447
- return false;
2448
- }
2449
- else if (aIsMap !== isMapLike(b)) {
2450
- return false;
2451
- }
2452
- else if (aIsArray) {
2453
- if (a.length !== b.length)
2454
- return false;
2455
- for (var i = a.length - 1; i >= 0; i--)
2456
- if (!deepEqual(a[i], b[i]))
2457
- return false;
2458
- return true;
2459
- }
2460
- else if (aIsMap) {
2461
- if (a.size !== b.size)
2462
- return false;
2463
- var equals_1 = true;
2464
- a.forEach(function (value, key) {
2465
- equals_1 = equals_1 && deepEqual(b.get(key), value);
2466
- });
2467
- return equals_1;
2468
- }
2469
- else if (typeof a === "object" && typeof b === "object") {
2470
- if (a === null || b === null)
2471
- return false;
2472
- if (isMapLike(a) && isMapLike(b)) {
2473
- if (a.size !== b.size)
2474
- return false;
2475
- // Freaking inefficient.... Create PR if you run into this :) Much appreciated!
2476
- return deepEqual(observable.shallowMap(a).entries(), observable.shallowMap(b).entries());
2477
- }
2478
- if (getEnumerableKeys(a).length !== getEnumerableKeys(b).length)
2479
- return false;
2480
- for (var prop in a) {
2481
- if (!(prop in b))
2482
- return false;
2483
- if (!deepEqual(a[prop], b[prop]))
2484
- return false;
2485
- }
2486
- return true;
2487
- }
2488
- return false;
2489
- }
2490
2564
  function createInstanceofPredicate(name, clazz) {
2491
2565
  var propName = "isMobX" + name;
2492
2566
  clazz.prototype[propName] = true;
@@ -2495,7 +2569,7 @@ function createInstanceofPredicate(name, clazz) {
2495
2569
  };
2496
2570
  }
2497
2571
  function areBothNaN(a, b) {
2498
- return (typeof a === "number" && typeof b === "number" && isNaN(a) && isNaN(b));
2572
+ return typeof a === "number" && typeof b === "number" && isNaN(a) && isNaN(b);
2499
2573
  }
2500
2574
  /**
2501
2575
  * Returns whether the argument is an array, disregarding observability.
@@ -2503,28 +2577,34 @@ function areBothNaN(a, b) {
2503
2577
  function isArrayLike(x) {
2504
2578
  return Array.isArray(x) || isObservableArray(x);
2505
2579
  }
2506
- function isMapLike(x) {
2507
- return isES6Map(x) || isObservableMap(x);
2508
- }
2509
2580
  function isES6Map(thing) {
2510
2581
  if (getGlobal().Map !== undefined && thing instanceof getGlobal().Map)
2511
2582
  return true;
2512
2583
  return false;
2513
2584
  }
2514
2585
  function getMapLikeKeys(map$$1) {
2515
- var keys;
2516
2586
  if (isPlainObject(map$$1))
2517
- keys = Object.keys(map$$1);
2518
- else if (Array.isArray(map$$1))
2519
- keys = map$$1.map(function (_a) {
2587
+ return Object.keys(map$$1);
2588
+ if (Array.isArray(map$$1))
2589
+ return map$$1.map(function (_a) {
2520
2590
  var key = _a[0];
2521
2591
  return key;
2522
2592
  });
2523
- else if (isMapLike(map$$1))
2524
- keys = Array.from(map$$1.keys());
2525
- else
2526
- fail("Cannot get keys from " + map$$1);
2527
- return keys;
2593
+ if (isES6Map(map$$1))
2594
+ return Array.from(map$$1.keys());
2595
+ if (isObservableMap(map$$1))
2596
+ return map$$1.keys();
2597
+ return fail("Cannot get keys from " + map$$1);
2598
+ }
2599
+ function iteratorToArray(it) {
2600
+ var res = [];
2601
+ while (true) {
2602
+ var r = it.next();
2603
+ if (r.done)
2604
+ break;
2605
+ res.push(r.value);
2606
+ }
2607
+ return res;
2528
2608
  }
2529
2609
  function primitiveSymbol() {
2530
2610
  return (typeof Symbol === "function" && Symbol.toPrimitive) || "@@toPrimitive";
@@ -2537,7 +2617,7 @@ function toPrimitive(value) {
2537
2617
  * These values will persist if global state is reset
2538
2618
  */
2539
2619
  var persistentKeys = ["mobxGuid", "resetId", "spyListeners", "strictMode", "runId"];
2540
- var MobXGlobals = (function () {
2620
+ var MobXGlobals = /** @class */ (function () {
2541
2621
  function MobXGlobals() {
2542
2622
  /**
2543
2623
  * MobXGlobals version.
@@ -2621,7 +2701,7 @@ var warnedAboutMultipleInstances = false;
2621
2701
  warnedAboutMultipleInstances = true;
2622
2702
  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.");
2623
2703
  }
2624
- });
2704
+ }, 1);
2625
2705
  }
2626
2706
  }
2627
2707
  function isolateGlobalState() {
@@ -2663,6 +2743,91 @@ function resetGlobalState() {
2663
2743
  globalState.allowStateChanges = !globalState.strictMode;
2664
2744
  }
2665
2745
 
2746
+ function getAtom(thing, property) {
2747
+ if (typeof thing === "object" && thing !== null) {
2748
+ if (isObservableArray(thing)) {
2749
+ invariant(property === undefined, getMessage("m036"));
2750
+ return thing.$mobx.atom;
2751
+ }
2752
+ if (isObservableMap(thing)) {
2753
+ var anyThing = thing;
2754
+ if (property === undefined)
2755
+ return getAtom(anyThing._keys);
2756
+ var observable = anyThing._data[property] || anyThing._hasMap[property];
2757
+ invariant(!!observable, "the entry '" + property + "' does not exist in the observable map '" + getDebugName(thing) + "'");
2758
+ return observable;
2759
+ }
2760
+ // Initializers run lazily when transpiling to babel, so make sure they are run...
2761
+ runLazyInitializers(thing);
2762
+ if (property && !thing.$mobx)
2763
+ thing[property]; // See #1072 // TODO: remove in 4.0
2764
+ if (isObservableObject(thing)) {
2765
+ if (!property)
2766
+ return fail("please specify a property");
2767
+ var observable = thing.$mobx.values[property];
2768
+ invariant(!!observable, "no observable property '" + property + "' found on the observable object '" + getDebugName(thing) + "'");
2769
+ return observable;
2770
+ }
2771
+ if (isAtom(thing) || isComputedValue(thing) || isReaction(thing)) {
2772
+ return thing;
2773
+ }
2774
+ }
2775
+ else if (typeof thing === "function") {
2776
+ if (isReaction(thing.$mobx)) {
2777
+ // disposer function
2778
+ return thing.$mobx;
2779
+ }
2780
+ }
2781
+ return fail("Cannot obtain atom from " + thing);
2782
+ }
2783
+ function getAdministration(thing, property) {
2784
+ invariant(thing, "Expecting some object");
2785
+ if (property !== undefined)
2786
+ return getAdministration(getAtom(thing, property));
2787
+ if (isAtom(thing) || isComputedValue(thing) || isReaction(thing))
2788
+ return thing;
2789
+ if (isObservableMap(thing))
2790
+ return thing;
2791
+ // Initializers run lazily when transpiling to babel, so make sure they are run...
2792
+ runLazyInitializers(thing);
2793
+ if (thing.$mobx)
2794
+ return thing.$mobx;
2795
+ invariant(false, "Cannot obtain administration from " + thing);
2796
+ }
2797
+ function getDebugName(thing, property) {
2798
+ var named;
2799
+ if (property !== undefined)
2800
+ named = getAtom(thing, property);
2801
+ else if (isObservableObject(thing) || isObservableMap(thing))
2802
+ named = getAdministration(thing);
2803
+ else
2804
+ named = getAtom(thing); // valid for arrays as well
2805
+ return named.name;
2806
+ }
2807
+
2808
+ function getDependencyTree(thing, property) {
2809
+ return nodeToDependencyTree(getAtom(thing, property));
2810
+ }
2811
+ function nodeToDependencyTree(node) {
2812
+ var result = {
2813
+ name: node.name
2814
+ };
2815
+ if (node.observing && node.observing.length > 0)
2816
+ result.dependencies = unique(node.observing).map(nodeToDependencyTree);
2817
+ return result;
2818
+ }
2819
+ function getObserverTree(thing, property) {
2820
+ return nodeToObserverTree(getAtom(thing, property));
2821
+ }
2822
+ function nodeToObserverTree(node) {
2823
+ var result = {
2824
+ name: node.name
2825
+ };
2826
+ if (hasObservers(node))
2827
+ result.observers = getObservers(node).map(nodeToObserverTree);
2828
+ return result;
2829
+ }
2830
+
2666
2831
  function hasObservers(observable) {
2667
2832
  return observable.observers && observable.observers.length > 0;
2668
2833
  }
@@ -2781,8 +2946,12 @@ function propagateChanged(observable) {
2781
2946
  var i = observers.length;
2782
2947
  while (i--) {
2783
2948
  var d = observers[i];
2784
- if (d.dependenciesState === exports.IDerivationState.UP_TO_DATE)
2949
+ if (d.dependenciesState === exports.IDerivationState.UP_TO_DATE) {
2950
+ if (d.isTracing !== TraceMode.NONE) {
2951
+ logTraceInfo(d, observable);
2952
+ }
2785
2953
  d.onBecomeStale();
2954
+ }
2786
2955
  d.dependenciesState = exports.IDerivationState.STALE;
2787
2956
  }
2788
2957
  // invariantLOS(observable, "changed end");
@@ -2817,11 +2986,32 @@ function propagateMaybeChanged(observable) {
2817
2986
  var d = observers[i];
2818
2987
  if (d.dependenciesState === exports.IDerivationState.UP_TO_DATE) {
2819
2988
  d.dependenciesState = exports.IDerivationState.POSSIBLY_STALE;
2989
+ if (d.isTracing !== TraceMode.NONE) {
2990
+ logTraceInfo(d, observable);
2991
+ }
2820
2992
  d.onBecomeStale();
2821
2993
  }
2822
2994
  }
2823
2995
  // invariantLOS(observable, "maybe end");
2824
2996
  }
2997
+ function logTraceInfo(derivation, observable) {
2998
+ console.log("[mobx.trace] '" + derivation.name + "' is invalidated due to a change in: '" + observable.name + "'");
2999
+ if (derivation.isTracing === TraceMode.BREAK) {
3000
+ var lines = [];
3001
+ printDepTree(getDependencyTree(derivation), lines, 1);
3002
+ // prettier-ignore
3003
+ 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 ")();
3004
+ }
3005
+ }
3006
+ function printDepTree(tree, lines, depth) {
3007
+ if (lines.length >= 1000) {
3008
+ lines.push("(and many more)");
3009
+ return;
3010
+ }
3011
+ lines.push("" + new Array(depth).join("\t") + tree.name); // MWE: not the fastest, but the easiest way :)
3012
+ if (tree.dependencies)
3013
+ tree.dependencies.forEach(function (child) { return printDepTree(child, lines, depth + 1); });
3014
+ }
2825
3015
 
2826
3016
  (function (IDerivationState) {
2827
3017
  // before being run or (outside batch and not being observed)
@@ -2842,7 +3032,13 @@ function propagateMaybeChanged(observable) {
2842
3032
  // will need to recompute when it's needed next.
2843
3033
  IDerivationState[IDerivationState["STALE"] = 2] = "STALE";
2844
3034
  })(exports.IDerivationState || (exports.IDerivationState = {}));
2845
- var CaughtException = (function () {
3035
+ var TraceMode;
3036
+ (function (TraceMode) {
3037
+ TraceMode[TraceMode["NONE"] = 0] = "NONE";
3038
+ TraceMode[TraceMode["LOG"] = 1] = "LOG";
3039
+ TraceMode[TraceMode["BREAK"] = 2] = "BREAK";
3040
+ })(TraceMode || (TraceMode = {}));
3041
+ var CaughtException = /** @class */ (function () {
2846
3042
  function CaughtException(cause) {
2847
3043
  this.cause = cause;
2848
3044
  // Empty
@@ -3030,7 +3226,48 @@ function changeDependenciesStateTo0(derivation) {
3030
3226
  obs[i].lowestObserverState = exports.IDerivationState.UP_TO_DATE;
3031
3227
  }
3032
3228
 
3033
- var Reaction = (function () {
3229
+ function log(msg) {
3230
+ console.log(msg);
3231
+ return msg;
3232
+ }
3233
+ function whyRun(thing, prop) {
3234
+ deprecated("`whyRun` is deprecated in favor of `trace`");
3235
+ thing = getAtomFromArgs(arguments);
3236
+ if (!thing)
3237
+ return log(getMessage("m024"));
3238
+ if (isComputedValue(thing) || isReaction(thing))
3239
+ return log(thing.whyRun());
3240
+ return fail(getMessage("m025"));
3241
+ }
3242
+ function trace() {
3243
+ var args = [];
3244
+ for (var _i = 0; _i < arguments.length; _i++) {
3245
+ args[_i] = arguments[_i];
3246
+ }
3247
+ var enterBreakPoint = false;
3248
+ if (typeof args[args.length - 1] === "boolean")
3249
+ enterBreakPoint = args.pop();
3250
+ var derivation = getAtomFromArgs(args);
3251
+ if (!derivation) {
3252
+ 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");
3253
+ }
3254
+ if (derivation.isTracing === TraceMode.NONE) {
3255
+ console.log("[mobx.trace] '" + derivation.name + "' tracing enabled");
3256
+ }
3257
+ derivation.isTracing = enterBreakPoint ? TraceMode.BREAK : TraceMode.LOG;
3258
+ }
3259
+ function getAtomFromArgs(args) {
3260
+ switch (args.length) {
3261
+ case 0:
3262
+ return globalState.trackingDerivation;
3263
+ case 1:
3264
+ return getAtom(args[0]);
3265
+ case 2:
3266
+ return getAtom(args[0], args[1]);
3267
+ }
3268
+ }
3269
+
3270
+ var Reaction = /** @class */ (function () {
3034
3271
  function Reaction(name, onInvalidate) {
3035
3272
  if (name === void 0) { name = "Reaction@" + getNextId(); }
3036
3273
  this.name = name;
@@ -3046,6 +3283,7 @@ var Reaction = (function () {
3046
3283
  this._isScheduled = false;
3047
3284
  this._isTrackPending = false;
3048
3285
  this._isRunning = false;
3286
+ this.isTracing = TraceMode.NONE;
3049
3287
  }
3050
3288
  Reaction.prototype.onBecomeStale = function () {
3051
3289
  this.schedule();
@@ -3158,6 +3396,10 @@ var Reaction = (function () {
3158
3396
  ? " (... or any observable accessed during the remainder of the current run)"
3159
3397
  : "") + "\n\t" + getMessage("m038") + "\n";
3160
3398
  };
3399
+ Reaction.prototype.trace = function (enterBreakPoint) {
3400
+ if (enterBreakPoint === void 0) { enterBreakPoint = false; }
3401
+ trace(this, enterBreakPoint);
3402
+ };
3161
3403
  return Reaction;
3162
3404
  }());
3163
3405
  function registerErrorHandler(handler) {
@@ -3266,68 +3508,6 @@ var computed = function computed(arg1, arg2, arg3) {
3266
3508
  computed.struct = computedStructDecorator;
3267
3509
  computed.equals = createComputedDecorator;
3268
3510
 
3269
- function getAtom(thing, property) {
3270
- if (typeof thing === "object" && thing !== null) {
3271
- if (isObservableArray(thing)) {
3272
- invariant(property === undefined, getMessage("m036"));
3273
- return thing.$mobx.atom;
3274
- }
3275
- if (isObservableMap(thing)) {
3276
- var anyThing = thing;
3277
- if (property === undefined)
3278
- return getAtom(anyThing._keys);
3279
- var observable = anyThing._data[property] || anyThing._hasMap[property];
3280
- invariant(!!observable, "the entry '" + property + "' does not exist in the observable map '" + getDebugName(thing) + "'");
3281
- return observable;
3282
- }
3283
- // Initializers run lazily when transpiling to babel, so make sure they are run...
3284
- runLazyInitializers(thing);
3285
- if (property && !thing.$mobx)
3286
- thing[property]; // See #1072 // TODO: remove in 4.0
3287
- if (isObservableObject(thing)) {
3288
- if (!property)
3289
- return fail("please specify a property");
3290
- var observable = thing.$mobx.values[property];
3291
- invariant(!!observable, "no observable property '" + property + "' found on the observable object '" + getDebugName(thing) + "'");
3292
- return observable;
3293
- }
3294
- if (isAtom(thing) || isComputedValue(thing) || isReaction(thing)) {
3295
- return thing;
3296
- }
3297
- }
3298
- else if (typeof thing === "function") {
3299
- if (isReaction(thing.$mobx)) {
3300
- // disposer function
3301
- return thing.$mobx;
3302
- }
3303
- }
3304
- return fail("Cannot obtain atom from " + thing);
3305
- }
3306
- function getAdministration(thing, property) {
3307
- invariant(thing, "Expecting some object");
3308
- if (property !== undefined)
3309
- return getAdministration(getAtom(thing, property));
3310
- if (isAtom(thing) || isComputedValue(thing) || isReaction(thing))
3311
- return thing;
3312
- if (isObservableMap(thing))
3313
- return thing;
3314
- // Initializers run lazily when transpiling to babel, so make sure they are run...
3315
- runLazyInitializers(thing);
3316
- if (thing.$mobx)
3317
- return thing.$mobx;
3318
- invariant(false, "Cannot obtain administration from " + thing);
3319
- }
3320
- function getDebugName(thing, property) {
3321
- var named;
3322
- if (property !== undefined)
3323
- named = getAtom(thing, property);
3324
- else if (isObservableObject(thing) || isObservableMap(thing))
3325
- named = getAdministration(thing);
3326
- else
3327
- named = getAtom(thing); // valid for arrays as well
3328
- return named.name;
3329
- }
3330
-
3331
3511
  function isComputed(value, property) {
3332
3512
  if (value === null || value === undefined)
3333
3513
  return false;
@@ -3440,7 +3620,7 @@ function createTransformer(transformer, onCleanup) {
3440
3620
  // This construction is used to avoid leaking refs to the objectCache directly
3441
3621
  var resetId = globalState.resetId;
3442
3622
  // Local transformer class specifically for this transformer
3443
- var Transformer = (function (_super) {
3623
+ var Transformer = /** @class */ (function (_super) {
3444
3624
  __extends(Transformer, _super);
3445
3625
  function Transformer(sourceIdentifier, sourceObject) {
3446
3626
  var _this = _super.call(this, function () { return transformer(sourceObject); }, undefined, comparer.default, "Transformer-" + transformer.name + "-" + sourceIdentifier, undefined) || this;
@@ -3484,52 +3664,6 @@ function getMemoizationId(object) {
3484
3664
  return tid;
3485
3665
  }
3486
3666
 
3487
- function log(msg) {
3488
- console.log(msg);
3489
- return msg;
3490
- }
3491
- function whyRun(thing, prop) {
3492
- switch (arguments.length) {
3493
- case 0:
3494
- thing = globalState.trackingDerivation;
3495
- if (!thing)
3496
- return log(getMessage("m024"));
3497
- break;
3498
- case 2:
3499
- thing = getAtom(thing, prop);
3500
- break;
3501
- }
3502
- thing = getAtom(thing);
3503
- if (isComputedValue(thing))
3504
- return log(thing.whyRun());
3505
- else if (isReaction(thing))
3506
- return log(thing.whyRun());
3507
- return fail(getMessage("m025"));
3508
- }
3509
-
3510
- function getDependencyTree(thing, property) {
3511
- return nodeToDependencyTree(getAtom(thing, property));
3512
- }
3513
- function nodeToDependencyTree(node) {
3514
- var result = {
3515
- name: node.name
3516
- };
3517
- if (node.observing && node.observing.length > 0)
3518
- result.dependencies = unique(node.observing).map(nodeToDependencyTree);
3519
- return result;
3520
- }
3521
- function getObserverTree(thing, property) {
3522
- return nodeToObserverTree(getAtom(thing, property));
3523
- }
3524
- function nodeToObserverTree(node) {
3525
- var result = {
3526
- name: node.name
3527
- };
3528
- if (hasObservers(node))
3529
- result.observers = getObservers(node).map(nodeToObserverTree);
3530
- return result;
3531
- }
3532
-
3533
3667
  function interceptReads(thing, propOrHandler, handler) {
3534
3668
  var target;
3535
3669
  if (isObservableMap(thing) || isObservableArray(thing) || isObservableValue(thing)) {
@@ -3696,6 +3830,7 @@ exports.expr = expr;
3696
3830
  exports.toJS = toJS;
3697
3831
  exports.createTransformer = createTransformer;
3698
3832
  exports.whyRun = whyRun;
3833
+ exports.trace = trace;
3699
3834
  exports.isArrayLike = isArrayLike;
3700
3835
 
3701
3836
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})