mobx 5.13.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 +6 -1
  2. package/LICENSE +0 -0
  3. package/README.md +0 -0
  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 +10 -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 +0 -0
  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 +1 -0
  27. package/lib/core/atom.d.ts +0 -0
  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 +15 -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 +0 -0
  36. package/lib/mobx.es6.js +303 -246
  37. package/lib/mobx.js +304 -246
  38. package/lib/mobx.js.flow +18 -0
  39. package/lib/mobx.min.js +1 -1
  40. package/lib/mobx.module.js +305 -247
  41. package/lib/mobx.umd.js +304 -246
  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 +1 -1
@@ -593,6 +593,275 @@ var computed = function computed(arg1, arg2, arg3) {
593
593
  };
594
594
  computed.struct = computedStructDecorator;
595
595
 
596
+ var IDerivationState;
597
+ (function (IDerivationState) {
598
+ // before being run or (outside batch and not being observed)
599
+ // at this point derivation is not holding any data about dependency tree
600
+ IDerivationState[IDerivationState["NOT_TRACKING"] = -1] = "NOT_TRACKING";
601
+ // no shallow dependency changed since last computation
602
+ // won't recalculate derivation
603
+ // this is what makes mobx fast
604
+ IDerivationState[IDerivationState["UP_TO_DATE"] = 0] = "UP_TO_DATE";
605
+ // some deep dependency changed, but don't know if shallow dependency changed
606
+ // will require to check first if UP_TO_DATE or POSSIBLY_STALE
607
+ // currently only ComputedValue will propagate POSSIBLY_STALE
608
+ //
609
+ // having this state is second big optimization:
610
+ // don't have to recompute on every dependency change, but only when it's needed
611
+ IDerivationState[IDerivationState["POSSIBLY_STALE"] = 1] = "POSSIBLY_STALE";
612
+ // A shallow dependency has changed since last computation and the derivation
613
+ // will need to recompute when it's needed next.
614
+ IDerivationState[IDerivationState["STALE"] = 2] = "STALE";
615
+ })(IDerivationState || (IDerivationState = {}));
616
+ var TraceMode;
617
+ (function (TraceMode) {
618
+ TraceMode[TraceMode["NONE"] = 0] = "NONE";
619
+ TraceMode[TraceMode["LOG"] = 1] = "LOG";
620
+ TraceMode[TraceMode["BREAK"] = 2] = "BREAK";
621
+ })(TraceMode || (TraceMode = {}));
622
+ var CaughtException = /** @class */ (function () {
623
+ function CaughtException(cause) {
624
+ this.cause = cause;
625
+ // Empty
626
+ }
627
+ return CaughtException;
628
+ }());
629
+ function isCaughtException(e) {
630
+ return e instanceof CaughtException;
631
+ }
632
+ /**
633
+ * Finds out whether any dependency of the derivation has actually changed.
634
+ * If dependenciesState is 1 then it will recalculate dependencies,
635
+ * if any dependency changed it will propagate it by changing dependenciesState to 2.
636
+ *
637
+ * By iterating over the dependencies in the same order that they were reported and
638
+ * stopping on the first change, all the recalculations are only called for ComputedValues
639
+ * that will be tracked by derivation. That is because we assume that if the first x
640
+ * dependencies of the derivation doesn't change then the derivation should run the same way
641
+ * up until accessing x-th dependency.
642
+ */
643
+ function shouldCompute(derivation) {
644
+ switch (derivation.dependenciesState) {
645
+ case IDerivationState.UP_TO_DATE:
646
+ return false;
647
+ case IDerivationState.NOT_TRACKING:
648
+ case IDerivationState.STALE:
649
+ return true;
650
+ case IDerivationState.POSSIBLY_STALE: {
651
+ var prevUntracked = untrackedStart(); // no need for those computeds to be reported, they will be picked up in trackDerivedFunction.
652
+ var obs = derivation.observing, l = obs.length;
653
+ for (var i = 0; i < l; i++) {
654
+ var obj = obs[i];
655
+ if (isComputedValue(obj)) {
656
+ if (globalState.disableErrorBoundaries) {
657
+ obj.get();
658
+ }
659
+ else {
660
+ try {
661
+ obj.get();
662
+ }
663
+ catch (e) {
664
+ // we are not interested in the value *or* exception at this moment, but if there is one, notify all
665
+ untrackedEnd(prevUntracked);
666
+ return true;
667
+ }
668
+ }
669
+ // if ComputedValue `obj` actually changed it will be computed and propagated to its observers.
670
+ // and `derivation` is an observer of `obj`
671
+ // invariantShouldCompute(derivation)
672
+ if (derivation.dependenciesState === IDerivationState.STALE) {
673
+ untrackedEnd(prevUntracked);
674
+ return true;
675
+ }
676
+ }
677
+ }
678
+ changeDependenciesStateTo0(derivation);
679
+ untrackedEnd(prevUntracked);
680
+ return false;
681
+ }
682
+ }
683
+ }
684
+ // function invariantShouldCompute(derivation: IDerivation) {
685
+ // const newDepState = (derivation as any).dependenciesState
686
+ // if (
687
+ // process.env.NODE_ENV === "production" &&
688
+ // (newDepState === IDerivationState.POSSIBLY_STALE ||
689
+ // newDepState === IDerivationState.NOT_TRACKING)
690
+ // )
691
+ // fail("Illegal dependency state")
692
+ // }
693
+ function isComputingDerivation() {
694
+ return globalState.trackingDerivation !== null; // filter out actions inside computations
695
+ }
696
+ function checkIfStateModificationsAreAllowed(atom) {
697
+ var hasObservers = atom.observers.size > 0;
698
+ // Should never be possible to change an observed observable from inside computed, see #798
699
+ if (globalState.computationDepth > 0 && hasObservers)
700
+ fail(process.env.NODE_ENV !== "production" &&
701
+ "Computed values are not allowed to cause side effects by changing observables that are already being observed. Tried to modify: " + atom.name);
702
+ // Should not be possible to change observed state outside strict mode, except during initialization, see #563
703
+ if (!globalState.allowStateChanges && (hasObservers || globalState.enforceActions === "strict"))
704
+ fail(process.env.NODE_ENV !== "production" &&
705
+ (globalState.enforceActions
706
+ ? "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: "
707
+ : "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: ") +
708
+ atom.name);
709
+ }
710
+ function checkIfStateReadsAreAllowed(observable) {
711
+ if (process.env.NODE_ENV !== "production" &&
712
+ !globalState.allowStateReads &&
713
+ globalState.observableRequiresReaction) {
714
+ console.warn("[mobx] Observable " + observable.name + " being read outside a reactive context");
715
+ }
716
+ }
717
+ /**
718
+ * Executes the provided function `f` and tracks which observables are being accessed.
719
+ * The tracking information is stored on the `derivation` object and the derivation is registered
720
+ * as observer of any of the accessed observables.
721
+ */
722
+ function trackDerivedFunction(derivation, f, context) {
723
+ var prevAllowStateReads = allowStateReadsStart(true);
724
+ // pre allocate array allocation + room for variation in deps
725
+ // array will be trimmed by bindDependencies
726
+ changeDependenciesStateTo0(derivation);
727
+ derivation.newObserving = new Array(derivation.observing.length + 100);
728
+ derivation.unboundDepsCount = 0;
729
+ derivation.runId = ++globalState.runId;
730
+ var prevTracking = globalState.trackingDerivation;
731
+ globalState.trackingDerivation = derivation;
732
+ var result;
733
+ if (globalState.disableErrorBoundaries === true) {
734
+ result = f.call(context);
735
+ }
736
+ else {
737
+ try {
738
+ result = f.call(context);
739
+ }
740
+ catch (e) {
741
+ result = new CaughtException(e);
742
+ }
743
+ }
744
+ globalState.trackingDerivation = prevTracking;
745
+ bindDependencies(derivation);
746
+ warnAboutDerivationWithoutDependencies(derivation);
747
+ allowStateReadsEnd(prevAllowStateReads);
748
+ return result;
749
+ }
750
+ function warnAboutDerivationWithoutDependencies(derivation) {
751
+ if (process.env.NODE_ENV === "production")
752
+ return;
753
+ if (derivation.observing.length !== 0)
754
+ return;
755
+ if (globalState.reactionRequiresObservable || derivation.requiresObservable) {
756
+ console.warn("[mobx] Derivation " + derivation.name + " is created/updated without reading any observable value");
757
+ }
758
+ }
759
+ /**
760
+ * diffs newObserving with observing.
761
+ * update observing to be newObserving with unique observables
762
+ * notify observers that become observed/unobserved
763
+ */
764
+ function bindDependencies(derivation) {
765
+ // invariant(derivation.dependenciesState !== IDerivationState.NOT_TRACKING, "INTERNAL ERROR bindDependencies expects derivation.dependenciesState !== -1");
766
+ var prevObserving = derivation.observing;
767
+ var observing = (derivation.observing = derivation.newObserving);
768
+ var lowestNewObservingDerivationState = IDerivationState.UP_TO_DATE;
769
+ // Go through all new observables and check diffValue: (this list can contain duplicates):
770
+ // 0: first occurrence, change to 1 and keep it
771
+ // 1: extra occurrence, drop it
772
+ var i0 = 0, l = derivation.unboundDepsCount;
773
+ for (var i = 0; i < l; i++) {
774
+ var dep = observing[i];
775
+ if (dep.diffValue === 0) {
776
+ dep.diffValue = 1;
777
+ if (i0 !== i)
778
+ observing[i0] = dep;
779
+ i0++;
780
+ }
781
+ // Upcast is 'safe' here, because if dep is IObservable, `dependenciesState` will be undefined,
782
+ // not hitting the condition
783
+ if (dep.dependenciesState > lowestNewObservingDerivationState) {
784
+ lowestNewObservingDerivationState = dep.dependenciesState;
785
+ }
786
+ }
787
+ observing.length = i0;
788
+ derivation.newObserving = null; // newObserving shouldn't be needed outside tracking (statement moved down to work around FF bug, see #614)
789
+ // Go through all old observables and check diffValue: (it is unique after last bindDependencies)
790
+ // 0: it's not in new observables, unobserve it
791
+ // 1: it keeps being observed, don't want to notify it. change to 0
792
+ l = prevObserving.length;
793
+ while (l--) {
794
+ var dep = prevObserving[l];
795
+ if (dep.diffValue === 0) {
796
+ removeObserver(dep, derivation);
797
+ }
798
+ dep.diffValue = 0;
799
+ }
800
+ // Go through all new observables and check diffValue: (now it should be unique)
801
+ // 0: it was set to 0 in last loop. don't need to do anything.
802
+ // 1: it wasn't observed, let's observe it. set back to 0
803
+ while (i0--) {
804
+ var dep = observing[i0];
805
+ if (dep.diffValue === 1) {
806
+ dep.diffValue = 0;
807
+ addObserver(dep, derivation);
808
+ }
809
+ }
810
+ // Some new observed derivations may become stale during this derivation computation
811
+ // so they have had no chance to propagate staleness (#916)
812
+ if (lowestNewObservingDerivationState !== IDerivationState.UP_TO_DATE) {
813
+ derivation.dependenciesState = lowestNewObservingDerivationState;
814
+ derivation.onBecomeStale();
815
+ }
816
+ }
817
+ function clearObserving(derivation) {
818
+ // invariant(globalState.inBatch > 0, "INTERNAL ERROR clearObserving should be called only inside batch");
819
+ var obs = derivation.observing;
820
+ derivation.observing = [];
821
+ var i = obs.length;
822
+ while (i--)
823
+ removeObserver(obs[i], derivation);
824
+ derivation.dependenciesState = IDerivationState.NOT_TRACKING;
825
+ }
826
+ function untracked(action) {
827
+ var prev = untrackedStart();
828
+ try {
829
+ return action();
830
+ }
831
+ finally {
832
+ untrackedEnd(prev);
833
+ }
834
+ }
835
+ function untrackedStart() {
836
+ var prev = globalState.trackingDerivation;
837
+ globalState.trackingDerivation = null;
838
+ return prev;
839
+ }
840
+ function untrackedEnd(prev) {
841
+ globalState.trackingDerivation = prev;
842
+ }
843
+ function allowStateReadsStart(allowStateReads) {
844
+ var prev = globalState.allowStateReads;
845
+ globalState.allowStateReads = allowStateReads;
846
+ return prev;
847
+ }
848
+ function allowStateReadsEnd(prev) {
849
+ globalState.allowStateReads = prev;
850
+ }
851
+ /**
852
+ * needed to keep `lowestObserverState` correct. when changing from (2 or 1) to 0
853
+ *
854
+ */
855
+ function changeDependenciesStateTo0(derivation) {
856
+ if (derivation.dependenciesState === IDerivationState.UP_TO_DATE)
857
+ return;
858
+ derivation.dependenciesState = IDerivationState.UP_TO_DATE;
859
+ var obs = derivation.observing;
860
+ var i = obs.length;
861
+ while (i--)
862
+ obs[i].lowestObserverState = IDerivationState.UP_TO_DATE;
863
+ }
864
+
596
865
  function createAction(actionName, fn, ref) {
597
866
  if (process.env.NODE_ENV !== "production") {
598
867
  invariant(typeof fn === "function", "`action` can only be invoked on functions");
@@ -638,9 +907,11 @@ function _startAction(actionName, scope, args) {
638
907
  var prevDerivation = untrackedStart();
639
908
  startBatch();
640
909
  var prevAllowStateChanges = allowStateChangesStart(true);
910
+ var prevAllowStateReads = allowStateReadsStart(true);
641
911
  var runInfo = {
642
912
  prevDerivation: prevDerivation,
643
913
  prevAllowStateChanges: prevAllowStateChanges,
914
+ prevAllowStateReads: prevAllowStateReads,
644
915
  notifySpy: notifySpy,
645
916
  startTime: startTime,
646
917
  actionId: globalState.nextActionId++,
@@ -658,6 +929,7 @@ function _endAction(runInfo) {
658
929
  globalState.suppressReactionErrors = true;
659
930
  }
660
931
  allowStateChangesEnd(runInfo.prevAllowStateChanges);
932
+ allowStateReadsEnd(runInfo.prevAllowStateReads);
661
933
  endBatch();
662
934
  untrackedEnd(runInfo.prevDerivation);
663
935
  if (runInfo.notifySpy && process.env.NODE_ENV !== "production") {
@@ -1024,248 +1296,6 @@ var ComputedValue = /** @class */ (function () {
1024
1296
  }());
1025
1297
  var isComputedValue = createInstanceofPredicate("ComputedValue", ComputedValue);
1026
1298
 
1027
- var IDerivationState;
1028
- (function (IDerivationState) {
1029
- // before being run or (outside batch and not being observed)
1030
- // at this point derivation is not holding any data about dependency tree
1031
- IDerivationState[IDerivationState["NOT_TRACKING"] = -1] = "NOT_TRACKING";
1032
- // no shallow dependency changed since last computation
1033
- // won't recalculate derivation
1034
- // this is what makes mobx fast
1035
- IDerivationState[IDerivationState["UP_TO_DATE"] = 0] = "UP_TO_DATE";
1036
- // some deep dependency changed, but don't know if shallow dependency changed
1037
- // will require to check first if UP_TO_DATE or POSSIBLY_STALE
1038
- // currently only ComputedValue will propagate POSSIBLY_STALE
1039
- //
1040
- // having this state is second big optimization:
1041
- // don't have to recompute on every dependency change, but only when it's needed
1042
- IDerivationState[IDerivationState["POSSIBLY_STALE"] = 1] = "POSSIBLY_STALE";
1043
- // A shallow dependency has changed since last computation and the derivation
1044
- // will need to recompute when it's needed next.
1045
- IDerivationState[IDerivationState["STALE"] = 2] = "STALE";
1046
- })(IDerivationState || (IDerivationState = {}));
1047
- var TraceMode;
1048
- (function (TraceMode) {
1049
- TraceMode[TraceMode["NONE"] = 0] = "NONE";
1050
- TraceMode[TraceMode["LOG"] = 1] = "LOG";
1051
- TraceMode[TraceMode["BREAK"] = 2] = "BREAK";
1052
- })(TraceMode || (TraceMode = {}));
1053
- var CaughtException = /** @class */ (function () {
1054
- function CaughtException(cause) {
1055
- this.cause = cause;
1056
- // Empty
1057
- }
1058
- return CaughtException;
1059
- }());
1060
- function isCaughtException(e) {
1061
- return e instanceof CaughtException;
1062
- }
1063
- /**
1064
- * Finds out whether any dependency of the derivation has actually changed.
1065
- * If dependenciesState is 1 then it will recalculate dependencies,
1066
- * if any dependency changed it will propagate it by changing dependenciesState to 2.
1067
- *
1068
- * By iterating over the dependencies in the same order that they were reported and
1069
- * stopping on the first change, all the recalculations are only called for ComputedValues
1070
- * that will be tracked by derivation. That is because we assume that if the first x
1071
- * dependencies of the derivation doesn't change then the derivation should run the same way
1072
- * up until accessing x-th dependency.
1073
- */
1074
- function shouldCompute(derivation) {
1075
- switch (derivation.dependenciesState) {
1076
- case IDerivationState.UP_TO_DATE:
1077
- return false;
1078
- case IDerivationState.NOT_TRACKING:
1079
- case IDerivationState.STALE:
1080
- return true;
1081
- case IDerivationState.POSSIBLY_STALE: {
1082
- var prevUntracked = untrackedStart(); // no need for those computeds to be reported, they will be picked up in trackDerivedFunction.
1083
- var obs = derivation.observing, l = obs.length;
1084
- for (var i = 0; i < l; i++) {
1085
- var obj = obs[i];
1086
- if (isComputedValue(obj)) {
1087
- if (globalState.disableErrorBoundaries) {
1088
- obj.get();
1089
- }
1090
- else {
1091
- try {
1092
- obj.get();
1093
- }
1094
- catch (e) {
1095
- // we are not interested in the value *or* exception at this moment, but if there is one, notify all
1096
- untrackedEnd(prevUntracked);
1097
- return true;
1098
- }
1099
- }
1100
- // if ComputedValue `obj` actually changed it will be computed and propagated to its observers.
1101
- // and `derivation` is an observer of `obj`
1102
- // invariantShouldCompute(derivation)
1103
- if (derivation.dependenciesState === IDerivationState.STALE) {
1104
- untrackedEnd(prevUntracked);
1105
- return true;
1106
- }
1107
- }
1108
- }
1109
- changeDependenciesStateTo0(derivation);
1110
- untrackedEnd(prevUntracked);
1111
- return false;
1112
- }
1113
- }
1114
- }
1115
- // function invariantShouldCompute(derivation: IDerivation) {
1116
- // const newDepState = (derivation as any).dependenciesState
1117
- // if (
1118
- // process.env.NODE_ENV === "production" &&
1119
- // (newDepState === IDerivationState.POSSIBLY_STALE ||
1120
- // newDepState === IDerivationState.NOT_TRACKING)
1121
- // )
1122
- // fail("Illegal dependency state")
1123
- // }
1124
- function isComputingDerivation() {
1125
- return globalState.trackingDerivation !== null; // filter out actions inside computations
1126
- }
1127
- function checkIfStateModificationsAreAllowed(atom) {
1128
- var hasObservers = atom.observers.size > 0;
1129
- // Should never be possible to change an observed observable from inside computed, see #798
1130
- if (globalState.computationDepth > 0 && hasObservers)
1131
- fail(process.env.NODE_ENV !== "production" &&
1132
- "Computed values are not allowed to cause side effects by changing observables that are already being observed. Tried to modify: " + atom.name);
1133
- // Should not be possible to change observed state outside strict mode, except during initialization, see #563
1134
- if (!globalState.allowStateChanges && (hasObservers || globalState.enforceActions === "strict"))
1135
- fail(process.env.NODE_ENV !== "production" &&
1136
- (globalState.enforceActions
1137
- ? "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: "
1138
- : "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: ") +
1139
- atom.name);
1140
- }
1141
- /**
1142
- * Executes the provided function `f` and tracks which observables are being accessed.
1143
- * The tracking information is stored on the `derivation` object and the derivation is registered
1144
- * as observer of any of the accessed observables.
1145
- */
1146
- function trackDerivedFunction(derivation, f, context) {
1147
- // pre allocate array allocation + room for variation in deps
1148
- // array will be trimmed by bindDependencies
1149
- changeDependenciesStateTo0(derivation);
1150
- derivation.newObserving = new Array(derivation.observing.length + 100);
1151
- derivation.unboundDepsCount = 0;
1152
- derivation.runId = ++globalState.runId;
1153
- var prevTracking = globalState.trackingDerivation;
1154
- globalState.trackingDerivation = derivation;
1155
- var result;
1156
- if (globalState.disableErrorBoundaries === true) {
1157
- result = f.call(context);
1158
- }
1159
- else {
1160
- try {
1161
- result = f.call(context);
1162
- }
1163
- catch (e) {
1164
- result = new CaughtException(e);
1165
- }
1166
- }
1167
- globalState.trackingDerivation = prevTracking;
1168
- bindDependencies(derivation);
1169
- return result;
1170
- }
1171
- /**
1172
- * diffs newObserving with observing.
1173
- * update observing to be newObserving with unique observables
1174
- * notify observers that become observed/unobserved
1175
- */
1176
- function bindDependencies(derivation) {
1177
- // invariant(derivation.dependenciesState !== IDerivationState.NOT_TRACKING, "INTERNAL ERROR bindDependencies expects derivation.dependenciesState !== -1");
1178
- var prevObserving = derivation.observing;
1179
- var observing = (derivation.observing = derivation.newObserving);
1180
- var lowestNewObservingDerivationState = IDerivationState.UP_TO_DATE;
1181
- // Go through all new observables and check diffValue: (this list can contain duplicates):
1182
- // 0: first occurrence, change to 1 and keep it
1183
- // 1: extra occurrence, drop it
1184
- var i0 = 0, l = derivation.unboundDepsCount;
1185
- for (var i = 0; i < l; i++) {
1186
- var dep = observing[i];
1187
- if (dep.diffValue === 0) {
1188
- dep.diffValue = 1;
1189
- if (i0 !== i)
1190
- observing[i0] = dep;
1191
- i0++;
1192
- }
1193
- // Upcast is 'safe' here, because if dep is IObservable, `dependenciesState` will be undefined,
1194
- // not hitting the condition
1195
- if (dep.dependenciesState > lowestNewObservingDerivationState) {
1196
- lowestNewObservingDerivationState = dep.dependenciesState;
1197
- }
1198
- }
1199
- observing.length = i0;
1200
- derivation.newObserving = null; // newObserving shouldn't be needed outside tracking (statement moved down to work around FF bug, see #614)
1201
- // Go through all old observables and check diffValue: (it is unique after last bindDependencies)
1202
- // 0: it's not in new observables, unobserve it
1203
- // 1: it keeps being observed, don't want to notify it. change to 0
1204
- l = prevObserving.length;
1205
- while (l--) {
1206
- var dep = prevObserving[l];
1207
- if (dep.diffValue === 0) {
1208
- removeObserver(dep, derivation);
1209
- }
1210
- dep.diffValue = 0;
1211
- }
1212
- // Go through all new observables and check diffValue: (now it should be unique)
1213
- // 0: it was set to 0 in last loop. don't need to do anything.
1214
- // 1: it wasn't observed, let's observe it. set back to 0
1215
- while (i0--) {
1216
- var dep = observing[i0];
1217
- if (dep.diffValue === 1) {
1218
- dep.diffValue = 0;
1219
- addObserver(dep, derivation);
1220
- }
1221
- }
1222
- // Some new observed derivations may become stale during this derivation computation
1223
- // so they have had no chance to propagate staleness (#916)
1224
- if (lowestNewObservingDerivationState !== IDerivationState.UP_TO_DATE) {
1225
- derivation.dependenciesState = lowestNewObservingDerivationState;
1226
- derivation.onBecomeStale();
1227
- }
1228
- }
1229
- function clearObserving(derivation) {
1230
- // invariant(globalState.inBatch > 0, "INTERNAL ERROR clearObserving should be called only inside batch");
1231
- var obs = derivation.observing;
1232
- derivation.observing = [];
1233
- var i = obs.length;
1234
- while (i--)
1235
- removeObserver(obs[i], derivation);
1236
- derivation.dependenciesState = IDerivationState.NOT_TRACKING;
1237
- }
1238
- function untracked(action) {
1239
- var prev = untrackedStart();
1240
- try {
1241
- return action();
1242
- }
1243
- finally {
1244
- untrackedEnd(prev);
1245
- }
1246
- }
1247
- function untrackedStart() {
1248
- var prev = globalState.trackingDerivation;
1249
- globalState.trackingDerivation = null;
1250
- return prev;
1251
- }
1252
- function untrackedEnd(prev) {
1253
- globalState.trackingDerivation = prev;
1254
- }
1255
- /**
1256
- * needed to keep `lowestObserverState` correct. when changing from (2 or 1) to 0
1257
- *
1258
- */
1259
- function changeDependenciesStateTo0(derivation) {
1260
- if (derivation.dependenciesState === IDerivationState.UP_TO_DATE)
1261
- return;
1262
- derivation.dependenciesState = IDerivationState.UP_TO_DATE;
1263
- var obs = derivation.observing;
1264
- var i = obs.length;
1265
- while (i--)
1266
- obs[i].lowestObserverState = IDerivationState.UP_TO_DATE;
1267
- }
1268
-
1269
1299
  /**
1270
1300
  * These values will persist if global state is reset
1271
1301
  */
@@ -1274,6 +1304,9 @@ var persistentKeys = [
1274
1304
  "spyListeners",
1275
1305
  "enforceActions",
1276
1306
  "computedRequiresReaction",
1307
+ "reactionRequiresObservable",
1308
+ "observableRequiresReaction",
1309
+ "allowStateReads",
1277
1310
  "disableErrorBoundaries",
1278
1311
  "runId",
1279
1312
  "UNCHANGED"
@@ -1334,6 +1367,11 @@ var MobXGlobals = /** @class */ (function () {
1334
1367
  * To ensure that those functions stay pure.
1335
1368
  */
1336
1369
  this.allowStateChanges = true;
1370
+ /**
1371
+ * Is it allowed to read observables at this point?
1372
+ * Used to hold the state needed for `observableRequiresReaction`
1373
+ */
1374
+ this.allowStateReads = true;
1337
1375
  /**
1338
1376
  * If strict mode is enabled, state changes are by default not allowed
1339
1377
  */
@@ -1350,6 +1388,16 @@ var MobXGlobals = /** @class */ (function () {
1350
1388
  * Warn if computed values are accessed outside a reactive context
1351
1389
  */
1352
1390
  this.computedRequiresReaction = false;
1391
+ /**
1392
+ * (Experimental)
1393
+ * Warn if you try to create to derivation / reactive context without accessing any observable.
1394
+ */
1395
+ this.reactionRequiresObservable = false;
1396
+ /**
1397
+ * (Experimental)
1398
+ * Warn if observables are accessed outside a reactive context
1399
+ */
1400
+ this.observableRequiresReaction = false;
1353
1401
  /**
1354
1402
  * Allows overwriting of computed properties, useful in tests but not prod as it can cause
1355
1403
  * memory leaks. See https://github.com/mobxjs/mobx/issues/1867
@@ -1525,6 +1573,7 @@ function endBatch() {
1525
1573
  }
1526
1574
  }
1527
1575
  function reportObserved(observable) {
1576
+ checkIfStateReadsAreAllowed(observable);
1528
1577
  var derivation = globalState.trackingDerivation;
1529
1578
  if (derivation !== null) {
1530
1579
  /**
@@ -1638,11 +1687,13 @@ function printDepTree(tree, lines, depth) {
1638
1687
  }
1639
1688
 
1640
1689
  var Reaction = /** @class */ (function () {
1641
- function Reaction(name, onInvalidate, errorHandler) {
1690
+ function Reaction(name, onInvalidate, errorHandler, requiresObservable) {
1642
1691
  if (name === void 0) { name = "Reaction@" + getNextId(); }
1692
+ if (requiresObservable === void 0) { requiresObservable = false; }
1643
1693
  this.name = name;
1644
1694
  this.onInvalidate = onInvalidate;
1645
1695
  this.errorHandler = errorHandler;
1696
+ this.requiresObservable = requiresObservable;
1646
1697
  this.observing = []; // nodes we are looking at. Our value depends on these nodes
1647
1698
  this.newObserving = [];
1648
1699
  this.dependenciesState = IDerivationState.NOT_TRACKING;
@@ -2005,7 +2056,7 @@ function autorun(view, opts) {
2005
2056
  // normal autorun
2006
2057
  reaction = new Reaction(name, function () {
2007
2058
  this.track(reactionRunner);
2008
- }, opts.onError);
2059
+ }, opts.onError, opts.requiresObservable);
2009
2060
  }
2010
2061
  else {
2011
2062
  var scheduler_1 = createSchedulerFromOptions(opts);
@@ -2020,7 +2071,7 @@ function autorun(view, opts) {
2020
2071
  reaction.track(reactionRunner);
2021
2072
  });
2022
2073
  }
2023
- }, opts.onError);
2074
+ }, opts.onError, opts.requiresObservable);
2024
2075
  }
2025
2076
  function reactionRunner() {
2026
2077
  view(reaction);
@@ -2060,7 +2111,7 @@ function reaction(expression, effect, opts) {
2060
2111
  isScheduled = true;
2061
2112
  scheduler(reactionRunner);
2062
2113
  }
2063
- }, opts.onError);
2114
+ }, opts.onError, opts.requiresObservable);
2064
2115
  function reactionRunner() {
2065
2116
  isScheduled = false; // Q: move into reaction runner?
2066
2117
  if (r.isDisposed)
@@ -2123,7 +2174,7 @@ function interceptHook(hook, thing, arg2, arg3) {
2123
2174
  }
2124
2175
 
2125
2176
  function configure(options) {
2126
- var enforceActions = options.enforceActions, computedRequiresReaction = options.computedRequiresReaction, computedConfigurable = options.computedConfigurable, disableErrorBoundaries = options.disableErrorBoundaries, reactionScheduler = options.reactionScheduler;
2177
+ var enforceActions = options.enforceActions, computedRequiresReaction = options.computedRequiresReaction, computedConfigurable = options.computedConfigurable, disableErrorBoundaries = options.disableErrorBoundaries, reactionScheduler = options.reactionScheduler, reactionRequiresObservable = options.reactionRequiresObservable, observableRequiresReaction = options.observableRequiresReaction;
2127
2178
  if (options.isolateGlobalState === true) {
2128
2179
  isolateGlobalState();
2129
2180
  }
@@ -2153,6 +2204,13 @@ function configure(options) {
2153
2204
  if (computedRequiresReaction !== undefined) {
2154
2205
  globalState.computedRequiresReaction = !!computedRequiresReaction;
2155
2206
  }
2207
+ if (reactionRequiresObservable !== undefined) {
2208
+ globalState.reactionRequiresObservable = !!reactionRequiresObservable;
2209
+ }
2210
+ if (observableRequiresReaction !== undefined) {
2211
+ globalState.observableRequiresReaction = !!observableRequiresReaction;
2212
+ globalState.allowStateReads = !globalState.observableRequiresReaction;
2213
+ }
2156
2214
  if (computedConfigurable !== undefined) {
2157
2215
  globalState.computedConfigurable = !!computedConfigurable;
2158
2216
  }