mobx 6.13.0 → 6.13.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 +6 -0
- package/dist/core/atom.d.ts +10 -3
- package/dist/core/computedvalue.d.ts +3 -1
- package/dist/core/observable.d.ts +1 -1
- package/dist/core/reaction.d.ts +16 -6
- package/dist/mobx.cjs.development.js +120 -49
- 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 +120 -49
- package/dist/mobx.esm.development.js.map +1 -1
- package/dist/mobx.esm.js +120 -49
- 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.umd.development.js +120 -49
- 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/dist/utils/utils.d.ts +2 -0
- package/package.json +1 -1
- package/src/api/autorun.ts +4 -4
- package/src/api/when.ts +1 -1
- package/src/core/atom.ts +29 -3
- package/src/core/computedvalue.ts +19 -18
- package/src/core/derivation.ts +6 -6
- package/src/core/observable.ts +1 -1
- package/src/core/reaction.ts +59 -23
- package/src/utils/utils.ts +13 -0
package/dist/utils/utils.d.ts
CHANGED
|
@@ -44,3 +44,5 @@ export declare function hasProp(target: Object, prop: PropertyKey): boolean;
|
|
|
44
44
|
export declare const getOwnPropertyDescriptors: <T>(o: T) => { [P in keyof T]: TypedPropertyDescriptor<T[P]>; } & {
|
|
45
45
|
[x: string]: PropertyDescriptor;
|
|
46
46
|
};
|
|
47
|
+
export declare function getFlag(flags: number, mask: number): boolean;
|
|
48
|
+
export declare function setFlag(flags: number, mask: number, newValue: boolean): number;
|
package/package.json
CHANGED
package/src/api/autorun.ts
CHANGED
|
@@ -75,7 +75,7 @@ export function autorun(
|
|
|
75
75
|
isScheduled = true
|
|
76
76
|
scheduler(() => {
|
|
77
77
|
isScheduled = false
|
|
78
|
-
if (!reaction.
|
|
78
|
+
if (!reaction.isDisposed) {
|
|
79
79
|
reaction.track(reactionRunner)
|
|
80
80
|
}
|
|
81
81
|
})
|
|
@@ -90,7 +90,7 @@ export function autorun(
|
|
|
90
90
|
view(reaction)
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
if(!opts?.signal?.aborted) {
|
|
93
|
+
if (!opts?.signal?.aborted) {
|
|
94
94
|
reaction.schedule_()
|
|
95
95
|
}
|
|
96
96
|
return reaction.getDisposer_(opts?.signal)
|
|
@@ -160,7 +160,7 @@ export function reaction<T, FireImmediately extends boolean = false>(
|
|
|
160
160
|
|
|
161
161
|
function reactionRunner() {
|
|
162
162
|
isScheduled = false
|
|
163
|
-
if (r.
|
|
163
|
+
if (r.isDisposed) {
|
|
164
164
|
return
|
|
165
165
|
}
|
|
166
166
|
let changed: boolean = false
|
|
@@ -181,7 +181,7 @@ export function reaction<T, FireImmediately extends boolean = false>(
|
|
|
181
181
|
firstTime = false
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
-
if(!opts?.signal?.aborted) {
|
|
184
|
+
if (!opts?.signal?.aborted) {
|
|
185
185
|
r.schedule_()
|
|
186
186
|
}
|
|
187
187
|
return r.getDisposer_(opts?.signal)
|
package/src/api/when.ts
CHANGED
|
@@ -38,7 +38,7 @@ function _when(predicate: () => boolean, effect: Lambda, opts: IWhenOptions): IR
|
|
|
38
38
|
if (typeof opts.timeout === "number") {
|
|
39
39
|
const error = new Error("WHEN_TIMEOUT")
|
|
40
40
|
timeoutHandle = setTimeout(() => {
|
|
41
|
-
if (!disposer[$mobx].
|
|
41
|
+
if (!disposer[$mobx].isDisposed) {
|
|
42
42
|
disposer()
|
|
43
43
|
if (opts.onError) {
|
|
44
44
|
opts.onError(error)
|
package/src/core/atom.ts
CHANGED
|
@@ -14,6 +14,8 @@ import {
|
|
|
14
14
|
Lambda
|
|
15
15
|
} from "../internal"
|
|
16
16
|
|
|
17
|
+
import { getFlag, setFlag } from "../utils/utils"
|
|
18
|
+
|
|
17
19
|
export const $mobx = Symbol("mobx administration")
|
|
18
20
|
|
|
19
21
|
export interface IAtom extends IObservable {
|
|
@@ -22,11 +24,13 @@ export interface IAtom extends IObservable {
|
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
export class Atom implements IAtom {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
private static readonly isBeingObservedMask_ = 0b001
|
|
28
|
+
private static readonly isPendingUnobservationMask_ = 0b010
|
|
29
|
+
private static readonly diffValueMask_ = 0b100
|
|
30
|
+
private flags_ = 0b000
|
|
31
|
+
|
|
27
32
|
observers_ = new Set<IDerivation>()
|
|
28
33
|
|
|
29
|
-
diffValue_ = 0
|
|
30
34
|
lastAccessedBy_ = 0
|
|
31
35
|
lowestObserverState_ = IDerivationState_.NOT_TRACKING_
|
|
32
36
|
/**
|
|
@@ -35,6 +39,28 @@ export class Atom implements IAtom {
|
|
|
35
39
|
*/
|
|
36
40
|
constructor(public name_ = __DEV__ ? "Atom@" + getNextId() : "Atom") {}
|
|
37
41
|
|
|
42
|
+
// for effective unobserving. BaseAtom has true, for extra optimization, so its onBecomeUnobserved never gets called, because it's not needed
|
|
43
|
+
get isBeingObserved(): boolean {
|
|
44
|
+
return getFlag(this.flags_, Atom.isBeingObservedMask_)
|
|
45
|
+
}
|
|
46
|
+
set isBeingObserved(newValue: boolean) {
|
|
47
|
+
this.flags_ = setFlag(this.flags_, Atom.isBeingObservedMask_, newValue)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
get isPendingUnobservation(): boolean {
|
|
51
|
+
return getFlag(this.flags_, Atom.isPendingUnobservationMask_)
|
|
52
|
+
}
|
|
53
|
+
set isPendingUnobservation(newValue: boolean) {
|
|
54
|
+
this.flags_ = setFlag(this.flags_, Atom.isPendingUnobservationMask_, newValue)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
get diffValue(): 0 | 1 {
|
|
58
|
+
return getFlag(this.flags_, Atom.diffValueMask_) ? 1 : 0
|
|
59
|
+
}
|
|
60
|
+
set diffValue(newValue: 0 | 1) {
|
|
61
|
+
this.flags_ = setFlag(this.flags_, Atom.diffValueMask_, newValue === 1 ? true : false)
|
|
62
|
+
}
|
|
63
|
+
|
|
38
64
|
// onBecomeObservedListeners
|
|
39
65
|
public onBOL: Set<Lambda> | undefined
|
|
40
66
|
// onBecomeUnobservedListeners
|
|
@@ -32,6 +32,8 @@ import {
|
|
|
32
32
|
allowStateChangesEnd
|
|
33
33
|
} from "../internal"
|
|
34
34
|
|
|
35
|
+
import { getFlag, setFlag } from "../utils/utils"
|
|
36
|
+
|
|
35
37
|
export interface IComputedValue<T> {
|
|
36
38
|
get(): T
|
|
37
39
|
set(value: T): void
|
|
@@ -56,18 +58,6 @@ export type IComputedDidChange<T = any> = {
|
|
|
56
58
|
oldValue: T | undefined
|
|
57
59
|
}
|
|
58
60
|
|
|
59
|
-
function getFlag(flags: number, mask: number) {
|
|
60
|
-
return !!(flags & mask)
|
|
61
|
-
}
|
|
62
|
-
function setFlag(flags: number, mask: number, newValue: boolean): number {
|
|
63
|
-
if (newValue) {
|
|
64
|
-
flags |= mask
|
|
65
|
-
} else {
|
|
66
|
-
flags &= ~mask
|
|
67
|
-
}
|
|
68
|
-
return flags
|
|
69
|
-
}
|
|
70
|
-
|
|
71
61
|
/**
|
|
72
62
|
* A node in the state dependency root that observes other nodes, and can be observed itself.
|
|
73
63
|
*
|
|
@@ -92,7 +82,6 @@ export class ComputedValue<T> implements IObservable, IComputedValue<T>, IDeriva
|
|
|
92
82
|
observing_: IObservable[] = [] // nodes we are looking at. Our value depends on these nodes
|
|
93
83
|
newObserving_ = null // during tracking it's an array with new observed observers
|
|
94
84
|
observers_ = new Set<IDerivation>()
|
|
95
|
-
diffValue_ = 0
|
|
96
85
|
runId_ = 0
|
|
97
86
|
lastAccessedBy_ = 0
|
|
98
87
|
lowestObserverState_ = IDerivationState_.UP_TO_DATE_
|
|
@@ -101,11 +90,12 @@ export class ComputedValue<T> implements IObservable, IComputedValue<T>, IDeriva
|
|
|
101
90
|
name_: string
|
|
102
91
|
triggeredBy_?: string
|
|
103
92
|
|
|
104
|
-
private static readonly isComputingMask_ =
|
|
105
|
-
private static readonly isRunningSetterMask_ =
|
|
106
|
-
private static readonly isBeingObservedMask_ =
|
|
107
|
-
private static readonly isPendingUnobservationMask_ =
|
|
108
|
-
private
|
|
93
|
+
private static readonly isComputingMask_ = 0b00001
|
|
94
|
+
private static readonly isRunningSetterMask_ = 0b00010
|
|
95
|
+
private static readonly isBeingObservedMask_ = 0b00100
|
|
96
|
+
private static readonly isPendingUnobservationMask_ = 0b01000
|
|
97
|
+
private static readonly diffValueMask_ = 0b10000
|
|
98
|
+
private flags_ = 0b00000
|
|
109
99
|
|
|
110
100
|
derivation: () => T // N.B: unminified as it is used by MST
|
|
111
101
|
setter_?: (value: T) => void
|
|
@@ -197,6 +187,17 @@ export class ComputedValue<T> implements IObservable, IComputedValue<T>, IDeriva
|
|
|
197
187
|
this.flags_ = setFlag(this.flags_, ComputedValue.isPendingUnobservationMask_, newValue)
|
|
198
188
|
}
|
|
199
189
|
|
|
190
|
+
get diffValue(): 0 | 1 {
|
|
191
|
+
return getFlag(this.flags_, ComputedValue.diffValueMask_) ? 1 : 0
|
|
192
|
+
}
|
|
193
|
+
set diffValue(newValue: 0 | 1) {
|
|
194
|
+
this.flags_ = setFlag(
|
|
195
|
+
this.flags_,
|
|
196
|
+
ComputedValue.diffValueMask_,
|
|
197
|
+
newValue === 1 ? true : false
|
|
198
|
+
)
|
|
199
|
+
}
|
|
200
|
+
|
|
200
201
|
/**
|
|
201
202
|
* Returns the current value of this computed value.
|
|
202
203
|
* Will evaluate its computation first if needed.
|
package/src/core/derivation.ts
CHANGED
|
@@ -235,8 +235,8 @@ function bindDependencies(derivation: IDerivation) {
|
|
|
235
235
|
l = derivation.unboundDepsCount_
|
|
236
236
|
for (let i = 0; i < l; i++) {
|
|
237
237
|
const dep = observing[i]
|
|
238
|
-
if (dep.
|
|
239
|
-
dep.
|
|
238
|
+
if (dep.diffValue === 0) {
|
|
239
|
+
dep.diffValue = 1
|
|
240
240
|
if (i0 !== i) {
|
|
241
241
|
observing[i0] = dep
|
|
242
242
|
}
|
|
@@ -259,10 +259,10 @@ function bindDependencies(derivation: IDerivation) {
|
|
|
259
259
|
l = prevObserving.length
|
|
260
260
|
while (l--) {
|
|
261
261
|
const dep = prevObserving[l]
|
|
262
|
-
if (dep.
|
|
262
|
+
if (dep.diffValue === 0) {
|
|
263
263
|
removeObserver(dep, derivation)
|
|
264
264
|
}
|
|
265
|
-
dep.
|
|
265
|
+
dep.diffValue = 0
|
|
266
266
|
}
|
|
267
267
|
|
|
268
268
|
// Go through all new observables and check diffValue: (now it should be unique)
|
|
@@ -270,8 +270,8 @@ function bindDependencies(derivation: IDerivation) {
|
|
|
270
270
|
// 1: it wasn't observed, let's observe it. set back to 0
|
|
271
271
|
while (i0--) {
|
|
272
272
|
const dep = observing[i0]
|
|
273
|
-
if (dep.
|
|
274
|
-
dep.
|
|
273
|
+
if (dep.diffValue === 1) {
|
|
274
|
+
dep.diffValue = 0
|
|
275
275
|
addObserver(dep, derivation)
|
|
276
276
|
}
|
|
277
277
|
}
|
package/src/core/observable.ts
CHANGED
|
@@ -17,7 +17,7 @@ export interface IDepTreeNode {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export interface IObservable extends IDepTreeNode {
|
|
20
|
-
|
|
20
|
+
diffValue: number
|
|
21
21
|
/**
|
|
22
22
|
* Id of the derivation *run* that last accessed this observable.
|
|
23
23
|
* If this id equals the *run* id of the current derivation,
|
package/src/core/reaction.ts
CHANGED
|
@@ -22,6 +22,8 @@ import {
|
|
|
22
22
|
GenericAbortSignal
|
|
23
23
|
} from "../internal"
|
|
24
24
|
|
|
25
|
+
import { getFlag, setFlag } from "../utils/utils"
|
|
26
|
+
|
|
25
27
|
/**
|
|
26
28
|
* Reactions are a special kind of derivations. Several things distinguishes them from normal reactive computations
|
|
27
29
|
*
|
|
@@ -55,13 +57,16 @@ export class Reaction implements IDerivation, IReactionPublic {
|
|
|
55
57
|
observing_: IObservable[] = [] // nodes we are looking at. Our value depends on these nodes
|
|
56
58
|
newObserving_: IObservable[] = []
|
|
57
59
|
dependenciesState_ = IDerivationState_.NOT_TRACKING_
|
|
58
|
-
diffValue_ = 0
|
|
59
60
|
runId_ = 0
|
|
60
61
|
unboundDepsCount_ = 0
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
|
|
63
|
+
private static readonly isDisposedMask_ = 0b00001
|
|
64
|
+
private static readonly isScheduledMask_ = 0b00010
|
|
65
|
+
private static readonly isTrackPendingMask_ = 0b00100
|
|
66
|
+
private static readonly isRunningMask_ = 0b01000
|
|
67
|
+
private static readonly diffValueMask_ = 0b10000
|
|
68
|
+
private flags_ = 0b00000
|
|
69
|
+
|
|
65
70
|
isTracing_: TraceMode = TraceMode.NONE
|
|
66
71
|
|
|
67
72
|
constructor(
|
|
@@ -71,37 +76,68 @@ export class Reaction implements IDerivation, IReactionPublic {
|
|
|
71
76
|
public requiresObservable_?
|
|
72
77
|
) {}
|
|
73
78
|
|
|
79
|
+
get isDisposed() {
|
|
80
|
+
return getFlag(this.flags_, Reaction.isDisposedMask_)
|
|
81
|
+
}
|
|
82
|
+
set isDisposed(newValue: boolean) {
|
|
83
|
+
this.flags_ = setFlag(this.flags_, Reaction.isDisposedMask_, newValue)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
get isScheduled() {
|
|
87
|
+
return getFlag(this.flags_, Reaction.isScheduledMask_)
|
|
88
|
+
}
|
|
89
|
+
set isScheduled(newValue: boolean) {
|
|
90
|
+
this.flags_ = setFlag(this.flags_, Reaction.isScheduledMask_, newValue)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
get isTrackPending() {
|
|
94
|
+
return getFlag(this.flags_, Reaction.isTrackPendingMask_)
|
|
95
|
+
}
|
|
96
|
+
set isTrackPending(newValue: boolean) {
|
|
97
|
+
this.flags_ = setFlag(this.flags_, Reaction.isTrackPendingMask_, newValue)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
get isRunning() {
|
|
101
|
+
return getFlag(this.flags_, Reaction.isRunningMask_)
|
|
102
|
+
}
|
|
103
|
+
set isRunning(newValue: boolean) {
|
|
104
|
+
this.flags_ = setFlag(this.flags_, Reaction.isRunningMask_, newValue)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
get diffValue(): 0 | 1 {
|
|
108
|
+
return getFlag(this.flags_, Reaction.diffValueMask_) ? 1 : 0
|
|
109
|
+
}
|
|
110
|
+
set diffValue(newValue: 0 | 1) {
|
|
111
|
+
this.flags_ = setFlag(this.flags_, Reaction.diffValueMask_, newValue === 1 ? true : false)
|
|
112
|
+
}
|
|
113
|
+
|
|
74
114
|
onBecomeStale_() {
|
|
75
115
|
this.schedule_()
|
|
76
116
|
}
|
|
77
117
|
|
|
78
118
|
schedule_() {
|
|
79
|
-
if (!this.
|
|
80
|
-
this.
|
|
119
|
+
if (!this.isScheduled) {
|
|
120
|
+
this.isScheduled = true
|
|
81
121
|
globalState.pendingReactions.push(this)
|
|
82
122
|
runReactions()
|
|
83
123
|
}
|
|
84
124
|
}
|
|
85
125
|
|
|
86
|
-
isScheduled() {
|
|
87
|
-
return this.isScheduled_
|
|
88
|
-
}
|
|
89
|
-
|
|
90
126
|
/**
|
|
91
127
|
* internal, use schedule() if you intend to kick off a reaction
|
|
92
128
|
*/
|
|
93
129
|
runReaction_() {
|
|
94
|
-
if (!this.
|
|
130
|
+
if (!this.isDisposed) {
|
|
95
131
|
startBatch()
|
|
96
|
-
this.
|
|
132
|
+
this.isScheduled = false
|
|
97
133
|
const prev = globalState.trackingContext
|
|
98
134
|
globalState.trackingContext = this
|
|
99
135
|
if (shouldCompute(this)) {
|
|
100
|
-
this.
|
|
136
|
+
this.isTrackPending = true
|
|
101
137
|
|
|
102
138
|
try {
|
|
103
139
|
this.onInvalidate_()
|
|
104
|
-
if (__DEV__ && this.
|
|
140
|
+
if (__DEV__ && this.isTrackPending && isSpyEnabled()) {
|
|
105
141
|
// onInvalidate didn't trigger track right away..
|
|
106
142
|
spyReport({
|
|
107
143
|
name: this.name_,
|
|
@@ -118,7 +154,7 @@ export class Reaction implements IDerivation, IReactionPublic {
|
|
|
118
154
|
}
|
|
119
155
|
|
|
120
156
|
track(fn: () => void) {
|
|
121
|
-
if (this.
|
|
157
|
+
if (this.isDisposed) {
|
|
122
158
|
return
|
|
123
159
|
// console.warn("Reaction already disposed") // Note: Not a warning / error in mobx 4 either
|
|
124
160
|
}
|
|
@@ -132,14 +168,14 @@ export class Reaction implements IDerivation, IReactionPublic {
|
|
|
132
168
|
type: "reaction"
|
|
133
169
|
})
|
|
134
170
|
}
|
|
135
|
-
this.
|
|
171
|
+
this.isRunning = true
|
|
136
172
|
const prevReaction = globalState.trackingContext // reactions could create reactions...
|
|
137
173
|
globalState.trackingContext = this
|
|
138
174
|
const result = trackDerivedFunction(this, fn, undefined)
|
|
139
175
|
globalState.trackingContext = prevReaction
|
|
140
|
-
this.
|
|
141
|
-
this.
|
|
142
|
-
if (this.
|
|
176
|
+
this.isRunning = false
|
|
177
|
+
this.isTrackPending = false
|
|
178
|
+
if (this.isDisposed) {
|
|
143
179
|
// disposed during last run. Clean up everything that was bound after the dispose call.
|
|
144
180
|
clearObserving(this)
|
|
145
181
|
}
|
|
@@ -185,9 +221,9 @@ export class Reaction implements IDerivation, IReactionPublic {
|
|
|
185
221
|
}
|
|
186
222
|
|
|
187
223
|
dispose() {
|
|
188
|
-
if (!this.
|
|
189
|
-
this.
|
|
190
|
-
if (!this.
|
|
224
|
+
if (!this.isDisposed) {
|
|
225
|
+
this.isDisposed = true
|
|
226
|
+
if (!this.isRunning) {
|
|
191
227
|
// if disposed while running, clean up later. Maybe not optimal, but rare case
|
|
192
228
|
startBatch()
|
|
193
229
|
clearObserving(this)
|
package/src/utils/utils.ts
CHANGED
|
@@ -212,3 +212,16 @@ export const getOwnPropertyDescriptors =
|
|
|
212
212
|
})
|
|
213
213
|
return res
|
|
214
214
|
}
|
|
215
|
+
|
|
216
|
+
export function getFlag(flags: number, mask: number) {
|
|
217
|
+
return !!(flags & mask)
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export function setFlag(flags: number, mask: number, newValue: boolean): number {
|
|
221
|
+
if (newValue) {
|
|
222
|
+
flags |= mask
|
|
223
|
+
} else {
|
|
224
|
+
flags &= ~mask
|
|
225
|
+
}
|
|
226
|
+
return flags
|
|
227
|
+
}
|