mobx 6.16.1 → 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.
Files changed (100) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/README.md +9 -13
  3. package/dist/api/action.d.ts +6 -4
  4. package/dist/api/annotation.d.ts +0 -1
  5. package/dist/api/computed.d.ts +4 -7
  6. package/dist/api/configure.d.ts +0 -1
  7. package/dist/api/decoratorannotation.d.ts +3 -0
  8. package/dist/api/decorators.d.ts +0 -19
  9. package/dist/api/flow.d.ts +4 -5
  10. package/dist/api/makeObservable.d.ts +2 -3
  11. package/dist/api/observable.d.ts +9 -15
  12. package/dist/core/atom.d.ts +1 -4
  13. package/dist/core/computedvalue.d.ts +5 -33
  14. package/dist/core/derivation.d.ts +1 -7
  15. package/dist/core/globalstate.d.ts +7 -2
  16. package/dist/core/observable.d.ts +9 -1
  17. package/dist/core/reaction.d.ts +1 -9
  18. package/dist/errors.d.ts +6 -4
  19. package/dist/internal.d.ts +1 -4
  20. package/dist/mobx.cjs.development.js +1704 -2484
  21. package/dist/mobx.cjs.development.js.map +1 -1
  22. package/dist/mobx.cjs.production.min.js +1 -1
  23. package/dist/mobx.cjs.production.min.js.map +1 -1
  24. package/dist/mobx.d.ts +2 -2
  25. package/dist/mobx.esm.development.js +1693 -2483
  26. package/dist/mobx.esm.development.js.map +1 -1
  27. package/dist/mobx.esm.js +1643 -2436
  28. package/dist/mobx.esm.js.map +1 -1
  29. package/dist/mobx.esm.production.min.js +1 -1
  30. package/dist/mobx.esm.production.min.js.map +1 -1
  31. package/dist/mobx.mjs +5308 -0
  32. package/dist/mobx.mjs.map +1 -0
  33. package/dist/mobx.umd.development.js +1707 -2487
  34. package/dist/mobx.umd.development.js.map +1 -1
  35. package/dist/mobx.umd.production.min.js +1 -1
  36. package/dist/mobx.umd.production.min.js.map +1 -1
  37. package/dist/types/actionannotation.d.ts +1 -0
  38. package/dist/types/computedannotation.d.ts +1 -0
  39. package/dist/types/decorator_fills.d.ts +2 -0
  40. package/dist/types/flowannotation.d.ts +1 -0
  41. package/dist/types/observableannotation.d.ts +5 -0
  42. package/dist/types/observablearray.d.ts +2 -5
  43. package/dist/types/observablemap.d.ts +1 -8
  44. package/dist/types/observableobject.d.ts +2 -13
  45. package/dist/types/observableset.d.ts +1 -3
  46. package/dist/types/observablevalue.d.ts +4 -6
  47. package/dist/types/overrideannotation.d.ts +1 -2
  48. package/dist/utils/comparer.d.ts +4 -11
  49. package/dist/utils/utils.d.ts +0 -2
  50. package/package.json +25 -15
  51. package/src/api/action.ts +27 -35
  52. package/src/api/annotation.ts +0 -1
  53. package/src/api/autorun.ts +2 -4
  54. package/src/api/computed.ts +21 -28
  55. package/src/api/configure.ts +1 -15
  56. package/src/api/decoratorannotation.ts +20 -0
  57. package/src/api/decorators.ts +1 -85
  58. package/src/api/extras.ts +1 -1
  59. package/src/api/flow.ts +26 -29
  60. package/src/api/intercept.ts +4 -3
  61. package/src/api/makeObservable.ts +45 -17
  62. package/src/api/object-api.ts +1 -1
  63. package/src/api/observable.ts +34 -67
  64. package/src/api/observe.ts +82 -3
  65. package/src/api/when.ts +4 -3
  66. package/src/core/action.ts +12 -5
  67. package/src/core/atom.ts +16 -14
  68. package/src/core/computedvalue.ts +36 -69
  69. package/src/core/derivation.ts +16 -15
  70. package/src/core/globalstate.ts +16 -13
  71. package/src/core/observable.ts +65 -73
  72. package/src/core/reaction.ts +19 -25
  73. package/src/core/spy.ts +3 -3
  74. package/src/errors.ts +23 -12
  75. package/src/internal.ts +1 -4
  76. package/src/mobx.ts +21 -10
  77. package/src/types/actionannotation.ts +5 -9
  78. package/src/types/autoannotation.ts +8 -11
  79. package/src/types/computedannotation.ts +13 -11
  80. package/src/types/decorator_fills.ts +4 -0
  81. package/src/types/dynamicobject.ts +0 -29
  82. package/src/types/flowannotation.ts +7 -4
  83. package/src/types/modifiers.ts +5 -0
  84. package/src/types/observableannotation.ts +6 -7
  85. package/src/types/observablearray.ts +8 -61
  86. package/src/types/observablemap.ts +4 -29
  87. package/src/types/observableobject.ts +5 -70
  88. package/src/types/observableset.ts +9 -52
  89. package/src/types/observablevalue.ts +7 -29
  90. package/src/types/overrideannotation.ts +7 -22
  91. package/src/types/type-utils.ts +4 -2
  92. package/src/utils/comparer.ts +4 -17
  93. package/src/utils/iterable.ts +3 -4
  94. package/src/utils/utils.ts +4 -46
  95. package/dist/api/trace.d.ts +0 -3
  96. package/dist/types/legacyobservablearray.d.ts +0 -14
  97. package/dist/utils/global.d.ts +0 -1
  98. package/src/api/trace.ts +0 -35
  99. package/src/types/legacyobservablearray.ts +0 -155
  100. package/src/utils/global.ts +0 -20
