mobx 6.3.10 → 6.4.0

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 (64) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +1 -0
  3. package/dist/api/tojs.d.ts +4 -1
  4. package/dist/errors.d.ts +2 -2
  5. package/dist/mobx.cjs.development.js +995 -304
  6. package/dist/mobx.cjs.development.js.map +1 -1
  7. package/dist/mobx.cjs.production.min.js +1 -1
  8. package/dist/mobx.cjs.production.min.js.map +1 -1
  9. package/dist/mobx.esm.development.js +995 -304
  10. package/dist/mobx.esm.development.js.map +1 -1
  11. package/dist/mobx.esm.js +1010 -307
  12. package/dist/mobx.esm.js.map +1 -1
  13. package/dist/mobx.esm.production.min.js +1 -1
  14. package/dist/mobx.esm.production.min.js.map +1 -1
  15. package/dist/mobx.umd.development.js +995 -304
  16. package/dist/mobx.umd.development.js.map +1 -1
  17. package/dist/mobx.umd.production.min.js +1 -1
  18. package/dist/mobx.umd.production.min.js.map +1 -1
  19. package/dist/types/observablemap.d.ts +2 -2
  20. package/dist/utils/utils.d.ts +1 -1
  21. package/package.json +1 -1
  22. package/src/api/action.ts +8 -3
  23. package/src/api/annotation.ts +1 -2
  24. package/src/api/autorun.ts +22 -8
  25. package/src/api/computed.ts +5 -2
  26. package/src/api/configure.ts +6 -2
  27. package/src/api/extendobservable.ts +11 -5
  28. package/src/api/extras.ts +4 -2
  29. package/src/api/flow.ts +11 -4
  30. package/src/api/intercept-read.ts +4 -2
  31. package/src/api/intercept.ts +5 -2
  32. package/src/api/iscomputed.ts +10 -4
  33. package/src/api/isobservable.ts +10 -4
  34. package/src/api/makeObservable.ts +4 -2
  35. package/src/api/object-api.ts +30 -16
  36. package/src/api/observable.ts +23 -9
  37. package/src/api/observe.ts +4 -2
  38. package/src/api/tojs.ts +11 -4
  39. package/src/api/trace.ts +6 -2
  40. package/src/api/when.ts +12 -5
  41. package/src/core/action.ts +8 -3
  42. package/src/core/computedvalue.ts +29 -9
  43. package/src/core/derivation.ts +25 -9
  44. package/src/core/globalstate.ts +18 -7
  45. package/src/core/observable.ts +14 -5
  46. package/src/core/reaction.ts +15 -6
  47. package/src/core/spy.ts +20 -7
  48. package/src/errors.ts +2 -2
  49. package/src/types/actionannotation.ts +2 -2
  50. package/src/types/dynamicobject.ts +10 -4
  51. package/src/types/flowannotation.ts +14 -4
  52. package/src/types/intercept-utils.ts +9 -3
  53. package/src/types/legacyobservablearray.ts +5 -3
  54. package/src/types/listen-utils.ts +6 -2
  55. package/src/types/modifiers.ts +39 -14
  56. package/src/types/observablearray.ts +78 -30
  57. package/src/types/observablemap.ts +65 -26
  58. package/src/types/observableobject.ts +52 -18
  59. package/src/types/observableset.ts +29 -10
  60. package/src/types/observablevalue.ts +13 -5
  61. package/src/types/type-utils.ts +33 -11
  62. package/src/utils/comparer.ts +4 -4
  63. package/src/utils/eq.ts +45 -15
  64. package/src/utils/utils.ts +42 -20
package/src/api/when.ts CHANGED
@@ -25,8 +25,9 @@ export function when(
25
25
  opts?: IWhenOptions
26
26
  ): IReactionDisposer
27
27
  export function when(predicate: any, arg1?: any, arg2?: any): any {
28
- if (arguments.length === 1 || (arg1 && typeof arg1 === "object"))
28
+ if (arguments.length === 1 || (arg1 && typeof arg1 === "object")) {
29
29
  return whenPromise(predicate, arg1)
30
+ }
30
31
  return _when(predicate, arg1, arg2 || {})
31
32
  }
32
33
 
@@ -37,8 +38,11 @@ function _when(predicate: () => boolean, effect: Lambda, opts: IWhenOptions): IR
37
38
  timeoutHandle = setTimeout(() => {
38
39
  if (!disposer[$mobx].isDisposed_) {
39
40
  disposer()
40
- if (opts.onError) opts.onError(error)
41
- else throw error
41
+ if (opts.onError) {
42
+ opts.onError(error)
43
+ } else {
44
+ throw error
45
+ }
42
46
  }
43
47
  }, opts.timeout)
