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.
- package/CHANGELOG.md +6 -1
- package/LICENSE +0 -0
- package/README.md +0 -0
- package/lib/api/action.d.ts +0 -0
- package/lib/api/actiondecorator.d.ts +0 -0
- package/lib/api/autorun.d.ts +5 -0
- package/lib/api/become-observed.d.ts +0 -0
- package/lib/api/computed.d.ts +0 -0
- package/lib/api/configure.d.ts +10 -0
- package/lib/api/decorate.d.ts +0 -0
- package/lib/api/extendobservable.d.ts +0 -0
- package/lib/api/extras.d.ts +0 -0
- package/lib/api/flow.d.ts +0 -0
- package/lib/api/intercept-read.d.ts +0 -0
- package/lib/api/intercept.d.ts +0 -0
- package/lib/api/iscomputed.d.ts +0 -0
- package/lib/api/isobservable.d.ts +0 -0
- package/lib/api/object-api.d.ts +0 -0
- package/lib/api/observable.d.ts +0 -0
- package/lib/api/observabledecorator.d.ts +0 -0
- package/lib/api/observe.d.ts +0 -0
- package/lib/api/tojs.d.ts +0 -0
- package/lib/api/trace.d.ts +0 -0
- package/lib/api/transaction.d.ts +0 -0
- package/lib/api/when.d.ts +5 -0
- package/lib/core/action.d.ts +1 -0
- package/lib/core/atom.d.ts +0 -0
- package/lib/core/computedvalue.d.ts +0 -0
- package/lib/core/derivation.d.ts +7 -0
- package/lib/core/globalstate.d.ts +15 -0
- package/lib/core/observable.d.ts +0 -0
- package/lib/core/reaction.d.ts +2 -1
- package/lib/core/spy.d.ts +0 -0
- package/lib/internal.d.ts +0 -0
- package/lib/mobx.d.ts +0 -0
- package/lib/mobx.es6.js +303 -246
- package/lib/mobx.js +304 -246
- package/lib/mobx.js.flow +18 -0
- package/lib/mobx.min.js +1 -1
- package/lib/mobx.module.js +305 -247
- package/lib/mobx.umd.js +304 -246
- package/lib/mobx.umd.min.js +1 -1
- package/lib/types/dynamicobject.d.ts +0 -0
- package/lib/types/intercept-utils.d.ts +0 -0
- package/lib/types/listen-utils.d.ts +0 -0
- package/lib/types/modifiers.d.ts +0 -0
- package/lib/types/observablearray.d.ts +0 -0
- package/lib/types/observablemap.d.ts +0 -0
- package/lib/types/observableobject.d.ts +0 -0
- package/lib/types/observableset.d.ts +0 -0
- package/lib/types/observablevalue.d.ts +0 -0
- package/lib/types/type-utils.d.ts +0 -0
- package/lib/utils/comparer.d.ts +0 -0
- package/lib/utils/decorators.d.ts +0 -0
- package/lib/utils/eq.d.ts +0 -0
- package/lib/utils/iterable.d.ts +0 -0
- package/lib/utils/utils.d.ts +0 -0
- package/package.json +1 -1
package/lib/mobx.module.js
CHANGED
|
@@ -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
|
}
|