package/src/core/atom.ts CHANGED
@@ -6,8 +6,6 @@ import {
6
6
  endBatch,
7
7
  getNextId,
8
8
  noop,
9
- onBecomeObserved,
10
- onBecomeUnobserved,
11
9
  propagateChanged,
12
10
  reportObserved,
13
11
  startBatch,
@@ -23,13 +21,17 @@ export interface IAtom extends IObservable {
23
21
  reportChanged(): void
24
22
  }
25
23
 
24
+ const enum AtomFlags {
25
+ isBeingObserved = 0b001,
26
+ isPendingUnobservation = 0b010,
27
+ diffValue = 0b100
28
+ }
29
+
26
30
  export class Atom implements IAtom {
27
- private static readonly isBeingObservedMask_ = 0b001
28
- private static readonly isPendingUnobservationMask_ = 0b010
29
- private static readonly diffValueMask_ = 0b100
30
31
  private flags_ = 0b000
31
32
 
32
- observers_ = new Set<IDerivation>()
33
+ // Allocated lazily on first observer to save memory.
34
+ observers_: Set<IDerivation> | null = null
33
35
 
34
36
  lastAccessedBy_ = 0
35
37
  lowestObserverState_ = IDerivationState_.NOT_TRACKING_
@@ -41,24 +43,24 @@ export class Atom implements IAtom {
41
43
 
42
44
  // for effective unobserving. BaseAtom has true, for extra optimization, so its onBecomeUnobserved never gets called, because it's not needed
43
45
  get isBeingObserved(): boolean {
44
- return getFlag(this.flags_, Atom.isBeingObservedMask_)
46
+ return getFlag(this.flags_, AtomFlags.isBeingObserved)
45
47
  }
46
48
  set isBeingObserved(newValue: boolean) {
47
- this.flags_ = setFlag(this.flags_, Atom.isBeingObservedMask_, newValue)
49
+ this.flags_ = setFlag(this.flags_, AtomFlags.isBeingObserved, newValue)
48
50
  }
49
51
 
50
52
  get isPendingUnobservation(): boolean {
51
- return getFlag(this.flags_, Atom.isPendingUnobservationMask_)
53
+ return getFlag(this.flags_, AtomFlags.isPendingUnobservation)
52
54
  }
53
55
  set isPendingUnobservation(newValue: boolean) {
54
- this.flags_ = setFlag(this.flags_, Atom.isPendingUnobservationMask_, newValue)
56
+ this.flags_ = setFlag(this.flags_, AtomFlags.isPendingUnobservation, newValue)
55
57
  }
56
58
 
57
59
  get diffValue(): 0 | 1 {
58
- return getFlag(this.flags_, Atom.diffValueMask_) ? 1 : 0
60
+ return getFlag(this.flags_, AtomFlags.diffValue) ? 1 : 0
59
61
  }
60
62
  set diffValue(newValue: 0 | 1) {
61
- this.flags_ = setFlag(this.flags_, Atom.diffValueMask_, newValue === 1 ? true : false)
63
+ this.flags_ = setFlag(this.flags_, AtomFlags.diffValue, newValue === 1 ? true : false)
62
64
  }
63
65
 
64
66
  // onBecomeObservedListeners
@@ -110,11 +112,11 @@ export function createAtom(
110
112
  const atom = new Atom(name)
111
113
  // default `noop` listener will not initialize the hook Set
112
114
  if (onBecomeObservedHandler !== noop) {
113
- onBecomeObserved(atom, onBecomeObservedHandler)
115
+ atom.onBOL = new Set([onBecomeObservedHandler])
114
116
  }
115
117
 
116
118
  if (onBecomeUnobservedHandler !== noop) {
117
- onBecomeUnobserved(atom, onBecomeUnobservedHandler)
119
+ atom.onBUOL = new Set([onBecomeUnobservedHandler])
118
120
  }
119
121
  return atom
120
122
  }
@@ -5,10 +5,8 @@ import {
5
5
  IEqualsComparer,
6
6
  IObservable,
7
7
  Lambda,
8
- TraceMode,
9
- autorun,
10
8
  clearObserving,
11
- comparer,
9
+ compareDefault,
12
10
  createAction,
13
11
  createInstanceofPredicate,
14
12
  endBatch,
@@ -16,6 +14,7 @@ import {
16
14
  globalState,
17
15
  isCaughtException,
18
16
  isSpyEnabled,
17
+ markObserved,
19
18
  propagateChangeConfirmed,
20
19
  propagateMaybeChanged,
21
20
  reportObserved,
@@ -24,9 +23,6 @@ import {
24
23
  startBatch,
25
24
  toPrimitive,
26
25
  trackDerivedFunction,
27
- untrackedEnd,
28
- untrackedStart,
29
- UPDATE,
30
26
  die,
31
27
  allowStateChangesStart,
32
28
  allowStateChangesEnd
@@ -77,11 +73,20 @@ export type IComputedDidChange<T = any> = {
77
73
  *
78
74
  * If at any point it's outside batch and it isn't observed: reset everything and go to 1.
79
75
  */
76
+ const enum ComputedValueFlags {
77
+ isComputing = 0b00001,
78
+ isRunningSetter = 0b00010,
79
+ isBeingObserved = 0b00100,
80
+ isPendingUnobservation = 0b01000,
81
+ diffValue = 0b10000
82
+ }
83
+
80
84
  export class ComputedValue<T> implements IObservable, IComputedValue<T>, IDerivation {
81
85
  dependenciesState_ = IDerivationState_.NOT_TRACKING_
82
86
  observing_: IObservable[] = [] // nodes we are looking at. Our value depends on these nodes
83
87
  newObserving_ = null // during tracking it's an array with new observed observers
84
- observers_ = new Set<IDerivation>()
88
+ // Lazily allocated on first observer - see Atom.observers_.
89
+ observers_: Set<IDerivation> | null = null
85
90
  runId_ = 0
86
91
  lastAccessedBy_ = 0
87
92
  lowestObserverState_ = IDerivationState_.UP_TO_DATE_
@@ -90,16 +95,10 @@ export class ComputedValue<T> implements IObservable, IComputedValue<T>, IDeriva
90
95
  name_: string
91
96
  triggeredBy_?: string
92
97
 
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
98
  private flags_ = 0b00000
99
99
 
100
100
  derivation: () => T // N.B: unminified as it is used by MST
101
101
  setter_?: (value: T) => void
102
- isTracing_: TraceMode = TraceMode.NONE
103
102
  scope_: Object | undefined
104
103
  private equals_: IEqualsComparer<any>
105
104
  private requiresReaction_: boolean | undefined
@@ -110,11 +109,9 @@ export class ComputedValue<T> implements IObservable, IComputedValue<T>, IDeriva
110
109
  *
111
110
  * The `name` property is for debug purposes only.
112
111
  *
113
- * The `equals` property specifies the comparer function to use to determine if a newly produced
114
- * value differs from the previous value. Two comparers are provided in the library; `defaultComparer`
115
- * compares based on identity comparison (===), and `structuralComparer` deeply compares the structure.
116
- * Structural comparison can be convenient if you always produce a new aggregated object and
117
- * don't want to notify observers if it is structurally the same.
112
+ * The `equals` property specifies the comparer function used to determine if a newly produced
113
+ * value differs from the previous value. Structural comparison can be convenient if you always
114
+ * produce a new aggregated object and don't want to notify observers if it is structurally the same.
118
115
  * This is useful for working with vectors, mouse coordinates etc.
119
116
  */
120
117
  constructor(options: IComputedValueOptions<T>) {
@@ -129,11 +126,7 @@ export class ComputedValue<T> implements IObservable, IComputedValue<T>, IDeriva
129
126
  options.set
130
127
  ) as any
131
128
  }
132
- this.equals_ =
133
- options.equals ||
134
- ((options as any).compareStructural || (options as any).struct
135
- ? comparer.structural
136
- : comparer.default)
129
+ this.equals_ = options.equals || compareDefault
137
130
  this.scope_ = options.context
138
131
  this.requiresReaction_ = options.requiresReaction
139
132
  this.keepAlive_ = !!options.keepAlive
@@ -160,40 +153,40 @@ export class ComputedValue<T> implements IObservable, IComputedValue<T>, IDeriva
160
153
 
161
154
  // to check for cycles
162
155
  private get isComputing(): boolean {
163
- return getFlag(this.flags_, ComputedValue.isComputingMask_)
156
+ return getFlag(this.flags_, ComputedValueFlags.isComputing)
164
157
  }
165
158
  private set isComputing(newValue: boolean) {
166
- this.flags_ = setFlag(this.flags_, ComputedValue.isComputingMask_, newValue)
159
+ this.flags_ = setFlag(this.flags_, ComputedValueFlags.isComputing, newValue)
167
160
  }
168
161
 
169
162
  private get isRunningSetter(): boolean {
170
- return getFlag(this.flags_, ComputedValue.isRunningSetterMask_)
163
+ return getFlag(this.flags_, ComputedValueFlags.isRunningSetter)
171
164
  }
172
165
  private set isRunningSetter(newValue: boolean) {
173
- this.flags_ = setFlag(this.flags_, ComputedValue.isRunningSetterMask_, newValue)
166
+ this.flags_ = setFlag(this.flags_, ComputedValueFlags.isRunningSetter, newValue)
174
167
  }
175
168
 
176
169
  get isBeingObserved(): boolean {
177
- return getFlag(this.flags_, ComputedValue.isBeingObservedMask_)
170
+ return getFlag(this.flags_, ComputedValueFlags.isBeingObserved)
178
171
  }
179
172
  set isBeingObserved(newValue: boolean) {
180
- this.flags_ = setFlag(this.flags_, ComputedValue.isBeingObservedMask_, newValue)
173
+ this.flags_ = setFlag(this.flags_, ComputedValueFlags.isBeingObserved, newValue)
181
174
  }
182
175
 
183
176
  get isPendingUnobservation(): boolean {
184
- return getFlag(this.flags_, ComputedValue.isPendingUnobservationMask_)
177
+ return getFlag(this.flags_, ComputedValueFlags.isPendingUnobservation)
185
178
  }
186
179
  set isPendingUnobservation(newValue: boolean) {
187
- this.flags_ = setFlag(this.flags_, ComputedValue.isPendingUnobservationMask_, newValue)
180
+ this.flags_ = setFlag(this.flags_, ComputedValueFlags.isPendingUnobservation, newValue)
188
181
  }
189
182
 
190
183
  get diffValue(): 0 | 1 {
191
- return getFlag(this.flags_, ComputedValue.diffValueMask_) ? 1 : 0
184
+ return getFlag(this.flags_, ComputedValueFlags.diffValue) ? 1 : 0
192
185
  }
193
186
  set diffValue(newValue: 0 | 1) {
194
187
  this.flags_ = setFlag(
195
188
  this.flags_,
196
- ComputedValue.diffValueMask_,
189
+ ComputedValueFlags.diffValue,
197
190
  newValue === 1 ? true : false
198
191
  )
199
192
  }
@@ -209,7 +202,7 @@ export class ComputedValue<T> implements IObservable, IComputedValue<T>, IDeriva
209
202
  if (
210
203
  globalState.inBatch === 0 &&
211
204
  // !globalState.trackingDerivatpion &&
212
- this.observers_.size === 0 &&
205
+ (!this.observers_ || this.observers_.size === 0) &&
213
206
  !this.keepAlive_
214
207
  ) {
215
208
  if (shouldCompute(this)) {
@@ -219,6 +212,7 @@ export class ComputedValue<T> implements IObservable, IComputedValue<T>, IDeriva
219
212
  endBatch()
220
213
  }
221
214
  } else {
215
+ const wasBeingObserved = this.isBeingObserved
222
216
  reportObserved(this)
223
217
  if (shouldCompute(this)) {
224
218
  let prevTrackingContext = globalState.trackingContext
@@ -229,6 +223,10 @@ export class ComputedValue<T> implements IObservable, IComputedValue<T>, IDeriva
229
223
  propagateChangeConfirmed(this)
230
224
  }
231
225
  globalState.trackingContext = prevTrackingContext
226
+ } else if (!wasBeingObserved && this.isBeingObserved) {
227
+ // We just became observed while serving a cached value, so the getter
228
+ // won't run and won't re-report our dependencies. Cascade to them. #4547
229
+ this.observing_.forEach(markObserved)
232
230
  }
233
231
  }
234
232
  const result = this.value_!
@@ -289,7 +287,7 @@ export class ComputedValue<T> implements IObservable, IComputedValue<T>, IDeriva
289
287
  computeValue_(track: boolean) {
290
288
  this.isComputing = true
291
289
  // don't allow state changes during computation
292
- const prev = allowStateChangesStart(false)
290
+ const prev = __DEV__ ? allowStateChangesStart(false) : false
293
291
  let res: T | CaughtException
294
292
  if (track) {
295
293
  res = trackDerivedFunction(this, this.derivation, this.scope_)
@@ -304,7 +302,9 @@ export class ComputedValue<T> implements IObservable, IComputedValue<T>, IDeriva
304
302
  }
305
303
  }
306
304
  }
307
- allowStateChangesEnd(prev)
305
+ if (__DEV__) {
306
+ allowStateChangesEnd(prev)
307
+ }
308
308
  this.isComputing = false
309
309
  return res
310
310
  }
@@ -313,46 +313,13 @@ export class ComputedValue<T> implements IObservable, IComputedValue<T>, IDeriva
313
313
  if (!this.keepAlive_) {
314
314
  clearObserving(this)
315
315
  this.value_ = undefined // don't hold on to computed value!
316
- if (__DEV__ && this.isTracing_ !== TraceMode.NONE) {
317
- console.log(
318
- `[mobx.trace] Computed value '${this.name_}' was suspended and it will recompute on the next access.`
319
- )
320
- }
321
316
  }
322
317
  }
323
318
 
324
- observe_(listener: (change: IComputedDidChange<T>) => void, fireImmediately?: boolean): Lambda {
325
- let firstTime = true
326
- let prevValue: T | undefined = undefined
327
- return autorun(() => {
328
- // TODO: why is this in a different place than the spyReport() function? in all other observables it's called in the same place
329
- let newValue = this.get()
330
- if (!firstTime || fireImmediately) {
331
- const prevU = untrackedStart()
332
- listener({
333
- observableKind: "computed",
334
- debugObjectName: this.name_,
335
- type: UPDATE,
336
- object: this,
337
- newValue,
338
- oldValue: prevValue
339
- })
340
- untrackedEnd(prevU)
341
- }
342
- firstTime = false
343
- prevValue = newValue
344
- })
345
- }
346
-
347
319
  warnAboutUntrackedRead_() {
348
320
  if (!__DEV__) {
349
321
  return
350
322
  }
351
- if (this.isTracing_ !== TraceMode.NONE) {
352
- console.log(
353
- `[mobx.trace] Computed value '${this.name_}' is being read outside a reactive context. Doing a full recompute.`
354
- )
355
- }
356
323
  if (
357
324
  typeof this.requiresReaction_ === "boolean"
358
325
  ? this.requiresReaction_
@@ -8,7 +8,7 @@ import {
8
8
  removeObserver
9
9
  } from "../internal"
10
10
 
11
- export enum IDerivationState_ {
11
+ export const enum IDerivationState_ {
12
12
  // before being run or (outside batch and not being observed)
13
13
  // at this point derivation is not holding any data about dependency tree
14
14
  NOT_TRACKING_ = -1,
@@ -28,12 +28,6 @@ export enum IDerivationState_ {
28
28
  STALE_ = 2
29
29
  }
30
30
 
31
- export enum TraceMode {
32
- NONE,
33
- LOG,
34
- BREAK
35
- }
36
-
37
31
  /**
38
32
  * A derivation is everything that can be derived from the state (all the atoms) in a pure manner.
39
33
  * See https://medium.com/@mweststrate/becoming-fully-reactive-an-in-depth-explanation-of-mobservable-55995262a254#.xvbh6qd74
@@ -52,7 +46,6 @@ export interface IDerivation extends IDepTreeNode {
52
46
  */
53
47
  unboundDepsCount_: number
54
48
  onBecomeStale_(): void
55
- isTracing_: TraceMode
56
49
 
57
50
  /**
58
51
  * warn if the derivation has no dependencies after creation/update
@@ -90,7 +83,7 @@ export function shouldCompute(derivation: IDerivation): boolean {
90
83
  return true
91
84
  case IDerivationState_.POSSIBLY_STALE_: {
92
85
  // state propagation can occur outside of action/reactive context #2195
93
- const prevAllowStateReads = allowStateReadsStart(true)
86
+ const prevAllowStateReads = __DEV__ ? allowStateReadsStart(true) : true
94
87
  const prevUntracked = untrackedStart() // no need for those computeds to be reported, they will be picked up in trackDerivedFunction.
95
88
  const obs = derivation.observing_,
96
89
  l = obs.length
@@ -105,7 +98,9 @@ export function shouldCompute(derivation: IDerivation): boolean {
105
98
  } catch (e) {
106
99
  // we are not interested in the value *or* exception at this moment, but if there is one, notify all
107
100
  untrackedEnd(prevUntracked)
108
- allowStateReadsEnd(prevAllowStateReads)
101
+ if (__DEV__) {
102
+ allowStateReadsEnd(prevAllowStateReads)
103
+ }
109
104
  return true
110
105
  }
111
106
  }
@@ -114,14 +109,18 @@ export function shouldCompute(derivation: IDerivation): boolean {
114
109
  // invariantShouldCompute(derivation)
115
110
  if ((derivation.dependenciesState_ as any) === IDerivationState_.STALE_) {
116
111
  untrackedEnd(prevUntracked)
117
- allowStateReadsEnd(prevAllowStateReads)
112
+ if (__DEV__) {
113
+ allowStateReadsEnd(prevAllowStateReads)
114
+ }
118
115
  return true
119
116
  }
120
117
  }
121
118
  }
122
119
  changeDependenciesStateTo0(derivation)
123
120
  untrackedEnd(prevUntracked)
124
- allowStateReadsEnd(prevAllowStateReads)
121
+ if (__DEV__) {
122
+ allowStateReadsEnd(prevAllowStateReads)
123
+ }
125
124
  return false
126
125
  }
127
126
  }
@@ -135,7 +134,7 @@ export function checkIfStateModificationsAreAllowed(atom: IAtom) {
135
134
  if (!__DEV__) {
136
135
  return
137
136
  }
138
- const hasObservers = atom.observers_.size > 0
137
+ const hasObservers = !!atom.observers_ && atom.observers_.size > 0
139
138
  // Should not be possible to change observed state outside strict mode, except during initialization, see #563
140
139
  if (
141
140
  !globalState.allowStateChanges &&
@@ -165,7 +164,7 @@ export function checkIfStateReadsAreAllowed(observable: IObservable) {
165
164
  * as observer of any of the accessed observables.
166
165
  */
167
166
  export function trackDerivedFunction<T>(derivation: IDerivation, f: () => T, context: any) {
168
- const prevAllowStateReads = allowStateReadsStart(true)
167
+ const prevAllowStateReads = __DEV__ ? allowStateReadsStart(true) : true
169
168
  changeDependenciesStateTo0(derivation)
170
169
  // Preallocate array; will be trimmed by bindDependencies.
171
170
  derivation.newObserving_ = new Array(
@@ -193,7 +192,9 @@ export function trackDerivedFunction<T>(derivation: IDerivation, f: () => T, con
193
192
  bindDependencies(derivation)
194
193
 
195
194
  warnAboutDerivationWithoutDependencies(derivation)
196
- allowStateReadsEnd(prevAllowStateReads)
195
+ if (__DEV__) {
196
+ allowStateReadsEnd(prevAllowStateReads)
197
+ }
197
198
  return result
198
199
  }
199
200
 
@@ -1,6 +1,8 @@
1
- import { IDerivation, IObservable, Reaction, die, getGlobal } from "../internal"
1
+ import { IDerivation, IObservable, Reaction, die } from "../internal"
2
2
  import { ComputedValue } from "./computedvalue"
3
3
 
4
+ const MOBX_GLOBALS_VERSION = 7
5
+
4
6
  /**
5
7
  * These values will persist if global state is reset
6
8
  */
@@ -14,8 +16,7 @@ const persistentKeys: (keyof MobXGlobals)[] = [
14
16
  "allowStateReads",
15
17
  "disableErrorBoundaries",
16
18
  "runId",
17
- "UNCHANGED",
18
- "useProxies"
19
+ "UNCHANGED"
19
20
  ]
20
21
 
21
22
  export type IUNCHANGED = {}
@@ -29,7 +30,7 @@ export class MobXGlobals {
29
30
  * N.B: this version is unrelated to the package version of MobX, and is only the version of the
30
31
  * internal state storage of MobX, and can be the same across many different package versions
31
32
  */
32
- version = 6
33
+ version = MOBX_GLOBALS_VERSION
33
34
 
34
35
  /**
35
36
  * globally unique token to signal unchanged
@@ -81,6 +82,14 @@ export class MobXGlobals {
81
82
  */
82
83
  isRunningReactions = false
83
84
 
85
+ /**
86
+ * Are we currently draining pendingUnobservations in endBatch?
87
+ * An onBecomeUnobserved handler can dispose a Reaction, which calls
88
+ * startBatch/endBatch again; this guards against re-entering the same
89
+ * drain loop recursively (see endBatch in observable.ts).
90
+ */
91
+ isRunningUnobservations = false
92
+
84
93
  /**
85
94
  * Is it allowed to change observables at this point?
86
95
  * In general, MobX doesn't allow that when running computations and React.render.
@@ -138,12 +147,6 @@ export class MobXGlobals {
138
147
  */
139
148
  suppressReactionErrors = false
140
149
 
141
- useProxies = true
142
- /*
143
- * print warnings about code that would fail if proxies weren't available
144
- */
145
- verifyProxies = false
146
-
147
150
  /**
148
151
  * False forces all object's descriptors to
149
152
  * writable: true
@@ -156,11 +159,11 @@ let canMergeGlobalState = true
156
159
  let isolateCalled = false
157
160
 
158
161
  export let globalState: MobXGlobals = (function () {
159
- let global = getGlobal()
162
+ let global = globalThis as any
160
163
  if (global.__mobxInstanceCount > 0 && !global.__mobxGlobals) {
161
164
  canMergeGlobalState = false
162
165
  }
163
- if (global.__mobxGlobals && global.__mobxGlobals.version !== new MobXGlobals().version) {
166
+ if (global.__mobxGlobals && global.__mobxGlobals.version !== MOBX_GLOBALS_VERSION) {
164
167
  canMergeGlobalState = false
165
168
  }
166
169
 
@@ -195,7 +198,7 @@ export function isolateGlobalState() {
195
198
  }
196
199
  isolateCalled = true
197
200
  if (canMergeGlobalState) {
198
- let global = getGlobal()
201
+ let global = globalThis as any
199
202
  if (--global.__mobxInstanceCount === 0) {
200
203
  global.__mobxGlobals = undefined
201
204
  }