mobx 5.10.1 → 5.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/CHANGELOG.md +29 -1
  2. package/LICENSE +0 -0
  3. package/README.md +66 -52
  4. package/lib/api/action.d.ts +0 -0
  5. package/lib/api/actiondecorator.d.ts +0 -0
  6. package/lib/api/autorun.d.ts +5 -0
  7. package/lib/api/become-observed.d.ts +0 -0
  8. package/lib/api/computed.d.ts +0 -0
  9. package/lib/api/configure.d.ts +11 -0
  10. package/lib/api/decorate.d.ts +0 -0
  11. package/lib/api/extendobservable.d.ts +0 -0
  12. package/lib/api/extras.d.ts +0 -0
  13. package/lib/api/flow.d.ts +0 -0
  14. package/lib/api/intercept-read.d.ts +0 -0
  15. package/lib/api/intercept.d.ts +0 -0
  16. package/lib/api/iscomputed.d.ts +0 -0
  17. package/lib/api/isobservable.d.ts +0 -0
  18. package/lib/api/object-api.d.ts +2 -2
  19. package/lib/api/observable.d.ts +0 -0
  20. package/lib/api/observabledecorator.d.ts +0 -0
  21. package/lib/api/observe.d.ts +0 -0
  22. package/lib/api/tojs.d.ts +0 -0
  23. package/lib/api/trace.d.ts +0 -0
  24. package/lib/api/transaction.d.ts +0 -0
  25. package/lib/api/when.d.ts +5 -0
  26. package/lib/core/action.d.ts +13 -0
  27. package/lib/core/atom.d.ts +2 -2
  28. package/lib/core/computedvalue.d.ts +0 -0
  29. package/lib/core/derivation.d.ts +7 -0
  30. package/lib/core/globalstate.d.ts +22 -0
  31. package/lib/core/observable.d.ts +0 -0
  32. package/lib/core/reaction.d.ts +2 -1
  33. package/lib/core/spy.d.ts +0 -0
  34. package/lib/internal.d.ts +0 -0
  35. package/lib/mobx.d.ts +1 -1
  36. package/lib/mobx.es6.js +471 -382
  37. package/lib/mobx.js +485 -371
  38. package/lib/mobx.js.flow +20 -2
  39. package/lib/mobx.min.js +1 -1
  40. package/lib/mobx.module.js +485 -373
  41. package/lib/mobx.umd.js +485 -371
  42. package/lib/mobx.umd.min.js +1 -1
  43. package/lib/types/dynamicobject.d.ts +0 -0
  44. package/lib/types/intercept-utils.d.ts +0 -0
  45. package/lib/types/listen-utils.d.ts +0 -0
  46. package/lib/types/modifiers.d.ts +0 -0
  47. package/lib/types/observablearray.d.ts +0 -0
  48. package/lib/types/observablemap.d.ts +0 -0
  49. package/lib/types/observableobject.d.ts +0 -0
  50. package/lib/types/observableset.d.ts +0 -0
  51. package/lib/types/observablevalue.d.ts +0 -0
  52. package/lib/types/type-utils.d.ts +0 -0
  53. package/lib/utils/comparer.d.ts +0 -0
  54. package/lib/utils/decorators.d.ts +0 -0
  55. package/lib/utils/eq.d.ts +0 -0
  56. package/lib/utils/iterable.d.ts +0 -0
  57. package/lib/utils/utils.d.ts +0 -0
  58. package/package.json +7 -6
package/lib/mobx.umd.js CHANGED
@@ -599,6 +599,274 @@
599
599
  };
600
600
  computed.struct = computedStructDecorator;
601
601
 
