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
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");
@@ -644,9 +912,11 @@
644
912
  var prevDerivation = untrackedStart();
645
913
  startBatch();
646
914
  var prevAllowStateChanges = allowStateChangesStart(true);
915
+ var prevAllowStateReads = allowStateReadsStart(true);
647
916
  var runInfo = {
648
917
  prevDerivation: prevDerivation,
649
918
  prevAllowStateChanges: prevAllowStateChanges,
919
+ prevAllowStateReads: prevAllowStateReads,
650
920
  notifySpy: notifySpy,
651
921
  startTime: startTime,
652
922
  actionId: globalState.nextActionId++,
@@ -664,6 +934,7 @@
664
934
  globalState.suppressReactionErrors = true;
665
935
  }
666
936
  allowStateChangesEnd(runInfo.prevAllowStateChanges);
937
+ allowStateReadsEnd(runInfo.prevAllowStateReads);
667
938
  endBatch();
668
939
  untrackedEnd(runInfo.prevDerivation);
669
940
  if (runInfo.notifySpy && process.env.NODE_ENV !== "production") {
@@ -1030,247 +1301,6 @@
1030
1301
  }());
1031
1302
  var isComputedValue = createInstanceofPredicate("ComputedValue", ComputedValue);
1032
1303
 
1033
- (function (IDerivationState) {
1034
- // before being run or (outside batch and not being observed)
1035
- // at this point derivation is not holding any data about dependency tree
1036
- IDerivationState[IDerivationState["NOT_TRACKING"] = -1] = "NOT_TRACKING";
1037
- // no shallow dependency changed since last computation
1038
- // won't recalculate derivation
1039
- // this is what makes mobx fast
1040
- IDerivationState[IDerivationState["UP_TO_DATE"] = 0] = "UP_TO_DATE";
1041
- // some deep dependency changed, but don't know if shallow dependency changed
1042
- // will require to check first if UP_TO_DATE or POSSIBLY_STALE
1043
- // currently only ComputedValue will propagate POSSIBLY_STALE
1044
- //
1045
- // having this state is second big optimization:
1046
- // don't have to recompute on every dependency change, but only when it's needed
1047
- IDerivationState[IDerivationState["POSSIBLY_STALE"] = 1] = "POSSIBLY_STALE";
1048
- // A shallow dependency has changed since last computation and the derivation
1049
- // will need to recompute when it's needed next.
1050
- IDerivationState[IDerivationState["STALE"] = 2] = "STALE";
1051
- })(exports.IDerivationState || (exports.IDerivationState = {}));
1052
- var TraceMode;
1053
- (function (TraceMode) {
1054
- TraceMode[TraceMode["NONE"] = 0] = "NONE";
1055
- TraceMode[TraceMode["LOG"] = 1] = "LOG";
1056
- TraceMode[TraceMode["BREAK"] = 2] = "BREAK";
1057
- })(TraceMode || (TraceMode = {}));
1058
- var CaughtException = /** @class */ (function () {
1059
- function CaughtException(cause) {
1060
- this.cause = cause;
1061
- // Empty
1062
- }
1063
- return CaughtException;
1064
- }());
1065
- function isCaughtException(e) {
1066
- return e instanceof CaughtException;
1067
- }
1068
- /**
1069
- * Finds out whether any dependency of the derivation has actually changed.
1070
- * If dependenciesState is 1 then it will recalculate dependencies,
1071
- * if any dependency changed it will propagate it by changing dependenciesState to 2.
1072
- *
1073
- * By iterating over the dependencies in the same order that they were reported and
1074
- * stopping on the first change, all the recalculations are only called for ComputedValues
1075
- * that will be tracked by derivation. That is because we assume that if the first x
1076
- * dependencies of the derivation doesn't change then the derivation should run the same way
1077
- * up until accessing x-th dependency.
1078
- */
1079
- function shouldCompute(derivation) {
1080
- switch (derivation.dependenciesState) {
1081
- case exports.IDerivationState.UP_TO_DATE:
1082
- return false;
1083
- case exports.IDerivationState.NOT_TRACKING:
1084
- case exports.IDerivationState.STALE:
1085
- return true;
1086
- case exports.IDerivationState.POSSIBLY_STALE: {
1087
- var prevUntracked = untrackedStart(); // no need for those computeds to be reported, they will be picked up in trackDerivedFunction.
1088
- var obs = derivation.observing, l = obs.length;
1089
- for (var i = 0; i < l; i++) {
1090
- var obj = obs[i];
1091
- if (isComputedValue(obj)) {
1092
- if (globalState.disableErrorBoundaries) {
1093
- obj.get();
1094
- }
1095
- else {
1096
- try {
1097
- obj.get();
1098
- }
1099
- catch (e) {
1100
- // we are not interested in the value *or* exception at this moment, but if there is one, notify all
1101
- untrackedEnd(prevUntracked);
1102
- return true;
1103
- }
1104
- }
1105
- // if ComputedValue `obj` actually changed it will be computed and propagated to its observers.
1106
- // and `derivation` is an observer of `obj`
1107
- // invariantShouldCompute(derivation)
1108
- if (derivation.dependenciesState === exports.IDerivationState.STALE) {
1109
- untrackedEnd(prevUntracked);
1110
- return true;
1111
- }
1112
- }
1113
- }
1114
- changeDependenciesStateTo0(derivation);
1115
- untrackedEnd(prevUntracked);
1116
- return false;
1117
- }
1118
- }
1119
- }
1120
- // function invariantShouldCompute(derivation: IDerivation) {
1121
- // const newDepState = (derivation as any).dependenciesState
1122
- // if (
1123
- // process.env.NODE_ENV === "production" &&
1124
- // (newDepState === IDerivationState.POSSIBLY_STALE ||
1125
- // newDepState === IDerivationState.NOT_TRACKING)
1126
- // )
1127
- // fail("Illegal dependency state")
1128
- // }
1129
- function isComputingDerivation() {
1130
- return globalState.trackingDerivation !== null; // filter out actions inside computations
1131
- }
1132
- function checkIfStateModificationsAreAllowed(atom) {
1133
- var hasObservers = atom.observers.size > 0;
1134
- // Should never be possible to change an observed observable from inside computed, see #798
1135
- if (globalState.computationDepth > 0 && hasObservers)
1136
- fail(process.env.NODE_ENV !== "production" &&
1137
- "Computed values are not allowed to cause side effects by changing observables that are already being observed. Tried to modify: " + atom.name);
1138
- // Should not be possible to change observed state outside strict mode, except during initialization, see #563
1139
- if (!globalState.allowStateChanges && (hasObservers || globalState.enforceActions === "strict"))
1140
- fail(process.env.NODE_ENV !== "production" &&
1141
- (globalState.enforceActions
1142
- ? "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: "
1143
- : "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: ") +
1144
- atom.name);
1145
- }
1146
- /**
1147
- * Executes the provided function `f` and tracks which observables are being accessed.
1148
- * The tracking information is stored on the `derivation` object and the derivation is registered
1149
- * as observer of any of the accessed observables.
1150
- */
1151
- function trackDerivedFunction(derivation, f, context) {
1152
- // pre allocate array allocation + room for variation in deps
1153
- // array will be trimmed by bindDependencies
1154
- changeDependenciesStateTo0(derivation);
1155
- derivation.newObserving = new Array(derivation.observing.length + 100);
1156
- derivation.unboundDepsCount = 0;
1157
- derivation.runId = ++globalState.runId;
1158
- var prevTracking = globalState.trackingDerivation;
1159
- globalState.trackingDerivation = derivation;
1160
- var result;
1161
- if (globalState.disableErrorBoundaries === true) {
1162
- result = f.call(context);
1163
- }
1164
- else {
1165
- try {
1166
- result = f.call(context);
1167
- }
1168
- catch (e) {
1169
- result = new CaughtException(e);
1170
- }
1171
- }
1172
- globalState.trackingDerivation = prevTracking;
1173
- bindDependencies(derivation);
1174
- return result;
1175
- }
1176
- /**
1177
- * diffs newObserving with observing.
1178
- * update observing to be newObserving with unique observables
1179
- * notify observers that become observed/unobserved
1180
- */
1181
- function bindDependencies(derivation) {
1182
- // invariant(derivation.dependenciesState !== IDerivationState.NOT_TRACKING, "INTERNAL ERROR bindDependencies expects derivation.dependenciesState !== -1");
1183
- var prevObserving = derivation.observing;
1184
- var observing = (derivation.observing = derivation.newObserving);
1185
- var lowestNewObservingDerivationState = exports.IDerivationState.UP_TO_DATE;
1186
- // Go through all new observables and check diffValue: (this list can contain duplicates):
1187
- // 0: first occurrence, change to 1 and keep it
1188
- // 1: extra occurrence, drop it
1189
- var i0 = 0, l = derivation.unboundDepsCount;
1190
- for (var i = 0; i < l; i++) {
1191
- var dep = observing[i];
1192
- if (dep.diffValue === 0) {
1193
- dep.diffValue = 1;
1194
- if (i0 !== i)
1195
- observing[i0] = dep;
1196
- i0++;
1197
- }
1198
- // Upcast is 'safe' here, because if dep is IObservable, `dependenciesState` will be undefined,
1199
- // not hitting the condition
1200
- if (dep.dependenciesState > lowestNewObservingDerivationState) {
1201
- lowestNewObservingDerivationState = dep.dependenciesState;
1202
- }
1203
- }
1204
- observing.length = i0;
1205
- derivation.newObserving = null; // newObserving shouldn't be needed outside tracking (statement moved down to work around FF bug, see #614)
1206
- // Go through all old observables and check diffValue: (it is unique after last bindDependencies)
1207
- // 0: it's not in new observables, unobserve it
1208
- // 1: it keeps being observed, don't want to notify it. change to 0
1209
- l = prevObserving.length;
1210
- while (l--) {
1211
- var dep = prevObserving[l];
1212
- if (dep.diffValue === 0) {
1213
- removeObserver(dep, derivation);
1214
- }
1215
- dep.diffValue = 0;
1216
- }
1217
- // Go through all new observables and check diffValue: (now it should be unique)
1218
- // 0: it was set to 0 in last loop. don't need to do anything.
1219
- // 1: it wasn't observed, let's observe it. set back to 0
1220
- while (i0--) {
1221
- var dep = observing[i0];
1222
- if (dep.diffValue === 1) {
1223
- dep.diffValue = 0;
1224
- addObserver(dep, derivation);
1225
- }
1226
- }
1227
- // Some new observed derivations may become stale during this derivation computation
1228
- // so they have had no chance to propagate staleness (#916)
1229
- if (lowestNewObservingDerivationState !== exports.IDerivationState.UP_TO_DATE) {
1230
- derivation.dependenciesState = lowestNewObservingDerivationState;
1231
- derivation.onBecomeStale();
1232
- }
1233
- }
1234
- function clearObserving(derivation) {
1235
- // invariant(globalState.inBatch > 0, "INTERNAL ERROR clearObserving should be called only inside batch");
1236
- var obs = derivation.observing;
1237
- derivation.observing = [];
1238
- var i = obs.length;
1239
- while (i--)
1240
- removeObserver(obs[i], derivation);
1241
- derivation.dependenciesState = exports.IDerivationState.NOT_TRACKING;
1242
- }
1243
- function untracked(action) {
1244
- var prev = untrackedStart();
1245
- try {
1246
- return action();
1247
- }
1248
- finally {
1249
- untrackedEnd(prev);
1250
- }
1251
- }
1252
- function untrackedStart() {
1253
- var prev = globalState.trackingDerivation;
1254
- globalState.trackingDerivation = null;
1255
- return prev;
1256
- }
1257
- function untrackedEnd(prev) {
1258
- globalState.trackingDerivation = prev;
1259
- }
1260
- /**
1261
- * needed to keep `lowestObserverState` correct. when changing from (2 or 1) to 0
1262
- *
1263
- */
1264
- function changeDependenciesStateTo0(derivation) {
1265
- if (derivation.dependenciesState === exports.IDerivationState.UP_TO_DATE)
1266
- return;
1267
- derivation.dependenciesState = exports.IDerivationState.UP_TO_DATE;
1268
- var obs = derivation.observing;
1269
- var i = obs.length;
1270
- while (i--)
1271
- obs[i].lowestObserverState = exports.IDerivationState.UP_TO_DATE;
1272
- }
1273
-
1274
1304
  /**
1275
1305
  * These values will persist if global state is reset
1276
1306
  */
