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