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.umd.js
CHANGED
|
@@ -73,8 +73,15 @@
|
|
|
73
73
|
Object.freeze(EMPTY_ARRAY);
|
|
74
74
|
var EMPTY_OBJECT = {};
|
|
75
75
|
Object.freeze(EMPTY_OBJECT);
|
|
76
|
+
var mockGlobal = {};
|
|
76
77
|
function getGlobal() {
|
|
77
|
-
|
|
78
|
+
if (typeof window !== "undefined") {
|
|
79
|
+
return window;
|
|
80
|
+
}
|
|
81
|
+
if (typeof global !== "undefined") {
|
|
82
|
+
return global;
|
|
83
|
+
}
|
|
84
|
+
return mockGlobal;
|
|
78
85
|
}
|
|
79
86
|
function getNextId() {
|
|
80
87
|
return ++globalState.mobxGuid;
|
|
@@ -134,6 +141,20 @@
|
|
|
134
141
|
var proto = Object.getPrototypeOf(value);
|
|
135
142
|
return proto === Object.prototype || proto === null;
|
|
136
143
|
}
|
|
144
|
+
function convertToMap(dataStructure) {
|
|
145
|
+
if (isES6Map(dataStructure) || isObservableMap(dataStructure)) {
|
|
146
|
+
return dataStructure;
|
|
147
|
+
}
|
|
148
|
+
else if (Array.isArray(dataStructure)) {
|
|
149
|
+
return new Map(dataStructure);
|
|
150
|
+
}
|
|
151
|
+
else if (isPlainObject(dataStructure)) {
|
|
152
|
+
return new Map(Object.entries(dataStructure));
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
return fail("Cannot convert to map from '" + dataStructure + "'");
|
|
156
|
+
}
|
|
157
|
+
}
|
|
137
158
|
function makeNonEnumerable(object, propNames) {
|
|
138
159
|
for (var i = 0; i < propNames.length; i++) {
|
|
139
160
|
addHiddenProp(object, propNames[i], object[propNames[i]]);
|
|
@@ -187,18 +208,6 @@
|
|
|
187
208
|
function isES6Set(thing) {
|
|
188
209
|
return thing instanceof Set;
|
|
189
210
|
}
|
|
190
|
-
function getMapLikeKeys(map) {
|
|
191
|
-
if (isPlainObject(map))
|
|
192
|
-
return Object.keys(map);
|
|
193
|
-
if (Array.isArray(map))
|
|
194
|
-
return map.map(function (_a) {
|
|
195
|
-
var _b = __read(_a, 1), key = _b[0];
|
|
196
|
-
return key;
|
|
197
|
-
});
|
|
198
|
-
if (isES6Map(map) || isObservableMap(map))
|
|
199
|
-
return iteratorToArray(map.keys());
|
|
200
|
-
return fail("Cannot get keys from '" + map + "'");
|
|
201
|
-
}
|
|
202
211
|
// use Array.from in Mobx 5
|
|
203
212
|
function iteratorToArray(it) {
|
|
204
213
|
var res = [];
|
|
@@ -225,13 +234,13 @@
|
|
|
225
234
|
addHiddenFinalProp(prototType, iteratorSymbol(), iteratorFactory);
|
|
226
235
|
}
|
|
227
236
|
function makeIterable(iterator) {
|
|
228
|
-
iterator[iteratorSymbol()] =
|
|
237
|
+
iterator[iteratorSymbol()] = getSelf;
|
|
229
238
|
return iterator;
|
|
230
239
|
}
|
|
231
240
|
function toStringTagSymbol() {
|
|
232
241
|
return (typeof Symbol === "function" && Symbol.toStringTag) || "@@toStringTag";
|
|
233
242
|
}
|
|
234
|
-
function
|
|
243
|
+
function getSelf() {
|
|
235
244
|
return this;
|
|
236
245
|
}
|
|
237
246
|
|
|
@@ -299,13 +308,17 @@
|
|
|
299
308
|
function structuralComparer(a, b) {
|
|
300
309
|
return deepEqual(a, b);
|
|
301
310
|
}
|
|
311
|
+
function shallowComparer(a, b) {
|
|
312
|
+
return deepEqual(a, b, 1);
|
|
313
|
+
}
|
|
302
314
|
function defaultComparer(a, b) {
|
|
303
315
|
return areBothNaN(a, b) || identityComparer(a, b);
|
|
304
316
|
}
|
|
305
317
|
var comparer = {
|
|
306
318
|
identity: identityComparer,
|
|
307
319
|
structural: structuralComparer,
|
|
308
|
-
default: defaultComparer
|
|
320
|
+
default: defaultComparer,
|
|
321
|
+
shallow: shallowComparer
|
|
309
322
|
};
|
|
310
323
|
|
|
311
324
|
var enumerableDescriptorCache = {};
|
|
@@ -625,6 +638,275 @@
|
|
|
625
638
|
};
|
|
626
639
|
computed.struct = computedStructDecorator;
|
|
627
640
|
|
|
641
|
+
(function (IDerivationState) {
|
|
642
|
+
// before being run or (outside batch and not being observed)
|
|
643
|
+
// at this point derivation is not holding any data about dependency tree
|
|
644
|
+
IDerivationState[IDerivationState["NOT_TRACKING"] = -1] = "NOT_TRACKING";
|
|
645
|
+
// no shallow dependency changed since last computation
|
|
646
|
+
// won't recalculate derivation
|
|
647
|
+
// this is what makes mobx fast
|
|
648
|
+
IDerivationState[IDerivationState["UP_TO_DATE"] = 0] = "UP_TO_DATE";
|
|
649
|
+
// some deep dependency changed, but don't know if shallow dependency changed
|
|
650
|
+
// will require to check first if UP_TO_DATE or POSSIBLY_STALE
|
|
651
|
+
// currently only ComputedValue will propagate POSSIBLY_STALE
|
|
652
|
+
//
|
|
653
|
+
// having this state is second big optimization:
|
|
654
|
+
// don't have to recompute on every dependency change, but only when it's needed
|
|
655
|
+
IDerivationState[IDerivationState["POSSIBLY_STALE"] = 1] = "POSSIBLY_STALE";
|
|
656
|
+
// A shallow dependency has changed since last computation and the derivation
|
|
657
|
+
// will need to recompute when it's needed next.
|
|
658
|
+
IDerivationState[IDerivationState["STALE"] = 2] = "STALE";
|
|
659
|
+
})(exports.IDerivationState || (exports.IDerivationState = {}));
|
|
660
|
+
var TraceMode;
|
|
661
|
+
(function (TraceMode) {
|
|
662
|
+
TraceMode[TraceMode["NONE"] = 0] = "NONE";
|
|
663
|
+
TraceMode[TraceMode["LOG"] = 1] = "LOG";
|
|
664
|
+
TraceMode[TraceMode["BREAK"] = 2] = "BREAK";
|
|
665
|
+
})(TraceMode || (TraceMode = {}));
|
|
666
|
+
var CaughtException = /** @class */ (function () {
|
|
667
|
+
function CaughtException(cause) {
|
|
668
|
+
this.cause = cause;
|
|
669
|
+
// Empty
|
|
670
|
+
}
|
|
671
|
+
return CaughtException;
|
|
672
|
+
}());
|
|
673
|
+
function isCaughtException(e) {
|
|
674
|
+
return e instanceof CaughtException;
|
|
675
|
+
}
|
|
676
|
+
/**
|
|
677
|
+
* Finds out whether any dependency of the derivation has actually changed.
|
|
678
|
+
* If dependenciesState is 1 then it will recalculate dependencies,
|
|
679
|
+
* if any dependency changed it will propagate it by changing dependenciesState to 2.
|
|
680
|
+
*
|
|
681
|
+
* By iterating over the dependencies in the same order that they were reported and
|
|
682
|
+
* stopping on the first change, all the recalculations are only called for ComputedValues
|
|
683
|
+
* that will be tracked by derivation. That is because we assume that if the first x
|
|
684
|
+
* dependencies of the derivation doesn't change then the derivation should run the same way
|
|
685
|
+
* up until accessing x-th dependency.
|
|
686
|
+
*/
|
|
687
|
+
function shouldCompute(derivation) {
|
|
688
|
+
switch (derivation.dependenciesState) {
|
|
689
|
+
case exports.IDerivationState.UP_TO_DATE:
|
|
690
|
+
return false;
|
|
691
|
+
case exports.IDerivationState.NOT_TRACKING:
|
|
692
|
+
case exports.IDerivationState.STALE:
|
|
693
|
+
return true;
|
|
694
|
+
case exports.IDerivationState.POSSIBLY_STALE: {
|
|
695
|
+
var prevUntracked = untrackedStart(); // no need for those computeds to be reported, they will be picked up in trackDerivedFunction.
|
|
696
|
+
var obs = derivation.observing, l = obs.length;
|
|
697
|
+
for (var i = 0; i < l; i++) {
|
|
698
|
+
var obj = obs[i];
|
|
699
|
+
if (isComputedValue(obj)) {
|
|
700
|
+
if (globalState.disableErrorBoundaries) {
|
|
701
|
+
obj.get();
|
|
702
|
+
}
|
|
703
|
+
else {
|
|
704
|
+
try {
|
|
705
|
+
obj.get();
|
|
706
|
+
}
|
|
707
|
+
catch (e) {
|
|
708
|
+
// we are not interested in the value *or* exception at this moment, but if there is one, notify all
|
|
709
|
+
untrackedEnd(prevUntracked);
|
|
710
|
+
return true;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
// if ComputedValue `obj` actually changed it will be computed and propagated to its observers.
|
|
714
|
+
// and `derivation` is an observer of `obj`
|
|
715
|
+
// invariantShouldCompute(derivation)
|
|
716
|
+
if (derivation.dependenciesState === exports.IDerivationState.STALE) {
|
|
717
|
+
untrackedEnd(prevUntracked);
|
|
718
|
+
return true;
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
changeDependenciesStateTo0(derivation);
|
|
723
|
+
untrackedEnd(prevUntracked);
|
|
724
|
+
return false;
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
// function invariantShouldCompute(derivation: IDerivation) {
|
|
729
|
+
// const newDepState = (derivation as any).dependenciesState
|
|
730
|
+
// if (
|
|
731
|
+
// process.env.NODE_ENV === "production" &&
|
|
732
|
+
// (newDepState === IDerivationState.POSSIBLY_STALE ||
|
|
733
|
+
// newDepState === IDerivationState.NOT_TRACKING)
|
|
734
|
+
// )
|
|
735
|
+
// fail("Illegal dependency state")
|
|
736
|
+
// }
|
|
737
|
+
function isComputingDerivation() {
|
|
738
|
+
return globalState.trackingDerivation !== null; // filter out actions inside computations
|
|
739
|
+
}
|
|
740
|
+
function checkIfStateModificationsAreAllowed(atom) {
|
|
741
|
+
var hasObservers = atom.observers.length > 0;
|
|
742
|
+
// Should never be possible to change an observed observable from inside computed, see #798
|
|
743
|
+
if (globalState.computationDepth > 0 && hasObservers)
|
|
744
|
+
fail(process.env.NODE_ENV !== "production" &&
|
|
745
|
+
"Computed values are not allowed to cause side effects by changing observables that are already being observed. Tried to modify: " + atom.name);
|
|
746
|
+
// Should not be possible to change observed state outside strict mode, except during initialization, see #563
|
|
747
|
+
if (!globalState.allowStateChanges && (hasObservers || globalState.enforceActions === "strict"))
|
|
748
|
+
fail(process.env.NODE_ENV !== "production" &&
|
|
749
|
+
(globalState.enforceActions
|
|
750
|
+
? "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: "
|
|
751
|
+
: "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: ") +
|
|
752
|
+
atom.name);
|
|
753
|
+
}
|
|
754
|
+
function checkIfStateReadsAreAllowed(observable) {
|
|
755
|
+
if (process.env.NODE_ENV !== "production" &&
|
|
756
|
+
!globalState.allowStateReads &&
|
|
757
|
+
globalState.observableRequiresReaction) {
|
|
758
|
+
console.warn("[mobx] Observable " + observable.name + " being read outside a reactive context");
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
/**
|
|
762
|
+
* Executes the provided function `f` and tracks which observables are being accessed.
|
|
763
|
+
* The tracking information is stored on the `derivation` object and the derivation is registered
|
|
764
|
+
* as observer of any of the accessed observables.
|
|
765
|
+
*/
|
|
766
|
+
function trackDerivedFunction(derivation, f, context) {
|
|
767
|
+
var prevAllowStateReads = allowStateReadsStart(true);
|
|
768
|
+
// pre allocate array allocation + room for variation in deps
|
|
769
|
+
// array will be trimmed by bindDependencies
|
|
770
|
+
changeDependenciesStateTo0(derivation);
|
|
771
|
+
derivation.newObserving = new Array(derivation.observing.length + 100);
|
|
772
|
+
derivation.unboundDepsCount = 0;
|
|
773
|
+
derivation.runId = ++globalState.runId;
|
|
774
|
+
var prevTracking = globalState.trackingDerivation;
|
|
775
|
+
globalState.trackingDerivation = derivation;
|
|
776
|
+
var result;
|
|
777
|
+
if (globalState.disableErrorBoundaries === true) {
|
|
778
|
+
result = f.call(context);
|
|
779
|
+
}
|
|
780
|
+
else {
|
|
781
|
+
try {
|
|
782
|
+
result = f.call(context);
|
|
783
|
+
}
|
|
784
|
+
catch (e) {
|
|
785
|
+
result = new CaughtException(e);
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
globalState.trackingDerivation = prevTracking;
|
|
789
|
+
bindDependencies(derivation);
|
|
790
|
+
if (derivation.observing.length === 0) {
|
|
791
|
+
warnAboutDerivationWithoutDependencies(derivation);
|
|
792
|
+
}
|
|
793
|
+
allowStateReadsEnd(prevAllowStateReads);
|
|
794
|
+
return result;
|
|
795
|
+
}
|
|
796
|
+
function warnAboutDerivationWithoutDependencies(derivation) {
|
|
797
|
+
if (process.env.NODE_ENV === "production")
|
|
798
|
+
return;
|
|
799
|
+
if (globalState.reactionRequiresObservable || derivation.requiresObservable) {
|
|
800
|
+
console.warn("[mobx] Derivation " + derivation.name + " is created/updated without reading any observable value");
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
/**
|
|
804
|
+
* diffs newObserving with observing.
|
|
805
|
+
* update observing to be newObserving with unique observables
|
|
806
|
+
* notify observers that become observed/unobserved
|
|
807
|
+
*/
|
|
808
|
+
function bindDependencies(derivation) {
|
|
809
|
+
// invariant(derivation.dependenciesState !== IDerivationState.NOT_TRACKING, "INTERNAL ERROR bindDependencies expects derivation.dependenciesState !== -1");
|
|
810
|
+
var prevObserving = derivation.observing;
|
|
811
|
+
var observing = (derivation.observing = derivation.newObserving);
|
|
812
|
+
var lowestNewObservingDerivationState = exports.IDerivationState.UP_TO_DATE;
|
|
813
|
+
// Go through all new observables and check diffValue: (this list can contain duplicates):
|
|
814
|
+
// 0: first occurrence, change to 1 and keep it
|
|
815
|
+
// 1: extra occurrence, drop it
|
|
816
|
+
var i0 = 0, l = derivation.unboundDepsCount;
|
|
817
|
+
for (var i = 0; i < l; i++) {
|
|
818
|
+
var dep = observing[i];
|
|
819
|
+
if (dep.diffValue === 0) {
|
|
820
|
+
dep.diffValue = 1;
|
|
821
|
+
if (i0 !== i)
|
|
822
|
+
observing[i0] = dep;
|
|
823
|
+
i0++;
|
|
824
|
+
}
|
|
825
|
+
// Upcast is 'safe' here, because if dep is IObservable, `dependenciesState` will be undefined,
|
|
826
|
+
// not hitting the condition
|
|
827
|
+
if (dep.dependenciesState > lowestNewObservingDerivationState) {
|
|
828
|
+
lowestNewObservingDerivationState = dep.dependenciesState;
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
observing.length = i0;
|
|
832
|
+
derivation.newObserving = null; // newObserving shouldn't be needed outside tracking (statement moved down to work around FF bug, see #614)
|
|
833
|
+
// Go through all old observables and check diffValue: (it is unique after last bindDependencies)
|
|
834
|
+
// 0: it's not in new observables, unobserve it
|
|
835
|
+
// 1: it keeps being observed, don't want to notify it. change to 0
|
|
836
|
+
l = prevObserving.length;
|
|
837
|
+
while (l--) {
|
|
838
|
+
var dep = prevObserving[l];
|
|
839
|
+
if (dep.diffValue === 0) {
|
|
840
|
+
removeObserver(dep, derivation);
|
|
841
|
+
}
|
|
842
|
+
dep.diffValue = 0;
|
|
843
|
+
}
|
|
844
|
+
// Go through all new observables and check diffValue: (now it should be unique)
|
|
845
|
+
// 0: it was set to 0 in last loop. don't need to do anything.
|
|
846
|
+
// 1: it wasn't observed, let's observe it. set back to 0
|
|
847
|
+
while (i0--) {
|
|
848
|
+
var dep = observing[i0];
|
|
849
|
+
if (dep.diffValue === 1) {
|
|
850
|
+
dep.diffValue = 0;
|
|
851
|
+
addObserver(dep, derivation);
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
// Some new observed derivations may become stale during this derivation computation
|
|
855
|
+
// so they have had no chance to propagate staleness (#916)
|
|
856
|
+
if (lowestNewObservingDerivationState !== exports.IDerivationState.UP_TO_DATE) {
|
|
857
|
+
derivation.dependenciesState = lowestNewObservingDerivationState;
|
|
858
|
+
derivation.onBecomeStale();
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
function clearObserving(derivation) {
|
|
862
|
+
// invariant(globalState.inBatch > 0, "INTERNAL ERROR clearObserving should be called only inside batch");
|
|
863
|
+
var obs = derivation.observing;
|
|
864
|
+
derivation.observing = [];
|
|
865
|
+
var i = obs.length;
|
|
866
|
+
while (i--)
|
|
867
|
+
removeObserver(obs[i], derivation);
|
|
868
|
+
derivation.dependenciesState = exports.IDerivationState.NOT_TRACKING;
|
|
869
|
+
}
|
|
870
|
+
function untracked(action) {
|
|
871
|
+
var prev = untrackedStart();
|
|
872
|
+
var res = action();
|
|
873
|
+
untrackedEnd(prev);
|
|
874
|
+
return res;
|
|
875
|
+
}
|
|
876
|
+
function untrackedStart() {
|
|
877
|
+
var prev = globalState.trackingDerivation;
|
|
878
|
+
globalState.trackingDerivation = null;
|
|
879
|
+
return prev;
|
|
880
|
+
}
|
|
881
|
+
function untrackedEnd(prev) {
|
|
882
|
+
globalState.trackingDerivation = prev;
|
|
883
|
+
}
|
|
884
|
+
function allowStateReadsStart(allowStateReads) {
|
|
885
|
+
var prev = globalState.allowStateReads;
|
|
886
|
+
globalState.allowStateReads = allowStateReads;
|
|
887
|
+
return prev;
|
|
888
|
+
}
|
|
889
|
+
function allowStateReadsEnd(prev) {
|
|
890
|
+
globalState.allowStateReads = prev;
|
|
891
|
+
}
|
|
892
|
+
/**
|
|
893
|
+
* needed to keep `lowestObserverState` correct. when changing from (2 or 1) to 0
|
|
894
|
+
*
|
|
895
|
+
*/
|
|
896
|
+
function changeDependenciesStateTo0(derivation) {
|
|
897
|
+
if (derivation.dependenciesState === exports.IDerivationState.UP_TO_DATE)
|
|
898
|
+
return;
|
|
899
|
+
derivation.dependenciesState = exports.IDerivationState.UP_TO_DATE;
|
|
900
|
+
var obs = derivation.observing;
|
|
901
|
+
var i = obs.length;
|
|
902
|
+
while (i--)
|
|
903
|
+
obs[i].lowestObserverState = exports.IDerivationState.UP_TO_DATE;
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
// we don't use globalState for these in order to avoid possible issues with multiple
|
|
907
|
+
// mobx versions
|
|
908
|
+
var currentActionId = 0;
|
|
909
|
+
var nextActionId = 1;
|
|
628
910
|
function createAction(actionName, fn) {
|
|
629
911
|
if (process.env.NODE_ENV !== "production") {
|
|
630
912
|
invariant(typeof fn === "function", "`action` can only be invoked on functions");
|
|
@@ -638,25 +920,19 @@
|
|
|
638
920
|
return res;
|
|
639
921
|
}
|
|
640
922
|
function executeAction(actionName, fn, scope, args) {
|
|
641
|
-
var runInfo =
|
|
642
|
-
var shouldSupressReactionError = true;
|
|
923
|
+
var runInfo = _startAction(actionName, scope, args);
|
|
643
924
|
try {
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
925
|
+
return fn.apply(scope, args);
|
|
926
|
+
}
|
|
927
|
+
catch (err) {
|
|
928
|
+
runInfo.error = err;
|
|
929
|
+
throw err;
|
|
647
930
|
}
|
|
648
931
|
finally {
|
|
649
|
-
|
|
650
|
-
globalState.suppressReactionErrors = shouldSupressReactionError;
|
|
651
|
-
endAction(runInfo);
|
|
652
|
-
globalState.suppressReactionErrors = false;
|
|
653
|
-
}
|
|
654
|
-
else {
|
|
655
|
-
endAction(runInfo);
|
|
656
|
-
}
|
|
932
|
+
_endAction(runInfo);
|
|
657
933
|
}
|
|
658
934
|
}
|
|
659
|
-
function
|
|
935
|
+
function _startAction(actionName, scope, args) {
|
|
660
936
|
var notifySpy = isSpyEnabled() && !!actionName;
|
|
661
937
|
var startTime = 0;
|
|
662
938
|
if (notifySpy) {
|
|
@@ -676,19 +952,35 @@
|
|
|
676
952
|
var prevDerivation = untrackedStart();
|
|
677
953
|
startBatch();
|
|
678
954
|
var prevAllowStateChanges = allowStateChangesStart(true);
|
|
679
|
-
|
|
955
|
+
var prevAllowStateReads = allowStateReadsStart(true);
|
|
956
|
+
var runInfo = {
|
|
680
957
|
prevDerivation: prevDerivation,
|
|
681
958
|
prevAllowStateChanges: prevAllowStateChanges,
|
|
959
|
+
prevAllowStateReads: prevAllowStateReads,
|
|
682
960
|
notifySpy: notifySpy,
|
|
683
|
-
startTime: startTime
|
|
961
|
+
startTime: startTime,
|
|
962
|
+
actionId: nextActionId++,
|
|
963
|
+
parentActionId: currentActionId
|
|
684
964
|
};
|
|
965
|
+
currentActionId = runInfo.actionId;
|
|
966
|
+
return runInfo;
|
|
685
967
|
}
|
|
686
|
-
function
|
|
968
|
+
function _endAction(runInfo) {
|
|
969
|
+
if (currentActionId !== runInfo.actionId) {
|
|
970
|
+
fail("invalid action stack. did you forget to finish an action?");
|
|
971
|
+
}
|
|
972
|
+
currentActionId = runInfo.parentActionId;
|
|
973
|
+
if (runInfo.error !== undefined) {
|
|
974
|
+
globalState.suppressReactionErrors = true;
|
|
975
|
+
}
|
|
687
976
|
allowStateChangesEnd(runInfo.prevAllowStateChanges);
|
|
977
|
+
allowStateReadsEnd(runInfo.prevAllowStateReads);
|
|
688
978
|
endBatch();
|
|
689
979
|
untrackedEnd(runInfo.prevDerivation);
|
|
690
|
-
if (runInfo.notifySpy)
|
|
980
|
+
if (runInfo.notifySpy) {
|
|
691
981
|
spyReportEnd({ time: Date.now() - runInfo.startTime });
|
|
982
|
+
}
|
|
983
|
+
globalState.suppressReactionErrors = false;
|
|
692
984
|
}
|
|
693
985
|
function allowStateChanges(allowStateChanges, func) {
|
|
694
986
|
var prev = allowStateChangesStart(allowStateChanges);
|
|
@@ -944,337 +1236,99 @@
|
|
|
944
1236
|
if (isSpyEnabled()) {
|
|
945
1237
|
spyReport({
|
|
946
1238
|
object: this.scope,
|
|
947
|
-
type: "compute",
|
|
948
|
-
name: this.name
|
|
949
|
-
});
|
|
950
|
-
}
|
|
951
|
-
var oldValue = this.value;
|
|
952
|
-
var wasSuspended =
|
|
953
|
-
/* see #1208 */ this.dependenciesState === exports.IDerivationState.NOT_TRACKING;
|
|
954
|
-
var newValue = this.computeValue(true);
|
|
955
|
-
var changed = wasSuspended ||
|
|
956
|
-
isCaughtException(oldValue) ||
|
|
957
|
-
isCaughtException(newValue) ||
|
|
958
|
-
!this.equals(oldValue, newValue);
|
|
959
|
-
if (changed) {
|
|
960
|
-
this.value = newValue;
|
|
961
|
-
}
|
|
962
|
-
return changed;
|
|
963
|
-
};
|
|
964
|
-
ComputedValue.prototype.computeValue = function (track) {
|
|
965
|
-
this.isComputing = true;
|
|
966
|
-
globalState.computationDepth++;
|
|
967
|
-
var res;
|
|
968
|
-
if (track) {
|
|
969
|
-
res = trackDerivedFunction(this, this.derivation, this.scope);
|
|
970
|
-
}
|
|
971
|
-
else {
|
|
972
|
-
if (globalState.disableErrorBoundaries === true) {
|
|
973
|
-
res = this.derivation.call(this.scope);
|
|
974
|
-
}
|
|
975
|
-
else {
|
|
976
|
-
try {
|
|
977
|
-
res = this.derivation.call(this.scope);
|
|
978
|
-
}
|
|
979
|
-
catch (e) {
|
|
980
|
-
res = new CaughtException(e);
|
|
981
|
-
}
|
|
982
|
-
}
|
|
983
|
-
}
|
|
984
|
-
globalState.computationDepth--;
|
|
985
|
-
this.isComputing = false;
|
|
986
|
-
return res;
|
|
987
|
-
};
|
|
988
|
-
ComputedValue.prototype.suspend = function () {
|
|
989
|
-
if (!this.keepAlive) {
|
|
990
|
-
clearObserving(this);
|
|
991
|
-
this.value = undefined; // don't hold on to computed value!
|
|
992
|
-
}
|
|
993
|
-
};
|
|
994
|
-
ComputedValue.prototype.observe = function (listener, fireImmediately) {
|
|
995
|
-
var _this = this;
|
|
996
|
-
var firstTime = true;
|
|
997
|
-
var prevValue = undefined;
|
|
998
|
-
return autorun(function () {
|
|
999
|
-
var newValue = _this.get();
|
|
1000
|
-
if (!firstTime || fireImmediately) {
|
|
1001
|
-
var prevU = untrackedStart();
|
|
1002
|
-
listener({
|
|
1003
|
-
type: "update",
|
|
1004
|
-
object: _this,
|
|
1005
|
-
newValue: newValue,
|
|
1006
|
-
oldValue: prevValue
|
|
1007
|
-
});
|
|
1008
|
-
untrackedEnd(prevU);
|
|
1009
|
-
}
|
|
1010
|
-
firstTime = false;
|
|
1011
|
-
prevValue = newValue;
|
|
1012
|
-
});
|
|
1013
|
-
};
|
|
1014
|
-
ComputedValue.prototype.warnAboutUntrackedRead = function () {
|
|
1015
|
-
if (process.env.NODE_ENV === "production")
|
|
1016
|
-
return;
|
|
1017
|
-
if (this.requiresReaction === true) {
|
|
1018
|
-
fail("[mobx] Computed value " + this.name + " is read outside a reactive context");
|
|
1019
|
-
}
|
|
1020
|
-
if (this.isTracing !== TraceMode.NONE) {
|
|
1021
|
-
console.log("[mobx.trace] '" + this.name + "' is being read outside a reactive context. Doing a full recompute");
|
|
1022
|
-
}
|
|
1023
|
-
if (globalState.computedRequiresReaction) {
|
|
1024
|
-
console.warn("[mobx] Computed value " + this.name + " is being read outside a reactive context. Doing a full recompute");
|
|
1025
|
-
}
|
|
1026
|
-
};
|
|
1027
|
-
ComputedValue.prototype.toJSON = function () {
|
|
1028
|
-
return this.get();
|
|
1029
|
-
};
|
|
1030
|
-
ComputedValue.prototype.toString = function () {
|
|
1031
|
-
return this.name + "[" + this.derivation.toString() + "]";
|
|
1032
|
-
};
|
|
1033
|
-
ComputedValue.prototype.valueOf = function () {
|
|
1034
|
-
return toPrimitive(this.get());
|
|
1035
|
-
};
|
|
1036
|
-
return ComputedValue;
|
|
1037
|
-
}());
|
|
1038
|
-
ComputedValue.prototype[primitiveSymbol()] = ComputedValue.prototype.valueOf;
|
|
1039
|
-
var isComputedValue = createInstanceofPredicate("ComputedValue", ComputedValue);
|
|
1040
|
-
|
|
1041
|
-
(function (IDerivationState) {
|
|
1042
|
-
// before being run or (outside batch and not being observed)
|
|
1043
|
-
// at this point derivation is not holding any data about dependency tree
|
|
1044
|
-
IDerivationState[IDerivationState["NOT_TRACKING"] = -1] = "NOT_TRACKING";
|
|
1045
|
-
// no shallow dependency changed since last computation
|
|
1046
|
-
// won't recalculate derivation
|
|
1047
|
-
// this is what makes mobx fast
|
|
1048
|
-
IDerivationState[IDerivationState["UP_TO_DATE"] = 0] = "UP_TO_DATE";
|
|
1049
|
-
// some deep dependency changed, but don't know if shallow dependency changed
|
|
1050
|
-
// will require to check first if UP_TO_DATE or POSSIBLY_STALE
|
|
1051
|
-
// currently only ComputedValue will propagate POSSIBLY_STALE
|
|
1052
|
-
//
|
|
1053
|
-
// having this state is second big optimization:
|
|
1054
|
-
// don't have to recompute on every dependency change, but only when it's needed
|
|
1055
|
-
IDerivationState[IDerivationState["POSSIBLY_STALE"] = 1] = "POSSIBLY_STALE";
|
|
1056
|
-
// A shallow dependency has changed since last computation and the derivation
|
|
1057
|
-
// will need to recompute when it's needed next.
|
|
1058
|
-
IDerivationState[IDerivationState["STALE"] = 2] = "STALE";
|
|
1059
|
-
})(exports.IDerivationState || (exports.IDerivationState = {}));
|
|
1060
|
-
var TraceMode;
|
|
1061
|
-
(function (TraceMode) {
|
|
1062
|
-
TraceMode[TraceMode["NONE"] = 0] = "NONE";
|
|
1063
|
-
TraceMode[TraceMode["LOG"] = 1] = "LOG";
|
|
1064
|
-
TraceMode[TraceMode["BREAK"] = 2] = "BREAK";
|
|
1065
|
-
})(TraceMode || (TraceMode = {}));
|
|
1066
|
-
var CaughtException = /** @class */ (function () {
|
|
1067
|
-
function CaughtException(cause) {
|
|
1068
|
-
this.cause = cause;
|
|
1069
|
-
// Empty
|
|
1070
|
-
}
|
|
1071
|
-
return CaughtException;
|
|
1072
|
-
}());
|
|
1073
|
-
function isCaughtException(e) {
|
|
1074
|
-
return e instanceof CaughtException;
|
|
1075
|
-
}
|
|
1076
|
-
/**
|
|
1077
|
-
* Finds out whether any dependency of the derivation has actually changed.
|
|
1078
|
-
* If dependenciesState is 1 then it will recalculate dependencies,
|
|
1079
|
-
* if any dependency changed it will propagate it by changing dependenciesState to 2.
|
|
1080
|
-
*
|
|
1081
|
-
* By iterating over the dependencies in the same order that they were reported and
|
|
1082
|
-
* stopping on the first change, all the recalculations are only called for ComputedValues
|
|
1083
|
-
* that will be tracked by derivation. That is because we assume that if the first x
|
|
1084
|
-
* dependencies of the derivation doesn't change then the derivation should run the same way
|
|
1085
|
-
* up until accessing x-th dependency.
|
|
1086
|
-
*/
|
|
1087
|
-
function shouldCompute(derivation) {
|
|
1088
|
-
switch (derivation.dependenciesState) {
|
|
1089
|
-
case exports.IDerivationState.UP_TO_DATE:
|
|
1090
|
-
return false;
|
|
1091
|
-
case exports.IDerivationState.NOT_TRACKING:
|
|
1092
|
-
case exports.IDerivationState.STALE:
|
|
1093
|
-
return true;
|
|
1094
|
-
case exports.IDerivationState.POSSIBLY_STALE: {
|
|
1095
|
-
var prevUntracked = untrackedStart(); // no need for those computeds to be reported, they will be picked up in trackDerivedFunction.
|
|
1096
|
-
var obs = derivation.observing, l = obs.length;
|
|
1097
|
-
for (var i = 0; i < l; i++) {
|
|
1098
|
-
var obj = obs[i];
|
|
1099
|
-
if (isComputedValue(obj)) {
|
|
1100
|
-
if (globalState.disableErrorBoundaries) {
|
|
1101
|
-
obj.get();
|
|
1102
|
-
}
|
|
1103
|
-
else {
|
|
1104
|
-
try {
|
|
1105
|
-
obj.get();
|
|
1106
|
-
}
|
|
1107
|
-
catch (e) {
|
|
1108
|
-
// we are not interested in the value *or* exception at this moment, but if there is one, notify all
|
|
1109
|
-
untrackedEnd(prevUntracked);
|
|
1110
|
-
return true;
|
|
1111
|
-
}
|
|
1112
|
-
}
|
|
1113
|
-
// if ComputedValue `obj` actually changed it will be computed and propagated to its observers.
|
|
1114
|
-
// and `derivation` is an observer of `obj`
|
|
1115
|
-
// invariantShouldCompute(derivation)
|
|
1116
|
-
if (derivation.dependenciesState === exports.IDerivationState.STALE) {
|
|
1117
|
-
untrackedEnd(prevUntracked);
|
|
1118
|
-
return true;
|
|
1119
|
-
}
|
|
1120
|
-
}
|
|
1121
|
-
}
|
|
1122
|
-
changeDependenciesStateTo0(derivation);
|
|
1123
|
-
untrackedEnd(prevUntracked);
|
|
1124
|
-
return false;
|
|
1239
|
+
type: "compute",
|
|
1240
|
+
name: this.name
|
|
1241
|
+
});
|
|
1125
1242
|
}
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
// }
|
|
1137
|
-
function isComputingDerivation() {
|
|
1138
|
-
return globalState.trackingDerivation !== null; // filter out actions inside computations
|
|
1139
|
-
}
|
|
1140
|
-
function checkIfStateModificationsAreAllowed(atom) {
|
|
1141
|
-
var hasObservers = atom.observers.length > 0;
|
|
1142
|
-
// Should never be possible to change an observed observable from inside computed, see #798
|
|
1143
|
-
if (globalState.computationDepth > 0 && hasObservers)
|
|
1144
|
-
fail(process.env.NODE_ENV !== "production" &&
|
|
1145
|
-
"Computed values are not allowed to cause side effects by changing observables that are already being observed. Tried to modify: " + atom.name);
|
|
1146
|
-
// Should not be possible to change observed state outside strict mode, except during initialization, see #563
|
|
1147
|
-
if (!globalState.allowStateChanges && (hasObservers || globalState.enforceActions === "strict"))
|
|
1148
|
-
fail(process.env.NODE_ENV !== "production" &&
|
|
1149
|
-
(globalState.enforceActions
|
|
1150
|
-
? "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: "
|
|
1151
|
-
: "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: ") +
|
|
1152
|
-
atom.name);
|
|
1153
|
-
}
|
|
1154
|
-
/**
|
|
1155
|
-
* Executes the provided function `f` and tracks which observables are being accessed.
|
|
1156
|
-
* The tracking information is stored on the `derivation` object and the derivation is registered
|
|
1157
|
-
* as observer of any of the accessed observables.
|
|
1158
|
-
*/
|
|
1159
|
-
function trackDerivedFunction(derivation, f, context) {
|
|
1160
|
-
// pre allocate array allocation + room for variation in deps
|
|
1161
|
-
// array will be trimmed by bindDependencies
|
|
1162
|
-
changeDependenciesStateTo0(derivation);
|
|
1163
|
-
derivation.newObserving = new Array(derivation.observing.length + 100);
|
|
1164
|
-
derivation.unboundDepsCount = 0;
|
|
1165
|
-
derivation.runId = ++globalState.runId;
|
|
1166
|
-
var prevTracking = globalState.trackingDerivation;
|
|
1167
|
-
globalState.trackingDerivation = derivation;
|
|
1168
|
-
var result;
|
|
1169
|
-
if (globalState.disableErrorBoundaries === true) {
|
|
1170
|
-
result = f.call(context);
|
|
1171
|
-
}
|
|
1172
|
-
else {
|
|
1173
|
-
try {
|
|
1174
|
-
result = f.call(context);
|
|
1243
|
+
var oldValue = this.value;
|
|
1244
|
+
var wasSuspended =
|
|
1245
|
+
/* see #1208 */ this.dependenciesState === exports.IDerivationState.NOT_TRACKING;
|
|
1246
|
+
var newValue = this.computeValue(true);
|
|
1247
|
+
var changed = wasSuspended ||
|
|
1248
|
+
isCaughtException(oldValue) ||
|
|
1249
|
+
isCaughtException(newValue) ||
|
|
1250
|
+
!this.equals(oldValue, newValue);
|
|
1251
|
+
if (changed) {
|
|
1252
|
+
this.value = newValue;
|
|
1175
1253
|
}
|
|
1176
|
-
|
|
1177
|
-
|
|
1254
|
+
return changed;
|
|
1255
|
+
};
|
|
1256
|
+
ComputedValue.prototype.computeValue = function (track) {
|
|
1257
|
+
this.isComputing = true;
|
|
1258
|
+
globalState.computationDepth++;
|
|
1259
|
+
var res;
|
|
1260
|
+
if (track) {
|
|
1261
|
+
res = trackDerivedFunction(this, this.derivation, this.scope);
|
|
1178
1262
|
}
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
var prevObserving = derivation.observing;
|
|
1192
|
-
var observing = (derivation.observing = derivation.newObserving);
|
|
1193
|
-
var lowestNewObservingDerivationState = exports.IDerivationState.UP_TO_DATE;
|
|
1194
|
-
// Go through all new observables and check diffValue: (this list can contain duplicates):
|
|
1195
|
-
// 0: first occurrence, change to 1 and keep it
|
|
1196
|
-
// 1: extra occurrence, drop it
|
|
1197
|
-
var i0 = 0, l = derivation.unboundDepsCount;
|
|
1198
|
-
for (var i = 0; i < l; i++) {
|
|
1199
|
-
var dep = observing[i];
|
|
1200
|
-
if (dep.diffValue === 0) {
|
|
1201
|
-
dep.diffValue = 1;
|
|
1202
|
-
if (i0 !== i)
|
|
1203
|
-
observing[i0] = dep;
|
|
1204
|
-
i0++;
|
|
1263
|
+
else {
|
|
1264
|
+
if (globalState.disableErrorBoundaries === true) {
|
|
1265
|
+
res = this.derivation.call(this.scope);
|
|
1266
|
+
}
|
|
1267
|
+
else {
|
|
1268
|
+
try {
|
|
1269
|
+
res = this.derivation.call(this.scope);
|
|
1270
|
+
}
|
|
1271
|
+
catch (e) {
|
|
1272
|
+
res = new CaughtException(e);
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1205
1275
|
}
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1276
|
+
globalState.computationDepth--;
|
|
1277
|
+
this.isComputing = false;
|
|
1278
|
+
return res;
|
|
1279
|
+
};
|
|
1280
|
+
ComputedValue.prototype.suspend = function () {
|
|
1281
|
+
if (!this.keepAlive) {
|
|
1282
|
+
clearObserving(this);
|
|
1283
|
+
this.value = undefined; // don't hold on to computed value!
|
|
1210
1284
|
}
|
|
1211
|
-
}
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1285
|
+
};
|
|
1286
|
+
ComputedValue.prototype.observe = function (listener, fireImmediately) {
|
|
1287
|
+
var _this = this;
|
|
1288
|
+
var firstTime = true;
|
|
1289
|
+
var prevValue = undefined;
|
|
1290
|
+
return autorun(function () {
|
|
1291
|
+
var newValue = _this.get();
|
|
1292
|
+
if (!firstTime || fireImmediately) {
|
|
1293
|
+
var prevU = untrackedStart();
|
|
1294
|
+
listener({
|
|
1295
|
+
type: "update",
|
|
1296
|
+
object: _this,
|
|
1297
|
+
newValue: newValue,
|
|
1298
|
+
oldValue: prevValue
|
|
1299
|
+
});
|
|
1300
|
+
untrackedEnd(prevU);
|
|
1301
|
+
}
|
|
1302
|
+
firstTime = false;
|
|
1303
|
+
prevValue = newValue;
|
|
1304
|
+
});
|
|
1305
|
+
};
|
|
1306
|
+
ComputedValue.prototype.warnAboutUntrackedRead = function () {
|
|
1307
|
+
if (process.env.NODE_ENV === "production")
|
|
1308
|
+
return;
|
|
1309
|
+
if (this.requiresReaction === true) {
|
|
1310
|
+
fail("[mobx] Computed value " + this.name + " is read outside a reactive context");
|
|
1222
1311
|
}
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
// Go through all new observables and check diffValue: (now it should be unique)
|
|
1226
|
-
// 0: it was set to 0 in last loop. don't need to do anything.
|
|
1227
|
-
// 1: it wasn't observed, let's observe it. set back to 0
|
|
1228
|
-
while (i0--) {
|
|
1229
|
-
var dep = observing[i0];
|
|
1230
|
-
if (dep.diffValue === 1) {
|
|
1231
|
-
dep.diffValue = 0;
|
|
1232
|
-
addObserver(dep, derivation);
|
|
1312
|
+
if (this.isTracing !== TraceMode.NONE) {
|
|
1313
|
+
console.log("[mobx.trace] '" + this.name + "' is being read outside a reactive context. Doing a full recompute");
|
|
1233
1314
|
}
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
}
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
function untracked(action) {
|
|
1252
|
-
var prev = untrackedStart();
|
|
1253
|
-
var res = action();
|
|
1254
|
-
untrackedEnd(prev);
|
|
1255
|
-
return res;
|
|
1256
|
-
}
|
|
1257
|
-
function untrackedStart() {
|
|
1258
|
-
var prev = globalState.trackingDerivation;
|
|
1259
|
-
globalState.trackingDerivation = null;
|
|
1260
|
-
return prev;
|
|
1261
|
-
}
|
|
1262
|
-
function untrackedEnd(prev) {
|
|
1263
|
-
globalState.trackingDerivation = prev;
|
|
1264
|
-
}
|
|
1265
|
-
/**
|
|
1266
|
-
* needed to keep `lowestObserverState` correct. when changing from (2 or 1) to 0
|
|
1267
|
-
*
|
|
1268
|
-
*/
|
|
1269
|
-
function changeDependenciesStateTo0(derivation) {
|
|
1270
|
-
if (derivation.dependenciesState === exports.IDerivationState.UP_TO_DATE)
|
|
1271
|
-
return;
|
|
1272
|
-
derivation.dependenciesState = exports.IDerivationState.UP_TO_DATE;
|
|
1273
|
-
var obs = derivation.observing;
|
|
1274
|
-
var i = obs.length;
|
|
1275
|
-
while (i--)
|
|
1276
|
-
obs[i].lowestObserverState = exports.IDerivationState.UP_TO_DATE;
|
|
1277
|
-
}
|
|
1315
|
+
if (globalState.computedRequiresReaction) {
|
|
1316
|
+
console.warn("[mobx] Computed value " + this.name + " is being read outside a reactive context. Doing a full recompute");
|
|
1317
|
+
}
|
|
1318
|
+
};
|
|
1319
|
+
ComputedValue.prototype.toJSON = function () {
|
|
1320
|
+
return this.get();
|
|
1321
|
+
};
|
|
1322
|
+
ComputedValue.prototype.toString = function () {
|
|
1323
|
+
return this.name + "[" + this.derivation.toString() + "]";
|
|
1324
|
+
};
|
|
1325
|
+
ComputedValue.prototype.valueOf = function () {
|
|
1326
|
+
return toPrimitive(this.get());
|
|
1327
|
+
};
|
|
1328
|
+
return ComputedValue;
|
|
1329
|
+
}());
|
|
1330
|
+
ComputedValue.prototype[primitiveSymbol()] = ComputedValue.prototype.valueOf;
|
|
1331
|
+
var isComputedValue = createInstanceofPredicate("ComputedValue", ComputedValue);
|
|
1278
1332
|
|
|
1279
1333
|
/**
|
|
1280
1334
|
* These values will persist if global state is reset
|
|
@@ -1284,6 +1338,9 @@
|
|
|
1284
1338
|
"spyListeners",
|
|
1285
1339
|
"enforceActions",
|
|
1286
1340
|
"computedRequiresReaction",
|
|
1341
|
+
"reactionRequiresObservable",
|
|
1342
|
+
"observableRequiresReaction",
|
|
1343
|
+
"allowStateReads",
|
|
1287
1344
|
"disableErrorBoundaries",
|
|
1288
1345
|
"runId",
|
|
1289
1346
|
"UNCHANGED"
|
|
@@ -1344,6 +1401,11 @@
|
|
|
1344
1401
|
* To ensure that those functions stay pure.
|
|
1345
1402
|
*/
|
|
1346
1403
|
this.allowStateChanges = true;
|
|
1404
|
+
/**
|
|
1405
|
+
* Is it allowed to read observables at this point?
|
|
1406
|
+
* Used to hold the state needed for `observableRequiresReaction`
|
|
1407
|
+
*/
|
|
1408
|
+
this.allowStateReads = true;
|
|
1347
1409
|
/**
|
|
1348
1410
|
* If strict mode is enabled, state changes are by default not allowed
|
|
1349
1411
|
*/
|
|
@@ -1360,6 +1422,16 @@
|
|
|
1360
1422
|
* Warn if computed values are accessed outside a reactive context
|
|
1361
1423
|
*/
|
|
1362
1424
|
this.computedRequiresReaction = false;
|
|
1425
|
+
/**
|
|
1426
|
+
* (Experimental)
|
|
1427
|
+
* Warn if you try to create to derivation / reactive context without accessing any observable.
|
|
1428
|
+
*/
|
|
1429
|
+
this.reactionRequiresObservable = false;
|
|
1430
|
+
/**
|
|
1431
|
+
* (Experimental)
|
|
1432
|
+
* Warn if observables are accessed outside a reactive context
|
|
1433
|
+
*/
|
|
1434
|
+
this.observableRequiresReaction = false;
|
|
1363
1435
|
/**
|
|
1364
1436
|
* Allows overwriting of computed properties, useful in tests but not prod as it can cause
|
|
1365
1437
|
* memory leaks. See https://github.com/mobxjs/mobx/issues/1867
|
|
@@ -1541,6 +1613,7 @@
|
|
|
1541
1613
|
}
|
|
1542
1614
|
}
|
|
1543
1615
|
function reportObserved(observable) {
|
|
1616
|
+
checkIfStateReadsAreAllowed(observable);
|
|
1544
1617
|
var derivation = globalState.trackingDerivation;
|
|
1545
1618
|
if (derivation !== null) {
|
|
1546
1619
|
/**
|
|
@@ -1661,11 +1734,13 @@
|
|
|
1661
1734
|
}
|
|
1662
1735
|
|
|
1663
1736
|
var Reaction = /** @class */ (function () {
|
|
1664
|
-
function Reaction(name, onInvalidate, errorHandler) {
|
|
1737
|
+
function Reaction(name, onInvalidate, errorHandler, requiresObservable) {
|
|
1665
1738
|
if (name === void 0) { name = "Reaction@" + getNextId(); }
|
|
1739
|
+
if (requiresObservable === void 0) { requiresObservable = false; }
|
|
1666
1740
|
this.name = name;
|
|
1667
1741
|
this.onInvalidate = onInvalidate;
|
|
1668
1742
|
this.errorHandler = errorHandler;
|
|
1743
|
+
this.requiresObservable = requiresObservable;
|
|
1669
1744
|
this.observing = []; // nodes we are looking at. Our value depends on these nodes
|
|
1670
1745
|
this.newObserving = [];
|
|
1671
1746
|
this.dependenciesState = exports.IDerivationState.NOT_TRACKING;
|
|
@@ -2011,7 +2086,7 @@
|
|
|
2011
2086
|
// normal autorun
|
|
2012
2087
|
reaction = new Reaction(name, function () {
|
|
2013
2088
|
this.track(reactionRunner);
|
|
2014
|
-
}, opts.onError);
|
|
2089
|
+
}, opts.onError, opts.requiresObservable);
|
|
2015
2090
|
}
|
|
2016
2091
|
else {
|
|
2017
2092
|
var scheduler_1 = createSchedulerFromOptions(opts);
|
|
@@ -2026,7 +2101,7 @@
|
|
|
2026
2101
|
reaction.track(reactionRunner);
|
|
2027
2102
|
});
|
|
2028
2103
|
}
|
|
2029
|
-
}, opts.onError);
|
|
2104
|
+
}, opts.onError, opts.requiresObservable);
|
|
2030
2105
|
}
|
|
2031
2106
|
function reactionRunner() {
|
|
2032
2107
|
view(reaction);
|
|
@@ -2070,7 +2145,7 @@
|
|
|
2070
2145
|
isScheduled = true;
|
|
2071
2146
|
scheduler(reactionRunner);
|
|
2072
2147
|
}
|
|
2073
|
-
}, opts.onError);
|
|
2148
|
+
}, opts.onError, opts.requiresObservable);
|
|
2074
2149
|
function reactionRunner() {
|
|
2075
2150
|
isScheduled = false; // Q: move into reaction runner?
|
|
2076
2151
|
if (r.isDisposed)
|
|
@@ -2109,8 +2184,8 @@
|
|
|
2109
2184
|
return interceptHook("onBecomeUnobserved", thing, arg2, arg3);
|
|
2110
2185
|
}
|
|
2111
2186
|
function interceptHook(hook, thing, arg2, arg3) {
|
|
2112
|
-
var atom = typeof
|
|
2113
|
-
var cb = typeof
|
|
2187
|
+
var atom = typeof arg3 === "function" ? getAtom(thing, arg2) : getAtom(thing);
|
|
2188
|
+
var cb = typeof arg3 === "function" ? arg3 : arg2;
|
|
2114
2189
|
var orig = atom[hook];
|
|
2115
2190
|
if (typeof orig !== "function")
|
|
2116
2191
|
return fail(process.env.NODE_ENV !== "production" && "Not an atom that can be (un)observed");
|
|
@@ -2124,7 +2199,7 @@
|
|
|
2124
2199
|
}
|
|
2125
2200
|
|
|
2126
2201
|
function configure(options) {
|
|
2127
|
-
var enforceActions = options.enforceActions, computedRequiresReaction = options.computedRequiresReaction, computedConfigurable = options.computedConfigurable, disableErrorBoundaries = options.disableErrorBoundaries, arrayBuffer = options.arrayBuffer, reactionScheduler = options.reactionScheduler;
|
|
2202
|
+
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;
|
|
2128
2203
|
if (options.isolateGlobalState === true) {
|
|
2129
2204
|
isolateGlobalState();
|
|
2130
2205
|
}
|
|
@@ -2154,6 +2229,13 @@
|
|
|
2154
2229
|
if (computedRequiresReaction !== undefined) {
|
|
2155
2230
|
globalState.computedRequiresReaction = !!computedRequiresReaction;
|
|
2156
2231
|
}
|
|
2232
|
+
if (reactionRequiresObservable !== undefined) {
|
|
2233
|
+
globalState.reactionRequiresObservable = !!reactionRequiresObservable;
|
|
2234
|
+
}
|
|
2235
|
+
if (observableRequiresReaction !== undefined) {
|
|
2236
|
+
globalState.observableRequiresReaction = !!observableRequiresReaction;
|
|
2237
|
+
globalState.allowStateReads = !globalState.observableRequiresReaction;
|
|
2238
|
+
}
|
|
2157
2239
|
if (computedConfigurable !== undefined) {
|
|
2158
2240
|
globalState.computedConfigurable = !!computedConfigurable;
|
|
2159
2241
|
}
|
|
@@ -3409,9 +3491,17 @@
|
|
|
3409
3491
|
return this._data.has(key);
|
|
3410
3492
|
};
|
|
3411
3493
|
ObservableMap.prototype.has = function (key) {
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3494
|
+
var _this = this;
|
|
3495
|
+
if (!globalState.trackingDerivation)
|
|
3496
|
+
return this._has(key);
|
|
3497
|
+
var entry = this._hasMap.get(key);
|
|
3498
|
+
if (!entry) {
|
|
3499
|
+
// todo: replace with atom (breaking change)
|
|
3500
|
+
var newEntry = (entry = new ObservableValue(this._has(key), referenceEnhancer, this.name + "." + stringifyKey(key) + "?", false));
|
|
3501
|
+
this._hasMap.set(key, newEntry);
|
|
3502
|
+
onBecomeUnobserved(newEntry, function () { return _this._hasMap.delete(key); });
|
|
3503
|
+
}
|
|
3504
|
+
return entry.get();
|
|
3415
3505
|
};
|
|
3416
3506
|
ObservableMap.prototype.set = function (key, value) {
|
|
3417
3507
|
var hasKey = this._has(key);
|
|
@@ -3474,16 +3564,10 @@
|
|
|
3474
3564
|
return false;
|
|
3475
3565
|
};
|
|
3476
3566
|
ObservableMap.prototype._updateHasMapEntry = function (key, value) {
|
|
3477
|
-
// optimization; don't fill the hasMap if we are not observing, or remove entry if there are no observers anymore
|
|
3478
3567
|
var entry = this._hasMap.get(key);
|
|
3479
3568
|
if (entry) {
|
|
3480
3569
|
entry.setNewValue(value);
|
|
3481
3570
|
}
|
|
3482
|
-
else {
|
|
3483
|
-
entry = new ObservableValue(value, referenceEnhancer, this.name + "." + stringifyKey(key) + "?", false);
|
|
3484
|
-
this._hasMap.set(key, entry);
|
|
3485
|
-
}
|
|
3486
|
-
return entry;
|
|
3487
3571
|
};
|
|
3488
3572
|
ObservableMap.prototype._updateValue = function (key, newValue) {
|
|
3489
3573
|
var observable = this._data.get(key);
|
|
@@ -3616,14 +3700,32 @@
|
|
|
3616
3700
|
ObservableMap.prototype.replace = function (values) {
|
|
3617
3701
|
var _this = this;
|
|
3618
3702
|
transaction(function () {
|
|
3619
|
-
|
|
3620
|
-
// and delete them from the map, then merge the new map
|
|
3621
|
-
// this will cause reactions only on changed values
|
|
3622
|
-
var newKeys = getMapLikeKeys(values);
|
|
3703
|
+
var replacementMap = convertToMap(values);
|
|
3623
3704
|
var oldKeys = _this._keys;
|
|
3624
|
-
var
|
|
3625
|
-
|
|
3626
|
-
|
|
3705
|
+
var newKeys = Array.from(replacementMap.keys());
|
|
3706
|
+
var keysChanged = false;
|
|
3707
|
+
for (var i = 0; i < oldKeys.length; i++) {
|
|
3708
|
+
var oldKey = oldKeys[i];
|
|
3709
|
+
// key order change
|
|
3710
|
+
if (oldKeys.length === newKeys.length && oldKey !== newKeys[i]) {
|
|
3711
|
+
keysChanged = true;
|
|
3712
|
+
}
|
|
3713
|
+
// deleted key
|
|
3714
|
+
if (!replacementMap.has(oldKey)) {
|
|
3715
|
+
keysChanged = true;
|
|
3716
|
+
_this.delete(oldKey);
|
|
3717
|
+
}
|
|
3718
|
+
}
|
|
3719
|
+
replacementMap.forEach(function (value, key) {
|
|
3720
|
+
// new key
|
|
3721
|
+
if (!_this._data.has(key)) {
|
|
3722
|
+
keysChanged = true;
|
|
3723
|
+
}
|
|
3724
|
+
_this.set(key, value);
|
|
3725
|
+
});
|
|
3726
|
+
if (keysChanged) {
|
|
3727
|
+
_this._keys.replace(newKeys);
|
|
3728
|
+
}
|
|
3627
3729
|
});
|
|
3628
3730
|
return this;
|
|
3629
3731
|
};
|
|
@@ -4227,12 +4329,13 @@
|
|
|
4227
4329
|
}
|
|
4228
4330
|
|
|
4229
4331
|
var toString = Object.prototype.toString;
|
|
4230
|
-
function deepEqual(a, b) {
|
|
4231
|
-
|
|
4332
|
+
function deepEqual(a, b, depth) {
|
|
4333
|
+
if (depth === void 0) { depth = -1; }
|
|
4334
|
+
return eq(a, b, depth);
|
|
4232
4335
|
}
|
|
4233
4336
|
// Copied from https://github.com/jashkenas/underscore/blob/5c237a7c682fb68fd5378203f0bf22dce1624854/underscore.js#L1186-L1289
|
|
4234
4337
|
// Internal recursive comparison function for `isEqual`.
|
|
4235
|
-
function eq(a, b, aStack, bStack) {
|
|
4338
|
+
function eq(a, b, depth, aStack, bStack) {
|
|
4236
4339
|
// Identical objects are equal. `0 === -0`, but they aren't identical.
|
|
4237
4340
|
// See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
|
|
4238
4341
|
if (a === b)
|
|
@@ -4247,10 +4350,6 @@
|
|
|
4247
4350
|
var type = typeof a;
|
|
4248
4351
|
if (type !== "function" && type !== "object" && typeof b != "object")
|
|
4249
4352
|
return false;
|
|
4250
|
-
return deepEq(a, b, aStack, bStack);
|
|
4251
|
-
}
|
|
4252
|
-
// Internal recursive comparison function for `isEqual`.
|
|
4253
|
-
function deepEq(a, b, aStack, bStack) {
|
|
4254
4353
|
// Unwrap any wrapped objects.
|
|
4255
4354
|
a = unwrap(a);
|
|
4256
4355
|
b = unwrap(b);
|
|
@@ -4300,6 +4399,12 @@
|
|
|
4300
4399
|
return false;
|
|
4301
4400
|
}
|
|
4302
4401
|
}
|
|
4402
|
+
if (depth === 0) {
|
|
4403
|
+
return false;
|
|
4404
|
+
}
|
|
4405
|
+
else if (depth < 0) {
|
|
4406
|
+
depth = -1;
|
|
4407
|
+
}
|
|
4303
4408
|
// Assume equality for cyclic structures. The algorithm for detecting cyclic
|
|
4304
4409
|
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
|
|
4305
4410
|
// Initializing stack of traversed objects.
|
|
@@ -4324,7 +4429,7 @@
|
|
|
4324
4429
|
return false;
|
|
4325
4430
|
// Deep compare the contents, ignoring non-numeric properties.
|
|
4326
4431
|
while (length--) {
|
|
4327
|
-
if (!eq(a[length], b[length], aStack, bStack))
|
|
4432
|
+
if (!eq(a[length], b[length], depth - 1, aStack, bStack))
|
|
4328
4433
|
return false;
|
|
4329
4434
|
}
|
|
4330
4435
|
}
|
|
@@ -4339,7 +4444,7 @@
|
|
|
4339
4444
|
while (length--) {
|
|
4340
4445
|
// Deep compare each member
|
|
4341
4446
|
key = keys[length];
|
|
4342
|
-
if (!(has$1(b, key) && eq(a[key], b[key], aStack, bStack)))
|
|
4447
|
+
if (!(has$1(b, key) && eq(a[key], b[key], depth - 1, aStack, bStack)))
|
|
4343
4448
|
return false;
|
|
4344
4449
|
}
|
|
4345
4450
|
}
|
|
@@ -4394,7 +4499,7 @@
|
|
|
4394
4499
|
process.env.NODE_ENV;
|
|
4395
4500
|
}
|
|
4396
4501
|
catch (e) {
|
|
4397
|
-
var g =
|
|
4502
|
+
var g = getGlobal();
|
|
4398
4503
|
if (typeof process === "undefined")
|
|
4399
4504
|
g.process = {};
|
|
4400
4505
|
g.process.env = {};
|
|
@@ -4469,11 +4574,13 @@
|
|
|
4469
4574
|
exports.Reaction = Reaction;
|
|
4470
4575
|
exports._allowStateChanges = allowStateChanges;
|
|
4471
4576
|
exports._allowStateChangesInsideComputed = allowStateChangesInsideComputed;
|
|
4577
|
+
exports._endAction = _endAction;
|
|
4472
4578
|
exports._getAdministration = getAdministration;
|
|
4473
4579
|
exports._getGlobalState = getGlobalState;
|
|
4474
4580
|
exports._interceptReads = interceptReads;
|
|
4475
4581
|
exports._isComputingDerivation = isComputingDerivation;
|
|
4476
4582
|
exports._resetGlobalState = resetGlobalState;
|
|
4583
|
+
exports._startAction = _startAction;
|
|
4477
4584
|
exports.action = action;
|
|
4478
4585
|
exports.autorun = autorun;
|
|
4479
4586
|
exports.comparer = comparer;
|