@@ -1279,6 +1309,9 @@
1279
1309
  "spyListeners",
1280
1310
  "enforceActions",
1281
1311
  "computedRequiresReaction",
1312
+ "reactionRequiresObservable",
1313
+ "observableRequiresReaction",
1314
+ "allowStateReads",
1282
1315
  "disableErrorBoundaries",
1283
1316
  "runId",
1284
1317
  "UNCHANGED"
@@ -1339,6 +1372,11 @@
1339
1372
  * To ensure that those functions stay pure.
1340
1373
  */
1341
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;
1342
1380
  /**
1343
1381
  * If strict mode is enabled, state changes are by default not allowed
1344
1382
  */
@@ -1355,6 +1393,16 @@
1355
1393
  * Warn if computed values are accessed outside a reactive context
1356
1394
  */
1357
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;
1358
1406
  /**
1359
1407
  * Allows overwriting of computed properties, useful in tests but not prod as it can cause
1360
1408
  * memory leaks. See https://github.com/mobxjs/mobx/issues/1867
@@ -1530,6 +1578,7 @@
1530
1578
  }
1531
1579
  }
1532
1580
  function reportObserved(observable) {
1581
+ checkIfStateReadsAreAllowed(observable);
1533
1582
  var derivation = globalState.trackingDerivation;
1534
1583
  if (derivation !== null) {
1535
1584
  /**
@@ -1643,11 +1692,13 @@
1643
1692
  }
1644
1693
 
1645
1694
  var Reaction = /** @class */ (function () {
1646
- function Reaction(name, onInvalidate, errorHandler) {
1695
+ function Reaction(name, onInvalidate, errorHandler, requiresObservable) {
1647
1696
  if (name === void 0) { name = "Reaction@" + getNextId(); }
1697
+ if (requiresObservable === void 0) { requiresObservable = false; }
1648
1698
  this.name = name;
1649
1699
  this.onInvalidate = onInvalidate;
1650
1700
  this.errorHandler = errorHandler;
1701
+ this.requiresObservable = requiresObservable;
1651
1702
  this.observing = []; // nodes we are looking at. Our value depends on these nodes
1652
1703
  this.newObserving = [];
1653
1704
  this.dependenciesState = exports.IDerivationState.NOT_TRACKING;
@@ -2010,7 +2061,7 @@
2010
2061
  // normal autorun
2011
2062
  reaction = new Reaction(name, function () {
2012
2063
  this.track(reactionRunner);
2013
- }, opts.onError);
2064
+ }, opts.onError, opts.requiresObservable);
2014
2065
  }
2015
2066
  else {
2016
2067
  var scheduler_1 = createSchedulerFromOptions(opts);
@@ -2025,7 +2076,7 @@
2025
2076
  reaction.track(reactionRunner);
2026
2077
  });
