mobx 6.12.3 → 6.12.4
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/README.md +6 -2
- package/dist/api/object-api.d.ts +2 -2
- package/dist/core/atom.d.ts +2 -2
- package/dist/core/computedvalue.d.ts +13 -4
- package/dist/core/observable.d.ts +2 -2
- package/dist/mobx.cjs.development.js +68 -23
- 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 +68 -23
- package/dist/mobx.esm.development.js.map +1 -1
- package/dist/mobx.esm.js +68 -23
- 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 +68 -23
- 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 -2
- package/src/core/computedvalue.ts +54 -10
- package/src/core/observable.ts +10 -10
package/package.json
CHANGED
package/src/core/atom.ts
CHANGED
|
@@ -22,8 +22,8 @@ export interface IAtom extends IObservable {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export class Atom implements IAtom {
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
isPendingUnobservation = false // for effective unobserving. BaseAtom has true, for extra optimization, so its onBecomeUnobserved never gets called, because it's not needed
|
|
26
|
+
isBeingObserved = false
|
|
27
27
|
observers_ = new Set<IDerivation>()
|
|
28
28
|
|
|
29
29
|
diffValue_ = 0
|
|
@@ -56,6 +56,18 @@ export type IComputedDidChange<T = any> = {
|
|
|
56
56
|
oldValue: T | undefined
|
|
57
57
|
}
|
|
58
58
|
|
|
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
|
+
|
|
59
71
|
/**
|
|
60
72
|
* A node in the state dependency root that observes other nodes, and can be observed itself.
|
|
61
73
|
*
|
|
@@ -79,8 +91,6 @@ export class ComputedValue<T> implements IObservable, IComputedValue<T>, IDeriva
|
|
|
79
91
|
dependenciesState_ = IDerivationState_.NOT_TRACKING_
|
|
80
92
|
observing_: IObservable[] = [] // nodes we are looking at. Our value depends on these nodes
|
|
81
93
|
newObserving_ = null // during tracking it's an array with new observed observers
|
|
82
|
-
isBeingObserved_ = false
|
|
83
|
-
isPendingUnobservation_: boolean = false
|
|
84
94
|
observers_ = new Set<IDerivation>()
|
|
85
95
|
diffValue_ = 0
|
|
86
96
|
runId_ = 0
|
|
@@ -90,8 +100,13 @@ export class ComputedValue<T> implements IObservable, IComputedValue<T>, IDeriva
|
|
|
90
100
|
protected value_: T | undefined | CaughtException = new CaughtException(null)
|
|
91
101
|
name_: string
|
|
92
102
|
triggeredBy_?: string
|
|
93
|
-
|
|
94
|
-
|
|
103
|
+
|
|
104
|
+
private static readonly isComputingMask_ = 0b0001
|
|
105
|
+
private static readonly isRunningSetterMask_ = 0b0010
|
|
106
|
+
private static readonly isBeingObservedMask_ = 0b0100
|
|
107
|
+
private static readonly isPendingUnobservationMask_ = 0b1000
|
|
108
|
+
private flags_ = 0b0000
|
|
109
|
+
|
|
95
110
|
derivation: () => T // N.B: unminified as it is used by MST
|
|
96
111
|
setter_?: (value: T) => void
|
|
97
112
|
isTracing_: TraceMode = TraceMode.NONE
|
|
@@ -153,12 +168,41 @@ export class ComputedValue<T> implements IObservable, IComputedValue<T>, IDeriva
|
|
|
153
168
|
}
|
|
154
169
|
}
|
|
155
170
|
|
|
171
|
+
// to check for cycles
|
|
172
|
+
private get isComputing(): boolean {
|
|
173
|
+
return getFlag(this.flags_, ComputedValue.isComputingMask_)
|
|
174
|
+
}
|
|
175
|
+
private set isComputing(newValue: boolean) {
|
|
176
|
+
this.flags_ = setFlag(this.flags_, ComputedValue.isComputingMask_, newValue)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
private get isRunningSetter(): boolean {
|
|
180
|
+
return getFlag(this.flags_, ComputedValue.isRunningSetterMask_)
|
|
181
|
+
}
|
|
182
|
+
private set isRunningSetter(newValue: boolean) {
|
|
183
|
+
this.flags_ = setFlag(this.flags_, ComputedValue.isRunningSetterMask_, newValue)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
get isBeingObserved(): boolean {
|
|
187
|
+
return getFlag(this.flags_, ComputedValue.isBeingObservedMask_)
|
|
188
|
+
}
|
|
189
|
+
set isBeingObserved(newValue: boolean) {
|
|
190
|
+
this.flags_ = setFlag(this.flags_, ComputedValue.isBeingObservedMask_, newValue)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
get isPendingUnobservation(): boolean {
|
|
194
|
+
return getFlag(this.flags_, ComputedValue.isPendingUnobservationMask_)
|
|
195
|
+
}
|
|
196
|
+
set isPendingUnobservation(newValue: boolean) {
|
|
197
|
+
this.flags_ = setFlag(this.flags_, ComputedValue.isPendingUnobservationMask_, newValue)
|
|
198
|
+
}
|
|
199
|
+
|
|
156
200
|
/**
|
|
157
201
|
* Returns the current value of this computed value.
|
|
158
202
|
* Will evaluate its computation first if needed.
|
|
159
203
|
*/
|
|
160
204
|
public get(): T {
|
|
161
|
-
if (this.
|
|
205
|
+
if (this.isComputing) {
|
|
162
206
|
die(32, this.name_, this.derivation)
|
|
163
207
|
}
|
|
164
208
|
if (
|
|
@@ -196,14 +240,14 @@ export class ComputedValue<T> implements IObservable, IComputedValue<T>, IDeriva
|
|
|
196
240
|
|
|
197
241
|
public set(value: T) {
|
|
198
242
|
if (this.setter_) {
|
|
199
|
-
if (this.
|
|
243
|
+
if (this.isRunningSetter) {
|
|
200
244
|
die(33, this.name_)
|
|
201
245
|
}
|
|
202
|
-
this.
|
|
246
|
+
this.isRunningSetter = true
|
|
203
247
|
try {
|
|
204
248
|
this.setter_.call(this.scope_, value)
|
|
205
249
|
} finally {
|
|
206
|
-
this.
|
|
250
|
+
this.isRunningSetter = false
|
|
207
251
|
}
|
|
208
252
|
} else {
|
|
209
253
|
die(34, this.name_)
|
|
@@ -242,7 +286,7 @@ export class ComputedValue<T> implements IObservable, IComputedValue<T>, IDeriva
|
|
|
242
286
|
}
|
|
243
287
|
|
|
244
288
|
computeValue_(track: boolean) {
|
|
245
|
-
this.
|
|
289
|
+
this.isComputing = true
|
|
246
290
|
// don't allow state changes during computation
|
|
247
291
|
const prev = allowStateChangesStart(false)
|
|
248
292
|
let res: T | CaughtException
|
|
@@ -260,7 +304,7 @@ export class ComputedValue<T> implements IObservable, IComputedValue<T>, IDeriva
|
|
|
260
304
|
}
|
|
261
305
|
}
|
|
262
306
|
allowStateChangesEnd(prev)
|
|
263
|
-
this.
|
|
307
|
+
this.isComputing = false
|
|
264
308
|
return res
|
|
265
309
|
}
|
|
266
310
|
|
package/src/core/observable.ts
CHANGED
|
@@ -24,10 +24,10 @@ export interface IObservable extends IDepTreeNode {
|
|
|
24
24
|
* the dependency is already established
|
|
25
25
|
*/
|
|
26
26
|
lastAccessedBy_: number
|
|
27
|
-
|
|
27
|
+
isBeingObserved: boolean
|
|
28
28
|
|
|
29
29
|
lowestObserverState_: IDerivationState_ // Used to avoid redundant propagations
|
|
30
|
-
|
|
30
|
+
isPendingUnobservation: boolean // Used to push itself to global.pendingUnobservations at most once per batch.
|
|
31
31
|
|
|
32
32
|
observers_: Set<IDerivation>
|
|
33
33
|
|
|
@@ -91,9 +91,9 @@ export function removeObserver(observable: IObservable, node: IDerivation) {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
export function queueForUnobservation(observable: IObservable) {
|
|
94
|
-
if (observable.
|
|
94
|
+
if (observable.isPendingUnobservation === false) {
|
|
95
95
|
// invariant(observable._observers.length === 0, "INTERNAL ERROR, should only queue for unobservation unobserved observables");
|
|
96
|
-
observable.
|
|
96
|
+
observable.isPendingUnobservation = true
|
|
97
97
|
globalState.pendingUnobservations.push(observable)
|
|
98
98
|
}
|
|
99
99
|
}
|
|
@@ -114,11 +114,11 @@ export function endBatch() {
|
|
|
114
114
|
const list = globalState.pendingUnobservations
|
|
115
115
|
for (let i = 0; i < list.length; i++) {
|
|
116
116
|
const observable = list[i]
|
|
117
|
-
observable.
|
|
117
|
+
observable.isPendingUnobservation = false
|
|
118
118
|
if (observable.observers_.size === 0) {
|
|
119
|
-
if (observable.
|
|
119
|
+
if (observable.isBeingObserved) {
|
|
120
120
|
// if this observable had reactive observers, trigger the hooks
|
|
121
|
-
observable.
|
|
121
|
+
observable.isBeingObserved = false
|
|
122
122
|
observable.onBUO()
|
|
123
123
|
}
|
|
124
124
|
if (observable instanceof ComputedValue) {
|
|
@@ -146,12 +146,12 @@ export function reportObserved(observable: IObservable): boolean {
|
|
|
146
146
|
observable.lastAccessedBy_ = derivation.runId_
|
|
147
147
|
// Tried storing newObserving, or observing, or both as Set, but performance didn't come close...
|
|
148
148
|
derivation.newObserving_![derivation.unboundDepsCount_++] = observable
|
|
149
|
-
if (!observable.
|
|
150
|
-
observable.
|
|
149
|
+
if (!observable.isBeingObserved && globalState.trackingContext) {
|
|
150
|
+
observable.isBeingObserved = true
|
|
151
151
|
observable.onBO()
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
|
-
return observable.
|
|
154
|
+
return observable.isBeingObserved
|
|
155
155
|
} else if (observable.observers_.size === 0 && globalState.inBatch > 0) {
|
|
156
156
|
queueForUnobservation(observable)
|
|
157
157
|
}
|