602
+ (function (IDerivationState) {
603
+ // before being run or (outside batch and not being observed)
604
+ // at this point derivation is not holding any data about dependency tree
605
+ IDerivationState[IDerivationState["NOT_TRACKING"] = -1] = "NOT_TRACKING";
606
+ // no shallow dependency changed since last computation
607
+ // won't recalculate derivation
608
+ // this is what makes mobx fast
609
+ IDerivationState[IDerivationState["UP_TO_DATE"] = 0] = "UP_TO_DATE";
610
+ // some deep dependency changed, but don't know if shallow dependency changed
611
+ // will require to check first if UP_TO_DATE or POSSIBLY_STALE
612
+ // currently only ComputedValue will propagate POSSIBLY_STALE
613
+ //
614
+ // having this state is second big optimization:
615
+ // don't have to recompute on every dependency change, but only when it's needed
616
+ IDerivationState[IDerivationState["POSSIBLY_STALE"] = 1] = "POSSIBLY_STALE";
617
+ // A shallow dependency has changed since last computation and the derivation
618
+ // will need to recompute when it's needed next.
619
+ IDerivationState[IDerivationState["STALE"] = 2] = "STALE";
620
+ })(exports.IDerivationState || (exports.IDerivationState = {}));
621
+ var TraceMode;
622
+ (function (TraceMode) {
623
+ TraceMode[TraceMode["NONE"] = 0] = "NONE";
624
+ TraceMode[TraceMode["LOG"] = 1] = "LOG";
625
+ TraceMode[TraceMode["BREAK"] = 2] = "BREAK";
626
+ })(TraceMode || (TraceMode = {}));
627
+ var CaughtException = /** @class */ (function () {
628
+ function CaughtException(cause) {
629
+ this.cause = cause;
630
+ // Empty
631
+ }
632
+ return CaughtException;
633
+ }());
634
+ function isCaughtException(e) {
635
+ return e instanceof CaughtException;
636
+ }
637
+ /**
638
+ * Finds out whether any dependency of the derivation has actually changed.
639
+ * If dependenciesState is 1 then it will recalculate dependencies,
640
+ * if any dependency changed it will propagate it by changing dependenciesState to 2.
641
+ *
642
+ * By iterating over the dependencies in the same order that they were reported and
643
+ * stopping on the first change, all the recalculations are only called for ComputedValues
644
+ * that will be tracked by derivation. That is because we assume that if the first x
645
+ * dependencies of the derivation doesn't change then the derivation should run the same way
646
+ * up until accessing x-th dependency.
647
+ */
648
+ function shouldCompute(derivation) {
649
+ switch (derivation.dependenciesState) {
650
+ case exports.IDerivationState.UP_TO_DATE:
651
+ return false;
652
+ case exports.IDerivationState.NOT_TRACKING:
653
+ case exports.IDerivationState.STALE:
654
+ return true;
655
+ case exports.IDerivationState.POSSIBLY_STALE: {
656
+ var prevUntracked = untrackedStart(); // no need for those computeds to be reported, they will be picked up in trackDerivedFunction.
657
+ var obs = derivation.observing, l = obs.length;
658
+ for (var i = 0; i < l; i++) {
659
+ var obj = obs[i];
660
+ if (isComputedValue(obj)) {
661
+ if (globalState.disableErrorBoundaries) {
662
+ obj.get();
663
+ }
664
+ else {
665
+ try {
666
+ obj.get();
667
+ }
668
+ catch (e) {
669
+ // we are not interested in the value *or* exception at this moment, but if there is one, notify all
670
+ untrackedEnd(prevUntracked);
671
+ return true;
672
+ }
673
+ }
674
+ // if ComputedValue `obj` actually changed it will be computed and propagated to its observers.
675
+ // and `derivation` is an observer of `obj`
676
+ // invariantShouldCompute(derivation)
677
+ if (derivation.dependenciesState === exports.IDerivationState.STALE) {
678
+ untrackedEnd(prevUntracked);
679
+ return true;
680
+ }
681
+ }
682
+ }
683
+ changeDependenciesStateTo0(derivation);
684
+ untrackedEnd(prevUntracked);
685
+ return false;
686
+ }
687
+ }
688
+ }
689
+ // function invariantShouldCompute(derivation: IDerivation) {
690
+ // const newDepState = (derivation as any).dependenciesState
691
+ // if (
692
+ // process.env.NODE_ENV === "production" &&
693
+ // (newDepState === IDerivationState.POSSIBLY_STALE ||
694
+ // newDepState === IDerivationState.NOT_TRACKING)
695
+ // )
696
+ // fail("Illegal dependency state")
697
+ // }
698
+ function isComputingDerivation() {
699
+ return globalState.trackingDerivation !== null; // filter out actions inside computations
700
+ }
701
+ function checkIfStateModificationsAreAllowed(atom) {
702
+ var hasObservers = atom.observers.size > 0;
703
+ // Should never be possible to change an observed observable from inside computed, see #798
704
+ if (globalState.computationDepth > 0 && hasObservers)
705
+ fail(process.env.NODE_ENV !== "production" &&
706
+ "Computed values are not allowed to cause side effects by changing observables that are already being observed. Tried to modify: " + atom.name);
707
+ // Should not be possible to change observed state outside strict mode, except during initialization, see #563
708
+ if (!globalState.allowStateChanges && (hasObservers || globalState.enforceActions === "strict"))
709
+ fail(process.env.NODE_ENV !== "production" &&
710
+ (globalState.enforceActions
711
+ ? "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: "
712
+ : "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: ") +
713
+ atom.name);
714
+ }
715
+ function checkIfStateReadsAreAllowed(observable) {
716
+ if (process.env.NODE_ENV !== "production" &&
717
+ !globalState.allowStateReads &&
718
+ globalState.observableRequiresReaction) {
719
+ console.warn("[mobx] Observable " + observable.name + " being read outside a reactive context");
720
+ }
721
+ }
722
+ /**
723
+ * Executes the provided function `f` and tracks which observables are being accessed.
724
+ * The tracking information is stored on the `derivation` object and the derivation is registered
725
+ * as observer of any of the accessed observables.
726
+ */
727
+ function trackDerivedFunction(derivation, f, context) {
728
+ var prevAllowStateReads = allowStateReadsStart(true);
729
+ // pre allocate array allocation + room for variation in deps
730
+ // array will be trimmed by bindDependencies
731
+ changeDependenciesStateTo0(derivation);
732
+ derivation.newObserving = new Array(derivation.observing.length + 100);
733
+ derivation.unboundDepsCount = 0;
734
+ derivation.runId = ++globalState.runId;
735
+ var prevTracking = globalState.trackingDerivation;
736
+ globalState.trackingDerivation = derivation;
737
+ var result;
738
+ if (globalState.disableErrorBoundaries === true) {
739
+ result = f.call(context);
740
+ }
741
+ else {
742
+ try {
743
+ result = f.call(context);
744
+ }
745
+ catch (e) {
746
+ result = new CaughtException(e);
747
+ }
748
+ }
749
+ globalState.trackingDerivation = prevTracking;
750
+ bindDependencies(derivation);
751
+ warnAboutDerivationWithoutDependencies(derivation);
752
+ allowStateReadsEnd(prevAllowStateReads);
753
+ return result;
754
+ }
755
+ function warnAboutDerivationWithoutDependencies(derivation) {
756
+ if (process.env.NODE_ENV === "production")
757
+ return;
758
+ if (derivation.observing.length !== 0)
759
+ return;
760
+ if (globalState.reactionRequiresObservable || derivation.requiresObservable) {
761
+ console.warn("[mobx] Derivation " + derivation.name + " is created/updated without reading any observable value");
762
+ }
763
+ }
764
+ /**
765
+ * diffs newObserving with observing.
766
+ * update observing to be newObserving with unique observables
767
+ * notify observers that become observed/unobserved
768
+ */
769
+ function bindDependencies(derivation) {
770
+ // invariant(derivation.dependenciesState !== IDerivationState.NOT_TRACKING, "INTERNAL ERROR bindDependencies expects derivation.dependenciesState !== -1");
771
+ var prevObserving = derivation.observing;
772
+ var observing = (derivation.observing = derivation.newObserving);
773
+ var lowestNewObservingDerivationState = exports.IDerivationState.UP_TO_DATE;
774
+ // Go through all new observables and check diffValue: (this list can contain duplicates):
775
+ // 0: first occurrence, change to 1 and keep it
776
+ // 1: extra occurrence, drop it
777
+ var i0 = 0, l = derivation.unboundDepsCount;
778
+ for (var i = 0; i < l; i++) {
779
+ var dep = observing[i];
780
+ if (dep.diffValue === 0) {
781
+ dep.diffValue = 1;
782
+ if (i0 !== i)
783
+ observing[i0] = dep;
784
+ i0++;
785
+ }
786
+ // Upcast is 'safe' here, because if dep is IObservable, `dependenciesState` will be undefined,
787
+ // not hitting the condition
788
+ if (dep.dependenciesState > lowestNewObservingDerivationState) {
789
+ lowestNewObservingDerivationState = dep.dependenciesState;
790
+ }
791
+ }
792
+ observing.length = i0;
793
+ derivation.newObserving = null; // newObserving shouldn't be needed outside tracking (statement moved down to work around FF bug, see #614)
794
+ // Go through all old observables and check diffValue: (it is unique after last bindDependencies)
795
+ // 0: it's not in new observables, unobserve it
796
+ // 1: it keeps being observed, don't want to notify it. change to 0
797
+ l = prevObserving.length;
798
+ while (l--) {
799
+ var dep = prevObserving[l];
800
+ if (dep.diffValue === 0) {
801
+ removeObserver(dep, derivation);
802
+ }
803
+ dep.diffValue = 0;
804
+ }
805
+ // Go through all new observables and check diffValue: (now it should be unique)
806
+ // 0: it was set to 0 in last loop. don't need to do anything.
807
+ // 1: it wasn't observed, let's observe it. set back to 0
808
+ while (i0--) {
809
+ var dep = observing[i0];
810
+ if (dep.diffValue === 1) {
811
+ dep.diffValue = 0;
812
+ addObserver(dep, derivation);
813
+ }
814
+ }
815
+ // Some new observed derivations may become stale during this derivation computation
816
+ // so they have had no chance to propagate staleness (#916)
817
+ if (lowestNewObservingDerivationState !== exports.IDerivationState.UP_TO_DATE) {
818
+ derivation.dependenciesState = lowestNewObservingDerivationState;
819
+ derivation.onBecomeStale();
820
+ }
821
+ }
822
+ function clearObserving(derivation) {
823
+ // invariant(globalState.inBatch > 0, "INTERNAL ERROR clearObserving should be called only inside batch");
824
+ var obs = derivation.observing;
825
+ derivation.observing = [];
826
+ var i = obs.length;
827
+ while (i--)
828
+ removeObserver(obs[i], derivation);
829
+ derivation.dependenciesState = exports.IDerivationState.NOT_TRACKING;
830
+ }
831
+ function untracked(action) {
832
+ var prev = untrackedStart();
833
+ try {
834
+ return action();
835
+ }
836
+ finally {
837
+ untrackedEnd(prev);
838
+ }
839
+ }
840
+ function untrackedStart() {
841
+ var prev = globalState.trackingDerivation;
842
+ globalState.trackingDerivation = null;
843
+ return prev;
844
+ }
845
+ function untrackedEnd(prev) {
846
+ globalState.trackingDerivation = prev;
847
+ }
848
+ function allowStateReadsStart(allowStateReads) {
849
+ var prev = globalState.allowStateReads;
850
+ globalState.allowStateReads = allowStateReads;
851
+ return prev;
852
+ }
853
+ function allowStateReadsEnd(prev) {
854
+ globalState.allowStateReads = prev;
855
+ }
856
+ /**
857
+ * needed to keep `lowestObserverState` correct. when changing from (2 or 1) to 0
858
+ *
859
+ */
860
+ function changeDependenciesStateTo0(derivation) {
861
+ if (derivation.dependenciesState === exports.IDerivationState.UP_TO_DATE)
862
+ return;
863
+ derivation.dependenciesState = exports.IDerivationState.UP_TO_DATE;
864
+ var obs = derivation.observing;
865
+ var i = obs.length;
866
+ while (i--)
867
+ obs[i].lowestObserverState = exports.IDerivationState.UP_TO_DATE;
868
+ }
869
+
602
870
  function createAction(actionName, fn, ref) {
603
871
  if (process.env.NODE_ENV !== "production") {
604
872
  invariant(typeof fn === "function", "`action` can only be invoked on functions");
@@ -612,25 +880,19 @@
612
880
  return res;
613
881
  }
614
882
  function executeAction(actionName, fn, scope, args) {
615
- var runInfo = startAction(actionName, fn, scope, args);
616
- var shouldSupressReactionError = true;
883
+ var runInfo = _startAction(actionName, scope, args);
617
884
  try {
618
- var res = fn.apply(scope, args);
619
- shouldSupressReactionError = false;
620
- return res;
885
+ return fn.apply(scope, args);
886
+ }
887
+ catch (err) {
888
+ runInfo.error = err;
889
+ throw err;
621
890
  }
622
891
  finally {
623
- if (shouldSupressReactionError) {
624
- globalState.suppressReactionErrors = shouldSupressReactionError;
625
- endAction(runInfo);
626
- globalState.suppressReactionErrors = false;
627
- }
628
- else {
629
- endAction(runInfo);
630
- }
892
+ _endAction(runInfo);
631
893
  }
632
894
  }
633
- function startAction(actionName, fn, scope, args) {
895
+ function _startAction(actionName, scope, args) {
634
896
  var notifySpy = isSpyEnabled() && !!actionName;
635
897
  var startTime = 0;
636
898
  if (notifySpy && process.env.NODE_ENV !== "production") {
@@ -650,19 +912,35 @@
650
912
  var prevDerivation = untrackedStart();
651
913
  startBatch();
652
914
  var prevAllowStateChanges = allowStateChangesStart(true);
653
- return {
915
+ var prevAllowStateReads = allowStateReadsStart(true);
916
+ var runInfo = {
654
917
  prevDerivation: prevDerivation,
655
918
  prevAllowStateChanges: prevAllowStateChanges,
919
+ prevAllowStateReads: prevAllowStateReads,
656
920
  notifySpy: notifySpy,
657
- startTime: startTime
921
+ startTime: startTime,
922
+ actionId: globalState.nextActionId++,
923
+ parentActionId: globalState.currentActionId
658
924
  };
925
+ globalState.currentActionId = runInfo.actionId;
926
+ return runInfo;
659
927
  }
660
- function endAction(runInfo) {
928
+ function _endAction(runInfo) {
929
+ if (globalState.currentActionId !== runInfo.actionId) {
930
+ fail("invalid action stack. did you forget to finish an action?");
931
+ }
932
+ globalState.currentActionId = runInfo.parentActionId;
933
+ if (runInfo.error !== undefined) {
934
+ globalState.suppressReactionErrors = true;
935
+ }
661
936
  allowStateChangesEnd(runInfo.prevAllowStateChanges);
937
+ allowStateReadsEnd(runInfo.prevAllowStateReads);
662
938
  endBatch();
663
939
  untrackedEnd(runInfo.prevDerivation);
664
- if (runInfo.notifySpy && process.env.NODE_ENV !== "production")
940
+ if (runInfo.notifySpy && process.env.NODE_ENV !== "production") {
665
941
  spyReportEnd({ time: Date.now() - runInfo.startTime });
942
+ }
943
+ globalState.suppressReactionErrors = false;
666
944
  }
667
945
  function allowStateChanges(allowStateChanges, func) {
668
946
  var prev = allowStateChangesStart(allowStateChanges);
@@ -956,313 +1234,72 @@
956
1234
  res = this.derivation.call(this.scope);
957
1235
  }
958
1236
  else {
959
- try {
960
- res = this.derivation.call(this.scope);
961
- }
962
- catch (e) {
963
- res = new CaughtException(e);
964
- }
965
- }
966
- }
967
- globalState.computationDepth--;
968
- this.isComputing = false;
969
- return res;
970
- };
971
- ComputedValue.prototype.suspend = function () {
972
- if (!this.keepAlive) {
973
- clearObserving(this);
974
- this.value = undefined; // don't hold on to computed value!
975
- }
976
- };
977
- ComputedValue.prototype.observe = function (listener, fireImmediately) {
978
- var _this = this;
979
- var firstTime = true;
980
- var prevValue = undefined;
981
- return autorun(function () {
982
- var newValue = _this.get();
983
- if (!firstTime || fireImmediately) {
984
- var prevU = untrackedStart();
985
- listener({
986
- type: "update",
987
- object: _this,
988
- newValue: newValue,
989
- oldValue: prevValue
990
- });
991
- untrackedEnd(prevU);
992
- }
993
- firstTime = false;
994
- prevValue = newValue;
995
- });
996
- };
997
- ComputedValue.prototype.warnAboutUntrackedRead = function () {
998
- if (process.env.NODE_ENV === "production")
999
- return;
1000
- if (this.requiresReaction === true) {
1001
- fail("[mobx] Computed value " + this.name + " is read outside a reactive context");
1002
- }
1003
- if (this.isTracing !== TraceMode.NONE) {
1004
- console.log("[mobx.trace] '" + this.name + "' is being read outside a reactive context. Doing a full recompute");
1005
- }
1006
- if (globalState.computedRequiresReaction) {
1007
- console.warn("[mobx] Computed value " + this.name + " is being read outside a reactive context. Doing a full recompute");
1008
- }
1009
- };
1010
- ComputedValue.prototype.toJSON = function () {
1011
- return this.get();
1012
- };
1013
- ComputedValue.prototype.toString = function () {
1014
- return this.name + "[" + this.derivation.toString() + "]";
1015
- };
1016
- ComputedValue.prototype.valueOf = function () {
1017
- return toPrimitive(this.get());
1018
- };
1019
- ComputedValue.prototype[Symbol.toPrimitive] = function () {
1020
- return this.valueOf();
1021
- };
1022
- return ComputedValue;
1023
- }());
1024
- var isComputedValue = createInstanceofPredicate("ComputedValue", ComputedValue);
1025
-
1026
- (function (IDerivationState) {
1027
- // before being run or (outside batch and not being observed)
1028
- // at this point derivation is not holding any data about dependency tree
1029
- IDerivationState[IDerivationState["NOT_TRACKING"] = -1] = "NOT_TRACKING";
1030
- // no shallow dependency changed since last computation
1031
- // won't recalculate derivation
1032
- // this is what makes mobx fast
1033
- IDerivationState[IDerivationState["UP_TO_DATE"] = 0] = "UP_TO_DATE";
1034
- // some deep dependency changed, but don't know if shallow dependency changed
1035
- // will require to check first if UP_TO_DATE or POSSIBLY_STALE
1036
- // currently only ComputedValue will propagate POSSIBLY_STALE
1037
- //
1038
- // having this state is second big optimization:
1039
- // don't have to recompute on every dependency change, but only when it's needed
1040
- IDerivationState[IDerivationState["POSSIBLY_STALE"] = 1] = "POSSIBLY_STALE";
1041
- // A shallow dependency has changed since last computation and the derivation
1042
- // will need to recompute when it's needed next.
1043
- IDerivationState[IDerivationState["STALE"] = 2] = "STALE";
1044
- })(exports.IDerivationState || (exports.IDerivationState = {}));
1045
- var TraceMode;
1046
- (function (TraceMode) {
1047
- TraceMode[TraceMode["NONE"] = 0] = "NONE";
1048
- TraceMode[TraceMode["LOG"] = 1] = "LOG";
1049
- TraceMode[TraceMode["BREAK"] = 2] = "BREAK";
1050
- })(TraceMode || (TraceMode = {}));
1051
- var CaughtException = /** @class */ (function () {
1052
- function CaughtException(cause) {
1053
- this.cause = cause;
1054
- // Empty
1055
- }
1056
- return CaughtException;
1057
- }());
1058
- function isCaughtException(e) {
1059
- return e instanceof CaughtException;
1060
- }
1061
- /**
1062
- * Finds out whether any dependency of the derivation has actually changed.
1063
- * If dependenciesState is 1 then it will recalculate dependencies,
1064
- * if any dependency changed it will propagate it by changing dependenciesState to 2.
1065
- *
1066
- * By iterating over the dependencies in the same order that they were reported and
1067
- * stopping on the first change, all the recalculations are only called for ComputedValues
1068
- * that will be tracked by derivation. That is because we assume that if the first x
1069
- * dependencies of the derivation doesn't change then the derivation should run the same way
1070
- * up until accessing x-th dependency.
1071
- */
1072
- function shouldCompute(derivation) {
1073
- switch (derivation.dependenciesState) {
1074
- case exports.IDerivationState.UP_TO_DATE:
1075
- return false;
1076
- case exports.IDerivationState.NOT_TRACKING:
1077
- case exports.IDerivationState.STALE:
1078
- return true;
1079
- case exports.IDerivationState.POSSIBLY_STALE: {
1080
- var prevUntracked = untrackedStart(); // no need for those computeds to be reported, they will be picked up in trackDerivedFunction.
1081
- var obs = derivation.observing, l = obs.length;
1082
- for (var i = 0; i < l; i++) {
1083
- var obj = obs[i];
1084
- if (isComputedValue(obj)) {
1085
- if (globalState.disableErrorBoundaries) {
1086
- obj.get();
1087
- }
1088
- else {
1089
- try {
1090
- obj.get();
1091
- }
1092
- catch (e) {
1093
- // we are not interested in the value *or* exception at this moment, but if there is one, notify all
1094
- untrackedEnd(prevUntracked);
1095
- return true;
1096
- }
1097
- }
1098
- // if ComputedValue `obj` actually changed it will be computed and propagated to its observers.
1099
- // and `derivation` is an observer of `obj`
1100
- // invariantShouldCompute(derivation)
1101
- if (derivation.dependenciesState === exports.IDerivationState.STALE) {
1102
- untrackedEnd(prevUntracked);
1103
- return true;
1104
- }
1237
+ try {
1238
+ res = this.derivation.call(this.scope);
1239
+ }
1240
+ catch (e) {
1241
+ res = new CaughtException(e);
1105
1242
  }
1106
1243
  }
1107
- changeDependenciesStateTo0(derivation);
1108
- untrackedEnd(prevUntracked);
1109
- return false;
1110
- }
1111
- }
1112
- }
1113
- // function invariantShouldCompute(derivation: IDerivation) {
1114
- // const newDepState = (derivation as any).dependenciesState
1115
- // if (
1116
- // process.env.NODE_ENV === "production" &&
1117
- // (newDepState === IDerivationState.POSSIBLY_STALE ||
1118
- // newDepState === IDerivationState.NOT_TRACKING)
1119
- // )
1120
- // fail("Illegal dependency state")
1121
- // }
1122
- function isComputingDerivation() {
1123
- return globalState.trackingDerivation !== null; // filter out actions inside computations
1124
- }
1125
- function checkIfStateModificationsAreAllowed(atom) {
1126
- var hasObservers = atom.observers.size > 0;
1127
- // Should never be possible to change an observed observable from inside computed, see #798
1128
- if (globalState.computationDepth > 0 && hasObservers)
1129
- fail(process.env.NODE_ENV !== "production" &&
1130
- "Computed values are not allowed to cause side effects by changing observables that are already being observed. Tried to modify: " + atom.name);
1131
- // Should not be possible to change observed state outside strict mode, except during initialization, see #563
1132
- if (!globalState.allowStateChanges && (hasObservers || globalState.enforceActions === "strict"))
1133
- fail(process.env.NODE_ENV !== "production" &&
1134
- (globalState.enforceActions
1135
- ? "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: "
1136
- : "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: ") +
1137
- atom.name);
1138
- }
1139
- /**
1140
- * Executes the provided function `f` and tracks which observables are being accessed.
1141
- * The tracking information is stored on the `derivation` object and the derivation is registered
1142
- * as observer of any of the accessed observables.
1143
- */
1144
- function trackDerivedFunction(derivation, f, context) {
1145
- // pre allocate array allocation + room for variation in deps
1146
- // array will be trimmed by bindDependencies
1147
- changeDependenciesStateTo0(derivation);
1148
- derivation.newObserving = new Array(derivation.observing.length + 100);
1149
- derivation.unboundDepsCount = 0;
1150
- derivation.runId = ++globalState.runId;
1151
- var prevTracking = globalState.trackingDerivation;
1152
- globalState.trackingDerivation = derivation;
1153
- var result;
1154
- if (globalState.disableErrorBoundaries === true) {
1155
- result = f.call(context);
1156
- }
1157
- else {
1158
- try {
1159
- result = f.call(context);
1160
- }
1161
- catch (e) {
1162
- result = new CaughtException(e);
1163
1244
  }
1164
- }
1165
- globalState.trackingDerivation = prevTracking;
1166
- bindDependencies(derivation);
1167
- return result;
1168
- }
1169
- /**
1170
- * diffs newObserving with observing.
1171
- * update observing to be newObserving with unique observables
1172
- * notify observers that become observed/unobserved
1173
- */
1174
- function bindDependencies(derivation) {
1175
- // invariant(derivation.dependenciesState !== IDerivationState.NOT_TRACKING, "INTERNAL ERROR bindDependencies expects derivation.dependenciesState !== -1");
1176
- var prevObserving = derivation.observing;
1177
- var observing = (derivation.observing = derivation.newObserving);
1178
- var lowestNewObservingDerivationState = exports.IDerivationState.UP_TO_DATE;
1179
- // Go through all new observables and check diffValue: (this list can contain duplicates):
1180
- // 0: first occurrence, change to 1 and keep it
1181
- // 1: extra occurrence, drop it
1182
- var i0 = 0, l = derivation.unboundDepsCount;
1183
- for (var i = 0; i < l; i++) {
1184
- var dep = observing[i];
1185
- if (dep.diffValue === 0) {
1186
- dep.diffValue = 1;
1187
- if (i0 !== i)
1188
- observing[i0] = dep;
1189
- i0++;
1245
+ globalState.computationDepth--;
1246
+ this.isComputing = false;
1247
+ return res;
1248
+ };
1249
+ ComputedValue.prototype.suspend = function () {
1250
+ if (!this.keepAlive) {
1251
+ clearObserving(this);
1252
+ this.value = undefined; // don't hold on to computed value!
1190
1253
  }
1191
- // Upcast is 'safe' here, because if dep is IObservable, `dependenciesState` will be undefined,
1192
- // not hitting the condition
1193
- if (dep.dependenciesState > lowestNewObservingDerivationState) {
1194
- lowestNewObservingDerivationState = dep.dependenciesState;
1254
+ };
1255
+ ComputedValue.prototype.observe = function (listener, fireImmediately) {
1256
+ var _this = this;
1257
+ var firstTime = true;
1258
+ var prevValue = undefined;
1259
+ return autorun(function () {
1260
+ var newValue = _this.get();
1261
+ if (!firstTime || fireImmediately) {
1262
+ var prevU = untrackedStart();
1263
+ listener({
1264
+ type: "update",
1265
+ object: _this,
1266
+ newValue: newValue,
1267
+ oldValue: prevValue
1268
+ });
1269
+ untrackedEnd(prevU);
1270
+ }
1271
+ firstTime = false;
1272
+ prevValue = newValue;
1273
+ });
1274
+ };
1275
+ ComputedValue.prototype.warnAboutUntrackedRead = function () {
1276
+ if (process.env.NODE_ENV === "production")
1277
+ return;
1278
+ if (this.requiresReaction === true) {
1279
+ fail("[mobx] Computed value " + this.name + " is read outside a reactive context");
1195
1280
  }
1196
- }
1197
- observing.length = i0;
1198
- derivation.newObserving = null; // newObserving shouldn't be needed outside tracking (statement moved down to work around FF bug, see #614)
1199
- // Go through all old observables and check diffValue: (it is unique after last bindDependencies)
1200
- // 0: it's not in new observables, unobserve it
1201
- // 1: it keeps being observed, don't want to notify it. change to 0
1202
- l = prevObserving.length;
1203
- while (l--) {
1204
- var dep = prevObserving[l];
1205
- if (dep.diffValue === 0) {
1206
- removeObserver(dep, derivation);
1281
+ if (this.isTracing !== TraceMode.NONE) {
1282
+ console.log("[mobx.trace] '" + this.name + "' is being read outside a reactive context. Doing a full recompute");
1207
1283
  }
1208
- dep.diffValue = 0;
1209
- }
1210
- // Go through all new observables and check diffValue: (now it should be unique)
1211
- // 0: it was set to 0 in last loop. don't need to do anything.
1212
- // 1: it wasn't observed, let's observe it. set back to 0
1213
- while (i0--) {
1214
- var dep = observing[i0];
1215
- if (dep.diffValue === 1) {
1216
- dep.diffValue = 0;
1217
- addObserver(dep, derivation);
1284
+ if (globalState.computedRequiresReaction) {
1285
+ console.warn("[mobx] Computed value " + this.name + " is being read outside a reactive context. Doing a full recompute");
1218
1286
  }
1219
- }
1220
- // Some new observed derivations may become stale during this derivation computation
1221
- // so they have had no chance to propagate staleness (#916)
1222
- if (lowestNewObservingDerivationState !== exports.IDerivationState.UP_TO_DATE) {
1223
- derivation.dependenciesState = lowestNewObservingDerivationState;
1224
- derivation.onBecomeStale();
1225
- }
1226
- }
1227
- function clearObserving(derivation) {
1228
- // invariant(globalState.inBatch > 0, "INTERNAL ERROR clearObserving should be called only inside batch");
1229
- var obs = derivation.observing;
1230
- derivation.observing = [];
1231
- var i = obs.length;
1232
- while (i--)
1233
- removeObserver(obs[i], derivation);
1234
- derivation.dependenciesState = exports.IDerivationState.NOT_TRACKING;
1235
- }
1236
- function untracked(action) {
1237
- var prev = untrackedStart();
1238
- try {
1239
- return action();
1240
- }
1241
- finally {
1242
- untrackedEnd(prev);
1243
- }
1244
- }
1245
- function untrackedStart() {
1246
- var prev = globalState.trackingDerivation;
1247
- globalState.trackingDerivation = null;
1248
- return prev;
1249
- }
1250
- function untrackedEnd(prev) {
1251
- globalState.trackingDerivation = prev;
1252
- }
1253
- /**
1254
- * needed to keep `lowestObserverState` correct. when changing from (2 or 1) to 0
1255
- *
1256
- */
1257
- function changeDependenciesStateTo0(derivation) {
1258
- if (derivation.dependenciesState === exports.IDerivationState.UP_TO_DATE)
1259
- return;
1260
- derivation.dependenciesState = exports.IDerivationState.UP_TO_DATE;
1261
- var obs = derivation.observing;
1262
- var i = obs.length;
1263
- while (i--)
1264
- obs[i].lowestObserverState = exports.IDerivationState.UP_TO_DATE;
1265
- }
1287
+ };
1288
+ ComputedValue.prototype.toJSON = function () {
1289
+ return this.get();
1290
+ };
1291
+ ComputedValue.prototype.toString = function () {
1292
+ return this.name + "[" + this.derivation.toString() + "]";
1293
+ };
1294
+ ComputedValue.prototype.valueOf = function () {
1295
+ return toPrimitive(this.get());
1296
+ };
1297
+ ComputedValue.prototype[Symbol.toPrimitive] = function () {
1298
+ return this.valueOf();
1299
+ };
1300
+ return ComputedValue;
1301
+ }());
1302
+ var isComputedValue = createInstanceofPredicate("ComputedValue", ComputedValue);
1266
1303
 
1267
1304
  /**
1268
1305
  * These values will persist if global state is reset
@@ -1272,6 +1309,9 @@
1272
1309
  "spyListeners",
1273
1310
  "enforceActions",
1274
1311
  "computedRequiresReaction",
1312
+ "reactionRequiresObservable",
1313
+ "observableRequiresReaction",
1314
+ "allowStateReads",
1275
1315
  "disableErrorBoundaries",
1276
1316
  "runId",
1277
1317
  "UNCHANGED"
@@ -1332,6 +1372,11 @@
1332
1372
  * To ensure that those functions stay pure.
1333
1373
  */
1334
1374
  this.allowStateChanges = true;
1375
+ /**
1376
+ * Is it allowed to read observables at this point?
1377
+ * Used to hold the state needed for `observableRequiresReaction`
1378
+ */
1379
+ this.allowStateReads = true;
1335
1380
  /**
1336
1381
  * If strict mode is enabled, state changes are by default not allowed
1337
1382
  */
@@ -1348,16 +1393,39 @@
1348
1393
  * Warn if computed values are accessed outside a reactive context
1349
1394
  */
1350
1395
  this.computedRequiresReaction = false;
1396
+ /**
1397
+ * (Experimental)
1398
+ * Warn if you try to create to derivation / reactive context without accessing any observable.
1399
+ */
1400
+ this.reactionRequiresObservable = false;
1401
+ /**
1402
+ * (Experimental)
1403
+ * Warn if observables are accessed outside a reactive context
1404
+ */
1405
+ this.observableRequiresReaction = false;
1406
+ /**
1407
+ * Allows overwriting of computed properties, useful in tests but not prod as it can cause
1408
+ * memory leaks. See https://github.com/mobxjs/mobx/issues/1867
1409
+ */
1410
+ this.computedConfigurable = false;
1351
1411
  /*
1352
1412
  * Don't catch and rethrow exceptions. This is useful for inspecting the state of
1353
1413
  * the stack when an exception occurs while debugging.
1354
1414
  */
1355
1415
  this.disableErrorBoundaries = false;
1356
1416
  /*
1357
- * If true, we are already handling an exception in an action. Any errors in reactions should be supressed, as
1417
+ * If true, we are already handling an exception in an action. Any errors in reactions should be suppressed, as
1358
1418
  * they are not the cause, see: https://github.com/mobxjs/mobx/issues/1836
1359
1419
  */
1360
1420
  this.suppressReactionErrors = false;
1421
+ /*
1422
+ * Current action id.
1423
+ */
1424
+ this.currentActionId = 0;
1425
+ /*
1426
+ * Next action id.
1427
+ */
1428
+ this.nextActionId = 1;
1361
1429
  }
1362
1430
  return MobXGlobals;
1363
1431
  }());