2027
2078
  }
2028
- }, opts.onError);
2079
+ }, opts.onError, opts.requiresObservable);
2029
2080
  }
2030
2081
  function reactionRunner() {
2031
2082
  view(reaction);
@@ -2065,7 +2116,7 @@
2065
2116
  isScheduled = true;
2066
2117
  scheduler(reactionRunner);
2067
2118
  }
2068
- }, opts.onError);
2119
+ }, opts.onError, opts.requiresObservable);
2069
2120
  function reactionRunner() {
2070
2121
  isScheduled = false; // Q: move into reaction runner?
2071
2122
  if (r.isDisposed)
@@ -2128,7 +2179,7 @@
2128
2179
  }
2129
2180
 
2130
2181
  function configure(options) {
2131
- var enforceActions = options.enforceActions, computedRequiresReaction = options.computedRequiresReaction, computedConfigurable = options.computedConfigurable, 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;
2132
2183
  if (options.isolateGlobalState === true) {
2133
2184
  isolateGlobalState();
2134
2185
  }
@@ -2158,6 +2209,13 @@
2158
2209
  if (computedRequiresReaction !== undefined) {
2159
2210
  globalState.computedRequiresReaction = !!computedRequiresReaction;
2160
2211
  }
2212
+ if (reactionRequiresObservable !== undefined) {
2213
+ globalState.reactionRequiresObservable = !!reactionRequiresObservable;
2214
+ }
2215
+ if (observableRequiresReaction !== undefined) {
2216
+ globalState.observableRequiresReaction = !!observableRequiresReaction;
2217
+ globalState.allowStateReads = !globalState.observableRequiresReaction;
2218
+ }
2161
2219
  if (computedConfigurable !== undefined) {
2162
2220
  globalState.computedConfigurable = !!computedConfigurable;
2163
2221
  }