mobx 7.0.0 → 7.0.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/CHANGELOG.md +14 -0
- package/dist/core/atom.d.ts +1 -1
- package/dist/core/computedvalue.d.ts +1 -1
- package/dist/core/globalstate.d.ts +7 -0
- package/dist/core/observable.d.ts +9 -1
- package/dist/mobx.cjs.development.js +93 -56
- package/dist/mobx.cjs.development.js.map +1 -1
- package/dist/mobx.cjs.production.min.js +1 -1
- package/dist/mobx.cjs.production.min.js.map +1 -1
- package/dist/mobx.esm.development.js +93 -56
- package/dist/mobx.esm.development.js.map +1 -1
- package/dist/mobx.esm.js +93 -56
- package/dist/mobx.esm.js.map +1 -1
- package/dist/mobx.esm.production.min.js +1 -1
- package/dist/mobx.esm.production.min.js.map +1 -1
- package/dist/mobx.mjs +93 -56
- package/dist/mobx.mjs.map +1 -1
- package/dist/mobx.umd.development.js +93 -56
- package/dist/mobx.umd.development.js.map +1 -1
- package/dist/mobx.umd.production.min.js +1 -1
- package/dist/mobx.umd.production.min.js.map +1 -1
- package/package.json +1 -1
- package/src/core/atom.ts +2 -1
- package/src/core/computedvalue.ts +9 -2
- package/src/core/derivation.ts +1 -1
- package/src/core/globalstate.ts +8 -0
- package/src/core/observable.ts +65 -25
- package/src/types/modifiers.ts +5 -0
- package/src/types/observableset.ts +4 -24
|
@@ -259,7 +259,8 @@ class Atom {
|
|
|
259
259
|
constructor(name_ = "Atom@" + getNextId() ) {
|
|
260
260
|
this.name_ = void 0;
|
|
261
261
|
this.flags_ = 0b000;
|
|
262
|
-
|
|
262
|
+
// Allocated lazily on first observer to save memory.
|
|
263
|
+
this.observers_ = null;
|
|
263
264
|
this.lastAccessedBy_ = 0;
|
|
264
265
|
this.lowestObserverState_ = -1 /* IDerivationState_.NOT_TRACKING_ */;
|
|
265
266
|
// onBecomeObservedListeners
|
|
@@ -341,6 +342,10 @@ function compareShallow(a, b) {
|
|
|
341
342
|
const compareDefault = Object.is;
|
|
342
343
|
|
|
343
344
|
function deepEnhancer(v, _, name) {
|
|
345
|
+
// primitives can never be made observable; skip the type checks below
|
|
346
|
+
if (v === null || typeof v !== "object" && typeof v !== "function") {
|
|
347
|
+
return v;
|
|
348
|
+
}
|
|
344
349
|
// it is an observable already, done
|
|
345
350
|
if (isObservable(v)) {
|
|
346
351
|
return v;
|
|
@@ -1281,7 +1286,8 @@ class ComputedValue {
|
|
|
1281
1286
|
// nodes we are looking at. Our value depends on these nodes
|
|
1282
1287
|
this.newObserving_ = null;
|
|
1283
1288
|
// during tracking it's an array with new observed observers
|
|
1284
|
-
|
|
1289
|
+
// Lazily allocated on first observer - see Atom.observers_.
|
|
1290
|
+
this.observers_ = null;
|
|
1285
1291
|
this.runId_ = 0;
|
|
1286
1292
|
this.lastAccessedBy_ = 0;
|
|
1287
1293
|
this.lowestObserverState_ = 0 /* IDerivationState_.UP_TO_DATE_ */;
|
|
@@ -1364,9 +1370,9 @@ class ComputedValue {
|
|
|
1364
1370
|
if (this.isComputing) {
|
|
1365
1371
|
die(32, this.name_, this.derivation);
|
|
1366
1372
|
}
|
|
1367
|
-
if (globalState.inBatch === 0 &&
|
|
1373
|
+
if (globalState.inBatch === 0 && (
|
|
1368
1374
|
// !globalState.trackingDerivatpion &&
|
|
1369
|
-
this.observers_.size === 0 && !this.keepAlive_) {
|
|
1375
|
+
!this.observers_ || this.observers_.size === 0) && !this.keepAlive_) {
|
|
1370
1376
|
if (shouldCompute(this)) {
|
|
1371
1377
|
this.warnAboutUntrackedRead_();
|
|
1372
1378
|
startBatch(); // See perf test 'computed memoization'
|
|
@@ -1374,6 +1380,7 @@ class ComputedValue {
|
|
|
1374
1380
|
endBatch();
|
|
1375
1381
|
}
|
|
1376
1382
|
} else {
|
|
1383
|
+
const wasBeingObserved = this.isBeingObserved;
|
|
1377
1384
|
reportObserved(this);
|
|
1378
1385
|
if (shouldCompute(this)) {
|
|
1379
1386
|
let prevTrackingContext = globalState.trackingContext;
|
|
@@ -1384,6 +1391,10 @@ class ComputedValue {
|
|
|
1384
1391
|
propagateChangeConfirmed(this);
|
|
1385
1392
|
}
|
|
1386
1393
|
globalState.trackingContext = prevTrackingContext;
|
|
1394
|
+
} else if (!wasBeingObserved && this.isBeingObserved) {
|
|
1395
|
+
// We just became observed while serving a cached value, so the getter
|
|
1396
|
+
// won't run and won't re-report our dependencies. Cascade to them. #4547
|
|
1397
|
+
this.observing_.forEach(markObserved);
|
|
1387
1398
|
}
|
|
1388
1399
|
}
|
|
1389
1400
|
const result = this.value_;
|
|
@@ -1552,7 +1563,7 @@ function isComputingDerivation() {
|
|
|
1552
1563
|
return globalState.trackingDerivation !== null; // filter out actions inside computations
|
|
1553
1564
|
}
|
|
1554
1565
|
function checkIfStateModificationsAreAllowed(atom) {
|
|
1555
|
-
const hasObservers = atom.observers_.size > 0;
|
|
1566
|
+
const hasObservers = !!atom.observers_ && atom.observers_.size > 0;
|
|
1556
1567
|
// Should not be possible to change observed state outside strict mode, except during initialization, see #563
|
|
1557
1568
|
if (!globalState.allowStateChanges && (hasObservers || globalState.enforceActions === "always")) {
|
|
1558
1569
|
console.warn("[MobX] " + (globalState.enforceActions ? "Since strict-mode is enabled, changing (observed) observable values without using an action is not allowed. Tried to modify: " : "Side effects like changing state are not allowed at this point. Are you trying to modify state from, for example, a computed value or the render function of a React component? You can wrap side effects in 'runInAction' (or decorate functions with 'action') if needed. Tried to modify: ") + atom.name_);
|
|
@@ -1775,6 +1786,13 @@ class MobXGlobals {
|
|
|
1775
1786
|
* Are we currently processing reactions?
|
|
1776
1787
|
*/
|
|
1777
1788
|
this.isRunningReactions = false;
|
|
1789
|
+
/**
|
|
1790
|
+
* Are we currently draining pendingUnobservations in endBatch?
|
|
1791
|
+
* An onBecomeUnobserved handler can dispose a Reaction, which calls
|
|
1792
|
+
* startBatch/endBatch again; this guards against re-entering the same
|
|
1793
|
+
* drain loop recursively (see endBatch in observable.ts).
|
|
1794
|
+
*/
|
|
1795
|
+
this.isRunningUnobservations = false;
|
|
1778
1796
|
/**
|
|
1779
1797
|
* Is it allowed to change observables at this point?
|
|
1780
1798
|
* In general, MobX doesn't allow that when running computations and React.render.
|
|
@@ -1891,10 +1909,11 @@ function resetGlobalState() {
|
|
|
1891
1909
|
}
|
|
1892
1910
|
|
|
1893
1911
|
function hasObservers(observable) {
|
|
1894
|
-
return observable.observers_ && observable.observers_.size > 0;
|
|
1912
|
+
return !!observable.observers_ && observable.observers_.size > 0;
|
|
1895
1913
|
}
|
|
1896
1914
|
function getObservers(observable) {
|
|
1897
|
-
|
|
1915
|
+
var _observable$observers;
|
|
1916
|
+
return (_observable$observers = observable.observers_) != null ? _observable$observers : new Set();
|
|
1898
1917
|
}
|
|
1899
1918
|
// function invariantObservers(observable: IObservable) {
|
|
1900
1919
|
// const list = observable.observers
|
|
@@ -1914,10 +1933,8 @@ function getObservers(observable) {
|
|
|
1914
1933
|
// )
|
|
1915
1934
|
// }
|
|
1916
1935
|
function addObserver(observable, node) {
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
// invariantObservers(observable);
|
|
1920
|
-
observable.observers_.add(node);
|
|
1936
|
+
var _observable$observers2;
|
|
1937
|
+
((_observable$observers2 = observable.observers_) != null ? _observable$observers2 : observable.observers_ = new Set()).add(node);
|
|
1921
1938
|
if (observable.lowestObserverState_ > node.dependenciesState_) {
|
|
1922
1939
|
observable.lowestObserverState_ = node.dependenciesState_;
|
|
1923
1940
|
}
|
|
@@ -1928,8 +1945,12 @@ function removeObserver(observable, node) {
|
|
|
1928
1945
|
// invariant(globalState.inBatch > 0, "INTERNAL ERROR, remove should be called only inside batch");
|
|
1929
1946
|
// invariant(observable._observers.indexOf(node) !== -1, "INTERNAL ERROR remove already removed node");
|
|
1930
1947
|
// invariantObservers(observable);
|
|
1931
|
-
observable.observers_
|
|
1932
|
-
if (
|
|
1948
|
+
const observers = observable.observers_;
|
|
1949
|
+
if (!observers) {
|
|
1950
|
+
return;
|
|
1951
|
+
}
|
|
1952
|
+
observers.delete(node);
|
|
1953
|
+
if (observers.size === 0) {
|
|
1933
1954
|
// deleting last observer
|
|
1934
1955
|
queueForUnobservation(observable);
|
|
1935
1956
|
}
|
|
@@ -1955,26 +1976,59 @@ function endBatch() {
|
|
|
1955
1976
|
if (--globalState.inBatch === 0) {
|
|
1956
1977
|
runReactions();
|
|
1957
1978
|
// the batch is actually about to finish, all unobserving should happen here.
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1979
|
+
// Guard against re-entering this loop: an onBUO handler can dispose a Reaction,
|
|
1980
|
+
// which calls startBatch/endBatch again while we're still iterating. Bail out of
|
|
1981
|
+
// the nested call instead of recursing; the outer loop re-reads list.length on
|
|
1982
|
+
// every iteration, so it picks up anything the nested dispose() pushes onto the
|
|
1983
|
+
// same pendingUnobservations array.
|
|
1984
|
+
if (!globalState.isRunningUnobservations) {
|
|
1985
|
+
globalState.isRunningUnobservations = true;
|
|
1986
|
+
try {
|
|
1987
|
+
const list = globalState.pendingUnobservations;
|
|
1988
|
+
for (let i = 0; i < list.length; i++) {
|
|
1989
|
+
const observable = list[i];
|
|
1990
|
+
observable.isPendingUnobservation = false;
|
|
1991
|
+
if (!observable.observers_ || observable.observers_.size === 0) {
|
|
1992
|
+
if (observable.isBeingObserved) {
|
|
1993
|
+
// if this observable had reactive observers, trigger the hooks
|
|
1994
|
+
observable.isBeingObserved = false;
|
|
1995
|
+
observable.onBUO();
|
|
1996
|
+
}
|
|
1997
|
+
if (observable instanceof ComputedValue) {
|
|
1998
|
+
// computed values are automatically teared down when the last observer leaves
|
|
1999
|
+
// this process happens recursively, this computed might be the last observabe of another, etc..
|
|
2000
|
+
observable.suspend_();
|
|
2001
|
+
}
|
|
2002
|
+
}
|
|
1972
2003
|
}
|
|
2004
|
+
globalState.pendingUnobservations = [];
|
|
2005
|
+
} finally {
|
|
2006
|
+
// Always release the guard, even if an onBUO handler (user code) threw,
|
|
2007
|
+
// otherwise every future endBatch() would see isRunningUnobservations
|
|
2008
|
+
// stuck true and silently stop draining pendingUnobservations forever.
|
|
2009
|
+
globalState.isRunningUnobservations = false;
|
|
1973
2010
|
}
|
|
1974
2011
|
}
|
|
1975
|
-
globalState.pendingUnobservations = [];
|
|
1976
2012
|
}
|
|
1977
2013
|
}
|
|
2014
|
+
/**
|
|
2015
|
+
* Marks an observable as observed, cascading into the dependencies of a ComputedValue.
|
|
2016
|
+
* Unobservation already cascades (`suspend_` -> `clearObserving`), observation normally
|
|
2017
|
+
* only does so by accident: a newly observed computed usually recomputes and re-reports
|
|
2018
|
+
* its dependencies. When it serves a cached value instead nothing re-reports them, so the
|
|
2019
|
+
* transition has to be propagated by hand. See #4547.
|
|
2020
|
+
*/
|
|
2021
|
+
function markObserved(observable) {
|
|
2022
|
+
var _observable$observing;
|
|
2023
|
+
if (observable.isBeingObserved) {
|
|
2024
|
+
return;
|
|
2025
|
+
}
|
|
2026
|
+
observable.isBeingObserved = true;
|
|
2027
|
+
observable.onBO();
|
|
2028
|
+
// No queueForUnobservation here: the observer links already exist, so the regular
|
|
2029
|
+
// suspend_ -> clearObserving -> removeObserver teardown still delivers the onBUO.
|
|
2030
|
+
(_observable$observing = observable.observing_) == null || _observable$observing.forEach(markObserved);
|
|
2031
|
+
}
|
|
1978
2032
|
function reportObserved(observable) {
|
|
1979
2033
|
checkIfStateReadsAreAllowed(observable);
|
|
1980
2034
|
const derivation = globalState.trackingDerivation;
|
|
@@ -1994,7 +2048,7 @@ function reportObserved(observable) {
|
|
|
1994
2048
|
}
|
|
1995
2049
|
}
|
|
1996
2050
|
return observable.isBeingObserved;
|
|
1997
|
-
} else if (observable.observers_.size === 0 && globalState.inBatch > 0) {
|
|
2051
|
+
} else if ((!observable.observers_ || observable.observers_.size === 0) && globalState.inBatch > 0) {
|
|
1998
2052
|
queueForUnobservation(observable);
|
|
1999
2053
|
}
|
|
2000
2054
|
return false;
|
|
@@ -2021,13 +2075,14 @@ function reportObserved(observable) {
|
|
|
2021
2075
|
*/
|
|
2022
2076
|
// Called by Atom when its value changes
|
|
2023
2077
|
function propagateChanged(observable) {
|
|
2078
|
+
var _observable$observers3;
|
|
2024
2079
|
// invariantLOS(observable, "changed start");
|
|
2025
2080
|
if (observable.lowestObserverState_ === 2 /* IDerivationState_.STALE_ */) {
|
|
2026
2081
|
return;
|
|
2027
2082
|
}
|
|
2028
2083
|
observable.lowestObserverState_ = 2 /* IDerivationState_.STALE_ */;
|
|
2029
2084
|
// Ideally we use for..of here, but the downcompiled version is really slow...
|
|
2030
|
-
observable.observers_.forEach(d => {
|
|
2085
|
+
(_observable$observers3 = observable.observers_) == null || _observable$observers3.forEach(d => {
|
|
2031
2086
|
if (d.dependenciesState_ === 0 /* IDerivationState_.UP_TO_DATE_ */) {
|
|
2032
2087
|
d.onBecomeStale_();
|
|
2033
2088
|
}
|
|
@@ -2037,12 +2092,13 @@ function propagateChanged(observable) {
|
|
|
2037
2092
|
}
|
|
2038
2093
|
// Called by ComputedValue when it recalculate and its value changed
|
|
2039
2094
|
function propagateChangeConfirmed(observable) {
|
|
2095
|
+
var _observable$observers4;
|
|
2040
2096
|
// invariantLOS(observable, "confirmed start");
|
|
2041
2097
|
if (observable.lowestObserverState_ === 2 /* IDerivationState_.STALE_ */) {
|
|
2042
2098
|
return;
|
|
2043
2099
|
}
|
|
2044
2100
|
observable.lowestObserverState_ = 2 /* IDerivationState_.STALE_ */;
|
|
2045
|
-
observable.observers_.forEach(d => {
|
|
2101
|
+
(_observable$observers4 = observable.observers_) == null || _observable$observers4.forEach(d => {
|
|
2046
2102
|
if (d.dependenciesState_ === 1 /* IDerivationState_.POSSIBLY_STALE_ */) {
|
|
2047
2103
|
d.dependenciesState_ = 2 /* IDerivationState_.STALE_ */;
|
|
2048
2104
|
} else if (d.dependenciesState_ === 0 /* IDerivationState_.UP_TO_DATE_ */ // this happens during computing of `d`, just keep lowestObserverState up to date.
|
|
@@ -2054,12 +2110,13 @@ function propagateChangeConfirmed(observable) {
|
|
|
2054
2110
|
}
|
|
2055
2111
|
// Used by computed when its dependency changed, but we don't wan't to immediately recompute.
|
|
2056
2112
|
function propagateMaybeChanged(observable) {
|
|
2113
|
+
var _observable$observers5;
|
|
2057
2114
|
// invariantLOS(observable, "maybe start");
|
|
2058
2115
|
if (observable.lowestObserverState_ !== 0 /* IDerivationState_.UP_TO_DATE_ */) {
|
|
2059
2116
|
return;
|
|
2060
2117
|
}
|
|
2061
2118
|
observable.lowestObserverState_ = 1 /* IDerivationState_.POSSIBLY_STALE_ */;
|
|
2062
|
-
observable.observers_.forEach(d => {
|
|
2119
|
+
(_observable$observers5 = observable.observers_) == null || _observable$observers5.forEach(d => {
|
|
2063
2120
|
if (d.dependenciesState_ === 0 /* IDerivationState_.UP_TO_DATE_ */) {
|
|
2064
2121
|
d.dependenciesState_ = 1 /* IDerivationState_.POSSIBLY_STALE_ */;
|
|
2065
2122
|
d.onBecomeStale_();
|
|
@@ -4314,31 +4371,16 @@ class ObservableSet {
|
|
|
4314
4371
|
});
|
|
4315
4372
|
}
|
|
4316
4373
|
intersection(otherSet) {
|
|
4317
|
-
|
|
4318
|
-
return otherSet.intersection(this);
|
|
4319
|
-
} else {
|
|
4320
|
-
const dehancedSet = new Set(this);
|
|
4321
|
-
return dehancedSet.intersection(otherSet);
|
|
4322
|
-
}
|
|
4374
|
+
return new Set(this).intersection(otherSet);
|
|
4323
4375
|
}
|
|
4324
4376
|
union(otherSet) {
|
|
4325
|
-
|
|
4326
|
-
return otherSet.union(this);
|
|
4327
|
-
} else {
|
|
4328
|
-
const dehancedSet = new Set(this);
|
|
4329
|
-
return dehancedSet.union(otherSet);
|
|
4330
|
-
}
|
|
4377
|
+
return new Set(this).union(otherSet);
|
|
4331
4378
|
}
|
|
4332
4379
|
difference(otherSet) {
|
|
4333
4380
|
return new Set(this).difference(otherSet);
|
|
4334
4381
|
}
|
|
4335
4382
|
symmetricDifference(otherSet) {
|
|
4336
|
-
|
|
4337
|
-
return otherSet.symmetricDifference(this);
|
|
4338
|
-
} else {
|
|
4339
|
-
const dehancedSet = new Set(this);
|
|
4340
|
-
return dehancedSet.symmetricDifference(otherSet);
|
|
4341
|
-
}
|
|
4383
|
+
return new Set(this).symmetricDifference(otherSet);
|
|
4342
4384
|
}
|
|
4343
4385
|
isSubsetOf(otherSet) {
|
|
4344
4386
|
return new Set(this).isSubsetOf(otherSet);
|
|
@@ -4347,12 +4389,7 @@ class ObservableSet {
|
|
|
4347
4389
|
return new Set(this).isSupersetOf(otherSet);
|
|
4348
4390
|
}
|
|
4349
4391
|
isDisjointFrom(otherSet) {
|
|
4350
|
-
|
|
4351
|
-
return otherSet.isDisjointFrom(this);
|
|
4352
|
-
} else {
|
|
4353
|
-
const dehancedSet = new Set(this);
|
|
4354
|
-
return dehancedSet.isDisjointFrom(otherSet);
|
|
4355
|
-
}
|
|
4392
|
+
return new Set(this).isDisjointFrom(otherSet);
|
|
4356
4393
|
}
|
|
4357
4394
|
replace(other) {
|
|
4358
4395
|
if (isObservableSet(other)) {
|