44
48
  }
@@ -54,7 +58,9 @@ function _when(predicate: () => boolean, effect: Lambda, opts: IWhenOptions): IR
54
58
  let cond = allowStateChanges(false, predicate)
55
59
  if (cond) {
56
60
  r.dispose()
57
- if (timeoutHandle) clearTimeout(timeoutHandle)
61
+ if (timeoutHandle) {
62
+ clearTimeout(timeoutHandle)
63
+ }
58
64
  effectAction()
59
65
  }
60
66
  }, opts)
@@ -65,8 +71,9 @@ function whenPromise(
65
71
  predicate: () => boolean,
66
72
  opts?: IWhenOptions
67
73
  ): Promise<void> & { cancel(): void } {
68
- if (__DEV__ && opts && opts.onError)
74
+ if (__DEV__ && opts && opts.onError) {
69
75
  return die(`the options 'onError' and 'promise' cannot be combined`)
76
+ }
70
77
  let cancel
71
78
  const res = new Promise((resolve, reject) => {
72
79
  let disposer = _when(predicate, resolve as Lambda, { ...opts, onError: reject })
@@ -38,9 +38,12 @@ export function createAction(
38
38
  ref?: Object
39
39
  ): Function {
40
40
  if (__DEV__) {
41
- if (!isFunction(fn)) die("`action` can only be invoked on functions")
42
- if (typeof actionName !== "string" || !actionName)
41
+ if (!isFunction(fn)) {
42
+ die("`action` can only be invoked on functions")
43
+ }
44
+ if (typeof actionName !== "string" || !actionName) {
43
45
  die(`actions should have valid names, got: '${actionName}'`)
46
+ }
44
47
  }
45
48
  function res() {
46
49
  return executeAction(actionName, autoAction, fn, ref || this, arguments)
@@ -136,7 +139,9 @@ export function _endAction(runInfo: IActionRunInfo) {
136
139
  allowStateChangesEnd(runInfo.prevAllowStateChanges_)
137
140
  allowStateReadsEnd(runInfo.prevAllowStateReads_)
138
141
  endBatch()
139
- if (runInfo.runAsAction_) untrackedEnd(runInfo.prevDerivation_)
142
+ if (runInfo.runAsAction_) {
143
+ untrackedEnd(runInfo.prevDerivation_)
144
+ }
140
145
  if (__DEV__ && runInfo.notifySpy_) {
141
146
  spyReportEnd({ time: Date.now() - runInfo.startTime_ })
142
147
  }
@@ -114,7 +114,9 @@ export class ComputedValue<T> implements IObservable, IComputedValue<T>, IDeriva
114
114
  * This is useful for working with vectors, mouse coordinates etc.
115
115
  */
116
116
  constructor(options: IComputedValueOptions<T>) {
117
- if (!options.get) die(31)
117
+ if (!options.get) {
118
+ die(31)
119
+ }
118
120
  this.derivation = options.get!
119
121
  this.name_ = options.name || (__DEV__ ? "ComputedValue@" + getNextId() : "ComputedValue")
120
122
  if (options.set) {
@@ -157,7 +159,9 @@ export class ComputedValue<T> implements IObservable, IComputedValue<T>, IDeriva
157
159
  * Will evaluate its computation first if needed.
158
160
  */
159
161
  public get(): T {
160
- if (this.isComputing_) die(32, this.name_, this.derivation)
162
+ if (this.isComputing_) {
163
+ die(32, this.name_, this.derivation)
164
+ }
161
165
  if (
162
166
  globalState.inBatch === 0 &&
163
167
  // !globalState.trackingDerivatpion &&
@@ -174,27 +178,37 @@ export class ComputedValue<T> implements IObservable, IComputedValue<T>, IDeriva
174
178
  reportObserved(this)
175
179
  if (shouldCompute(this)) {
176
180
  let prevTrackingContext = globalState.trackingContext
177
- if (this.keepAlive_ && !prevTrackingContext) globalState.trackingContext = this
178
- if (this.trackAndCompute()) propagateChangeConfirmed(this)
181
+ if (this.keepAlive_ && !prevTrackingContext) {
182
+ globalState.trackingContext = this
183
+ }
184
+ if (this.trackAndCompute()) {
185
+ propagateChangeConfirmed(this)
186
+ }
179
187
  globalState.trackingContext = prevTrackingContext
180
188
  }
181
189
  }
182
190
  const result = this.value_!
183
191
 
184
- if (isCaughtException(result)) throw result.cause
192
+ if (isCaughtException(result)) {
193
+ throw result.cause
194
+ }
185
195
  return result
186
196
  }
187
197
 
188
198
  public set(value: T) {
189
199
  if (this.setter_) {
190
- if (this.isRunningSetter_) die(33, this.name_)
200
+ if (this.isRunningSetter_) {
201
+ die(33, this.name_)
202
+ }
191
203
  this.isRunningSetter_ = true
192
204
  try {
193
205
  this.setter_.call(this.scope_, value)
194
206
  } finally {
195
207
  this.isRunningSetter_ = false
196
208
  }
197
- } else die(34, this.name_)
209
+ } else {
210
+ die(34, this.name_)
211
+ }
198
212
  }
199
213
 
200
214
  trackAndCompute(): boolean {
@@ -287,13 +301,19 @@ export class ComputedValue<T> implements IObservable, IComputedValue<T>, IDeriva
287
301
  }
288
302
 
289
303
  warnAboutUntrackedRead_() {
290
- if (!__DEV__) return
304
+ if (!__DEV__) {
305
+ return
306
+ }
291
307
  if (this.isTracing_ !== TraceMode.NONE) {
292
308
  console.log(
293
309
  `[mobx.trace] Computed value '${this.name_}' is being read outside a reactive context. Doing a full recompute.`
294
310
  )
295
311
  }
296
- if (typeof this.requiresReaction_ === "boolean" ? this.requiresReaction_ : globalState.computedRequiresReaction) {
312
+ if (
313
+ typeof this.requiresReaction_ === "boolean"
314
+ ? this.requiresReaction_
315
+ : globalState.computedRequiresReaction
316
+ ) {
297
317
  console.warn(
298
318
  `[mobx] Computed value '${this.name_}' is being read outside a reactive context. Doing a full recompute.`
299
319
  )
@@ -137,7 +137,10 @@ export function checkIfStateModificationsAreAllowed(atom: IAtom) {
137
137
  }
138
138
  const hasObservers = atom.observers_.size > 0
139
139
  // Should not be possible to change observed state outside strict mode, except during initialization, see #563
140
- if (!globalState.allowStateChanges && (hasObservers || globalState.enforceActions === "always"))
140
+ if (
141
+ !globalState.allowStateChanges &&
142
+ (hasObservers || globalState.enforceActions === "always")
143
+ ) {
141
144
  console.warn(
142
145
  "[MobX] " +
143
146
  (globalState.enforceActions
@@ -145,6 +148,7 @@ export function checkIfStateModificationsAreAllowed(atom: IAtom) {
145
148
  : "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: ") +
146
149
  atom.name_
147
150
  )
151
+ }
148
152
  }
149
153
 
150
154
  export function checkIfStateReadsAreAllowed(observable: IObservable) {
@@ -191,9 +195,13 @@ export function trackDerivedFunction<T>(derivation: IDerivation, f: () => T, con
191
195
  }
192
196
 
193
197
  function warnAboutDerivationWithoutDependencies(derivation: IDerivation) {
194
- if (!__DEV__) return
198
+ if (!__DEV__) {
199
+ return
200
+ }
195
201
 
196
- if (derivation.observing_.length !== 0) return
202
+ if (derivation.observing_.length !== 0) {
203
+ return
204
+ }
197
205
 
198
206
  if (globalState.reactionRequiresObservable || derivation.requiresObservable_) {
199
207
  console.warn(
@@ -222,14 +230,16 @@ function bindDependencies(derivation: IDerivation) {
222
230
  const dep = observing[i]
223
231
  if (dep.diffValue_ === 0) {
224
232
  dep.diffValue_ = 1
225
- if (i0 !== i) observing[i0] = dep
233
+ if (i0 !== i) {
234
+ observing[i0] = dep
235
+ }
226
236
  i0++
227
237
  }
228
238
 
229
239
  // Upcast is 'safe' here, because if dep is IObservable, `dependenciesState` will be undefined,
230
240
  // not hitting the condition
231
- if (((dep as any) as IDerivation).dependenciesState_ > lowestNewObservingDerivationState) {
232
- lowestNewObservingDerivationState = ((dep as any) as IDerivation).dependenciesState_
241
+ if ((dep as any as IDerivation).dependenciesState_ > lowestNewObservingDerivationState) {
242
+ lowestNewObservingDerivationState = (dep as any as IDerivation).dependenciesState_
233
243
  }
234
244
  }
235
245
  observing.length = i0
@@ -272,7 +282,9 @@ export function clearObserving(derivation: IDerivation) {
272
282
  const obs = derivation.observing_
273
283
  derivation.observing_ = []
274
284
  let i = obs.length
275
- while (i--) removeObserver(obs[i], derivation)
285
+ while (i--) {
286
+ removeObserver(obs[i], derivation)
287
+ }
276
288
 
277
289
  derivation.dependenciesState_ = IDerivationState_.NOT_TRACKING_
278
290
  }
@@ -311,10 +323,14 @@ export function allowStateReadsEnd(prev: boolean) {
311
323
  *
312
324
  */
313
325
  export function changeDependenciesStateTo0(derivation: IDerivation) {
314
- if (derivation.dependenciesState_ === IDerivationState_.UP_TO_DATE_) return
326
+ if (derivation.dependenciesState_ === IDerivationState_.UP_TO_DATE_) {
327
+ return
328
+ }
315
329
  derivation.dependenciesState_ = IDerivationState_.UP_TO_DATE_
316
330
 
317
331
  const obs = derivation.observing_
318
332
  let i = obs.length
319
- while (i--) obs[i].lowestObserverState_ = IDerivationState_.UP_TO_DATE_
333
+ while (i--) {
334
+ obs[i].lowestObserverState_ = IDerivationState_.UP_TO_DATE_
335
+ }
320
336
  }
@@ -157,9 +157,12 @@ let isolateCalled = false
157
157
 
158
158
  export let globalState: MobXGlobals = (function () {
159
159
  let global = getGlobal()
160
- if (global.__mobxInstanceCount > 0 && !global.__mobxGlobals) canMergeGlobalState = false
161
- if (global.__mobxGlobals && global.__mobxGlobals.version !== new MobXGlobals().version)
160
+ if (global.__mobxInstanceCount > 0 && !global.__mobxGlobals) {
162
161
  canMergeGlobalState = false
162
+ }
163
+ if (global.__mobxGlobals && global.__mobxGlobals.version !== new MobXGlobals().version) {
164
+ canMergeGlobalState = false
165
+ }
163
166
 
164
167
  if (!canMergeGlobalState) {
165
168
  // Because this is a IIFE we need to let isolateCalled a chance to change
@@ -172,7 +175,9 @@ export let globalState: MobXGlobals = (function () {
172
175
  return new MobXGlobals()
173
176
  } else if (global.__mobxGlobals) {
174
177
  global.__mobxInstanceCount += 1
175
- if (!global.__mobxGlobals.UNCHANGED) global.__mobxGlobals.UNCHANGED = {} // make merge backward compatible
178
+ if (!global.__mobxGlobals.UNCHANGED) {
179
+ global.__mobxGlobals.UNCHANGED = {}
180
+ } // make merge backward compatible
176
181
  return global.__mobxGlobals
177
182
  } else {
178
183
  global.__mobxInstanceCount = 1
@@ -185,12 +190,15 @@ export function isolateGlobalState() {
185
190
  globalState.pendingReactions.length ||
186
191
  globalState.inBatch ||
187
192
  globalState.isRunningReactions
188
- )
193
+ ) {
189
194
  die(36)
195
+ }
190
196
  isolateCalled = true
191
197
  if (canMergeGlobalState) {
192
198
  let global = getGlobal()
193
- if (--global.__mobxInstanceCount === 0) global.__mobxGlobals = undefined
199
+ if (--global.__mobxInstanceCount === 0) {
200
+ global.__mobxGlobals = undefined
201
+ }
194
202
  globalState = new MobXGlobals()
195
203
  }
196
204
  }
@@ -205,7 +213,10 @@ export function getGlobalState(): any {
205
213
  */
206
214
  export function resetGlobalState() {
207
215
  const defaultGlobals = new MobXGlobals()
208
- for (let key in defaultGlobals)
209
- if (persistentKeys.indexOf(key as any) === -1) globalState[key] = defaultGlobals[key]
216
+ for (let key in defaultGlobals) {
217
+ if (persistentKeys.indexOf(key as any) === -1) {
218
+ globalState[key] = defaultGlobals[key]
219
+ }
220
+ }
210
221
  globalState.allowStateChanges = !globalState.enforceActions
211
222
  }
@@ -69,8 +69,9 @@ export function addObserver(observable: IObservable, node: IDerivation) {
69
69
  // invariantObservers(observable);
70
70
 
71
71
  observable.observers_.add(node)
72
- if (observable.lowestObserverState_ > node.dependenciesState_)
72
+ if (observable.lowestObserverState_ > node.dependenciesState_) {
73
73
  observable.lowestObserverState_ = node.dependenciesState_
74
+ }
74
75
 
75
76
  // invariantObservers(observable);
76
77
  // invariant(observable._observers.indexOf(node) !== -1, "INTERNAL ERROR didn't add node");
@@ -183,7 +184,9 @@ export function reportObserved(observable: IObservable): boolean {
183
184
  // Called by Atom when its value changes
184
185
  export function propagateChanged(observable: IObservable) {
185
186
  // invariantLOS(observable, "changed start");
186
- if (observable.lowestObserverState_ === IDerivationState_.STALE_) return
187
+ if (observable.lowestObserverState_ === IDerivationState_.STALE_) {
188
+ return
189
+ }
187
190
  observable.lowestObserverState_ = IDerivationState_.STALE_
188
191
 
189
192
  // Ideally we use for..of here, but the downcompiled version is really slow...
@@ -202,7 +205,9 @@ export function propagateChanged(observable: IObservable) {
202
205
  // Called by ComputedValue when it recalculate and its value changed
203
206
  export function propagateChangeConfirmed(observable: IObservable) {
204
207
  // invariantLOS(observable, "confirmed start");
205
- if (observable.lowestObserverState_ === IDerivationState_.STALE_) return
208
+ if (observable.lowestObserverState_ === IDerivationState_.STALE_) {
209
+ return
210
+ }
206
211
  observable.lowestObserverState_ = IDerivationState_.STALE_
207
212
 
208
213
  observable.observers_.forEach(d => {
@@ -223,7 +228,9 @@ export function propagateChangeConfirmed(observable: IObservable) {
223
228
  // Used by computed when its dependency changed, but we don't wan't to immediately recompute.
224
229
  export function propagateMaybeChanged(observable: IObservable) {
225
230
  // invariantLOS(observable, "maybe start");
226
- if (observable.lowestObserverState_ !== IDerivationState_.UP_TO_DATE_) return
231
+ if (observable.lowestObserverState_ !== IDerivationState_.UP_TO_DATE_) {
232
+ return
233
+ }
227
234
  observable.lowestObserverState_ = IDerivationState_.POSSIBLY_STALE_
228
235
 
229
236
  observable.observers_.forEach(d => {
@@ -269,5 +276,7 @@ function printDepTree(tree: IDependencyTree, lines: string[], depth: number) {
269
276
  return
270
277
  }
271
278
  lines.push(`${"\t".repeat(depth - 1)}${tree.name}`)
272
- if (tree.dependencies) tree.dependencies.forEach(child => printDepTree(child, lines, depth + 1))
279
+ if (tree.dependencies) {
280
+ tree.dependencies.forEach(child => printDepTree(child, lines, depth + 1))
281
+ }
273
282
  }
@@ -142,7 +142,9 @@ export class Reaction implements IDerivation, IReactionPublic {
142
142
  // disposed during last run. Clean up everything that was bound after the dispose call.
143
143
  clearObserving(this)
144
144
  }
145
- if (isCaughtException(result)) this.reportExceptionInDerivation_(result.cause)
145
+ if (isCaughtException(result)) {
146
+ this.reportExceptionInDerivation_(result.cause)
147
+ }
146
148
  if (__DEV__ && notify) {
147
149
  spyReportEnd({
148
150
  time: Date.now() - startTime
@@ -157,7 +159,9 @@ export class Reaction implements IDerivation, IReactionPublic {
157
159
  return
158
160
  }
159
161
 
160
- if (globalState.disableErrorBoundaries) throw error
162
+ if (globalState.disableErrorBoundaries) {
163
+ throw error
164
+ }
161
165
 
162
166
  const message = __DEV__
163
167
  ? `[mobx] Encountered an uncaught exception that was thrown by a reaction or observer component, in: '${this}'`
@@ -165,7 +169,7 @@ export class Reaction implements IDerivation, IReactionPublic {
165
169
  if (!globalState.suppressReactionErrors) {
166
170
  console.error(message, error)
167
171
  /** If debugging brought you here, please, read the above message :-). Tnx! */
168
- } else if (__DEV__) console.warn(`[mobx] (error in reaction '${this.name_}' suppressed, fix error of causing action below)`) // prettier-ignore
172
+ } else if (__DEV__) {console.warn(`[mobx] (error in reaction '${this.name_}' suppressed, fix error of causing action below)`)} // prettier-ignore
169
173
 
170
174
  if (__DEV__ && isSpyEnabled()) {
171
175
  spyReport({
@@ -210,7 +214,9 @@ export function onReactionError(handler: (error: any, derivation: IDerivation) =
210
214
  globalState.globalReactionErrorHandlers.push(handler)
211
215
  return () => {
212
216
  const idx = globalState.globalReactionErrorHandlers.indexOf(handler)
213
- if (idx >= 0) globalState.globalReactionErrorHandlers.splice(idx, 1)
217
+ if (idx >= 0) {
218
+ globalState.globalReactionErrorHandlers.splice(idx, 1)
219
+ }
214
220
  }
215
221
  }
216
222
 
@@ -225,7 +231,9 @@ let reactionScheduler: (fn: () => void) => void = f => f()
225
231
 
226
232
  export function runReactions() {
227
233
  // Trampolining, if runReactions are already running, new reactions will be picked up
228
- if (globalState.inBatch > 0 || globalState.isRunningReactions) return
234
+ if (globalState.inBatch > 0 || globalState.isRunningReactions) {
235
+ return
236
+ }
229
237
  reactionScheduler(runReactionsHelper)
230
238
  }
231
239
 
@@ -248,8 +256,9 @@ function runReactionsHelper() {
248
256
  allReactions.splice(0) // clear reactions
249
257
  }
250
258
  let remainingReactions = allReactions.splice(0)
251
- for (let i = 0, l = remainingReactions.length; i < l; i++)
259
+ for (let i = 0, l = remainingReactions.length; i < l; i++) {
252
260
  remainingReactions[i].runReaction_()
261
+ }
253
262
  }
254
263
  globalState.isRunningReactions = false
255
264
  }
package/src/core/spy.ts CHANGED
@@ -25,14 +25,22 @@ export type PureSpyEvent =
25
25
  type SpyEvent = PureSpyEvent & { spyReportStart?: true }
26
26
 
27
27
  export function spyReport(event: SpyEvent) {
28
- if (!__DEV__) return // dead code elimination can do the rest
29
- if (!globalState.spyListeners.length) return
28
+ if (!__DEV__) {
29
+ return
30
+ } // dead code elimination can do the rest
31
+ if (!globalState.spyListeners.length) {
32
+ return
33
+ }
30
34
  const listeners = globalState.spyListeners
31
- for (let i = 0, l = listeners.length; i < l; i++) listeners[i](event)
35
+ for (let i = 0, l = listeners.length; i < l; i++) {
36
+ listeners[i](event)
37
+ }
32
38
  }
33
39
 
34
40
  export function spyReportStart(event: PureSpyEvent) {
35
- if (!__DEV__) return
41
+ if (!__DEV__) {
42
+ return
43
+ }
36
44
  const change = { ...event, spyReportStart: true as const }
37
45
  spyReport(change)
38
46
  }
@@ -40,9 +48,14 @@ export function spyReportStart(event: PureSpyEvent) {
40
48
  const END_EVENT: SpyEvent = { type: "report-end", spyReportEnd: true }
41
49
 
42
50
  export function spyReportEnd(change?: { time?: number }) {
43
- if (!__DEV__) return
44
- if (change) spyReport({ ...change, type: "report-end", spyReportEnd: true })
45
- else spyReport(END_EVENT)
51
+ if (!__DEV__) {
52
+ return
53
+ }
54
+ if (change) {
55
+ spyReport({ ...change, type: "report-end", spyReportEnd: true })
56
+ } else {
57
+ spyReport(END_EVENT)
58
+ }
46
59
  }
47
60
 
48
61
  export function spy(listener: (change: SpyEvent) => void): Lambda {
package/src/errors.ts CHANGED
@@ -22,9 +22,9 @@ const niceErrors = {
22
22
  10: "'has()' can only be used on observable objects, arrays and maps",
23
23
  11: "'get()' can only be used on observable objects, arrays and maps",
24
24
  12: `Invalid annotation`,
25
- 13: `Dynamic observable objects cannot be frozen`,
25
+ 13: `Dynamic observable objects cannot be frozen. If you're passing observables to 3rd party component/function that calls Object.freeze, pass copy instead: toJS(observable)`,
26
26
  14: "Intercept handlers should return nothing or a change object",
27
- 15: `Observable arrays cannot be frozen`,
27
+ 15: `Observable arrays cannot be frozen. If you're passing observables to 3rd party component/function that calls Object.freeze, pass copy instead: toJS(observable)`,
28
28
  16: `Modification exception: the internal structure of an observable array was changed.`,
29
29
  17(index, length) {
30
30
  return `[mobx.array] Index out of bounds, ${index} is larger than ${length}`
@@ -67,7 +67,7 @@ function assertActionDescriptor(
67
67
  if (__DEV__ && !isFunction(value)) {
68
68
  die(
69
69
  `Cannot apply '${annotationType_}' to '${adm.name_}.${key.toString()}':` +
70
- `\n'${annotationType_}' can only be used on properties with a function value.`
70
+ `\n'${annotationType_}' can only be used on properties with a function value.`
71
71
  )
72
72
  }
73
73
  }
@@ -91,7 +91,7 @@ export function createActionDescriptor(
91
91
  value,
92
92
  annotation.options_?.autoAction ?? false,
93
93
  // https://github.com/mobxjs/mobx/discussions/3140
94
- annotation.options_?.bound ? (adm.proxy_ ?? adm.target_) : undefined,
94
+ annotation.options_?.bound ? adm.proxy_ ?? adm.target_ : undefined
95
95
  ),
96
96
  // Non-configurable for classes
97
97
  // prevents accidental field redefinition in subclass
@@ -19,17 +19,20 @@ function getAdm(target): ObservableObjectAdministration {
19
19
  // and skip either the internal values map, or the base object with its property descriptors!
20
20
  const objectProxyTraps: ProxyHandler<any> = {
21
21
  has(target: IIsObservableObject, name: PropertyKey): boolean {
22
- if (__DEV__ && globalState.trackingDerivation)
22
+ if (__DEV__ && globalState.trackingDerivation) {
23
23
  warnAboutProxyRequirement(
24
24
  "detect new properties using the 'in' operator. Use 'has' from 'mobx' instead."
25
25
  )
26
+ }
26
27
  return getAdm(target).has_(name)
27
28
  },
28
29
  get(target: IIsObservableObject, name: PropertyKey): any {
29
30
  return getAdm(target).get_(name)
30
31
  },
31
32
  set(target: IIsObservableObject, name: PropertyKey, value: any): boolean {
32
- if (!isStringish(name)) return false
33
+ if (!isStringish(name)) {
34
+ return false
35
+ }
33
36
  if (__DEV__ && !getAdm(target).values_.has(name)) {
34
37
  warnAboutProxyRequirement(
35
38
  "add a new observable property through direct assignment. Use 'set' from 'mobx' instead."
@@ -44,7 +47,9 @@ const objectProxyTraps: ProxyHandler<any> = {
44
47
  "delete properties from an observable object. Use 'remove' from 'mobx' instead."
45
48
  )
46
49
  }
47
- if (!isStringish(name)) return false
50
+ if (!isStringish(name)) {
51
+ return false
52
+ }
48
53
  // null (intercepted) -> true (success)
49
54
  return getAdm(target).delete_(name, true) ?? true
50
55
  },
@@ -62,10 +67,11 @@ const objectProxyTraps: ProxyHandler<any> = {
62
67
  return getAdm(target).defineProperty_(name, descriptor) ?? true
63
68
  },
64
69
  ownKeys(target: IIsObservableObject): ArrayLike<string | symbol> {
65
- if (__DEV__ && globalState.trackingDerivation)
70
+ if (__DEV__ && globalState.trackingDerivation) {
66
71
  warnAboutProxyRequirement(
67
72
  "iterate keys to detect added / removed properties. Use 'keys' from 'mobx' instead."
68
73
  )
74
+ }
69
75
  return getAdm(target).ownKeys_()
70
76
  },
71
77
  preventExtensions(target) {
@@ -7,7 +7,8 @@ import {
7
7
  isFlow,
8
8
  isFunction,
9
9
  globalState,
10
- MakeResult
10
+ MakeResult,
11
+ hasProp
11
12
  } from "../internal"
12
13
 
13
14
  export function createFlowAnnotation(name: string, options?: object): Annotation {
@@ -33,8 +34,10 @@ function make_(
33
34
  }
34
35
  // prototype
35
36
  // bound - must annotate protos to support super.flow()
36
- if (this.options_?.bound && !isFlow(adm.target_[key])) {
37
- if (this.extend_(adm, key, descriptor, false) === null) return MakeResult.Cancel
37
+ if (this.options_?.bound && (!hasProp(adm.target_, key) || !isFlow(adm.target_[key]))) {
38
+ if (this.extend_(adm, key, descriptor, false) === null) {
39
+ return MakeResult.Cancel
40
+ }
38
41
  }
39
42
  if (isFlow(descriptor.value)) {
40
43
  // A prototype could have been annotated already by other constructor,
@@ -81,11 +84,18 @@ function createFlowDescriptor(
81
84
  ): PropertyDescriptor {
82
85
  assertFlowDescriptor(adm, annotation, key, descriptor)
83
86
  let { value } = descriptor
87
+ // In case of flow.bound, the descriptor can be from already annotated prototype
88
+ if (!isFlow(value)) {
89
+ value = flow(value)
90
+ }
84
91
  if (bound) {
92
+ // We do not keep original function around, so we bind the existing flow
85
93
  value = value.bind(adm.proxy_ ?? adm.target_)
94
+ // This is normally set by `flow`, but `bind` returns new function...
95
+ value.isMobXFlow = true
86
96
  }
87
97
  return {
88
- value: flow(value),
98
+ value,
89
99
  // Non-configurable for classes
90
100
  // prevents accidental field redefinition in subclass
91
101
  configurable: safeDescriptors ? adm.isPlainObject_ : true,
@@ -18,7 +18,9 @@ export function registerInterceptor<T>(
18
18
  interceptors.push(handler)
19
19
  return once(() => {
20
20
  const idx = interceptors.indexOf(handler)
21
- if (idx !== -1) interceptors.splice(idx, 1)
21
+ if (idx !== -1) {
22
+ interceptors.splice(idx, 1)
23
+ }
22
24
  })
23
25
  }
24
26
 
@@ -32,8 +34,12 @@ export function interceptChange<T>(
32
34
  const interceptors = [...(interceptable.interceptors_ || [])]
33
35
  for (let i = 0, l = interceptors.length; i < l; i++) {
34
36
  change = interceptors[i](change)
35
- if (change && !(change as any).type) die(14)
36
- if (!change) break
37
+ if (change && !(change as any).type) {
38
+ die(14)
39
+ }
40
+ if (!change) {
41
+ break
42
+ }
37
43
  }
38
44
  return change
39
45
  } finally {
@@ -85,7 +85,6 @@ class LegacyObservableArray<T> extends StubArray {
85
85
  let nextIndex = 0
86
86
  return makeIterable({
87
87
  next() {
88
- // @ts-ignore
89
88
  return nextIndex < self.length
90
89
  ? { value: self[nextIndex++], done: false }
91
90
  : { done: true, value: undefined }
@@ -95,7 +94,9 @@ class LegacyObservableArray<T> extends StubArray {
95
94
  }
96
95
 
97
96
  Object.entries(arrayExtensions).forEach(([prop, fn]) => {
98
- if (prop !== "concat") addHiddenProp(LegacyObservableArray.prototype, prop, fn)
97
+ if (prop !== "concat") {
98
+ addHiddenProp(LegacyObservableArray.prototype, prop, fn)
99
+ }
99
100
  })
100
101
 
101
102
  function createArrayEntryDescriptor(index: number) {
@@ -117,8 +118,9 @@ function createArrayBufferItem(index: number) {
117
118
 
118
119
  export function reserveArrayBuffer(max: number) {
119
120
  if (max > OBSERVABLE_ARRAY_BUFFER_SIZE) {
120
- for (let index = OBSERVABLE_ARRAY_BUFFER_SIZE; index < max + 100; index++)
121
+ for (let index = OBSERVABLE_ARRAY_BUFFER_SIZE; index < max + 100; index++) {
121
122
  createArrayBufferItem(index)
123
+ }
122
124
  OBSERVABLE_ARRAY_BUFFER_SIZE = max
123
125
  }
124
126
  }
@@ -13,14 +13,18 @@ export function registerListener(listenable: IListenable, handler: Function): La
13
13
  listeners.push(handler)
14
14
  return once(() => {
15
15
  const idx = listeners.indexOf(handler)
16
- if (idx !== -1) listeners.splice(idx, 1)
16
+ if (idx !== -1) {
17
+ listeners.splice(idx, 1)
18
+ }
17
19
  })
18
20
  }
19
21
 
20
22
  export function notifyListeners<T>(listenable: IListenable, change: T) {
21
23
  const prevU = untrackedStart()
22
24
  let listeners = listenable.changeListeners_
23
- if (!listeners) return
25
+ if (!listeners) {
26
+ return
27
+ }
24
28
  listeners = listeners.slice()
25
29
  for (let i = 0, l = listeners.length; i < l; i++) {
26
30
  listeners[i](change)