@@ -1414,8 +1482,15 @@
1414
1482
  globalState[key] = defaultGlobals[key];
1415
1483
  globalState.allowStateChanges = !globalState.enforceActions;
1416
1484
  }
1485
+ var mockGlobal = {};
1417
1486
  function getGlobal() {
1418
- return typeof window !== "undefined" ? window : global;
1487
+ if (typeof window !== "undefined") {
1488
+ return window;
1489
+ }
1490
+ if (typeof global !== "undefined") {
1491
+ return global;
1492
+ }
1493
+ return mockGlobal;
1419
1494
  }
1420
1495
 
1421
1496
  function hasObservers(observable) {
@@ -1503,6 +1578,7 @@
1503
1578
  }
1504
1579
  }
1505
1580
  function reportObserved(observable) {
1581
+ checkIfStateReadsAreAllowed(observable);
1506
1582
  var derivation = globalState.trackingDerivation;
1507
1583
  if (derivation !== null) {
1508
1584
  /**
@@ -1616,11 +1692,13 @@
1616
1692
  }
1617
1693
 
1618
1694
  var Reaction = /** @class */ (function () {
1619
- function Reaction(name, onInvalidate, errorHandler) {
1695
+ function Reaction(name, onInvalidate, errorHandler, requiresObservable) {
1620
1696
  if (name === void 0) { name = "Reaction@" + getNextId(); }
1697
+ if (requiresObservable === void 0) { requiresObservable = false; }
1621
1698
  this.name = name;
1622
1699
  this.onInvalidate = onInvalidate;
1623
1700
  this.errorHandler = errorHandler;
1701
+ this.requiresObservable = requiresObservable;
1624
1702
  this.observing = []; // nodes we are looking at. Our value depends on these nodes
1625
1703
  this.newObserving = [];
1626
1704
  this.dependenciesState = exports.IDerivationState.NOT_TRACKING;
@@ -1983,7 +2061,7 @@
1983
2061
  // normal autorun
1984
2062
  reaction = new Reaction(name, function () {
1985
2063
  this.track(reactionRunner);
1986
- }, opts.onError);
2064
+ }, opts.onError, opts.requiresObservable);
1987
2065
  }
1988
2066
  else {
1989
2067
  var scheduler_1 = createSchedulerFromOptions(opts);
@@ -1998,7 +2076,7 @@
1998
2076
  reaction.track(reactionRunner);
1999
2077
  });
2000
2078
  }
2001
- }, opts.onError);
2079
+ }, opts.onError, opts.requiresObservable);
2002
2080
  }
