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