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