mobx 4.12.0 → 4.14.1
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/lib/api/autorun.d.ts +5 -0
- package/lib/api/configure.d.ts +10 -0
- package/lib/api/when.d.ts +5 -0
- package/lib/core/action.d.ts +13 -0
- package/lib/core/derivation.d.ts +7 -0
- package/lib/core/globalstate.d.ts +15 -0
- package/lib/core/reaction.d.ts +2 -1
- package/lib/mobx.d.ts +1 -1
- package/lib/mobx.es6.js +499 -394
- package/lib/mobx.js +498 -391
- package/lib/mobx.js.flow +20 -2
- package/lib/mobx.min.js +1 -1
- package/lib/mobx.module.js +498 -393
- package/lib/mobx.umd.js +498 -391
- package/lib/mobx.umd.min.js +1 -1
- package/lib/utils/comparer.d.ts +2 -0
- package/lib/utils/eq.d.ts +1 -1
- package/lib/utils/utils.d.ts +1 -0
- package/package.json +1 -1
package/lib/mobx.module.js
CHANGED
|
@@ -67,8 +67,15 @@ var EMPTY_ARRAY = [];
|
|
|
67
67
|
Object.freeze(EMPTY_ARRAY);
|
|
68
68
|
var EMPTY_OBJECT = {};
|
|
69
69
|
Object.freeze(EMPTY_OBJECT);
|
|
70
|
+
var mockGlobal = {};
|
|
70
71
|
function getGlobal() {
|
|
71
|
-
|
|
72
|
+
if (typeof window !== "undefined") {
|
|
73
|
+
return window;
|
|
74
|
+
}
|
|
75
|
+
if (typeof global !== "undefined") {
|
|
76
|
+
return global;
|
|
77
|
+
}
|
|
78
|
+
return mockGlobal;
|
|
72
79
|
}
|
|
73
80
|
function getNextId() {
|
|
74
81
|
return ++globalState.mobxGuid;
|
|
@@ -128,6 +135,20 @@ function isPlainObject(value) {
|
|
|
128
135
|
var proto = Object.getPrototypeOf(value);
|
|
129
136
|
return proto === Object.prototype || proto === null;
|
|
130
137
|
}
|
|
138
|
+
function convertToMap(dataStructure) {
|
|
139
|
+
if (isES6Map(dataStructure) || isObservableMap(dataStructure)) {
|
|
140
|
+
return dataStructure;
|
|
141
|
+
}
|
|
142
|
+
else if (Array.isArray(dataStructure)) {
|
|
143
|
+
return new Map(dataStructure);
|
|
144
|
+
}
|
|
145
|
+
else if (isPlainObject(dataStructure)) {
|
|
146
|
+
return new Map(Object.entries(dataStructure));
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
return fail("Cannot convert to map from '" + dataStructure + "'");
|
|
150
|
+
}
|
|
151
|
+
}
|
|
131
152
|
function makeNonEnumerable(object, propNames) {
|
|
132
153
|
for (var i = 0; i < propNames.length; i++) {
|
|
133
154
|
addHiddenProp(object, propNames[i], object[propNames[i]]);
|
|
@@ -181,18 +202,6 @@ function isES6Map(thing) {
|
|
|
181
202
|
function isES6Set(thing) {
|
|
182
203
|
return thing instanceof Set;
|
|
183
204
|
}
|
|
184
|
-
function getMapLikeKeys(map) {
|
|
185
|
-
if (isPlainObject(map))
|
|
186
|
-
return Object.keys(map);
|
|
187
|
-
if (Array.isArray(map))
|
|
188
|
-
return map.map(function (_a) {
|
|
189
|
-
var _b = __read(_a, 1), key = _b[0];
|
|
190
|
-
return key;
|
|
191
|
-
});
|
|
192
|
-
if (isES6Map(map) || isObservableMap(map))
|
|
193
|
-
return iteratorToArray(map.keys());
|
|
194
|
-
return fail("Cannot get keys from '" + map + "'");
|
|
195
|
-
}
|
|
196
205
|
// use Array.from in Mobx 5
|
|
197
206
|
function iteratorToArray(it) {
|
|
198
207
|
var res = [];
|
|
@@ -219,13 +228,13 @@ function declareIterator(prototType, iteratorFactory) {
|
|
|
219
228
|
addHiddenFinalProp(prototType, iteratorSymbol(), iteratorFactory);
|
|
220
229
|
}
|
|
221
230
|
function makeIterable(iterator) {
|
|
222
|
-
iterator[iteratorSymbol()] =
|
|
231
|
+
iterator[iteratorSymbol()] = getSelf;
|
|
223
232
|
return iterator;
|
|
224
233
|
}
|
|
225
234
|
function toStringTagSymbol() {
|
|
226
235
|
return (typeof Symbol === "function" && Symbol.toStringTag) || "@@toStringTag";
|
|
227
236
|
}
|
|
228
|
-
function
|
|
237
|
+
function getSelf() {
|
|
229
238
|
return this;
|
|
230
239
|
}
|
|
231
240
|
|
|
@@ -293,13 +302,17 @@ function identityComparer(a, b) {
|
|
|
293
302
|
function structuralComparer(a, b) {
|
|
294
303
|
return deepEqual(a, b);
|
|
295
304
|
}
|
|
305
|
+
function shallowComparer(a, b) {
|
|
306
|
+
return deepEqual(a, b, 1);
|
|
307
|
+
}
|
|
296
308
|
function defaultComparer(a, b) {
|
|
297
309
|
return areBothNaN(a, b) || identityComparer(a, b);
|
|
298
310
|
}
|
|
299
311
|
var comparer = {
|
|
300
312
|
identity: identityComparer,
|
|
301
313
|
structural: structuralComparer,
|
|
302
|
-
default: defaultComparer
|
|
314
|
+
default: defaultComparer,
|
|
315
|
+
shallow: shallowComparer
|
|
303
316
|
};
|
|
304
317
|
|
|
305
318
|
var enumerableDescriptorCache = {};
|
|
@@ -619,6 +632,276 @@ var computed = function computed(arg1, arg2, arg3) {
|
|
|
619
632
|
};
|
|
620
633
|
computed.struct = computedStructDecorator;
|
|
621
634
|
|
|
635
|
+
var IDerivationState;
|
|
636
|
+
(function (IDerivationState) {
|
|
637
|
+
// before being run or (outside batch and not being observed)
|
|
638
|
+
// at this point derivation is not holding any data about dependency tree
|
|
639
|
+
IDerivationState[IDerivationState["NOT_TRACKING"] = -1] = "NOT_TRACKING";
|
|
640
|
+
// no shallow dependency changed since last computation
|
|
641
|
+
// won't recalculate derivation
|
|
642
|
+
// this is what makes mobx fast
|
|
643
|
+
IDerivationState[IDerivationState["UP_TO_DATE"] = 0] = "UP_TO_DATE";
|
|
644
|
+
// some deep dependency changed, but don't know if shallow dependency changed
|
|
645
|
+
// will require to check first if UP_TO_DATE or POSSIBLY_STALE
|
|
646
|
+
// currently only ComputedValue will propagate POSSIBLY_STALE
|
|
647
|
+
//
|
|
648
|
+
// having this state is second big optimization:
|
|
649
|
+
// don't have to recompute on every dependency change, but only when it's needed
|
|
650
|
+
IDerivationState[IDerivationState["POSSIBLY_STALE"] = 1] = "POSSIBLY_STALE";
|
|
651
|
+
// A shallow dependency has changed since last computation and the derivation
|
|
652
|
+
// will need to recompute when it's needed next.
|
|
653
|
+
IDerivationState[IDerivationState["STALE"] = 2] = "STALE";
|
|
654
|
+
})(IDerivationState || (IDerivationState = {}));
|
|
655
|
+
var TraceMode;
|
|
656
|
+
(function (TraceMode) {
|
|
657
|
+
TraceMode[TraceMode["NONE"] = 0] = "NONE";
|
|
658
|
+
TraceMode[TraceMode["LOG"] = 1] = "LOG";
|
|
659
|
+
TraceMode[TraceMode["BREAK"] = 2] = "BREAK";
|
|
660
|
+
})(TraceMode || (TraceMode = {}));
|
|
661
|
+
var CaughtException = /** @class */ (function () {
|
|
662
|
+
function CaughtException(cause) {
|
|
663
|
+
this.cause = cause;
|
|
664
|
+
// Empty
|
|
665
|
+
}
|
|
666
|
+
return CaughtException;
|
|
667
|
+
}());
|
|
668
|
+
function isCaughtException(e) {
|
|
669
|
+
return e instanceof CaughtException;
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* Finds out whether any dependency of the derivation has actually changed.
|
|
673
|
+
* If dependenciesState is 1 then it will recalculate dependencies,
|
|
674
|
+
* if any dependency changed it will propagate it by changing dependenciesState to 2.
|
|
675
|
+
*
|
|
676
|
+
* By iterating over the dependencies in the same order that they were reported and
|
|
677
|
+
* stopping on the first change, all the recalculations are only called for ComputedValues
|
|
678
|
+
* that will be tracked by derivation. That is because we assume that if the first x
|
|
679
|
+
* dependencies of the derivation doesn't change then the derivation should run the same way
|
|
680
|
+
* up until accessing x-th dependency.
|
|
681
|
+
*/
|
|
682
|
+
function shouldCompute(derivation) {
|
|
683
|
+
switch (derivation.dependenciesState) {
|
|
684
|
+
case IDerivationState.UP_TO_DATE:
|
|
685
|
+
return false;
|
|
686
|
+
case IDerivationState.NOT_TRACKING:
|
|
687
|
+
case IDerivationState.STALE:
|
|
688
|
+
return true;
|
|
689
|
+
case IDerivationState.POSSIBLY_STALE: {
|
|
690
|
+
var prevUntracked = untrackedStart(); // no need for those computeds to be reported, they will be picked up in trackDerivedFunction.
|
|
691
|
+
var obs = derivation.observing, l = obs.length;
|
|
692
|
+
for (var i = 0; i < l; i++) {
|
|
693
|
+
var obj = obs[i];
|
|
694
|
+
if (isComputedValue(obj)) {
|
|
695
|
+
if (globalState.disableErrorBoundaries) {
|
|
696
|
+
obj.get();
|
|
697
|
+
}
|
|
698
|
+
else {
|
|
699
|
+
try {
|
|
700
|
+
obj.get();
|
|
701
|
+
}
|
|
702
|
+
catch (e) {
|
|
703
|
+
// we are not interested in the value *or* exception at this moment, but if there is one, notify all
|
|
704
|
+
untrackedEnd(prevUntracked);
|
|
705
|
+
return true;
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
// if ComputedValue `obj` actually changed it will be computed and propagated to its observers.
|
|
709
|
+
// and `derivation` is an observer of `obj`
|
|
710
|
+
// invariantShouldCompute(derivation)
|
|
711
|
+
if (derivation.dependenciesState === IDerivationState.STALE) {
|
|
712
|
+
untrackedEnd(prevUntracked);
|
|
713
|
+
return true;
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
changeDependenciesStateTo0(derivation);
|
|
718
|
+
untrackedEnd(prevUntracked);
|
|
719
|
+
return false;
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
// function invariantShouldCompute(derivation: IDerivation) {
|
|
724
|
+
// const newDepState = (derivation as any).dependenciesState
|
|
725
|
+
// if (
|
|
726
|
+
// process.env.NODE_ENV === "production" &&
|
|
727
|
+
// (newDepState === IDerivationState.POSSIBLY_STALE ||
|
|
728
|
+
// newDepState === IDerivationState.NOT_TRACKING)
|
|
729
|
+
// )
|
|
730
|
+
// fail("Illegal dependency state")
|
|
731
|
+
// }
|
|
732
|
+
function isComputingDerivation() {
|
|
733
|
+
return globalState.trackingDerivation !== null; // filter out actions inside computations
|
|
734
|
+
}
|
|
735
|
+
function checkIfStateModificationsAreAllowed(atom) {
|
|
736
|
+
var hasObservers = atom.observers.length > 0;
|
|
737
|
+
// Should never be possible to change an observed observable from inside computed, see #798
|
|
738
|
+
if (globalState.computationDepth > 0 && hasObservers)
|
|
739
|
+
fail(process.env.NODE_ENV !== "production" &&
|
|
740
|
+
"Computed values are not allowed to cause side effects by changing observables that are already being observed. Tried to modify: " + atom.name);
|
|
741
|
+
// Should not be possible to change observed state outside strict mode, except during initialization, see #563
|
|
742
|
+
if (!globalState.allowStateChanges && (hasObservers || globalState.enforceActions === "strict"))
|
|
743
|
+
fail(process.env.NODE_ENV !== "production" &&
|
|
744
|
+
(globalState.enforceActions
|
|
745
|
+
? "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: "
|
|
746
|
+
: "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: ") +
|
|
747
|
+
atom.name);
|
|
748
|
+
}
|
|
749
|
+
function checkIfStateReadsAreAllowed(observable) {
|
|
750
|
+
if (process.env.NODE_ENV !== "production" &&
|
|
751
|
+
!globalState.allowStateReads &&
|
|
752
|
+
globalState.observableRequiresReaction) {
|
|
753
|
+
console.warn("[mobx] Observable " + observable.name + " being read outside a reactive context");
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
/**
|
|
757
|
+
* Executes the provided function `f` and tracks which observables are being accessed.
|
|
758
|
+
* The tracking information is stored on the `derivation` object and the derivation is registered
|
|
759
|
+
* as observer of any of the accessed observables.
|
|
760
|
+
*/
|
|
761
|
+
function trackDerivedFunction(derivation, f, context) {
|
|
762
|
+
var prevAllowStateReads = allowStateReadsStart(true);
|
|
763
|
+
// pre allocate array allocation + room for variation in deps
|
|
764
|
+
// array will be trimmed by bindDependencies
|
|
765
|
+
changeDependenciesStateTo0(derivation);
|
|
766
|
+
derivation.newObserving = new Array(derivation.observing.length + 100);
|
|
767
|
+
derivation.unboundDepsCount = 0;
|
|
768
|
+
derivation.runId = ++globalState.runId;
|
|
769
|
+
var prevTracking = globalState.trackingDerivation;
|
|
770
|
+
globalState.trackingDerivation = derivation;
|
|
771
|
+
var result;
|
|
772
|
+
if (globalState.disableErrorBoundaries === true) {
|
|
773
|
+
result = f.call(context);
|
|
774
|
+
}
|
|
775
|
+
else {
|
|
776
|
+
try {
|
|
777
|
+
result = f.call(context);
|
|
778
|
+
}
|
|
779
|
+
catch (e) {
|
|
780
|
+
result = new CaughtException(e);
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
globalState.trackingDerivation = prevTracking;
|
|
784
|
+
bindDependencies(derivation);
|
|
785
|
+
if (derivation.observing.length === 0) {
|
|
786
|
+
warnAboutDerivationWithoutDependencies(derivation);
|
|
787
|
+
}
|
|
788
|
+
allowStateReadsEnd(prevAllowStateReads);
|
|
789
|
+
return result;
|
|
790
|
+
}
|
|
791
|
+
function warnAboutDerivationWithoutDependencies(derivation) {
|
|
792
|
+
if (process.env.NODE_ENV === "production")
|
|
793
|
+
return;
|
|
794
|
+
if (globalState.reactionRequiresObservable || derivation.requiresObservable) {
|
|
795
|
+
console.warn("[mobx] Derivation " + derivation.name + " is created/updated without reading any observable value");
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
/**
|
|
799
|
+
* diffs newObserving with observing.
|
|
800
|
+
* update observing to be newObserving with unique observables
|
|
801
|
+
* notify observers that become observed/unobserved
|
|
802
|
+
*/
|
|
803
|
+
function bindDependencies(derivation) {
|
|
804
|
+
// invariant(derivation.dependenciesState !== IDerivationState.NOT_TRACKING, "INTERNAL ERROR bindDependencies expects derivation.dependenciesState !== -1");
|
|
805
|
+
var prevObserving = derivation.observing;
|
|
806
|
+
var observing = (derivation.observing = derivation.newObserving);
|
|
807
|
+
var lowestNewObservingDerivationState = IDerivationState.UP_TO_DATE;
|
|
808
|
+
// Go through all new observables and check diffValue: (this list can contain duplicates):
|
|
809
|
+
// 0: first occurrence, change to 1 and keep it
|
|
810
|
+
// 1: extra occurrence, drop it
|
|
811
|
+
var i0 = 0, l = derivation.unboundDepsCount;
|
|
812
|
+
for (var i = 0; i < l; i++) {
|
|
813
|
+
var dep = observing[i];
|
|
814
|
+
if (dep.diffValue === 0) {
|
|
815
|
+
dep.diffValue = 1;
|
|
816
|
+
if (i0 !== i)
|
|
817
|
+
observing[i0] = dep;
|
|
818
|
+
i0++;
|
|
819
|
+
}
|
|
820
|
+
// Upcast is 'safe' here, because if dep is IObservable, `dependenciesState` will be undefined,
|
|
821
|
+
// not hitting the condition
|
|
822
|
+
if (dep.dependenciesState > lowestNewObservingDerivationState) {
|
|
823
|
+
lowestNewObservingDerivationState = dep.dependenciesState;
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
observing.length = i0;
|
|
827
|
+
derivation.newObserving = null; // newObserving shouldn't be needed outside tracking (statement moved down to work around FF bug, see #614)
|
|
828
|
+
// Go through all old observables and check diffValue: (it is unique after last bindDependencies)
|
|
829
|
+
// 0: it's not in new observables, unobserve it
|
|
830
|
+
// 1: it keeps being observed, don't want to notify it. change to 0
|
|
831
|
+
l = prevObserving.length;
|
|
832
|
+
while (l--) {
|
|
833
|
+
var dep = prevObserving[l];
|
|
834
|
+
if (dep.diffValue === 0) {
|
|
835
|
+
removeObserver(dep, derivation);
|
|
836
|
+
}
|
|
837
|
+
dep.diffValue = 0;
|
|
838
|
+
}
|
|
839
|
+
// Go through all new observables and check diffValue: (now it should be unique)
|
|
840
|
+
// 0: it was set to 0 in last loop. don't need to do anything.
|
|
841
|
+
// 1: it wasn't observed, let's observe it. set back to 0
|
|
842
|
+
while (i0--) {
|
|
843
|
+
var dep = observing[i0];
|
|
844
|
+
if (dep.diffValue === 1) {
|
|
845
|
+
dep.diffValue = 0;
|
|
846
|
+
addObserver(dep, derivation);
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
// Some new observed derivations may become stale during this derivation computation
|
|
850
|
+
// so they have had no chance to propagate staleness (#916)
|
|
851
|
+
if (lowestNewObservingDerivationState !== IDerivationState.UP_TO_DATE) {
|
|
852
|
+
derivation.dependenciesState = lowestNewObservingDerivationState;
|
|
853
|
+
derivation.onBecomeStale();
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
function clearObserving(derivation) {
|
|
857
|
+
// invariant(globalState.inBatch > 0, "INTERNAL ERROR clearObserving should be called only inside batch");
|
|
858
|
+
var obs = derivation.observing;
|
|
859
|
+
derivation.observing = [];
|
|
860
|
+
var i = obs.length;
|
|
861
|
+
while (i--)
|
|
862
|
+
removeObserver(obs[i], derivation);
|
|
863
|
+
derivation.dependenciesState = IDerivationState.NOT_TRACKING;
|
|
864
|
+
}
|
|
865
|
+
function untracked(action) {
|
|
866
|
+
var prev = untrackedStart();
|
|
867
|
+
var res = action();
|
|
868
|
+
untrackedEnd(prev);
|
|
869
|
+
return res;
|
|
870
|
+
}
|
|
871
|
+
function untrackedStart() {
|
|
872
|
+
var prev = globalState.trackingDerivation;
|
|
873
|
+
globalState.trackingDerivation = null;
|
|
874
|
+
return prev;
|
|
875
|
+
}
|
|
876
|
+
function untrackedEnd(prev) {
|
|
877
|
+
globalState.trackingDerivation = prev;
|
|
878
|
+
}
|
|
879
|
+
function allowStateReadsStart(allowStateReads) {
|
|
880
|
+
var prev = globalState.allowStateReads;
|
|
881
|
+
globalState.allowStateReads = allowStateReads;
|
|
882
|
+
return prev;
|
|
883
|
+
}
|
|
884
|
+
function allowStateReadsEnd(prev) {
|
|
885
|
+
globalState.allowStateReads = prev;
|
|
886
|
+
}
|
|
887
|
+
/**
|
|
888
|
+
* needed to keep `lowestObserverState` correct. when changing from (2 or 1) to 0
|
|
889
|
+
*
|
|
890
|
+
*/
|
|
891
|
+
function changeDependenciesStateTo0(derivation) {
|
|
892
|
+
if (derivation.dependenciesState === IDerivationState.UP_TO_DATE)
|
|
893
|
+
return;
|
|
894
|
+
derivation.dependenciesState = IDerivationState.UP_TO_DATE;
|
|
895
|
+
var obs = derivation.observing;
|
|
896
|
+
var i = obs.length;
|
|
897
|
+
while (i--)
|
|
898
|
+
obs[i].lowestObserverState = IDerivationState.UP_TO_DATE;
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
// we don't use globalState for these in order to avoid possible issues with multiple
|
|
902
|
+
// mobx versions
|
|
903
|
+
var currentActionId = 0;
|
|
904
|
+
var nextActionId = 1;
|
|
622
905
|
function createAction(actionName, fn) {
|
|
623
906
|
if (process.env.NODE_ENV !== "production") {
|
|
624
907
|
invariant(typeof fn === "function", "`action` can only be invoked on functions");
|
|
@@ -632,25 +915,19 @@ function createAction(actionName, fn) {
|
|
|
632
915
|
return res;
|
|
633
916
|
}
|
|
634
917
|
function executeAction(actionName, fn, scope, args) {
|
|
635
|
-
var runInfo =
|
|
636
|
-
var shouldSupressReactionError = true;
|
|
918
|
+
var runInfo = _startAction(actionName, scope, args);
|
|
637
919
|
try {
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
920
|
+
return fn.apply(scope, args);
|
|
921
|
+
}
|
|
922
|
+
catch (err) {
|
|
923
|
+
runInfo.error = err;
|
|
924
|
+
throw err;
|
|
641
925
|
}
|
|
642
926
|
finally {
|
|
643
|
-
|
|
644
|
-
globalState.suppressReactionErrors = shouldSupressReactionError;
|
|
645
|
-
endAction(runInfo);
|
|
646
|
-
globalState.suppressReactionErrors = false;
|
|
647
|
-
}
|
|
648
|
-
else {
|
|
649
|
-
endAction(runInfo);
|
|
650
|
-
}
|
|
927
|
+
_endAction(runInfo);
|
|
651
928
|
}
|
|
652
929
|
}
|
|
653
|
-
function
|
|
930
|
+
function _startAction(actionName, scope, args) {
|
|
654
931
|
var notifySpy = isSpyEnabled() && !!actionName;
|
|
655
932
|
var startTime = 0;
|
|
656
933
|
if (notifySpy) {
|
|
@@ -670,19 +947,35 @@ function startAction(actionName, fn, scope, args) {
|
|
|
670
947
|
var prevDerivation = untrackedStart();
|
|
671
948
|
startBatch();
|
|
672
949
|
var prevAllowStateChanges = allowStateChangesStart(true);
|
|
673
|
-
|
|
950
|
+
var prevAllowStateReads = allowStateReadsStart(true);
|
|
951
|
+
var runInfo = {
|
|
674
952
|
prevDerivation: prevDerivation,
|
|
675
953
|
prevAllowStateChanges: prevAllowStateChanges,
|
|
954
|
+
prevAllowStateReads: prevAllowStateReads,
|
|
676
955
|
notifySpy: notifySpy,
|
|
677
|
-
startTime: startTime
|
|
956
|
+
startTime: startTime,
|
|
957
|
+
actionId: nextActionId++,
|
|
958
|
+
parentActionId: currentActionId
|
|
678
959
|
};
|
|
960
|
+
currentActionId = runInfo.actionId;
|
|
961
|
+
return runInfo;
|
|
679
962
|
}
|
|
680
|
-
function
|
|
963
|
+
function _endAction(runInfo) {
|
|
964
|
+
if (currentActionId !== runInfo.actionId) {
|
|
965
|
+
fail("invalid action stack. did you forget to finish an action?");
|
|
966
|
+
}
|
|
967
|
+
currentActionId = runInfo.parentActionId;
|
|
968
|
+
if (runInfo.error !== undefined) {
|
|
969
|
+
globalState.suppressReactionErrors = true;
|
|
970
|
+
}
|
|
681
971
|
allowStateChangesEnd(runInfo.prevAllowStateChanges);
|
|
972
|
+
allowStateReadsEnd(runInfo.prevAllowStateReads);
|
|
682
973
|
endBatch();
|
|
683
974
|
untrackedEnd(runInfo.prevDerivation);
|
|
684
|
-
if (runInfo.notifySpy)
|
|
975
|
+
if (runInfo.notifySpy) {
|
|
685
976
|
spyReportEnd({ time: Date.now() - runInfo.startTime });
|
|
977
|
+
}
|
|
978
|
+
globalState.suppressReactionErrors = false;
|
|
686
979
|
}
|
|
687
980
|
function allowStateChanges(allowStateChanges, func) {
|
|
688
981
|
var prev = allowStateChangesStart(allowStateChanges);
|
|
@@ -938,338 +1231,99 @@ var ComputedValue = /** @class */ (function () {
|
|
|
938
1231
|
if (isSpyEnabled()) {
|
|
939
1232
|
spyReport({
|
|
940
1233
|
object: this.scope,
|
|
941
|
-
type: "compute",
|
|
942
|
-
name: this.name
|
|
943
|
-
});
|
|
944
|
-
}
|
|
945
|
-
var oldValue = this.value;
|
|
946
|
-
var wasSuspended =
|
|
947
|
-
/* see #1208 */ this.dependenciesState === IDerivationState.NOT_TRACKING;
|
|
948
|
-
var newValue = this.computeValue(true);
|
|
949
|
-
var changed = wasSuspended ||
|
|
950
|
-
isCaughtException(oldValue) ||
|
|
951
|
-
isCaughtException(newValue) ||
|
|
952
|
-
!this.equals(oldValue, newValue);
|
|
953
|
-
if (changed) {
|
|
954
|
-
this.value = newValue;
|
|
955
|
-
}
|
|
956
|
-
return changed;
|
|
957
|
-
};
|
|
958
|
-
ComputedValue.prototype.computeValue = function (track) {
|
|
959
|
-
this.isComputing = true;
|
|
960
|
-
globalState.computationDepth++;
|
|
961
|
-
var res;
|
|
962
|
-
if (track) {
|
|
963
|
-
res = trackDerivedFunction(this, this.derivation, this.scope);
|
|
964
|
-
}
|
|
965
|
-
else {
|
|
966
|
-
if (globalState.disableErrorBoundaries === true) {
|
|
967
|
-
res = this.derivation.call(this.scope);
|
|
968
|
-
}
|
|
969
|
-
else {
|
|
970
|
-
try {
|
|
971
|
-
res = this.derivation.call(this.scope);
|
|
972
|
-
}
|
|
973
|
-
catch (e) {
|
|
974
|
-
res = new CaughtException(e);
|
|
975
|
-
}
|
|
976
|
-
}
|
|
977
|
-
}
|
|
978
|
-
globalState.computationDepth--;
|
|
979
|
-
this.isComputing = false;
|
|
980
|
-
return res;
|
|
981
|
-
};
|
|
982
|
-
ComputedValue.prototype.suspend = function () {
|
|
983
|
-
if (!this.keepAlive) {
|
|
984
|
-
clearObserving(this);
|
|
985
|
-
this.value = undefined; // don't hold on to computed value!
|
|
986
|
-
}
|
|
987
|
-
};
|
|
988
|
-
ComputedValue.prototype.observe = function (listener, fireImmediately) {
|
|
989
|
-
var _this = this;
|
|
990
|
-
var firstTime = true;
|
|
991
|
-
var prevValue = undefined;
|
|
992
|
-
return autorun(function () {
|
|
993
|
-
var newValue = _this.get();
|
|
994
|
-
if (!firstTime || fireImmediately) {
|
|
995
|
-
var prevU = untrackedStart();
|
|
996
|
-
listener({
|
|
997
|
-
type: "update",
|
|
998
|
-
object: _this,
|
|
999
|
-
newValue: newValue,
|
|
1000
|
-
oldValue: prevValue
|
|
1001
|
-
});
|
|
1002
|
-
untrackedEnd(prevU);
|
|
1003
|
-
}
|
|
1004
|
-
firstTime = false;
|
|
1005
|
-
prevValue = newValue;
|
|
1006
|
-
});
|
|
1007
|
-
};
|
|
1008
|
-
ComputedValue.prototype.warnAboutUntrackedRead = function () {
|
|
1009
|
-
if (process.env.NODE_ENV === "production")
|
|
1010
|
-
return;
|
|
1011
|
-
if (this.requiresReaction === true) {
|
|
1012
|
-
fail("[mobx] Computed value " + this.name + " is read outside a reactive context");
|
|
1013
|
-
}
|
|
1014
|
-
if (this.isTracing !== TraceMode.NONE) {
|
|
1015
|
-
console.log("[mobx.trace] '" + this.name + "' is being read outside a reactive context. Doing a full recompute");
|
|
1016
|
-
}
|
|
1017
|
-
if (globalState.computedRequiresReaction) {
|
|
1018
|
-
console.warn("[mobx] Computed value " + this.name + " is being read outside a reactive context. Doing a full recompute");
|
|
1019
|
-
}
|
|
1020
|
-
};
|
|
1021
|
-
ComputedValue.prototype.toJSON = function () {
|
|
1022
|
-
return this.get();
|
|
1023
|
-
};
|
|
1024
|
-
ComputedValue.prototype.toString = function () {
|
|
1025
|
-
return this.name + "[" + this.derivation.toString() + "]";
|
|
1026
|
-
};
|
|
1027
|
-
ComputedValue.prototype.valueOf = function () {
|
|
1028
|
-
return toPrimitive(this.get());
|
|
1029
|
-
};
|
|
1030
|
-
return ComputedValue;
|
|
1031
|
-
}());
|
|
1032
|
-
ComputedValue.prototype[primitiveSymbol()] = ComputedValue.prototype.valueOf;
|
|
1033
|
-
var isComputedValue = createInstanceofPredicate("ComputedValue", ComputedValue);
|
|
1034
|
-
|
|
1035
|
-
var IDerivationState;
|
|
1036
|
-
(function (IDerivationState) {
|
|
1037
|
-
// before being run or (outside batch and not being observed)
|
|
1038
|
-
// at this point derivation is not holding any data about dependency tree
|
|
1039
|
-
IDerivationState[IDerivationState["NOT_TRACKING"] = -1] = "NOT_TRACKING";
|
|
1040
|
-
// no shallow dependency changed since last computation
|
|
1041
|
-
// won't recalculate derivation
|
|
1042
|
-
// this is what makes mobx fast
|
|
1043
|
-
IDerivationState[IDerivationState["UP_TO_DATE"] = 0] = "UP_TO_DATE";
|
|
1044
|
-
// some deep dependency changed, but don't know if shallow dependency changed
|
|
1045
|
-
// will require to check first if UP_TO_DATE or POSSIBLY_STALE
|
|
1046
|
-
// currently only ComputedValue will propagate POSSIBLY_STALE
|
|
1047
|
-
//
|
|
1048
|
-
// having this state is second big optimization:
|
|
1049
|
-
// don't have to recompute on every dependency change, but only when it's needed
|
|
1050
|
-
IDerivationState[IDerivationState["POSSIBLY_STALE"] = 1] = "POSSIBLY_STALE";
|
|
1051
|
-
// A shallow dependency has changed since last computation and the derivation
|
|
1052
|
-
// will need to recompute when it's needed next.
|
|
1053
|
-
IDerivationState[IDerivationState["STALE"] = 2] = "STALE";
|
|
1054
|
-
})(IDerivationState || (IDerivationState = {}));
|
|
1055
|
-
var TraceMode;
|
|
1056
|
-
(function (TraceMode) {
|
|
1057
|
-
TraceMode[TraceMode["NONE"] = 0] = "NONE";
|
|
1058
|
-
TraceMode[TraceMode["LOG"] = 1] = "LOG";
|
|
1059
|
-
TraceMode[TraceMode["BREAK"] = 2] = "BREAK";
|
|
1060
|
-
})(TraceMode || (TraceMode = {}));
|
|
1061
|
-
var CaughtException = /** @class */ (function () {
|
|
1062
|
-
function CaughtException(cause) {
|
|
1063
|
-
this.cause = cause;
|
|
1064
|
-
// Empty
|
|
1065
|
-
}
|
|
1066
|
-
return CaughtException;
|
|
1067
|
-
}());
|
|
1068
|
-
function isCaughtException(e) {
|
|
1069
|
-
return e instanceof CaughtException;
|
|
1070
|
-
}
|
|
1071
|
-
/**
|
|
1072
|
-
* Finds out whether any dependency of the derivation has actually changed.
|
|
1073
|
-
* If dependenciesState is 1 then it will recalculate dependencies,
|
|
1074
|
-
* if any dependency changed it will propagate it by changing dependenciesState to 2.
|
|
1075
|
-
*
|
|
1076
|
-
* By iterating over the dependencies in the same order that they were reported and
|
|
1077
|
-
* stopping on the first change, all the recalculations are only called for ComputedValues
|
|
1078
|
-
* that will be tracked by derivation. That is because we assume that if the first x
|
|
1079
|
-
* dependencies of the derivation doesn't change then the derivation should run the same way
|
|
1080
|
-
* up until accessing x-th dependency.
|
|
1081
|
-
*/
|
|
1082
|
-
function shouldCompute(derivation) {
|
|
1083
|
-
switch (derivation.dependenciesState) {
|
|
1084
|
-
case IDerivationState.UP_TO_DATE:
|
|
1085
|
-
return false;
|
|
1086
|
-
case IDerivationState.NOT_TRACKING:
|
|
1087
|
-
case IDerivationState.STALE:
|
|
1088
|
-
return true;
|
|
1089
|
-
case IDerivationState.POSSIBLY_STALE: {
|
|
1090
|
-
var prevUntracked = untrackedStart(); // no need for those computeds to be reported, they will be picked up in trackDerivedFunction.
|
|
1091
|
-
var obs = derivation.observing, l = obs.length;
|
|
1092
|
-
for (var i = 0; i < l; i++) {
|
|
1093
|
-
var obj = obs[i];
|
|
1094
|
-
if (isComputedValue(obj)) {
|
|
1095
|
-
if (globalState.disableErrorBoundaries) {
|
|
1096
|
-
obj.get();
|
|
1097
|
-
}
|
|
1098
|
-
else {
|
|
1099
|
-
try {
|
|
1100
|
-
obj.get();
|
|
1101
|
-
}
|
|
1102
|
-
catch (e) {
|
|
1103
|
-
// we are not interested in the value *or* exception at this moment, but if there is one, notify all
|
|
1104
|
-
untrackedEnd(prevUntracked);
|
|
1105
|
-
return true;
|
|
1106
|
-
}
|
|
1107
|
-
}
|
|
1108
|
-
// if ComputedValue `obj` actually changed it will be computed and propagated to its observers.
|
|
1109
|
-
// and `derivation` is an observer of `obj`
|
|
1110
|
-
// invariantShouldCompute(derivation)
|
|
1111
|
-
if (derivation.dependenciesState === IDerivationState.STALE) {
|
|
1112
|
-
untrackedEnd(prevUntracked);
|
|
1113
|
-
return true;
|
|
1114
|
-
}
|
|
1115
|
-
}
|
|
1116
|
-
}
|
|
1117
|
-
changeDependenciesStateTo0(derivation);
|
|
1118
|
-
untrackedEnd(prevUntracked);
|
|
1119
|
-
return false;
|
|
1234
|
+
type: "compute",
|
|
1235
|
+
name: this.name
|
|
1236
|
+
});
|
|
1120
1237
|
}
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
// }
|
|
1132
|
-
function isComputingDerivation() {
|
|
1133
|
-
return globalState.trackingDerivation !== null; // filter out actions inside computations
|
|
1134
|
-
}
|
|
1135
|
-
function checkIfStateModificationsAreAllowed(atom) {
|
|
1136
|
-
var hasObservers = atom.observers.length > 0;
|
|
1137
|
-
// Should never be possible to change an observed observable from inside computed, see #798
|
|
1138
|
-
if (globalState.computationDepth > 0 && hasObservers)
|
|
1139
|
-
fail(process.env.NODE_ENV !== "production" &&
|
|
1140
|
-
"Computed values are not allowed to cause side effects by changing observables that are already being observed. Tried to modify: " + atom.name);
|
|
1141
|
-
// Should not be possible to change observed state outside strict mode, except during initialization, see #563
|
|
1142
|
-
if (!globalState.allowStateChanges && (hasObservers || globalState.enforceActions === "strict"))
|
|
1143
|
-
fail(process.env.NODE_ENV !== "production" &&
|
|
1144
|
-
(globalState.enforceActions
|
|
1145
|
-
? "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: "
|
|
1146
|
-
: "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: ") +
|
|
1147
|
-
atom.name);
|
|
1148
|
-
}
|
|
1149
|
-
/**
|
|
1150
|
-
* Executes the provided function `f` and tracks which observables are being accessed.
|
|
1151
|
-
* The tracking information is stored on the `derivation` object and the derivation is registered
|
|
1152
|
-
* as observer of any of the accessed observables.
|
|
1153
|
-
*/
|
|
1154
|
-
function trackDerivedFunction(derivation, f, context) {
|
|
1155
|
-
// pre allocate array allocation + room for variation in deps
|
|
1156
|
-
// array will be trimmed by bindDependencies
|
|
1157
|
-
changeDependenciesStateTo0(derivation);
|
|
1158
|
-
derivation.newObserving = new Array(derivation.observing.length + 100);
|
|
1159
|
-
derivation.unboundDepsCount = 0;
|
|
1160
|
-
derivation.runId = ++globalState.runId;
|
|
1161
|
-
var prevTracking = globalState.trackingDerivation;
|
|
1162
|
-
globalState.trackingDerivation = derivation;
|
|
1163
|
-
var result;
|
|
1164
|
-
if (globalState.disableErrorBoundaries === true) {
|
|
1165
|
-
result = f.call(context);
|
|
1166
|
-
}
|
|
1167
|
-
else {
|
|
1168
|
-
try {
|
|
1169
|
-
result = f.call(context);
|
|
1238
|
+
var oldValue = this.value;
|
|
1239
|
+
var wasSuspended =
|
|
1240
|
+
/* see #1208 */ this.dependenciesState === IDerivationState.NOT_TRACKING;
|
|
1241
|
+
var newValue = this.computeValue(true);
|
|
1242
|
+
var changed = wasSuspended ||
|
|
1243
|
+
isCaughtException(oldValue) ||
|
|
1244
|
+
isCaughtException(newValue) ||
|
|
1245
|
+
!this.equals(oldValue, newValue);
|
|
1246
|
+
if (changed) {
|
|
1247
|
+
this.value = newValue;
|
|
1170
1248
|
}
|
|
1171
|
-
|
|
1172
|
-
|
|
1249
|
+
return changed;
|
|
1250
|
+
};
|
|
1251
|
+
ComputedValue.prototype.computeValue = function (track) {
|
|
1252
|
+
this.isComputing = true;
|
|
1253
|
+
globalState.computationDepth++;
|
|
1254
|
+
var res;
|
|
1255
|
+
if (track) {
|
|
1256
|
+
res = trackDerivedFunction(this, this.derivation, this.scope);
|
|
1173
1257
|
}
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
var prevObserving = derivation.observing;
|
|
1187
|
-
var observing = (derivation.observing = derivation.newObserving);
|
|
1188
|
-
var lowestNewObservingDerivationState = IDerivationState.UP_TO_DATE;
|
|
1189
|
-
// Go through all new observables and check diffValue: (this list can contain duplicates):
|
|
1190
|
-
// 0: first occurrence, change to 1 and keep it
|
|
1191
|
-
// 1: extra occurrence, drop it
|
|
1192
|
-
var i0 = 0, l = derivation.unboundDepsCount;
|
|
1193
|
-
for (var i = 0; i < l; i++) {
|
|
1194
|
-
var dep = observing[i];
|
|
1195
|
-
if (dep.diffValue === 0) {
|
|
1196
|
-
dep.diffValue = 1;
|
|
1197
|
-
if (i0 !== i)
|
|
1198
|
-
observing[i0] = dep;
|
|
1199
|
-
i0++;
|
|
1258
|
+
else {
|
|
1259
|
+
if (globalState.disableErrorBoundaries === true) {
|
|
1260
|
+
res = this.derivation.call(this.scope);
|
|
1261
|
+
}
|
|
1262
|
+
else {
|
|
1263
|
+
try {
|
|
1264
|
+
res = this.derivation.call(this.scope);
|
|
1265
|
+
}
|
|
1266
|
+
catch (e) {
|
|
1267
|
+
res = new CaughtException(e);
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1200
1270
|
}
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1271
|
+
globalState.computationDepth--;
|
|
1272
|
+
this.isComputing = false;
|
|
1273
|
+
return res;
|
|
1274
|
+
};
|
|
1275
|
+
ComputedValue.prototype.suspend = function () {
|
|
1276
|
+
if (!this.keepAlive) {
|
|
1277
|
+
clearObserving(this);
|
|
1278
|
+
this.value = undefined; // don't hold on to computed value!
|
|
1205
1279
|
}
|
|
1206
|
-
}
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1280
|
+
};
|
|
1281
|
+
ComputedValue.prototype.observe = function (listener, fireImmediately) {
|
|
1282
|
+
var _this = this;
|
|
1283
|
+
var firstTime = true;
|
|
1284
|
+
var prevValue = undefined;
|
|
1285
|
+
return autorun(function () {
|
|
1286
|
+
var newValue = _this.get();
|
|
1287
|
+
if (!firstTime || fireImmediately) {
|
|
1288
|
+
var prevU = untrackedStart();
|
|
1289
|
+
listener({
|
|
1290
|
+
type: "update",
|
|
1291
|
+
object: _this,
|
|
1292
|
+
newValue: newValue,
|
|
1293
|
+
oldValue: prevValue
|
|
1294
|
+
});
|
|
1295
|
+
untrackedEnd(prevU);
|
|
1296
|
+
}
|
|
1297
|
+
firstTime = false;
|
|
1298
|
+
prevValue = newValue;
|
|
1299
|
+
});
|
|
1300
|
+
};
|
|
1301
|
+
ComputedValue.prototype.warnAboutUntrackedRead = function () {
|
|
1302
|
+
if (process.env.NODE_ENV === "production")
|
|
1303
|
+
return;
|
|
1304
|
+
if (this.requiresReaction === true) {
|
|
1305
|
+
fail("[mobx] Computed value " + this.name + " is read outside a reactive context");
|
|
1217
1306
|
}
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
// Go through all new observables and check diffValue: (now it should be unique)
|
|
1221
|
-
// 0: it was set to 0 in last loop. don't need to do anything.
|
|
1222
|
-
// 1: it wasn't observed, let's observe it. set back to 0
|
|
1223
|
-
while (i0--) {
|
|
1224
|
-
var dep = observing[i0];
|
|
1225
|
-
if (dep.diffValue === 1) {
|
|
1226
|
-
dep.diffValue = 0;
|
|
1227
|
-
addObserver(dep, derivation);
|
|
1307
|
+
if (this.isTracing !== TraceMode.NONE) {
|
|
1308
|
+
console.log("[mobx.trace] '" + this.name + "' is being read outside a reactive context. Doing a full recompute");
|
|
1228
1309
|
}
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
}
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
function untracked(action) {
|
|
1247
|
-
var prev = untrackedStart();
|
|
1248
|
-
var res = action();
|
|
1249
|
-
untrackedEnd(prev);
|
|
1250
|
-
return res;
|
|
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 === IDerivationState.UP_TO_DATE)
|
|
1266
|
-
return;
|
|
1267
|
-
derivation.dependenciesState = IDerivationState.UP_TO_DATE;
|
|
1268
|
-
var obs = derivation.observing;
|
|
1269
|
-
var i = obs.length;
|
|
1270
|
-
while (i--)
|
|
1271
|
-
obs[i].lowestObserverState = IDerivationState.UP_TO_DATE;
|
|
1272
|
-
}
|
|
1310
|
+
if (globalState.computedRequiresReaction) {
|
|
1311
|
+
console.warn("[mobx] Computed value " + this.name + " is being read outside a reactive context. Doing a full recompute");
|
|
1312
|
+
}
|
|
1313
|
+
};
|
|
1314
|
+
ComputedValue.prototype.toJSON = function () {
|
|
1315
|
+
return this.get();
|
|
1316
|
+
};
|
|
1317
|
+
ComputedValue.prototype.toString = function () {
|
|
1318
|
+
return this.name + "[" + this.derivation.toString() + "]";
|
|
1319
|
+
};
|
|
1320
|
+
ComputedValue.prototype.valueOf = function () {
|
|
1321
|
+
return toPrimitive(this.get());
|
|
1322
|
+
};
|
|
1323
|
+
return ComputedValue;
|
|
1324
|
+
}());
|
|
1325
|
+
ComputedValue.prototype[primitiveSymbol()] = ComputedValue.prototype.valueOf;
|
|
1326
|
+
var isComputedValue = createInstanceofPredicate("ComputedValue", ComputedValue);
|
|
1273
1327
|
|
|
1274
1328
|
/**
|
|
1275
1329
|
* These values will persist if global state is reset
|
|
@@ -1279,6 +1333,9 @@ var persistentKeys = [
|
|
|
1279
1333
|
"spyListeners",
|
|
1280
1334
|
"enforceActions",
|
|
1281
1335
|
"computedRequiresReaction",
|
|
1336
|
+
"reactionRequiresObservable",
|
|
1337
|
+
"observableRequiresReaction",
|
|
1338
|
+
"allowStateReads",
|
|
1282
1339
|
"disableErrorBoundaries",
|
|
1283
1340
|
"runId",
|
|
1284
1341
|
"UNCHANGED"
|
|
@@ -1339,6 +1396,11 @@ var MobXGlobals = /** @class */ (function () {
|
|
|
1339
1396
|
* To ensure that those functions stay pure.
|
|
1340
1397
|
*/
|
|
1341
1398
|
this.allowStateChanges = true;
|
|
1399
|
+
/**
|
|
1400
|
+
* Is it allowed to read observables at this point?
|
|
1401
|
+
* Used to hold the state needed for `observableRequiresReaction`
|
|
1402
|
+
*/
|
|
1403
|
+
this.allowStateReads = true;
|
|
1342
1404
|
/**
|
|
1343
1405
|
* If strict mode is enabled, state changes are by default not allowed
|
|
1344
1406
|
*/
|
|
@@ -1355,6 +1417,16 @@ var MobXGlobals = /** @class */ (function () {
|
|
|
1355
1417
|
* Warn if computed values are accessed outside a reactive context
|
|
1356
1418
|
*/
|
|
1357
1419
|
this.computedRequiresReaction = false;
|
|
1420
|
+
/**
|
|
1421
|
+
* (Experimental)
|
|
1422
|
+
* Warn if you try to create to derivation / reactive context without accessing any observable.
|
|
1423
|
+
*/
|
|
1424
|
+
this.reactionRequiresObservable = false;
|
|
1425
|
+
/**
|
|
1426
|
+
* (Experimental)
|
|
1427
|
+
* Warn if observables are accessed outside a reactive context
|
|
1428
|
+
*/
|
|
1429
|
+
this.observableRequiresReaction = false;
|
|
1358
1430
|
/**
|
|
1359
1431
|
* Allows overwriting of computed properties, useful in tests but not prod as it can cause
|
|
1360
1432
|
* memory leaks. See https://github.com/mobxjs/mobx/issues/1867
|
|
@@ -1536,6 +1608,7 @@ function endBatch() {
|
|
|
1536
1608
|
}
|
|
1537
1609
|
}
|
|
1538
1610
|
function reportObserved(observable) {
|
|
1611
|
+
checkIfStateReadsAreAllowed(observable);
|
|
1539
1612
|
var derivation = globalState.trackingDerivation;
|
|
1540
1613
|
if (derivation !== null) {
|
|
1541
1614
|
/**
|
|
@@ -1656,11 +1729,13 @@ function printDepTree(tree, lines, depth) {
|
|
|
1656
1729
|
}
|
|
1657
1730
|
|
|
1658
1731
|
var Reaction = /** @class */ (function () {
|
|
1659
|
-
function Reaction(name, onInvalidate, errorHandler) {
|
|
1732
|
+
function Reaction(name, onInvalidate, errorHandler, requiresObservable) {
|
|
1660
1733
|
if (name === void 0) { name = "Reaction@" + getNextId(); }
|
|
1734
|
+
if (requiresObservable === void 0) { requiresObservable = false; }
|
|
1661
1735
|
this.name = name;
|
|
1662
1736
|
this.onInvalidate = onInvalidate;
|
|
1663
1737
|
this.errorHandler = errorHandler;
|
|
1738
|
+
this.requiresObservable = requiresObservable;
|
|
1664
1739
|
this.observing = []; // nodes we are looking at. Our value depends on these nodes
|
|
1665
1740
|
this.newObserving = [];
|
|
1666
1741
|
this.dependenciesState = IDerivationState.NOT_TRACKING;
|
|
@@ -2006,7 +2081,7 @@ function autorun(view, opts) {
|
|
|
2006
2081
|
// normal autorun
|
|
2007
2082
|
reaction = new Reaction(name, function () {
|
|
2008
2083
|
this.track(reactionRunner);
|
|
2009
|
-
}, opts.onError);
|
|
2084
|
+
}, opts.onError, opts.requiresObservable);
|
|
2010
2085
|
}
|
|
2011
2086
|
else {
|
|
2012
2087
|
var scheduler_1 = createSchedulerFromOptions(opts);
|
|
@@ -2021,7 +2096,7 @@ function autorun(view, opts) {
|
|
|
2021
2096
|
reaction.track(reactionRunner);
|
|
2022
2097
|
});
|
|
2023
2098
|
}
|
|
2024
|
-
}, opts.onError);
|
|
2099
|
+
}, opts.onError, opts.requiresObservable);
|
|
2025
2100
|
}
|
|
2026
2101
|
function reactionRunner() {
|
|
2027
2102
|
view(reaction);
|
|
@@ -2065,7 +2140,7 @@ function reaction(expression, effect, opts) {
|
|
|
2065
2140
|
isScheduled = true;
|
|
2066
2141
|
scheduler(reactionRunner);
|
|
2067
2142
|
}
|
|
2068
|
-
}, opts.onError);
|
|
2143
|
+
}, opts.onError, opts.requiresObservable);
|
|
2069
2144
|
function reactionRunner() {
|
|
2070
2145
|
isScheduled = false; // Q: move into reaction runner?
|
|
2071
2146
|
if (r.isDisposed)
|
|
@@ -2104,8 +2179,8 @@ function onBecomeUnobserved(thing, arg2, arg3) {
|
|
|
2104
2179
|
return interceptHook("onBecomeUnobserved", thing, arg2, arg3);
|
|
2105
2180
|
}
|
|
2106
2181
|
function interceptHook(hook, thing, arg2, arg3) {
|
|
2107
|
-
var atom = typeof
|
|
2108
|
-
var cb = typeof
|
|
2182
|
+
var atom = typeof arg3 === "function" ? getAtom(thing, arg2) : getAtom(thing);
|
|
2183
|
+
var cb = typeof arg3 === "function" ? arg3 : arg2;
|
|
2109
2184
|
var orig = atom[hook];
|
|
2110
2185
|
if (typeof orig !== "function")
|
|
2111
2186
|
return fail(process.env.NODE_ENV !== "production" && "Not an atom that can be (un)observed");
|
|
@@ -2119,7 +2194,7 @@ function interceptHook(hook, thing, arg2, arg3) {
|
|
|
2119
2194
|
}
|
|
2120
2195
|
|
|
2121
2196
|
function configure(options) {
|
|
2122
|
-
var enforceActions = options.enforceActions, computedRequiresReaction = options.computedRequiresReaction, computedConfigurable = options.computedConfigurable, disableErrorBoundaries = options.disableErrorBoundaries, arrayBuffer = options.arrayBuffer, reactionScheduler = options.reactionScheduler;
|
|
2197
|
+
var enforceActions = options.enforceActions, computedRequiresReaction = options.computedRequiresReaction, computedConfigurable = options.computedConfigurable, disableErrorBoundaries = options.disableErrorBoundaries, arrayBuffer = options.arrayBuffer, reactionScheduler = options.reactionScheduler, reactionRequiresObservable = options.reactionRequiresObservable, observableRequiresReaction = options.observableRequiresReaction;
|
|
2123
2198
|
if (options.isolateGlobalState === true) {
|
|
2124
2199
|
isolateGlobalState();
|
|
2125
2200
|
}
|
|
@@ -2149,6 +2224,13 @@ function configure(options) {
|
|
|
2149
2224
|
if (computedRequiresReaction !== undefined) {
|
|
2150
2225
|
globalState.computedRequiresReaction = !!computedRequiresReaction;
|
|
2151
2226
|
}
|
|
2227
|
+
if (reactionRequiresObservable !== undefined) {
|
|
2228
|
+
globalState.reactionRequiresObservable = !!reactionRequiresObservable;
|
|
2229
|
+
}
|
|
2230
|
+
if (observableRequiresReaction !== undefined) {
|
|
2231
|
+
globalState.observableRequiresReaction = !!observableRequiresReaction;
|
|
2232
|
+
globalState.allowStateReads = !globalState.observableRequiresReaction;
|
|
2233
|
+
}
|
|
2152
2234
|
if (computedConfigurable !== undefined) {
|
|
2153
2235
|
globalState.computedConfigurable = !!computedConfigurable;
|
|
2154
2236
|
}
|
|
@@ -3404,9 +3486,17 @@ var ObservableMap = /** @class */ (function () {
|
|
|
3404
3486
|
return this._data.has(key);
|
|
3405
3487
|
};
|
|
3406
3488
|
ObservableMap.prototype.has = function (key) {
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3489
|
+
var _this = this;
|
|
3490
|
+
if (!globalState.trackingDerivation)
|
|
3491
|
+
return this._has(key);
|
|
3492
|
+
var entry = this._hasMap.get(key);
|
|
3493
|
+
if (!entry) {
|
|
3494
|
+
// todo: replace with atom (breaking change)
|
|
3495
|
+
var newEntry = (entry = new ObservableValue(this._has(key), referenceEnhancer, this.name + "." + stringifyKey(key) + "?", false));
|
|
3496
|
+
this._hasMap.set(key, newEntry);
|
|
3497
|
+
onBecomeUnobserved(newEntry, function () { return _this._hasMap.delete(key); });
|
|
3498
|
+
}
|
|
3499
|
+
return entry.get();
|
|
3410
3500
|
};
|
|
3411
3501
|
ObservableMap.prototype.set = function (key, value) {
|
|
3412
3502
|
var hasKey = this._has(key);
|
|
@@ -3469,16 +3559,10 @@ var ObservableMap = /** @class */ (function () {
|
|
|
3469
3559
|
return false;
|
|
3470
3560
|
};
|
|
3471
3561
|
ObservableMap.prototype._updateHasMapEntry = function (key, value) {
|
|
3472
|
-
// optimization; don't fill the hasMap if we are not observing, or remove entry if there are no observers anymore
|
|
3473
3562
|
var entry = this._hasMap.get(key);
|
|
3474
3563
|
if (entry) {
|
|
3475
3564
|
entry.setNewValue(value);
|
|
3476
3565
|
}
|
|
3477
|
-
else {
|
|
3478
|
-
entry = new ObservableValue(value, referenceEnhancer, this.name + "." + stringifyKey(key) + "?", false);
|
|
3479
|
-
this._hasMap.set(key, entry);
|
|
3480
|
-
}
|
|
3481
|
-
return entry;
|
|
3482
3566
|
};
|
|
3483
3567
|
ObservableMap.prototype._updateValue = function (key, newValue) {
|
|
3484
3568
|
var observable = this._data.get(key);
|
|
@@ -3611,14 +3695,32 @@ var ObservableMap = /** @class */ (function () {
|
|
|
3611
3695
|
ObservableMap.prototype.replace = function (values) {
|
|
3612
3696
|
var _this = this;
|
|
3613
3697
|
transaction(function () {
|
|
3614
|
-
|
|
3615
|
-
// and delete them from the map, then merge the new map
|
|
3616
|
-
// this will cause reactions only on changed values
|
|
3617
|
-
var newKeys = getMapLikeKeys(values);
|
|
3698
|
+
var replacementMap = convertToMap(values);
|
|
3618
3699
|
var oldKeys = _this._keys;
|
|
3619
|
-
var
|
|
3620
|
-
|
|
3621
|
-
|
|
3700
|
+
var newKeys = Array.from(replacementMap.keys());
|
|
3701
|
+
var keysChanged = false;
|
|
3702
|
+
for (var i = 0; i < oldKeys.length; i++) {
|
|
3703
|
+
var oldKey = oldKeys[i];
|
|
3704
|
+
// key order change
|
|
3705
|
+
if (oldKeys.length === newKeys.length && oldKey !== newKeys[i]) {
|
|
3706
|
+
keysChanged = true;
|
|
3707
|
+
}
|
|
3708
|
+
// deleted key
|
|
3709
|
+
if (!replacementMap.has(oldKey)) {
|
|
3710
|
+
keysChanged = true;
|
|
3711
|
+
_this.delete(oldKey);
|
|
3712
|
+
}
|
|
3713
|
+
}
|
|
3714
|
+
replacementMap.forEach(function (value, key) {
|
|
3715
|
+
// new key
|
|
3716
|
+
if (!_this._data.has(key)) {
|
|
3717
|
+
keysChanged = true;
|
|
3718
|
+
}
|
|
3719
|
+
_this.set(key, value);
|
|
3720
|
+
});
|
|
3721
|
+
if (keysChanged) {
|
|
3722
|
+
_this._keys.replace(newKeys);
|
|
3723
|
+
}
|
|
3622
3724
|
});
|
|
3623
3725
|
return this;
|
|
3624
3726
|
};
|
|
@@ -4222,12 +4324,13 @@ function getDebugName(thing, property) {
|
|
|
4222
4324
|
}
|
|
4223
4325
|
|
|
4224
4326
|
var toString = Object.prototype.toString;
|
|
4225
|
-
function deepEqual(a, b) {
|
|
4226
|
-
|
|
4327
|
+
function deepEqual(a, b, depth) {
|
|
4328
|
+
if (depth === void 0) { depth = -1; }
|
|
4329
|
+
return eq(a, b, depth);
|
|
4227
4330
|
}
|
|
4228
4331
|
// Copied from https://github.com/jashkenas/underscore/blob/5c237a7c682fb68fd5378203f0bf22dce1624854/underscore.js#L1186-L1289
|
|
4229
4332
|
// Internal recursive comparison function for `isEqual`.
|
|
4230
|
-
function eq(a, b, aStack, bStack) {
|
|
4333
|
+
function eq(a, b, depth, aStack, bStack) {
|
|
4231
4334
|
// Identical objects are equal. `0 === -0`, but they aren't identical.
|
|
4232
4335
|
// See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
|
|
4233
4336
|
if (a === b)
|
|
@@ -4242,10 +4345,6 @@ function eq(a, b, aStack, bStack) {
|
|
|
4242
4345
|
var type = typeof a;
|
|
4243
4346
|
if (type !== "function" && type !== "object" && typeof b != "object")
|
|
4244
4347
|
return false;
|
|
4245
|
-
return deepEq(a, b, aStack, bStack);
|
|
4246
|
-
}
|
|
4247
|
-
// Internal recursive comparison function for `isEqual`.
|
|
4248
|
-
function deepEq(a, b, aStack, bStack) {
|
|
4249
4348
|
// Unwrap any wrapped objects.
|
|
4250
4349
|
a = unwrap(a);
|
|
4251
4350
|
b = unwrap(b);
|
|
@@ -4295,6 +4394,12 @@ function deepEq(a, b, aStack, bStack) {
|
|
|
4295
4394
|
return false;
|
|
4296
4395
|
}
|
|
4297
4396
|
}
|
|
4397
|
+
if (depth === 0) {
|
|
4398
|
+
return false;
|
|
4399
|
+
}
|
|
4400
|
+
else if (depth < 0) {
|
|
4401
|
+
depth = -1;
|
|
4402
|
+
}
|
|
4298
4403
|
// Assume equality for cyclic structures. The algorithm for detecting cyclic
|
|
4299
4404
|
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
|
|
4300
4405
|
// Initializing stack of traversed objects.
|
|
@@ -4319,7 +4424,7 @@ function deepEq(a, b, aStack, bStack) {
|
|
|
4319
4424
|
return false;
|
|
4320
4425
|
// Deep compare the contents, ignoring non-numeric properties.
|
|
4321
4426
|
while (length--) {
|
|
4322
|
-
if (!eq(a[length], b[length], aStack, bStack))
|
|
4427
|
+
if (!eq(a[length], b[length], depth - 1, aStack, bStack))
|
|
4323
4428
|
return false;
|
|
4324
4429
|
}
|
|
4325
4430
|
}
|
|
@@ -4334,7 +4439,7 @@ function deepEq(a, b, aStack, bStack) {
|
|
|
4334
4439
|
while (length--) {
|
|
4335
4440
|
// Deep compare each member
|
|
4336
4441
|
key = keys[length];
|
|
4337
|
-
if (!(has$1(b, key) && eq(a[key], b[key], aStack, bStack)))
|
|
4442
|
+
if (!(has$1(b, key) && eq(a[key], b[key], depth - 1, aStack, bStack)))
|
|
4338
4443
|
return false;
|
|
4339
4444
|
}
|
|
4340
4445
|
}
|
|
@@ -4389,7 +4494,7 @@ try {
|
|
|
4389
4494
|
process.env.NODE_ENV;
|
|
4390
4495
|
}
|
|
4391
4496
|
catch (e) {
|
|
4392
|
-
var g =
|
|
4497
|
+
var g = getGlobal();
|
|
4393
4498
|
if (typeof process === "undefined")
|
|
4394
4499
|
g.process = {};
|
|
4395
4500
|
g.process.env = {};
|
|
@@ -4458,4 +4563,4 @@ if (process.env.NODE_ENV !== "production" &&
|
|
|
4458
4563
|
});
|
|
4459
4564
|
}
|
|
4460
4565
|
|
|
4461
|
-
export { $mobx, IDerivationState, ObservableMap, ObservableSet, Reaction, allowStateChanges as _allowStateChanges, allowStateChangesInsideComputed as _allowStateChangesInsideComputed, getAdministration as _getAdministration, getGlobalState as _getGlobalState, interceptReads as _interceptReads, isComputingDerivation as _isComputingDerivation, resetGlobalState as _resetGlobalState, action, autorun, comparer, computed, configure, createAtom, decorate, entries, extendObservable, extendShallowObservable, flow, get, getAtom, getDebugName, getDependencyTree, getObserverTree, has, intercept, isAction, isArrayLike, isObservableValue as isBoxedObservable, isComputed, isComputedProp, isObservable, isObservableArray, isObservableMap, isObservableObject, isObservableProp, isObservableSet, keys, observable, observe, onBecomeObserved, onBecomeUnobserved, onReactionError, reaction, remove, runInAction, set, spy, toJS, trace, transaction, untracked, values, when };
|
|
4566
|
+
export { $mobx, IDerivationState, ObservableMap, ObservableSet, Reaction, allowStateChanges as _allowStateChanges, allowStateChangesInsideComputed as _allowStateChangesInsideComputed, _endAction, getAdministration as _getAdministration, getGlobalState as _getGlobalState, interceptReads as _interceptReads, isComputingDerivation as _isComputingDerivation, resetGlobalState as _resetGlobalState, _startAction, action, autorun, comparer, computed, configure, createAtom, decorate, entries, extendObservable, extendShallowObservable, flow, get, getAtom, getDebugName, getDependencyTree, getObserverTree, has, intercept, isAction, isArrayLike, isObservableValue as isBoxedObservable, isComputed, isComputedProp, isObservable, isObservableArray, isObservableMap, isObservableObject, isObservableProp, isObservableSet, keys, observable, observe, onBecomeObserved, onBecomeUnobserved, onReactionError, reaction, remove, runInAction, set, spy, toJS, trace, transaction, untracked, values, when };
|