2003
2081
  function reactionRunner() {
2004
2082
  view(reaction);
@@ -2038,7 +2116,7 @@
2038
2116
  isScheduled = true;
2039
2117
  scheduler(reactionRunner);
2040
2118
  }
2041
- }, opts.onError);
2119
+ }, opts.onError, opts.requiresObservable);
2042
2120
  function reactionRunner() {
2043
2121
  isScheduled = false; // Q: move into reaction runner?
2044
2122
  if (r.isDisposed)
@@ -2077,8 +2155,8 @@
2077
2155
  return interceptHook("onBecomeUnobserved", thing, arg2, arg3);
2078
2156
  }
2079
2157
  function interceptHook(hook, thing, arg2, arg3) {
2080
- var atom = typeof arg2 === "string" ? getAtom(thing, arg2) : getAtom(thing);
2081
- var cb = typeof arg2 === "string" ? arg3 : arg2;
2158
+ var atom = typeof arg3 === "function" ? getAtom(thing, arg2) : getAtom(thing);
2159
+ var cb = typeof arg3 === "function" ? arg3 : arg2;
2082
2160
  var listenersKey = hook + "Listeners";
2083
2161
  if (atom[listenersKey]) {
2084
2162
  atom[listenersKey].add(cb);
@@ -2101,7 +2179,7 @@
2101
2179
  }
2102
2180
 
2103
2181
  function configure(options) {
2104
- var enforceActions = options.enforceActions, computedRequiresReaction = options.computedRequiresReaction, disableErrorBoundaries = options.disableErrorBoundaries, reactionScheduler = options.reactionScheduler;
2182
+ var enforceActions = options.enforceActions, computedRequiresReaction = options.computedRequiresReaction, computedConfigurable = options.computedConfigurable, disableErrorBoundaries = options.disableErrorBoundaries, reactionScheduler = options.reactionScheduler, reactionRequiresObservable = options.reactionRequiresObservable, observableRequiresReaction = options.observableRequiresReaction;
2105
2183
  if (options.isolateGlobalState === true) {
2106
2184
  isolateGlobalState();
2107
2185
  }
@@ -2131,6 +2209,16 @@
2131
2209
  if (computedRequiresReaction !== undefined) {
2132
2210
  globalState.computedRequiresReaction = !!computedRequiresReaction;
2133
2211
  }
2212
+ if (reactionRequiresObservable !== undefined) {
2213
+ globalState.reactionRequiresObservable = !!reactionRequiresObservable;
2214
+ }
2215
+ if (observableRequiresReaction !== undefined) {
2216
+ globalState.observableRequiresReaction = !!observableRequiresReaction;
2217
+ globalState.allowStateReads = !globalState.observableRequiresReaction;
2218
+ }
2219
+ if (computedConfigurable !== undefined) {
2220
+ globalState.computedConfigurable = !!computedConfigurable;
2221
+ }
2134
2222
  if (disableErrorBoundaries !== undefined) {
2135
2223
  if (disableErrorBoundaries === true)
2136
2224
  console.warn("WARNING: Debug feature only. MobX will NOT recover from errors when `disableErrorBoundaries` is enabled.");
@@ -2181,40 +2269,61 @@
2181
2269
  return options.defaultDecorator || (options.deep === false ? refDecorator : deepDecorator);
2182
2270
  }
2183
2271
  function extendObservableObjectWithProperties(target, properties, decorators, defaultDecorator) {
2272
+ var e_1, _a, e_2, _b;
2184
2273
  if (process.env.NODE_ENV !== "production") {
2185
2274
  invariant(!isObservable(properties), "Extending an object with another observable (object) is not supported. Please construct an explicit propertymap, using `toJS` if need. See issue #540");
2186
2275
  if (decorators) {
2187
2276
  var keys = getPlainObjectKeys(decorators);
2188
- for (var i in keys) {
2189
- var key = keys[i];
2190
- if (!(key in properties))
2191
- fail("Trying to declare a decorator for unspecified property '" + stringifyKey(key) + "'");
2277
+ try {
2278
+ for (var keys_1 = __values(keys), keys_1_1 = keys_1.next(); !keys_1_1.done; keys_1_1 = keys_1.next()) {
2279
+ var key = keys_1_1.value;
2280
+ if (!(key in properties))
2281
+ fail("Trying to declare a decorator for unspecified property '" + stringifyKey(key) + "'");
2282
+ }
2283
+ }
2284
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
2285
+ finally {
2286
+ try {
2287
+ if (keys_1_1 && !keys_1_1.done && (_a = keys_1.return)) _a.call(keys_1);
2288
+ }
2289
+ finally { if (e_1) throw e_1.error; }
2192
2290
  }
2193
2291
  }
2194
2292
  }
2195
2293
  startBatch();
2196
2294
  try {
2197
2295
  var keys = getPlainObjectKeys(properties);
2198
- for (var i in keys) {
2199
- var key = keys[i];
2200
- var descriptor = Object.getOwnPropertyDescriptor(properties, key);
2201
- if (process.env.NODE_ENV !== "production") {
2202
- if (Object.getOwnPropertyDescriptor(target, key))
2203
- fail("'extendObservable' can only be used to introduce new properties. Use 'set' or 'decorate' instead. The property '" + stringifyKey(key) + "' already exists on '" + target + "'");
2204
- if (isComputed(descriptor.value))
2205
- fail("Passing a 'computed' as initial property value is no longer supported by extendObservable. Use a getter or decorator instead");
2296
+ try {
2297
+ for (var keys_2 = __values(keys), keys_2_1 = keys_2.next(); !keys_2_1.done; keys_2_1 = keys_2.next()) {
2298
+ var key = keys_2_1.value;
2299
+ var descriptor = Object.getOwnPropertyDescriptor(properties, key);
2300
+ if (process.env.NODE_ENV !== "production") {
2301
+ if (!isPlainObject(properties))
2302
+ fail("'extendObservabe' only accepts plain objects as second argument");
2303
+ if (Object.getOwnPropertyDescriptor(target, key))
2304
+ fail("'extendObservable' can only be used to introduce new properties. Use 'set' or 'decorate' instead. The property '" + stringifyKey(key) + "' already exists on '" + target + "'");
2305
+ if (isComputed(descriptor.value))
2306
+ fail("Passing a 'computed' as initial property value is no longer supported by extendObservable. Use a getter or decorator instead");
2307
+ }
2308
+ var decorator = decorators && key in decorators
2309
+ ? decorators[key]
2310
+ : descriptor.get
2311
+ ? computedDecorator
2312
+ : defaultDecorator;
2313
+ if (process.env.NODE_ENV !== "production" && typeof decorator !== "function")
2314
+ fail("Not a valid decorator for '" + stringifyKey(key) + "', got: " + decorator);
2315
+ var resultDescriptor = decorator(target, key, descriptor, true);
2316
+ if (resultDescriptor // otherwise, assume already applied, due to `applyToInstance`
2317
+ )
2318
+ Object.defineProperty(target, key, resultDescriptor);
2319
+ }
2320
+ }
2321
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
2322
+ finally {
2323
+ try {
2324
+ if (keys_2_1 && !keys_2_1.done && (_b = keys_2.return)) _b.call(keys_2);
2206
2325
  }
2207
- var decorator = decorators && key in decorators
2208
- ? decorators[key]
2209
- : descriptor.get
2210
- ? computedDecorator
2211
- : defaultDecorator;
2212
- if (process.env.NODE_ENV !== "production" && typeof decorator !== "function")
2213
- fail("Not a valid decorator for '" + stringifyKey(key) + "', got: " + decorator);
2214
- var resultDescriptor = decorator(target, key, descriptor, true);
2215
- if (resultDescriptor // otherwise, assume already applied, due to `applyToInstance`
2216
- )
2217
- Object.defineProperty(target, key, resultDescriptor);
2326
+ finally { if (e_2) throw e_2.error; }
2218
2327
  }
2219
2328
  }
2220
2329
  finally {
@@ -2909,17 +3018,18 @@
2909
3018
  set: function (target, name, value) {
2910
3019
  if (name === "length") {
2911
3020
  target[$mobx].setArrayLength(value);
2912
- return true;
2913
3021
  }
2914
3022
  if (typeof name === "number") {
2915
3023
  arrayExtensions.set.call(target, name, value);
2916
- return true;
2917
3024
  }
2918
- if (!isNaN(name)) {
3025
+ if (typeof name === "symbol" || isNaN(name)) {
3026
+ target[name] = value;
3027
+ }
3028
+ else {
3029
+ // numeric string
2919
3030
  arrayExtensions.set.call(target, parseInt(name), value);
2920
- return true;
2921
3031
  }
2922
- return false;
3032
+ return true;
2923
3033
  },
2924
3034
  preventExtensions: function (target) {
2925
3035
  fail("Observable arrays cannot be frozen");
@@ -3184,7 +3294,7 @@
3184
3294
  // which makes it both a 'derivation' and a 'mutation'.
3185
3295
  // so we deviate from the default and just make it an dervitation
3186
3296
  if (process.env.NODE_ENV !== "production") {
3187
- console.warn("[mobx] `observableArray.reverse()` will not update the array in place. Use `observableArray.slice().reverse()` to supress this warning and perform the operation on a copy, or `observableArray.replace(observableArray.slice().reverse())` to reverse & update in place");
3297
+ console.warn("[mobx] `observableArray.reverse()` will not update the array in place. Use `observableArray.slice().reverse()` to suppress this warning and perform the operation on a copy, or `observableArray.replace(observableArray.slice().reverse())` to reverse & update in place");
3188
3298
  }
3189
3299
  var clone = this.slice();
3190
3300
  return clone.reverse.apply(clone, arguments);
@@ -3193,7 +3303,7 @@
3193
3303
  // sort by default mutates in place before returning the result
3194
3304
  // which goes against all good practices. Let's not change the array in place!
3195
3305
  if (process.env.NODE_ENV !== "production") {
3196
- console.warn("[mobx] `observableArray.sort()` will not update the array in place. Use `observableArray.slice().sort()` to supress this warning and perform the operation on a copy, or `observableArray.replace(observableArray.slice().sort())` to sort & update in place");
3306
+ console.warn("[mobx] `observableArray.sort()` will not update the array in place. Use `observableArray.slice().sort()` to suppress this warning and perform the operation on a copy, or `observableArray.replace(observableArray.slice().sort())` to sort & update in place");
3197
3307
  }
3198
3308
  var clone = this.slice();
3199
3309
  return clone.sort.apply(clone, arguments);
@@ -3305,9 +3415,17 @@
3305
3415
  return this._data.has(key);
3306
3416
  };
3307
3417
  ObservableMap.prototype.has = function (key) {
3308
- if (this._hasMap.has(key))
3309
- return this._hasMap.get(key).get();
3310
- return this._updateHasMapEntry(key, false).get();
3418
+ var _this = this;
3419
+ if (!globalState.trackingDerivation)
3420
+ return this._has(key);
3421
+ var entry = this._hasMap.get(key);
3422
+ if (!entry) {
3423
+ // todo: replace with atom (breaking change)
3424
+ var newEntry = (entry = new ObservableValue(this._has(key), referenceEnhancer, this.name + "." + stringifyKey(key) + "?", false));
3425
+ this._hasMap.set(key, newEntry);
3426
+ onBecomeUnobserved(newEntry, function () { return _this._hasMap.delete(key); });
3427
+ }
3428
+ return entry.get();
3311
3429
  };
3312
3430
  ObservableMap.prototype.set = function (key, value) {
3313
3431
  var hasKey = this._has(key);
@@ -3370,16 +3488,10 @@
3370
3488
  return false;
3371
3489
  };
3372
3490
  ObservableMap.prototype._updateHasMapEntry = function (key, value) {
3373
- // optimization; don't fill the hasMap if we are not observing, or remove entry if there are no observers anymore
3374
3491
  var entry = this._hasMap.get(key);
3375
3492
  if (entry) {
3376
3493
  entry.setNewValue(value);
3377
3494
  }
3378
- else {
3379
- entry = new ObservableValue(value, referenceEnhancer, this.name + "." + stringifyKey(key) + "?", false);
3380
- this._hasMap.set(key, entry);
3381
- }
3382
- return entry;
3383
3495
  };
3384
3496
  ObservableMap.prototype._updateValue = function (key, newValue) {
3385
3497
  var observable = this._data.get(key);
@@ -4113,7 +4225,7 @@
4113
4225
  function generateComputedPropConfig(propName) {
4114
4226
  return (computedPropertyConfigs[propName] ||
4115
4227
  (computedPropertyConfigs[propName] = {
4116
- configurable: false,
4228
+ configurable: globalState.computedConfigurable,
4117
4229
  enumerable: false,
4118
4230
  get: function () {
4119
4231
  return getAdministrationForComputedPropOwner(this).read(propName);
@@ -4339,17 +4451,17 @@
4339
4451
  }
4340
4452
 
4341
4453
  function makeIterable(iterator) {
4342
- iterator[Symbol.iterator] = self;
4454
+ iterator[Symbol.iterator] = getSelf;
4343
4455
  return iterator;
4344
4456
  }
4345
- function self() {
4457
+ function getSelf() {
4346
4458
  return this;
4347
4459
  }
4348
4460
 
4349
4461
  /*
4350
4462
  The only reason for this file to exist is pure horror:
4351
4463
  Without it rollup can make the bundling fail at any point in time; when it rolls up the files in the wrong order
4352
- it will cause undefined errors (for example because super classes or local variables not being hosted).
4464
+ it will cause undefined errors (for example because super classes or local variables not being hoisted).
4353
4465
  With this file that will still happen,
4354
4466
  but at least in this file we can magically reorder the imports with trial and error until the build succeeds again.
4355
4467
  */
@@ -4381,7 +4493,7 @@
4381
4493
  process.env.NODE_ENV;
4382
4494
  }
4383
4495
  catch (e) {
4384
- var g = typeof window !== "undefined" ? window : global;
4496
+ var g = getGlobal();
4385
4497
  if (typeof process === "undefined")
4386
4498
  g.process = {};
4387
4499
  g.process.env = {};
@@ -4413,11 +4525,13 @@
4413
4525
  exports.Reaction = Reaction;
4414
4526
  exports._allowStateChanges = allowStateChanges;
4415
4527
  exports._allowStateChangesInsideComputed = allowStateChangesInsideComputed;
4528
+ exports._endAction = _endAction;
4416
4529
  exports._getAdministration = getAdministration;
4417
4530
  exports._getGlobalState = getGlobalState;
4418
4531
  exports._interceptReads = interceptReads;
4419
4532
  exports._isComputingDerivation = isComputingDerivation;
4420
4533
  exports._resetGlobalState = resetGlobalState;
4534
+ exports._startAction = _startAction;
4421
4535
  exports.action = action;
4422
4536
  exports.autorun = autorun;
4423
4537
  exports.comparer = comparer;