mobx 4.12.0 → 4.14.1

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.
@@ -67,8 +67,15 @@ var EMPTY_ARRAY = [];
67
67
  Object.freeze(EMPTY_ARRAY);
68
68
  var EMPTY_OBJECT = {};
69
69
  Object.freeze(EMPTY_OBJECT);
70
+ var mockGlobal = {};
70
71
  function getGlobal() {
71
- return typeof window !== "undefined" ? window : global;
72
+ if (typeof window !== "undefined") {
73
+ return window;
74
+ }
75
+ if (typeof global !== "undefined") {
76
+ return global;
77
+ }
78
+ return mockGlobal;
72
79
  }
73
80
  function getNextId() {
74
81
  return ++globalState.mobxGuid;
@@ -128,6 +135,20 @@ function isPlainObject(value) {
128
135
  var proto = Object.getPrototypeOf(value);
129
136
  return proto === Object.prototype || proto === null;
130
137
  }
138
+ function convertToMap(dataStructure) {
139
+ if (isES6Map(dataStructure) || isObservableMap(dataStructure)) {
140
+ return dataStructure;
141
+ }
142
+ else if (Array.isArray(dataStructure)) {
143
+ return new Map(dataStructure);
144
+ }
145
+ else if (isPlainObject(dataStructure)) {
146
+ return new Map(Object.entries(dataStructure));
147
+ }
148
+ else {
149
+ return fail("Cannot convert to map from '" + dataStructure + "'");
150
+ }
151
+ }
131
152
  function makeNonEnumerable(object, propNames) {
132
153
  for (var i = 0; i < propNames.length; i++) {
133
154
  addHiddenProp(object, propNames[i], object[propNames[i]]);
@@ -181,18 +202,6 @@ function isES6Map(thing) {
181
202
  function isES6Set(thing) {
182
203
  return thing instanceof Set;
183
204
  }
184
- function getMapLikeKeys(map) {
185
- if (isPlainObject(map))
186
- return Object.keys(map);
187
- if (Array.isArray(map))
188
- return map.map(function (_a) {
189
- var _b = __read(_a, 1), key = _b[0];
190
- return key;
191
- });
192
- if (isES6Map(map) || isObservableMap(map))
193
- return iteratorToArray(map.keys());
194
- return fail("Cannot get keys from '" + map + "'");
195
- }
196
205
  // use Array.from in Mobx 5
197
206
  function iteratorToArray(it) {
198
207
  var res = [];
@@ -219,13 +228,13 @@ function declareIterator(prototType, iteratorFactory) {
219
228
  addHiddenFinalProp(prototType, iteratorSymbol(), iteratorFactory);
220
229
  }
221
230
  function makeIterable(iterator) {
222
- iterator[iteratorSymbol()] = self;
231
+ iterator[iteratorSymbol()] = getSelf;
223
232
  return iterator;
224
233
  }
225
234
  function toStringTagSymbol() {
226
235
  return (typeof Symbol === "function" && Symbol.toStringTag) || "@@toStringTag";
227
236
  }
228
- function self() {
237
+ function getSelf() {
229
238
  return this;
230
239
  }
231
240
 
@@ -293,13 +302,17 @@ function identityComparer(a, b) {
293
302
  function structuralComparer(a, b) {
294
303
  return deepEqual(a, b);
295
304
  }
305
+ function shallowComparer(a, b) {
306
+ return deepEqual(a, b, 1);
307
+ }
296
308
  function defaultComparer(a, b) {
297
309
  return areBothNaN(a, b) || identityComparer(a, b);
298
310
  }
299
311
  var comparer = {
300
312
  identity: identityComparer,
301
313
  structural: structuralComparer,
302
- default: defaultComparer
314
+ default: defaultComparer,
315
+ shallow: shallowComparer
303
316
  };
304
317
 
305
318
  var enumerableDescriptorCache = {};
@@ -619,6 +632,276 @@ var computed = function computed(arg1, arg2, arg3) {
619
632
  };
620
633
  computed.struct = computedStructDecorator;
621
634
 
635
+ var IDerivationState;
636
+ (function (IDerivationState) {
637
+ // before being run or (outside batch and not being observed)
638
+ // at this point derivation is not holding any data about dependency tree
639
+ IDerivationState[IDerivationState["NOT_TRACKING"] = -1] = "NOT_TRACKING";
640
+ // no shallow dependency changed since last computation
641
+ // won't recalculate derivation
642
+ // this is what makes mobx fast
643
+ IDerivationState[IDerivationState["UP_TO_DATE"] = 0] = "UP_TO_DATE";
644
+ // some deep dependency changed, but don't know if shallow dependency changed
645
+ // will require to check first if UP_TO_DATE or POSSIBLY_STALE
646
+ // currently only ComputedValue will propagate POSSIBLY_STALE
647
+ //
648
+ // having this state is second big optimization:
649
+ // don't have to recompute on every dependency change, but only when it's needed
650
+ IDerivationState[IDerivationState["POSSIBLY_STALE"] = 1] = "POSSIBLY_STALE";
651
+ // A shallow dependency has changed since last computation and the derivation
652
+ // will need to recompute when it's needed next.
653
+ IDerivationState[IDerivationState["STALE"] = 2] = "STALE";
654
+ })(IDerivationState || (IDerivationState = {}));
655
+ var TraceMode;
656
+ (function (TraceMode) {
657
+ TraceMode[TraceMode["NONE"] = 0] = "NONE";
658
+ TraceMode[TraceMode["LOG"] = 1] = "LOG";
659
+ TraceMode[TraceMode["BREAK"] = 2] = "BREAK";
660
+ })(TraceMode || (TraceMode = {}));
661
+ var CaughtException = /** @class */ (function () {
662
+ function CaughtException(cause) {
663
+ this.cause = cause;
664
+ // Empty
665
+ }
666
+ return CaughtException;
667
+ }());
668
+ function isCaughtException(e) {
669
+ return e instanceof CaughtException;
670
+ }
671
+ /**
672
+ * Finds out whether any dependency of the derivation has actually changed.
673
+ * If dependenciesState is 1 then it will recalculate dependencies,
674
+ * if any dependency changed it will propagate it by changing dependenciesState to 2.
675
+ *
676
+ * By iterating over the dependencies in the same order that they were reported and
677
+ * stopping on the first change, all the recalculations are only called for ComputedValues
678
+ * that will be tracked by derivation. That is because we assume that if the first x
679
+ * dependencies of the derivation doesn't change then the derivation should run the same way
680
+ * up until accessing x-th dependency.
681
+ */
682
+ function shouldCompute(derivation) {
683
+ switch (derivation.dependenciesState) {
684
+ case IDerivationState.UP_TO_DATE:
685
+ return false;
686
+ case IDerivationState.NOT_TRACKING:
687
+ case IDerivationState.STALE:
688
+ return true;
689
+ case IDerivationState.POSSIBLY_STALE: {
690
+ var prevUntracked = untrackedStart(); // no need for those computeds to be reported, they will be picked up in trackDerivedFunction.
691
+ var obs = derivation.observing, l = obs.length;
692
+ for (var i = 0; i < l; i++) {
693
+ var obj = obs[i];
694
+ if (isComputedValue(obj)) {
695
+ if (globalState.disableErrorBoundaries) {
696
+ obj.get();
697
+ }
698
+ else {
699
+ try {
700
+ obj.get();
701
+ }
702
+ catch (e) {
703
+ // we are not interested in the value *or* exception at this moment, but if there is one, notify all
704
+ untrackedEnd(prevUntracked);
705
+ return true;
706
+ }
707
+ }
708
+ // if ComputedValue `obj` actually changed it will be computed and propagated to its observers.
709
+ // and `derivation` is an observer of `obj`
710
+ // invariantShouldCompute(derivation)
711
+ if (derivation.dependenciesState === IDerivationState.STALE) {
712
+ untrackedEnd(prevUntracked);
713
+ return true;
714
+ }
715
+ }
716
+ }
717
+ changeDependenciesStateTo0(derivation);
718
+ untrackedEnd(prevUntracked);
719
+ return false;
720
+ }
721
+ }
722
+ }
723
+ // function invariantShouldCompute(derivation: IDerivation) {
724
+ // const newDepState = (derivation as any).dependenciesState
725
+ // if (
726
+ // process.env.NODE_ENV === "production" &&
727
+ // (newDepState === IDerivationState.POSSIBLY_STALE ||
728
+ // newDepState === IDerivationState.NOT_TRACKING)
729
+ // )
730
+ // fail("Illegal dependency state")
731
+ // }
732
+ function isComputingDerivation() {
733
+ return globalState.trackingDerivation !== null; // filter out actions inside computations
734
+ }
735
+ function checkIfStateModificationsAreAllowed(atom) {
736
+ var hasObservers = atom.observers.length > 0;
737
+ // Should never be possible to change an observed observable from inside computed, see #798
738
+ if (globalState.computationDepth > 0 && hasObservers)
739
+ fail(process.env.NODE_ENV !== "production" &&
740
+ "Computed values are not allowed to cause side effects by changing observables that are already being observed. Tried to modify: " + atom.name);
741
+ // Should not be possible to change observed state outside strict mode, except during initialization, see #563
742
+ if (!globalState.allowStateChanges && (hasObservers || globalState.enforceActions === "strict"))
743
+ fail(process.env.NODE_ENV !== "production" &&
744
+ (globalState.enforceActions
745
+ ? "Since strict-mode is enabled, changing observed observable values outside actions is not allowed. Please wrap the code in an `action` if this change is intended. Tried to modify: "
746
+ : "Side effects like changing state are not allowed at this point. Are you trying to modify state from, for example, the render function of a React component? Tried to modify: ") +
747
+ atom.name);
748
+ }
749
+ function checkIfStateReadsAreAllowed(observable) {
750
+ if (process.env.NODE_ENV !== "production" &&
751
+ !globalState.allowStateReads &&
752
+ globalState.observableRequiresReaction) {
753
+ console.warn("[mobx] Observable " + observable.name + " being read outside a reactive context");
754
+ }
755
+ }
756
+ /**
757
+ * Executes the provided function `f` and tracks which observables are being accessed.
758
+ * The tracking information is stored on the `derivation` object and the derivation is registered
759
+ * as observer of any of the accessed observables.
760
+ */
761
+ function trackDerivedFunction(derivation, f, context) {
762
+ var prevAllowStateReads = allowStateReadsStart(true);
763
+ // pre allocate array allocation + room for variation in deps
764
+ // array will be trimmed by bindDependencies
765
+ changeDependenciesStateTo0(derivation);
766
+ derivation.newObserving = new Array(derivation.observing.length + 100);
767
+ derivation.unboundDepsCount = 0;
768
+ derivation.runId = ++globalState.runId;
769
+ var prevTracking = globalState.trackingDerivation;
770
+ globalState.trackingDerivation = derivation;
771
+ var result;
772
+ if (globalState.disableErrorBoundaries === true) {
773
+ result = f.call(context);
774
+ }
775
+ else {
776
+ try {
777
+ result = f.call(context);
778
+ }
779
+ catch (e) {
780
+ result = new CaughtException(e);
781
+ }
782
+ }
783
+ globalState.trackingDerivation = prevTracking;
784
+ bindDependencies(derivation);
785
+ if (derivation.observing.length === 0) {
786
+ warnAboutDerivationWithoutDependencies(derivation);
787
+ }
788
+ allowStateReadsEnd(prevAllowStateReads);
789
+ return result;
790
+ }
791
+ function warnAboutDerivationWithoutDependencies(derivation) {
792
+ if (process.env.NODE_ENV === "production")
793
+ return;
794
+ if (globalState.reactionRequiresObservable || derivation.requiresObservable) {
795
+ console.warn("[mobx] Derivation " + derivation.name + " is created/updated without reading any observable value");
796
+ }
797
+ }
798
+ /**
799
+ * diffs newObserving with observing.
800
+ * update observing to be newObserving with unique observables
801
+ * notify observers that become observed/unobserved
802
+ */
803
+ function bindDependencies(derivation) {
804
+ // invariant(derivation.dependenciesState !== IDerivationState.NOT_TRACKING, "INTERNAL ERROR bindDependencies expects derivation.dependenciesState !== -1");
805
+ var prevObserving = derivation.observing;
806
+ var observing = (derivation.observing = derivation.newObserving);
807
+ var lowestNewObservingDerivationState = IDerivationState.UP_TO_DATE;
808
+ // Go through all new observables and check diffValue: (this list can contain duplicates):
809
+ // 0: first occurrence, change to 1 and keep it
810
+ // 1: extra occurrence, drop it
811
+ var i0 = 0, l = derivation.unboundDepsCount;
812
+ for (var i = 0; i < l; i++) {
813
+ var dep = observing[i];
814
+ if (dep.diffValue === 0) {
815
+ dep.diffValue = 1;
816
+ if (i0 !== i)
817
+ observing[i0] = dep;
818
+ i0++;
819
+ }
820
+ // Upcast is 'safe' here, because if dep is IObservable, `dependenciesState` will be undefined,
821
+ // not hitting the condition
822
+ if (dep.dependenciesState > lowestNewObservingDerivationState) {
823
+ lowestNewObservingDerivationState = dep.dependenciesState;
824
+ }
825
+ }
826
+ observing.length = i0;
827
+ derivation.newObserving = null; // newObserving shouldn't be needed outside tracking (statement moved down to work around FF bug, see #614)
828
+ // Go through all old observables and check diffValue: (it is unique after last bindDependencies)
829
+ // 0: it's not in new observables, unobserve it
830
+ // 1: it keeps being observed, don't want to notify it. change to 0
831
+ l = prevObserving.length;
832
+ while (l--) {
833
+ var dep = prevObserving[l];
834
+ if (dep.diffValue === 0) {
835
+ removeObserver(dep, derivation);
836
+ }
837
+ dep.diffValue = 0;
838
+ }
839
+ // Go through all new observables and check diffValue: (now it should be unique)
840
+ // 0: it was set to 0 in last loop. don't need to do anything.
841
+ // 1: it wasn't observed, let's observe it. set back to 0
842
+ while (i0--) {
843
+ var dep = observing[i0];
844
+ if (dep.diffValue === 1) {
845
+ dep.diffValue = 0;
846
+ addObserver(dep, derivation);
847
+ }
848
+ }
849
+ // Some new observed derivations may become stale during this derivation computation
850
+ // so they have had no chance to propagate staleness (#916)
851
+ if (lowestNewObservingDerivationState !== IDerivationState.UP_TO_DATE) {
852
+ derivation.dependenciesState = lowestNewObservingDerivationState;
853
+ derivation.onBecomeStale();
854
+ }
855
+ }
856
+ function clearObserving(derivation) {
857
+ // invariant(globalState.inBatch > 0, "INTERNAL ERROR clearObserving should be called only inside batch");
858
+ var obs = derivation.observing;
859
+ derivation.observing = [];
860
+ var i = obs.length;
861
+ while (i--)
862
+ removeObserver(obs[i], derivation);
863
+ derivation.dependenciesState = IDerivationState.NOT_TRACKING;
864
+ }
865
+ function untracked(action) {
866
+ var prev = untrackedStart();
867
+ var res = action();
868
+ untrackedEnd(prev);
869
+ return res;
870
+ }
871
+ function untrackedStart() {
872
+ var prev = globalState.trackingDerivation;
873
+ globalState.trackingDerivation = null;
874
+ return prev;
875
+ }
876
+ function untrackedEnd(prev) {
877
+ globalState.trackingDerivation = prev;
878
+ }
879
+ function allowStateReadsStart(allowStateReads) {
880
+ var prev = globalState.allowStateReads;
881
+ globalState.allowStateReads = allowStateReads;
882
+ return prev;
883
+ }
884
+ function allowStateReadsEnd(prev) {
885
+ globalState.allowStateReads = prev;
886
+ }
887
+ /**
888
+ * needed to keep `lowestObserverState` correct. when changing from (2 or 1) to 0
889
+ *
890
+ */
891
+ function changeDependenciesStateTo0(derivation) {
892
+ if (derivation.dependenciesState === IDerivationState.UP_TO_DATE)
893
+ return;
894
+ derivation.dependenciesState = IDerivationState.UP_TO_DATE;
895
+ var obs = derivation.observing;
896
+ var i = obs.length;
897
+ while (i--)
898
+ obs[i].lowestObserverState = IDerivationState.UP_TO_DATE;
899
+ }
900
+
901
+ // we don't use globalState for these in order to avoid possible issues with multiple
902
+ // mobx versions
903
+ var currentActionId = 0;
904
+ var nextActionId = 1;
622
905
  function createAction(actionName, fn) {
623
906
  if (process.env.NODE_ENV !== "production") {
624
907
  invariant(typeof fn === "function", "`action` can only be invoked on functions");
@@ -632,25 +915,19 @@ function createAction(actionName, fn) {
632
915
  return res;
633
916
  }
634
917
  function executeAction(actionName, fn, scope, args) {
635
- var runInfo = startAction(actionName, fn, scope, args);
636
- var shouldSupressReactionError = true;
918
+ var runInfo = _startAction(actionName, scope, args);
637
919
  try {
638
- var res = fn.apply(scope, args);
639
- shouldSupressReactionError = false;
640
- return res;
920
+ return fn.apply(scope, args);
921
+ }
922
+ catch (err) {
923
+ runInfo.error = err;
924
+ throw err;
641
925
  }
642
926
  finally {
643
- if (shouldSupressReactionError) {
644
- globalState.suppressReactionErrors = shouldSupressReactionError;
645
- endAction(runInfo);
646
- globalState.suppressReactionErrors = false;
647
- }
648
- else {
649
- endAction(runInfo);
650
- }
927
+ _endAction(runInfo);
651
928
  }
652
929
  }
653
- function startAction(actionName, fn, scope, args) {
930
+ function _startAction(actionName, scope, args) {
654
931
  var notifySpy = isSpyEnabled() && !!actionName;
655
932
  var startTime = 0;
656
933
  if (notifySpy) {
@@ -670,19 +947,35 @@ function startAction(actionName, fn, scope, args) {
670
947
  var prevDerivation = untrackedStart();
671
948
  startBatch();
672
949
  var prevAllowStateChanges = allowStateChangesStart(true);
673
- return {
950
+ var prevAllowStateReads = allowStateReadsStart(true);
951
+ var runInfo = {
674
952
  prevDerivation: prevDerivation,
675
953
  prevAllowStateChanges: prevAllowStateChanges,
954
+ prevAllowStateReads: prevAllowStateReads,
676
955
  notifySpy: notifySpy,
677
- startTime: startTime
956
+ startTime: startTime,
957
+ actionId: nextActionId++,
958
+ parentActionId: currentActionId
678
959
  };
960
+ currentActionId = runInfo.actionId;
961
+ return runInfo;
679
962
  }
680
- function endAction(runInfo) {
963
+ function _endAction(runInfo) {
964
+ if (currentActionId !== runInfo.actionId) {
965
+ fail("invalid action stack. did you forget to finish an action?");
966
+ }
967
+ currentActionId = runInfo.parentActionId;
968
+ if (runInfo.error !== undefined) {
969
+ globalState.suppressReactionErrors = true;
970
+ }
681
971
  allowStateChangesEnd(runInfo.prevAllowStateChanges);
972
+ allowStateReadsEnd(runInfo.prevAllowStateReads);
682
973
  endBatch();
683
974
  untrackedEnd(runInfo.prevDerivation);
684
- if (runInfo.notifySpy)
975
+ if (runInfo.notifySpy) {
685
976
  spyReportEnd({ time: Date.now() - runInfo.startTime });
977
+ }
978
+ globalState.suppressReactionErrors = false;
686
979
  }
687
980
  function allowStateChanges(allowStateChanges, func) {
688
981
  var prev = allowStateChangesStart(allowStateChanges);
@@ -938,338 +1231,99 @@ var ComputedValue = /** @class */ (function () {
938
1231
  if (isSpyEnabled()) {
939
1232
  spyReport({
940
1233
  object: this.scope,
941
- type: "compute",
942
- name: this.name
943
- });
944
- }
945
- var oldValue = this.value;
946
- var wasSuspended =
947
- /* see #1208 */ this.dependenciesState === IDerivationState.NOT_TRACKING;
948
- var newValue = this.computeValue(true);
949
- var changed = wasSuspended ||
950
- isCaughtException(oldValue) ||
951
- isCaughtException(newValue) ||
952
- !this.equals(oldValue, newValue);
953
- if (changed) {
954
- this.value = newValue;
955
- }
956
- return changed;
957
- };
958
- ComputedValue.prototype.computeValue = function (track) {
959
- this.isComputing = true;
960
- globalState.computationDepth++;
961
- var res;
962
- if (track) {
963
- res = trackDerivedFunction(this, this.derivation, this.scope);
964
- }
965
- else {
966
- if (globalState.disableErrorBoundaries === true) {
967
- res = this.derivation.call(this.scope);
968
- }
969
- else {
970
- try {
971
- res = this.derivation.call(this.scope);
972
- }
973
- catch (e) {
974
- res = new CaughtException(e);
975
- }
976
- }
977
- }
978
- globalState.computationDepth--;
979
- this.isComputing = false;
980
- return res;
981
- };
982
- ComputedValue.prototype.suspend = function () {
983
- if (!this.keepAlive) {
984
- clearObserving(this);
985
- this.value = undefined; // don't hold on to computed value!
986
- }
987
- };
988
- ComputedValue.prototype.observe = function (listener, fireImmediately) {
989
- var _this = this;
990
- var firstTime = true;
991
- var prevValue = undefined;
992
- return autorun(function () {
993
- var newValue = _this.get();
994
- if (!firstTime || fireImmediately) {
995
- var prevU = untrackedStart();
996
- listener({
997
- type: "update",
998
- object: _this,
999
- newValue: newValue,
1000
- oldValue: prevValue
1001
- });
1002
- untrackedEnd(prevU);
1003
- }
1004
- firstTime = false;
1005
- prevValue = newValue;
1006
- });
1007
- };
1008
- ComputedValue.prototype.warnAboutUntrackedRead = function () {
1009
- if (process.env.NODE_ENV === "production")
1010
- return;
1011
- if (this.requiresReaction === true) {
1012
- fail("[mobx] Computed value " + this.name + " is read outside a reactive context");
1013
- }
1014
- if (this.isTracing !== TraceMode.NONE) {
1015
- console.log("[mobx.trace] '" + this.name + "' is being read outside a reactive context. Doing a full recompute");
1016
- }
1017
- if (globalState.computedRequiresReaction) {
1018
- console.warn("[mobx] Computed value " + this.name + " is being read outside a reactive context. Doing a full recompute");
1019
- }
1020
- };
1021
- ComputedValue.prototype.toJSON = function () {
1022
- return this.get();
1023
- };
1024
- ComputedValue.prototype.toString = function () {
1025
- return this.name + "[" + this.derivation.toString() + "]";
1026
- };
1027
- ComputedValue.prototype.valueOf = function () {
1028
- return toPrimitive(this.get());
1029
- };
1030
- return ComputedValue;
1031
- }());
1032
- ComputedValue.prototype[primitiveSymbol()] = ComputedValue.prototype.valueOf;
1033
- var isComputedValue = createInstanceofPredicate("ComputedValue", ComputedValue);
1034
-
1035
- var IDerivationState;
1036
- (function (IDerivationState) {
1037
- // before being run or (outside batch and not being observed)
1038
- // at this point derivation is not holding any data about dependency tree
1039
- IDerivationState[IDerivationState["NOT_TRACKING"] = -1] = "NOT_TRACKING";
1040
- // no shallow dependency changed since last computation
1041
- // won't recalculate derivation
1042
- // this is what makes mobx fast
1043
- IDerivationState[IDerivationState["UP_TO_DATE"] = 0] = "UP_TO_DATE";
1044
- // some deep dependency changed, but don't know if shallow dependency changed
1045
- // will require to check first if UP_TO_DATE or POSSIBLY_STALE
1046
- // currently only ComputedValue will propagate POSSIBLY_STALE
1047
- //
1048
- // having this state is second big optimization:
1049
- // don't have to recompute on every dependency change, but only when it's needed
1050
- IDerivationState[IDerivationState["POSSIBLY_STALE"] = 1] = "POSSIBLY_STALE";
1051
- // A shallow dependency has changed since last computation and the derivation
1052
- // will need to recompute when it's needed next.
1053
- IDerivationState[IDerivationState["STALE"] = 2] = "STALE";
1054
- })(IDerivationState || (IDerivationState = {}));
1055
- var TraceMode;
1056
- (function (TraceMode) {
1057
- TraceMode[TraceMode["NONE"] = 0] = "NONE";
1058
- TraceMode[TraceMode["LOG"] = 1] = "LOG";
1059
- TraceMode[TraceMode["BREAK"] = 2] = "BREAK";
1060
- })(TraceMode || (TraceMode = {}));
1061
- var CaughtException = /** @class */ (function () {
1062
- function CaughtException(cause) {
1063
- this.cause = cause;
1064
- // Empty
1065
- }
1066
- return CaughtException;
1067
- }());
1068
- function isCaughtException(e) {
1069
- return e instanceof CaughtException;
1070
- }
1071
- /**
1072
- * Finds out whether any dependency of the derivation has actually changed.
1073
- * If dependenciesState is 1 then it will recalculate dependencies,
1074
- * if any dependency changed it will propagate it by changing dependenciesState to 2.
1075
- *
1076
- * By iterating over the dependencies in the same order that they were reported and
1077
- * stopping on the first change, all the recalculations are only called for ComputedValues
1078
- * that will be tracked by derivation. That is because we assume that if the first x
1079
- * dependencies of the derivation doesn't change then the derivation should run the same way
1080
- * up until accessing x-th dependency.
1081
- */
1082
- function shouldCompute(derivation) {
1083
- switch (derivation.dependenciesState) {
1084
- case IDerivationState.UP_TO_DATE:
1085
- return false;
1086
- case IDerivationState.NOT_TRACKING:
1087
- case IDerivationState.STALE:
1088
- return true;
1089
- case IDerivationState.POSSIBLY_STALE: {
1090
- var prevUntracked = untrackedStart(); // no need for those computeds to be reported, they will be picked up in trackDerivedFunction.
1091
- var obs = derivation.observing, l = obs.length;
1092
- for (var i = 0; i < l; i++) {
1093
- var obj = obs[i];
1094
- if (isComputedValue(obj)) {
1095
- if (globalState.disableErrorBoundaries) {
1096
- obj.get();
1097
- }
1098
- else {
1099
- try {
1100
- obj.get();
1101
- }
1102
- catch (e) {
1103
- // we are not interested in the value *or* exception at this moment, but if there is one, notify all
1104
- untrackedEnd(prevUntracked);
1105
- return true;
1106
- }
1107
- }
1108
- // if ComputedValue `obj` actually changed it will be computed and propagated to its observers.
1109
- // and `derivation` is an observer of `obj`
1110
- // invariantShouldCompute(derivation)
1111
- if (derivation.dependenciesState === IDerivationState.STALE) {
1112
- untrackedEnd(prevUntracked);
1113
- return true;
1114
- }
1115
- }
1116
- }
1117
- changeDependenciesStateTo0(derivation);
1118
- untrackedEnd(prevUntracked);
1119
- return false;
1234
+ type: "compute",
1235
+ name: this.name
1236
+ });
1120
1237
  }
1121
- }
1122
- }
1123
- // function invariantShouldCompute(derivation: IDerivation) {
1124
- // const newDepState = (derivation as any).dependenciesState
1125
- // if (
1126
- // process.env.NODE_ENV === "production" &&
1127
- // (newDepState === IDerivationState.POSSIBLY_STALE ||
1128
- // newDepState === IDerivationState.NOT_TRACKING)
1129
- // )
1130
- // fail("Illegal dependency state")
1131
- // }
1132
- function isComputingDerivation() {
1133
- return globalState.trackingDerivation !== null; // filter out actions inside computations
1134
- }
1135
- function checkIfStateModificationsAreAllowed(atom) {
1136
- var hasObservers = atom.observers.length > 0;
1137
- // Should never be possible to change an observed observable from inside computed, see #798
1138
- if (globalState.computationDepth > 0 && hasObservers)
1139
- fail(process.env.NODE_ENV !== "production" &&
1140
- "Computed values are not allowed to cause side effects by changing observables that are already being observed. Tried to modify: " + atom.name);
1141
- // Should not be possible to change observed state outside strict mode, except during initialization, see #563
1142
- if (!globalState.allowStateChanges && (hasObservers || globalState.enforceActions === "strict"))
1143
- fail(process.env.NODE_ENV !== "production" &&
1144
- (globalState.enforceActions
1145
- ? "Since strict-mode is enabled, changing observed observable values outside actions is not allowed. Please wrap the code in an `action` if this change is intended. Tried to modify: "
1146
- : "Side effects like changing state are not allowed at this point. Are you trying to modify state from, for example, the render function of a React component? Tried to modify: ") +
1147
- atom.name);
1148
- }
1149
- /**
1150
- * Executes the provided function `f` and tracks which observables are being accessed.
1151
- * The tracking information is stored on the `derivation` object and the derivation is registered
1152
- * as observer of any of the accessed observables.
1153
- */
1154
- function trackDerivedFunction(derivation, f, context) {
1155
- // pre allocate array allocation + room for variation in deps
1156
- // array will be trimmed by bindDependencies
1157
- changeDependenciesStateTo0(derivation);
1158
- derivation.newObserving = new Array(derivation.observing.length + 100);
1159
- derivation.unboundDepsCount = 0;
1160
- derivation.runId = ++globalState.runId;
1161
- var prevTracking = globalState.trackingDerivation;
1162
- globalState.trackingDerivation = derivation;
1163
- var result;
1164
- if (globalState.disableErrorBoundaries === true) {
1165
- result = f.call(context);
1166
- }
1167
- else {
1168
- try {
1169
- result = f.call(context);
1238
+ var oldValue = this.value;
1239
+ var wasSuspended =
1240
+ /* see #1208 */ this.dependenciesState === IDerivationState.NOT_TRACKING;
1241
+ var newValue = this.computeValue(true);
1242
+ var changed = wasSuspended ||
1243
+ isCaughtException(oldValue) ||
1244
+ isCaughtException(newValue) ||
1245
+ !this.equals(oldValue, newValue);
1246
+ if (changed) {
1247
+ this.value = newValue;
1170
1248
  }
1171
- catch (e) {
1172
- result = new CaughtException(e);
1249
+ return changed;
1250
+ };
1251
+ ComputedValue.prototype.computeValue = function (track) {
1252
+ this.isComputing = true;
1253
+ globalState.computationDepth++;
1254
+ var res;
1255
+ if (track) {
1256
+ res = trackDerivedFunction(this, this.derivation, this.scope);
1173
1257
  }
1174
- }
1175
- globalState.trackingDerivation = prevTracking;
1176
- bindDependencies(derivation);
1177
- return result;
1178
- }
1179
- /**
1180
- * diffs newObserving with observing.
1181
- * update observing to be newObserving with unique observables
1182
- * notify observers that become observed/unobserved
1183
- */
1184
- function bindDependencies(derivation) {
1185
- // invariant(derivation.dependenciesState !== IDerivationState.NOT_TRACKING, "INTERNAL ERROR bindDependencies expects derivation.dependenciesState !== -1");
1186
- var prevObserving = derivation.observing;
1187
- var observing = (derivation.observing = derivation.newObserving);
1188
- var lowestNewObservingDerivationState = IDerivationState.UP_TO_DATE;
1189
- // Go through all new observables and check diffValue: (this list can contain duplicates):
1190
- // 0: first occurrence, change to 1 and keep it
1191
- // 1: extra occurrence, drop it
1192
- var i0 = 0, l = derivation.unboundDepsCount;
1193
- for (var i = 0; i < l; i++) {
1194
- var dep = observing[i];
1195
- if (dep.diffValue === 0) {
1196
- dep.diffValue = 1;
1197
- if (i0 !== i)
1198
- observing[i0] = dep;
1199
- i0++;
1258
+ else {
1259
+ if (globalState.disableErrorBoundaries === true) {
1260
+ res = this.derivation.call(this.scope);
1261
+ }
1262
+ else {
1263
+ try {
1264
+ res = this.derivation.call(this.scope);
1265
+ }
1266
+ catch (e) {
1267
+ res = new CaughtException(e);
1268
+ }
1269
+ }
1200
1270
  }
1201
- // Upcast is 'safe' here, because if dep is IObservable, `dependenciesState` will be undefined,
1202
- // not hitting the condition
1203
- if (dep.dependenciesState > lowestNewObservingDerivationState) {
1204
- lowestNewObservingDerivationState = dep.dependenciesState;
1271
+ globalState.computationDepth--;
1272
+ this.isComputing = false;
1273
+ return res;
1274
+ };
1275
+ ComputedValue.prototype.suspend = function () {
1276
+ if (!this.keepAlive) {
1277
+ clearObserving(this);
1278
+ this.value = undefined; // don't hold on to computed value!
1205
1279
  }
1206
- }
1207
- observing.length = i0;
1208
- derivation.newObserving = null; // newObserving shouldn't be needed outside tracking (statement moved down to work around FF bug, see #614)
1209
- // Go through all old observables and check diffValue: (it is unique after last bindDependencies)
1210
- // 0: it's not in new observables, unobserve it
1211
- // 1: it keeps being observed, don't want to notify it. change to 0
1212
- l = prevObserving.length;
1213
- while (l--) {
1214
- var dep = prevObserving[l];
1215
- if (dep.diffValue === 0) {
1216
- removeObserver(dep, derivation);
1280
+ };
1281
+ ComputedValue.prototype.observe = function (listener, fireImmediately) {
1282
+ var _this = this;
1283
+ var firstTime = true;
1284
+ var prevValue = undefined;
1285
+ return autorun(function () {
1286
+ var newValue = _this.get();
1287
+ if (!firstTime || fireImmediately) {
1288
+ var prevU = untrackedStart();
1289
+ listener({
1290
+ type: "update",
1291
+ object: _this,
1292
+ newValue: newValue,
1293
+ oldValue: prevValue
1294
+ });
1295
+ untrackedEnd(prevU);
1296
+ }
1297
+ firstTime = false;
1298
+ prevValue = newValue;
1299
+ });
1300
+ };
1301
+ ComputedValue.prototype.warnAboutUntrackedRead = function () {
1302
+ if (process.env.NODE_ENV === "production")
1303
+ return;
1304
+ if (this.requiresReaction === true) {
1305
+ fail("[mobx] Computed value " + this.name + " is read outside a reactive context");
1217
1306
  }
1218
- dep.diffValue = 0;
1219
- }
1220
- // Go through all new observables and check diffValue: (now it should be unique)
1221
- // 0: it was set to 0 in last loop. don't need to do anything.
1222
- // 1: it wasn't observed, let's observe it. set back to 0
1223
- while (i0--) {
1224
- var dep = observing[i0];
1225
- if (dep.diffValue === 1) {
1226
- dep.diffValue = 0;
1227
- addObserver(dep, derivation);
1307
+ if (this.isTracing !== TraceMode.NONE) {
1308
+ console.log("[mobx.trace] '" + this.name + "' is being read outside a reactive context. Doing a full recompute");
1228
1309
  }
1229
- }
1230
- // Some new observed derivations may become stale during this derivation computation
1231
- // so they have had no chance to propagate staleness (#916)
1232
- if (lowestNewObservingDerivationState !== IDerivationState.UP_TO_DATE) {
1233
- derivation.dependenciesState = lowestNewObservingDerivationState;
1234
- derivation.onBecomeStale();
1235
- }
1236
- }
1237
- function clearObserving(derivation) {
1238
- // invariant(globalState.inBatch > 0, "INTERNAL ERROR clearObserving should be called only inside batch");
1239
- var obs = derivation.observing;
1240
- derivation.observing = [];
1241
- var i = obs.length;
1242
- while (i--)
1243
- removeObserver(obs[i], derivation);
1244
- derivation.dependenciesState = IDerivationState.NOT_TRACKING;
1245
- }
1246
- function untracked(action) {
1247
- var prev = untrackedStart();
1248
- var res = action();
1249
- untrackedEnd(prev);
1250
- return res;
1251
- }
1252
- function untrackedStart() {
1253
- var prev = globalState.trackingDerivation;
1254
- globalState.trackingDerivation = null;
1255
- return prev;
1256
- }
1257
- function untrackedEnd(prev) {
1258
- globalState.trackingDerivation = prev;
1259
- }
1260
- /**
1261
- * needed to keep `lowestObserverState` correct. when changing from (2 or 1) to 0
1262
- *
1263
- */
1264
- function changeDependenciesStateTo0(derivation) {
1265
- if (derivation.dependenciesState === IDerivationState.UP_TO_DATE)
1266
- return;
1267
- derivation.dependenciesState = IDerivationState.UP_TO_DATE;
1268
- var obs = derivation.observing;
1269
- var i = obs.length;
1270
- while (i--)
1271
- obs[i].lowestObserverState = IDerivationState.UP_TO_DATE;
1272
- }
1310
+ if (globalState.computedRequiresReaction) {
1311
+ console.warn("[mobx] Computed value " + this.name + " is being read outside a reactive context. Doing a full recompute");
1312
+ }
1313
+ };
1314
+ ComputedValue.prototype.toJSON = function () {
1315
+ return this.get();
1316
+ };
1317
+ ComputedValue.prototype.toString = function () {
1318
+ return this.name + "[" + this.derivation.toString() + "]";
1319
+ };
1320
+ ComputedValue.prototype.valueOf = function () {
1321
+ return toPrimitive(this.get());
1322
+ };
1323
+ return ComputedValue;
1324
+ }());
1325
+ ComputedValue.prototype[primitiveSymbol()] = ComputedValue.prototype.valueOf;
1326
+ var isComputedValue = createInstanceofPredicate("ComputedValue", ComputedValue);
1273
1327
 
1274
1328
  /**
1275
1329
  * These values will persist if global state is reset
@@ -1279,6 +1333,9 @@ var persistentKeys = [
1279
1333
  "spyListeners",
1280
1334
  "enforceActions",
1281
1335
  "computedRequiresReaction",
1336
+ "reactionRequiresObservable",
1337
+ "observableRequiresReaction",
1338
+ "allowStateReads",
1282
1339
  "disableErrorBoundaries",
1283
1340
  "runId",
1284
1341
  "UNCHANGED"
@@ -1339,6 +1396,11 @@ var MobXGlobals = /** @class */ (function () {
1339
1396
  * To ensure that those functions stay pure.
1340
1397
  */
1341
1398
  this.allowStateChanges = true;
1399
+ /**
1400
+ * Is it allowed to read observables at this point?
1401
+ * Used to hold the state needed for `observableRequiresReaction`
1402
+ */
1403
+ this.allowStateReads = true;
1342
1404
  /**
1343
1405
  * If strict mode is enabled, state changes are by default not allowed
1344
1406
  */
@@ -1355,6 +1417,16 @@ var MobXGlobals = /** @class */ (function () {
1355
1417
  * Warn if computed values are accessed outside a reactive context
1356
1418
  */
1357
1419
  this.computedRequiresReaction = false;
1420
+ /**
1421
+ * (Experimental)
1422
+ * Warn if you try to create to derivation / reactive context without accessing any observable.
1423
+ */
1424
+ this.reactionRequiresObservable = false;
1425
+ /**
1426
+ * (Experimental)
1427
+ * Warn if observables are accessed outside a reactive context
1428
+ */
1429
+ this.observableRequiresReaction = false;
1358
1430
  /**
1359
1431
  * Allows overwriting of computed properties, useful in tests but not prod as it can cause
1360
1432
  * memory leaks. See https://github.com/mobxjs/mobx/issues/1867
@@ -1536,6 +1608,7 @@ function endBatch() {
1536
1608
  }
1537
1609
  }
1538
1610
  function reportObserved(observable) {
1611
+ checkIfStateReadsAreAllowed(observable);
1539
1612
  var derivation = globalState.trackingDerivation;
1540
1613
  if (derivation !== null) {
1541
1614
  /**
@@ -1656,11 +1729,13 @@ function printDepTree(tree, lines, depth) {
1656
1729
  }
1657
1730
 
1658
1731
  var Reaction = /** @class */ (function () {
1659
- function Reaction(name, onInvalidate, errorHandler) {
1732
+ function Reaction(name, onInvalidate, errorHandler, requiresObservable) {
1660
1733
  if (name === void 0) { name = "Reaction@" + getNextId(); }
1734
+ if (requiresObservable === void 0) { requiresObservable = false; }
1661
1735
  this.name = name;
1662
1736
  this.onInvalidate = onInvalidate;
1663
1737
  this.errorHandler = errorHandler;
1738
+ this.requiresObservable = requiresObservable;
1664
1739
  this.observing = []; // nodes we are looking at. Our value depends on these nodes
1665
1740
  this.newObserving = [];
1666
1741
  this.dependenciesState = IDerivationState.NOT_TRACKING;
@@ -2006,7 +2081,7 @@ function autorun(view, opts) {
2006
2081
  // normal autorun
2007
2082
  reaction = new Reaction(name, function () {
2008
2083
  this.track(reactionRunner);
2009
- }, opts.onError);
2084
+ }, opts.onError, opts.requiresObservable);
2010
2085
  }
2011
2086
  else {
2012
2087
  var scheduler_1 = createSchedulerFromOptions(opts);
@@ -2021,7 +2096,7 @@ function autorun(view, opts) {
2021
2096
  reaction.track(reactionRunner);
2022
2097
  });
2023
2098
  }
2024
- }, opts.onError);
2099
+ }, opts.onError, opts.requiresObservable);
2025
2100
  }
2026
2101
  function reactionRunner() {
2027
2102
  view(reaction);
@@ -2065,7 +2140,7 @@ function reaction(expression, effect, opts) {
2065
2140
  isScheduled = true;
2066
2141
  scheduler(reactionRunner);
2067
2142
  }
2068
- }, opts.onError);
2143
+ }, opts.onError, opts.requiresObservable);
2069
2144
  function reactionRunner() {
2070
2145
  isScheduled = false; // Q: move into reaction runner?
2071
2146
  if (r.isDisposed)
@@ -2104,8 +2179,8 @@ function onBecomeUnobserved(thing, arg2, arg3) {
2104
2179
  return interceptHook("onBecomeUnobserved", thing, arg2, arg3);
2105
2180
  }
2106
2181
  function interceptHook(hook, thing, arg2, arg3) {
2107
- var atom = typeof arg2 === "string" ? getAtom(thing, arg2) : getAtom(thing);
2108
- var cb = typeof arg2 === "string" ? arg3 : arg2;
2182
+ var atom = typeof arg3 === "function" ? getAtom(thing, arg2) : getAtom(thing);
2183
+ var cb = typeof arg3 === "function" ? arg3 : arg2;
2109
2184
  var orig = atom[hook];
2110
2185
  if (typeof orig !== "function")
2111
2186
  return fail(process.env.NODE_ENV !== "production" && "Not an atom that can be (un)observed");
@@ -2119,7 +2194,7 @@ function interceptHook(hook, thing, arg2, arg3) {
2119
2194
  }
2120
2195
 
2121
2196
  function configure(options) {
2122
- var enforceActions = options.enforceActions, computedRequiresReaction = options.computedRequiresReaction, computedConfigurable = options.computedConfigurable, disableErrorBoundaries = options.disableErrorBoundaries, arrayBuffer = options.arrayBuffer, reactionScheduler = options.reactionScheduler;
2197
+ var enforceActions = options.enforceActions, computedRequiresReaction = options.computedRequiresReaction, computedConfigurable = options.computedConfigurable, disableErrorBoundaries = options.disableErrorBoundaries, arrayBuffer = options.arrayBuffer, reactionScheduler = options.reactionScheduler, reactionRequiresObservable = options.reactionRequiresObservable, observableRequiresReaction = options.observableRequiresReaction;
2123
2198
  if (options.isolateGlobalState === true) {
2124
2199
  isolateGlobalState();
2125
2200
  }
@@ -2149,6 +2224,13 @@ function configure(options) {
2149
2224
  if (computedRequiresReaction !== undefined) {
2150
2225
  globalState.computedRequiresReaction = !!computedRequiresReaction;
2151
2226
  }
2227
+ if (reactionRequiresObservable !== undefined) {
2228
+ globalState.reactionRequiresObservable = !!reactionRequiresObservable;
2229
+ }
2230
+ if (observableRequiresReaction !== undefined) {
2231
+ globalState.observableRequiresReaction = !!observableRequiresReaction;
2232
+ globalState.allowStateReads = !globalState.observableRequiresReaction;
2233
+ }
2152
2234
  if (computedConfigurable !== undefined) {
2153
2235
  globalState.computedConfigurable = !!computedConfigurable;
2154
2236
  }
@@ -3404,9 +3486,17 @@ var ObservableMap = /** @class */ (function () {
3404
3486
  return this._data.has(key);
3405
3487
  };
3406
3488
  ObservableMap.prototype.has = function (key) {
3407
- if (this._hasMap.has(key))
3408
- return this._hasMap.get(key).get();
3409
- return this._updateHasMapEntry(key, false).get();
3489
+ var _this = this;
3490
+ if (!globalState.trackingDerivation)
3491
+ return this._has(key);
3492
+ var entry = this._hasMap.get(key);
3493
+ if (!entry) {
3494
+ // todo: replace with atom (breaking change)
3495
+ var newEntry = (entry = new ObservableValue(this._has(key), referenceEnhancer, this.name + "." + stringifyKey(key) + "?", false));
3496
+ this._hasMap.set(key, newEntry);
3497
+ onBecomeUnobserved(newEntry, function () { return _this._hasMap.delete(key); });
3498
+ }
3499
+ return entry.get();
3410
3500
  };
3411
3501
  ObservableMap.prototype.set = function (key, value) {
3412
3502
  var hasKey = this._has(key);
@@ -3469,16 +3559,10 @@ var ObservableMap = /** @class */ (function () {
3469
3559
  return false;
3470
3560
  };
3471
3561
  ObservableMap.prototype._updateHasMapEntry = function (key, value) {
3472
- // optimization; don't fill the hasMap if we are not observing, or remove entry if there are no observers anymore
3473
3562
  var entry = this._hasMap.get(key);
3474
3563
  if (entry) {
3475
3564
  entry.setNewValue(value);
3476
3565
  }
3477
- else {
3478
- entry = new ObservableValue(value, referenceEnhancer, this.name + "." + stringifyKey(key) + "?", false);
3479
- this._hasMap.set(key, entry);
3480
- }
3481
- return entry;
3482
3566
  };
3483
3567
  ObservableMap.prototype._updateValue = function (key, newValue) {
3484
3568
  var observable = this._data.get(key);
@@ -3611,14 +3695,32 @@ var ObservableMap = /** @class */ (function () {
3611
3695
  ObservableMap.prototype.replace = function (values) {
3612
3696
  var _this = this;
3613
3697
  transaction(function () {
3614
- // grab all the keys that are present in the new map but not present in the current map
3615
- // and delete them from the map, then merge the new map
3616
- // this will cause reactions only on changed values
3617
- var newKeys = getMapLikeKeys(values);
3698
+ var replacementMap = convertToMap(values);
3618
3699
  var oldKeys = _this._keys;
3619
- var missingKeys = oldKeys.filter(function (k) { return newKeys.indexOf(k) === -1; });
3620
- missingKeys.forEach(function (k) { return _this.delete(k); });
3621
- _this.merge(values);
3700
+ var newKeys = Array.from(replacementMap.keys());
3701
+ var keysChanged = false;
3702
+ for (var i = 0; i < oldKeys.length; i++) {
3703
+ var oldKey = oldKeys[i];
3704
+ // key order change
3705
+ if (oldKeys.length === newKeys.length && oldKey !== newKeys[i]) {
3706
+ keysChanged = true;
3707
+ }
3708
+ // deleted key
3709
+ if (!replacementMap.has(oldKey)) {
3710
+ keysChanged = true;
3711
+ _this.delete(oldKey);
3712
+ }
3713
+ }
3714
+ replacementMap.forEach(function (value, key) {
3715
+ // new key
3716
+ if (!_this._data.has(key)) {
3717
+ keysChanged = true;
3718
+ }
3719
+ _this.set(key, value);
3720
+ });
3721
+ if (keysChanged) {
3722
+ _this._keys.replace(newKeys);
3723
+ }
3622
3724
  });
3623
3725
  return this;
3624
3726
  };
@@ -4222,12 +4324,13 @@ function getDebugName(thing, property) {
4222
4324
  }
4223
4325
 
4224
4326
  var toString = Object.prototype.toString;
4225
- function deepEqual(a, b) {
4226
- return eq(a, b);
4327
+ function deepEqual(a, b, depth) {
4328
+ if (depth === void 0) { depth = -1; }
4329
+ return eq(a, b, depth);
4227
4330
  }
4228
4331
  // Copied from https://github.com/jashkenas/underscore/blob/5c237a7c682fb68fd5378203f0bf22dce1624854/underscore.js#L1186-L1289
4229
4332
  // Internal recursive comparison function for `isEqual`.
4230
- function eq(a, b, aStack, bStack) {
4333
+ function eq(a, b, depth, aStack, bStack) {
4231
4334
  // Identical objects are equal. `0 === -0`, but they aren't identical.
4232
4335
  // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
4233
4336
  if (a === b)
@@ -4242,10 +4345,6 @@ function eq(a, b, aStack, bStack) {
4242
4345
  var type = typeof a;
4243
4346
  if (type !== "function" && type !== "object" && typeof b != "object")
4244
4347
  return false;
4245
- return deepEq(a, b, aStack, bStack);
4246
- }
4247
- // Internal recursive comparison function for `isEqual`.
4248
- function deepEq(a, b, aStack, bStack) {
4249
4348
  // Unwrap any wrapped objects.
4250
4349
  a = unwrap(a);
4251
4350
  b = unwrap(b);
@@ -4295,6 +4394,12 @@ function deepEq(a, b, aStack, bStack) {
4295
4394
  return false;
4296
4395
  }
4297
4396
  }
4397
+ if (depth === 0) {
4398
+ return false;
4399
+ }
4400
+ else if (depth < 0) {
4401
+ depth = -1;
4402
+ }
4298
4403
  // Assume equality for cyclic structures. The algorithm for detecting cyclic
4299
4404
  // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
4300
4405
  // Initializing stack of traversed objects.
@@ -4319,7 +4424,7 @@ function deepEq(a, b, aStack, bStack) {
4319
4424
  return false;
4320
4425
  // Deep compare the contents, ignoring non-numeric properties.
4321
4426
  while (length--) {
4322
- if (!eq(a[length], b[length], aStack, bStack))
4427
+ if (!eq(a[length], b[length], depth - 1, aStack, bStack))
4323
4428
  return false;
4324
4429
  }
4325
4430
  }
@@ -4334,7 +4439,7 @@ function deepEq(a, b, aStack, bStack) {
4334
4439
  while (length--) {
4335
4440
  // Deep compare each member
4336
4441
  key = keys[length];
4337
- if (!(has$1(b, key) && eq(a[key], b[key], aStack, bStack)))
4442
+ if (!(has$1(b, key) && eq(a[key], b[key], depth - 1, aStack, bStack)))
4338
4443
  return false;
4339
4444
  }
4340
4445
  }
@@ -4389,7 +4494,7 @@ try {
4389
4494
  process.env.NODE_ENV;
4390
4495
  }
4391
4496
  catch (e) {
4392
- var g = typeof window !== "undefined" ? window : global;
4497
+ var g = getGlobal();
4393
4498
  if (typeof process === "undefined")
4394
4499
  g.process = {};
4395
4500
  g.process.env = {};
@@ -4458,4 +4563,4 @@ if (process.env.NODE_ENV !== "production" &&
4458
4563
  });
4459
4564
  }
4460
4565
 
4461
- export { $mobx, IDerivationState, ObservableMap, ObservableSet, Reaction, allowStateChanges as _allowStateChanges, allowStateChangesInsideComputed as _allowStateChangesInsideComputed, getAdministration as _getAdministration, getGlobalState as _getGlobalState, interceptReads as _interceptReads, isComputingDerivation as _isComputingDerivation, resetGlobalState as _resetGlobalState, action, autorun, comparer, computed, configure, createAtom, decorate, entries, extendObservable, extendShallowObservable, flow, get, getAtom, getDebugName, getDependencyTree, getObserverTree, has, intercept, isAction, isArrayLike, isObservableValue as isBoxedObservable, isComputed, isComputedProp, isObservable, isObservableArray, isObservableMap, isObservableObject, isObservableProp, isObservableSet, keys, observable, observe, onBecomeObserved, onBecomeUnobserved, onReactionError, reaction, remove, runInAction, set, spy, toJS, trace, transaction, untracked, values, when };
4566
+ export { $mobx, IDerivationState, ObservableMap, ObservableSet, Reaction, allowStateChanges as _allowStateChanges, allowStateChangesInsideComputed as _allowStateChangesInsideComputed, _endAction, getAdministration as _getAdministration, getGlobalState as _getGlobalState, interceptReads as _interceptReads, isComputingDerivation as _isComputingDerivation, resetGlobalState as _resetGlobalState, _startAction, action, autorun, comparer, computed, configure, createAtom, decorate, entries, extendObservable, extendShallowObservable, flow, get, getAtom, getDebugName, getDependencyTree, getObserverTree, has, intercept, isAction, isArrayLike, isObservableValue as isBoxedObservable, isComputed, isComputedProp, isObservable, isObservableArray, isObservableMap, isObservableObject, isObservableProp, isObservableSet, keys, observable, observe, onBecomeObserved, onBecomeUnobserved, onReactionError, reaction, remove, runInAction, set, spy, toJS, trace, transaction, untracked, values, when };