mobx 6.1.8 → 6.9.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 (91) hide show
  1. package/CHANGELOG.md +224 -7
  2. package/README.md +54 -52
  3. package/dist/api/annotation.d.ts +6 -12
  4. package/dist/api/autorun.d.ts +4 -4
  5. package/dist/api/flow.d.ts +1 -0
  6. package/dist/api/intercept.d.ts +5 -5
  7. package/dist/api/object-api.d.ts +2 -0
  8. package/dist/api/observable.d.ts +5 -1
  9. package/dist/api/observe.d.ts +4 -4
  10. package/dist/api/tojs.d.ts +4 -1
  11. package/dist/api/when.d.ts +8 -0
  12. package/dist/core/atom.d.ts +1 -1
  13. package/dist/core/computedvalue.d.ts +0 -1
  14. package/dist/core/globalstate.d.ts +4 -0
  15. package/dist/core/reaction.d.ts +2 -2
  16. package/dist/errors.d.ts +4 -2
  17. package/dist/internal.d.ts +1 -0
  18. package/dist/mobx.cjs.development.js +1477 -1719
  19. package/dist/mobx.cjs.development.js.map +1 -1
  20. package/dist/mobx.cjs.production.min.js +1 -1
  21. package/dist/mobx.cjs.production.min.js.map +1 -1
  22. package/dist/mobx.d.ts +1 -1
  23. package/dist/mobx.esm.development.js +1475 -1720
  24. package/dist/mobx.esm.development.js.map +1 -1
  25. package/dist/mobx.esm.js +1492 -1726
  26. package/dist/mobx.esm.js.map +1 -1
  27. package/dist/mobx.esm.production.min.js +1 -1
  28. package/dist/mobx.esm.production.min.js.map +1 -1
  29. package/dist/mobx.umd.development.js +1477 -1719
  30. package/dist/mobx.umd.development.js.map +1 -1
  31. package/dist/mobx.umd.production.min.js +1 -1
  32. package/dist/mobx.umd.production.min.js.map +1 -1
  33. package/dist/types/actionannotation.d.ts +7 -1
  34. package/dist/types/autoannotation.d.ts +3 -0
  35. package/dist/types/observablemap.d.ts +5 -4
  36. package/dist/types/observableobject.d.ts +6 -9
  37. package/dist/types/observableset.d.ts +4 -4
  38. package/dist/types/observablevalue.d.ts +3 -5
  39. package/dist/utils/utils.d.ts +4 -4
  40. package/package.json +1 -1
  41. package/src/api/action.ts +8 -3
  42. package/src/api/annotation.ts +14 -44
  43. package/src/api/autorun.ts +38 -17
  44. package/src/api/computed.ts +5 -2
  45. package/src/api/configure.ts +6 -2
  46. package/src/api/decorators.ts +1 -1
  47. package/src/api/extendobservable.ts +12 -6
  48. package/src/api/extras.ts +4 -2
  49. package/src/api/flow.ts +17 -5
  50. package/src/api/intercept-read.ts +4 -2
  51. package/src/api/intercept.ts +10 -7
  52. package/src/api/iscomputed.ts +14 -8
  53. package/src/api/isobservable.ts +10 -4
  54. package/src/api/makeObservable.ts +35 -36
  55. package/src/api/object-api.ts +42 -14
  56. package/src/api/observable.ts +39 -25
  57. package/src/api/observe.ts +9 -6
  58. package/src/api/tojs.ts +20 -10
  59. package/src/api/trace.ts +6 -2
  60. package/src/api/when.ts +34 -9
  61. package/src/core/action.ts +11 -5
  62. package/src/core/atom.ts +9 -2
  63. package/src/core/computedvalue.ts +48 -27
  64. package/src/core/derivation.ts +34 -12
  65. package/src/core/globalstate.ts +25 -7
  66. package/src/core/observable.ts +23 -13
  67. package/src/core/reaction.ts +16 -7
  68. package/src/core/spy.ts +20 -7
  69. package/src/errors.ts +16 -3
  70. package/src/internal.ts +1 -0
  71. package/src/mobx.ts +6 -2
  72. package/src/types/actionannotation.ts +30 -52
  73. package/src/types/autoannotation.ts +107 -0
  74. package/src/types/computedannotation.ts +7 -37
  75. package/src/types/dynamicobject.ts +12 -6
  76. package/src/types/flowannotation.ts +40 -41
  77. package/src/types/intercept-utils.ts +9 -3
  78. package/src/types/legacyobservablearray.ts +26 -3
  79. package/src/types/listen-utils.ts +6 -2
  80. package/src/types/modifiers.ts +52 -16
  81. package/src/types/observableannotation.ts +7 -34
  82. package/src/types/observablearray.ts +106 -45
  83. package/src/types/observablemap.ts +71 -35
  84. package/src/types/observableobject.ts +88 -82
  85. package/src/types/observableset.ts +32 -13
  86. package/src/types/observablevalue.ts +16 -10
  87. package/src/types/overrideannotation.ts +4 -2
  88. package/src/types/type-utils.ts +34 -12
  89. package/src/utils/comparer.ts +5 -1
  90. package/src/utils/eq.ts +45 -15
  91. package/src/utils/utils.ts +39 -16
@@ -33,7 +33,6 @@ import {
33
33
  startBatch,
34
34
  stringifyKey,
35
35
  globalState,
36
- observable,
37
36
  ADD,
38
37
  UPDATE,
39
38
  die,
@@ -43,15 +42,13 @@ import {
43
42
  ownKeys,
44
43
  isOverride,
45
44
  defineProperty,
46
- inferAnnotationFromDescriptor,
47
- getDebugName,
45
+ autoAnnotation,
48
46
  getAdministration,
49
- objectPrototype
47
+ getDebugName,
48
+ objectPrototype,
49
+ MakeResult
50
50
  } from "../internal"
51
51
 
52
- // closestPrototypeofTarget[inferredAnnotationsSymbol] = new Map<PropertyKes, Annotation>()
53
- export const inferredAnnotationsSymbol = Symbol("mobx-inferred-annotations")
54
-
55
52
  const descriptorCache = Object.create(null)
56
53
 
57
54
  export type IObjectDidChange<T = any> = {
@@ -91,7 +88,8 @@ export type IObjectWillChange<T = any> =
91
88
  const REMOVE = "remove"
92
89
 
93
90
  export class ObservableObjectAdministration
94
- implements IInterceptable<IObjectWillChange>, IListenable {
91
+ implements IInterceptable<IObjectWillChange>, IListenable
92
+ {
95
93
  keysAtom_: IAtom
96
94
  changeListeners_
97
95
  interceptors_
@@ -105,9 +103,7 @@ export class ObservableObjectAdministration
105
103
  public values_ = new Map<PropertyKey, ObservableValue<any> | ComputedValue<any>>(),
106
104
  public name_: string,
107
105
  // Used anytime annotation is not explicitely provided
108
- public defaultAnnotation_: Annotation = observable,
109
- // Bind automatically inferred actions?
110
- public autoBind_: boolean = false
106
+ public defaultAnnotation_: Annotation = autoAnnotation
111
107
  ) {
112
108
  this.keysAtom_ = new Atom(__DEV__ ? `${this.name_}.keys` : "ObservableObject.keys")
113
109
  // Optimization: we use this frequently
@@ -115,9 +111,6 @@ export class ObservableObjectAdministration
115
111
  if (__DEV__ && !isAnnotation(this.defaultAnnotation_)) {
116
112
  die(`defaultAnnotation must be valid annotation`)
117
113
  }
118
- if (__DEV__ && typeof this.autoBind_ !== "boolean") {
119
- die(`autoBind must be boolean`)
120
- }
121
114
  if (__DEV__) {
122
115
  // Prepare structure for tracking which fields were already annotated
123
116
  this.appliedAnnotations_ = {}
@@ -143,7 +136,9 @@ export class ObservableObjectAdministration
143
136
  name: key,
144
137
  newValue
145
138
  })
146
- if (!change) return null
139
+ if (!change) {
140
+ return null
141
+ }
147
142
  newValue = (change as any).newValue
148
143
  }
149
144
  newValue = (observable as any).prepareNewValue_(newValue)
@@ -165,10 +160,16 @@ export class ObservableObjectAdministration
165
160
  }
166
161
  : null
167
162
 
168
- if (__DEV__ && notifySpy) spyReportStart(change!)
163
+ if (__DEV__ && notifySpy) {
164
+ spyReportStart(change!)
165
+ }
169
166
  ;(observable as ObservableValue<any>).setNewValue_(newValue)
170
- if (notify) notifyListeners(this, change)
171
- if (__DEV__ && notifySpy) spyReportEnd()
167
+ if (notify) {
168
+ notifyListeners(this, change)
169
+ }
170
+ if (__DEV__ && notifySpy) {
171
+ spyReportEnd()
172
+ }
172
173
  }
173
174
  return true
174
175
  }
@@ -184,7 +185,7 @@ export class ObservableObjectAdministration
184
185
  /**
185
186
  * @param {PropertyKey} key
186
187
  * @param {any} value
187
- * @param {Annotation|boolean} annotation true - infer from descriptor, false - copy as is
188
+ * @param {Annotation|boolean} annotation true - use default annotation, false - copy as is
188
189
  * @param {boolean} proxyTrap whether it's called from proxy trap
189
190
  * @returns {boolean|null} true on success, false on failure (proxyTrap + non-configurable), null when cancelled by interceptor
190
191
  */
@@ -236,23 +237,49 @@ export class ObservableObjectAdministration
236
237
 
237
238
  /**
238
239
  * @param {PropertyKey} key
239
- * @param {Annotation|boolean} annotation true - infer from object or it's prototype, false - ignore
240
+ * @param {Annotation|boolean} annotation true - use default annotation, false - ignore prop
240
241
  */
241
242
  make_(key: PropertyKey, annotation: Annotation | boolean): void {
242
243
  if (annotation === true) {
243
- annotation = this.inferAnnotation_(key)
244
+ annotation = this.defaultAnnotation_
244
245
  }
245
246
  if (annotation === false) {
246
247
  return
247
248
  }
248
249
  assertAnnotable(this, annotation, key)
249
- annotation.make_(this, key)
250
+ if (!(key in this.target_)) {
251
+ // Throw on missing key, except for decorators:
252
+ // Decorator annotations are collected from whole prototype chain.
253
+ // When called from super() some props may not exist yet.
254
+ // However we don't have to worry about missing prop,
255
+ // because the decorator must have been applied to something.
256
+ if (this.target_[storedAnnotationsSymbol]?.[key]) {
257
+ return // will be annotated by subclass constructor
258
+ } else {
259
+ die(1, annotation.annotationType_, `${this.name_}.${key.toString()}`)
260
+ }
261
+ }
262
+ let source = this.target_
263
+ while (source && source !== objectPrototype) {
264
+ const descriptor = getDescriptor(source, key)
265
+ if (descriptor) {
266
+ const outcome = annotation.make_(this, key, descriptor, source)
267
+ if (outcome === MakeResult.Cancel) {
268
+ return
269
+ }
270
+ if (outcome === MakeResult.Break) {
271
+ break
272
+ }
273
+ }
274
+ source = Object.getPrototypeOf(source)
275
+ }
276
+ recordAnnotationApplied(this, annotation, key)
250
277
  }
251
278
 
252
279
  /**
253
280
  * @param {PropertyKey} key
254
281
  * @param {PropertyDescriptor} descriptor
255
- * @param {Annotation|boolean} annotation true - infer from descriptor, false - copy as is
282
+ * @param {Annotation|boolean} annotation true - use default annotation, false - copy as is
256
283
  * @param {boolean} proxyTrap whether it's called from proxy trap
257
284
  * @returns {boolean|null} true on success, false on failure (proxyTrap + non-configurable), null when cancelled by interceptor
258
285
  */
@@ -263,11 +290,7 @@ export class ObservableObjectAdministration
263
290
  proxyTrap: boolean = false
264
291
  ): boolean | null {
265
292
  if (annotation === true) {
266
- annotation = inferAnnotationFromDescriptor(
267
- descriptor,
268
- this.defaultAnnotation_,
269
- this.autoBind_
270
- )
293
+ annotation = this.defaultAnnotation_
271
294
  }
272
295
  if (annotation === false) {
273
296
  return this.defineProperty_(key, descriptor, proxyTrap)
@@ -280,44 +303,6 @@ export class ObservableObjectAdministration
280
303
  return outcome
281
304
  }
282
305
 
283
- inferAnnotation_(key: PropertyKey): Annotation | false {
284
- // Inherited is fine - annotation cannot differ in subclass
285
- let annotation = this.target_[inferredAnnotationsSymbol]?.get(key)
286
- if (annotation) return annotation
287
-
288
- let current = this.target_
289
- while (current && current !== objectPrototype) {
290
- const descriptor = getDescriptor(current, key)
291
- if (descriptor) {
292
- annotation = inferAnnotationFromDescriptor(
293
- descriptor,
294
- this.defaultAnnotation_,
295
- this.autoBind_
296
- )
297
- break
298
- }
299
- current = Object.getPrototypeOf(current)
300
- }
301
-
302
- // Not found (false means ignore)
303
- if (annotation === undefined) {
304
- die(1, "true", key)
305
- }
306
-
307
- // Cache the annotation.
308
- // Note we can do this only because annotation and field can't change.
309
- if (!this.isPlainObject_) {
310
- // We could also place it on furthest proto, shoudn't matter
311
- const closestProto = Object.getPrototypeOf(this.target_)
312
- if (!hasProp(closestProto, inferredAnnotationsSymbol)) {
313
- addHiddenProp(closestProto, inferredAnnotationsSymbol, new Map())
314
- }
315
- closestProto[inferredAnnotationsSymbol].set(key, annotation)
316
- }
317
-
318
- return annotation
319
- }
320
-
321
306
  /**
322
307
  * @param {PropertyKey} key
323
308
  * @param {PropertyDescriptor} descriptor
@@ -347,7 +332,9 @@ export class ObservableObjectAdministration
347
332
  type: ADD,
348
333
  newValue: descriptor.value
349
334
  })
350
- if (!change) return null
335
+ if (!change) {
336
+ return null
337
+ }
351
338
  const { newValue } = change as any
352
339
  if (descriptor.value !== newValue) {
353
340
  descriptor = {
@@ -399,7 +386,9 @@ export class ObservableObjectAdministration
399
386
  type: ADD,
400
387
  newValue: value
401
388
  })
402
- if (!change) return null
389
+ if (!change) {
390
+ return null
391
+ }
403
392
  value = (change as any).newValue
404
393
  }
405
394
 
@@ -461,7 +450,9 @@ export class ObservableObjectAdministration
461
450
  type: ADD,
462
451
  newValue: undefined
463
452
  })
464
- if (!change) return null
453
+ if (!change) {
454
+ return null
455
+ }
465
456
  }
466
457
  options.name ||= __DEV__ ? `${this.name_}.${key.toString()}` : "ObservableObject.key"
467
458
  options.context = this.proxy_ || this.target_
@@ -512,7 +503,9 @@ export class ObservableObjectAdministration
512
503
  type: REMOVE
513
504
  })
514
505
  // Cancelled
515
- if (!change) return null
506
+ if (!change) {
507
+ return null
508
+ }
516
509
  }
517
510
 
518
511
  // Delete
@@ -566,9 +559,15 @@ export class ObservableObjectAdministration
566
559
  oldValue: value,
567
560
  name: key
568
561
  }
569
- if (__DEV__ && notifySpy) spyReportStart(change!)
570
- if (notify) notifyListeners(this, change)
571
- if (__DEV__ && notifySpy) spyReportEnd()
562
+ if (__DEV__ && notifySpy) {
563
+ spyReportStart(change!)
564
+ }
565
+ if (notify) {
566
+ notifyListeners(this, change)
567
+ }
568
+ if (__DEV__ && notifySpy) {
569
+ spyReportEnd()
570
+ }
572
571
  }
573
572
  } finally {
574
573
  endBatch()
@@ -582,8 +581,9 @@ export class ObservableObjectAdministration
582
581
  * for callback details
583
582
  */
584
583
  observe_(callback: (changes: IObjectDidChange) => void, fireImmediately?: boolean): Lambda {
585
- if (__DEV__ && fireImmediately === true)
584
+ if (__DEV__ && fireImmediately === true) {
586
585
  die("`observe` doesn't support the fire immediately property for observable objects.")
586
+ }
587
587
  return registerListener(this, callback)
588
588
  }
589
589
 
@@ -607,9 +607,15 @@ export class ObservableObjectAdministration
607
607
  } as const)
608
608
  : null
609
609
 
610
- if (__DEV__ && notifySpy) spyReportStart(change!)
611
- if (notify) notifyListeners(this, change)
612
- if (__DEV__ && notifySpy) spyReportEnd()
610
+ if (__DEV__ && notifySpy) {
611
+ spyReportStart(change!)
612
+ }
613
+ if (notify) {
614
+ notifyListeners(this, change)
615
+ }
616
+ if (__DEV__ && notifySpy) {
617
+ spyReportEnd()
618
+ }
613
619
  }
614
620
 
615
621
  this.pendingKeys_?.get(key)?.set(true)
@@ -618,7 +624,7 @@ export class ObservableObjectAdministration
618
624
  this.keysAtom_.reportChanged()
619
625
  }
620
626
 
621
- ownKeys_(): PropertyKey[] {
627
+ ownKeys_(): ArrayLike<string | symbol> {
622
628
  this.keysAtom_.reportObserved()
623
629
  return ownKeys(this.target_)
624
630
  }
@@ -658,8 +664,9 @@ export function asObservableObject(
658
664
  return target
659
665
  }
660
666
 
661
- if (__DEV__ && !Object.isExtensible(target))
667
+ if (__DEV__ && !Object.isExtensible(target)) {
662
668
  die("Cannot make the designated object observable; it is not extensible")
669
+ }
663
670
 
664
671
  const name =
665
672
  options?.name ??
@@ -673,8 +680,7 @@ export function asObservableObject(
673
680
  target,
674
681
  new Map(),
675
682
  String(name),
676
- getAnnotationFromOptions(options),
677
- options?.autoBind
683
+ getAnnotationFromOptions(options)
678
684
  )
679
685
 
680
686
  addHiddenProp(target, $mobx, adm)
@@ -770,7 +776,7 @@ function assertAnnotable(
770
776
  `Cannot apply '${requestedAnnotationType}' to '${fieldName}':` +
771
777
  `\nThe field is already annotated with '${currentAnnotationType}'.` +
772
778
  `\nRe-annotating fields is not allowed.` +
773
- `\nUse 'override' annotation for methods overriden by subclass.`
779
+ `\nUse 'override' annotation for methods overridden by subclass.`
774
780
  )
775
781
  }
776
782
  }
@@ -65,7 +65,7 @@ export type ISetWillChange<T = any> =
65
65
  export class ObservableSet<T = any> implements Set<T>, IInterceptable<ISetWillChange>, IListenable {
66
66
  [$mobx] = ObservableSetMarker
67
67
  private data_: Set<any> = new Set()
68
- private atom_: IAtom
68
+ atom_: IAtom
69
69
  changeListeners_
70
70
  interceptors_
71
71
  dehancer: any
@@ -96,7 +96,9 @@ export class ObservableSet<T = any> implements Set<T>, IInterceptable<ISetWillCh
96
96
  clear() {
97
97
  transaction(() => {
98
98
  untracked(() => {
99
- for (const value of this.data_.values()) this.delete(value)
99
+ for (const value of this.data_.values()) {
100
+ this.delete(value)
101
+ }
100
102
  })
101
103
  })
102
104
  }
@@ -120,7 +122,9 @@ export class ObservableSet<T = any> implements Set<T>, IInterceptable<ISetWillCh
120
122
  object: this,
121
123
  newValue: value
122
124
  })
123
- if (!change) return this
125
+ if (!change) {
126
+ return this
127
+ }
124
128
  // ideally, value = change.value would be done here, so that values can be
125
129
  // changed by interceptor. Same applies for other Set and Map api's.
126
130
  }
@@ -141,22 +145,30 @@ export class ObservableSet<T = any> implements Set<T>, IInterceptable<ISetWillCh
141
145
  newValue: value
142
146
  }
143
147
  : null
144
- if (notifySpy && __DEV__) spyReportStart(change!)
145
- if (notify) notifyListeners(this, change)
146
- if (notifySpy && __DEV__) spyReportEnd()
148
+ if (notifySpy && __DEV__) {
149
+ spyReportStart(change!)
150
+ }
151
+ if (notify) {
152
+ notifyListeners(this, change)
153
+ }
154
+ if (notifySpy && __DEV__) {
155
+ spyReportEnd()
156
+ }
147
157
  }
148
158
 
149
159
  return this
150
160
  }
151
161
 
152
- delete(value: any) {
162
+ delete(value: T) {
153
163
  if (hasInterceptors(this)) {
154
164
  const change = interceptChange<ISetWillChange<T>>(this, {
155
165
  type: DELETE,
156
166
  object: this,
157
167
  oldValue: value
158
168
  })
159
- if (!change) return false
169
+ if (!change) {
170
+ return false
171
+ }
160
172
  }
161
173
  if (this.has(value)) {
162
174
  const notifySpy = __DEV__ && isSpyEnabled()
@@ -172,19 +184,25 @@ export class ObservableSet<T = any> implements Set<T>, IInterceptable<ISetWillCh
172
184
  }
173
185
  : null
174
186
 
175
- if (notifySpy && __DEV__) spyReportStart(change!)
187
+ if (notifySpy && __DEV__) {
188
+ spyReportStart(change!)
189
+ }
176
190
  transaction(() => {
177
191
  this.atom_.reportChanged()
178
192
  this.data_.delete(value)
179
193
  })
180
- if (notify) notifyListeners(this, change)
181
- if (notifySpy && __DEV__) spyReportEnd()
194
+ if (notify) {
195
+ notifyListeners(this, change)
196
+ }
197
+ if (notifySpy && __DEV__) {
198
+ spyReportEnd()
199
+ }
182
200
  return true
183
201
  }
184
202
  return false
185
203
  }
186
204
 
187
- has(value: any) {
205
+ has(value: T) {
188
206
  this.atom_.reportObserved()
189
207
  return this.data_.has(this.dehanceValue_(value))
190
208
  }
@@ -243,8 +261,9 @@ export class ObservableSet<T = any> implements Set<T>, IInterceptable<ISetWillCh
243
261
  }
244
262
  observe_(listener: (changes: ISetDidChange<T>) => void, fireImmediately?: boolean): Lambda {
245
263
  // ... 'fireImmediately' could also be true?
246
- if (__DEV__ && fireImmediately === true)
264
+ if (__DEV__ && fireImmediately === true) {
247
265
  die("`observe` doesn't support fireImmediately=true in combination with sets.")
266
+ }
248
267
  return registerListener(this, listener)
249
268
  }
250
269
 
@@ -37,8 +37,8 @@ export type IValueDidChange<T = any> = {
37
37
  observableKind: "value"
38
38
  object: IObservableValue<T>
39
39
  debugObjectName: string
40
- newValue: unknown
41
- oldValue: unknown
40
+ newValue: T
41
+ oldValue: T | undefined
42
42
  }
43
43
  export type IBoxDidChange<T = any> =
44
44
  | {
@@ -46,22 +46,21 @@ export type IBoxDidChange<T = any> =
46
46
  observableKind: "value"
47
47
  object: IObservableValue<T>
48
48
  debugObjectName: string
49
- newValue: unknown
49
+ newValue: T
50
50
  }
51
51
  | IValueDidChange<T>
52
52
 
53
53
  export interface IObservableValue<T> {
54
54
  get(): T
55
55
  set(value: T): void
56
- intercept_(handler: IInterceptor<IValueWillChange<T>>): Lambda
57
- observe_(listener: (change: IValueDidChange<T>) => void, fireImmediately?: boolean): Lambda
58
56
  }
59
57
 
60
58
  const CREATE = "create"
61
59
 
62
60
  export class ObservableValue<T>
63
61
  extends Atom
64
- implements IObservableValue<T>, IInterceptable<IValueWillChange<T>>, IListenable {
62
+ implements IObservableValue<T>, IInterceptable<IValueWillChange<T>>, IListenable
63
+ {
65
64
  hasUnreportedChange_ = false
66
65
  interceptors_
67
66
  changeListeners_
@@ -90,7 +89,9 @@ export class ObservableValue<T>
90
89
  }
91
90
 
92
91
  private dehanceValue(value: T): T {
93
- if (this.dehancer !== undefined) return this.dehancer(value)
92
+ if (this.dehancer !== undefined) {
93
+ return this.dehancer(value)
94
+ }
94
95
  return value
95
96
  }
96
97
 
@@ -110,7 +111,9 @@ export class ObservableValue<T>
110
111
  })
111
112
  }
112
113
  this.setNewValue_(newValue)
113
- if (__DEV__ && notifySpy) spyReportEnd()
114
+ if (__DEV__ && notifySpy) {
115
+ spyReportEnd()
116
+ }
114
117
  }
115
118
  }
116
119
 
@@ -122,7 +125,9 @@ export class ObservableValue<T>
122
125
  type: UPDATE,
123
126
  newValue
124
127
  })
125
- if (!change) return globalState.UNCHANGED
128
+ if (!change) {
129
+ return globalState.UNCHANGED
130
+ }
126
131
  newValue = change.newValue
127
132
  }
128
133
  // apply modifier
@@ -154,7 +159,7 @@ export class ObservableValue<T>
154
159
  }
155
160
 
156
161
  observe_(listener: (change: IValueDidChange<T>) => void, fireImmediately?: boolean): Lambda {
157
- if (fireImmediately)
162
+ if (fireImmediately) {
158
163
  listener({
159
164
  observableKind: "value",
160
165
  debugObjectName: this.name_,
@@ -163,6 +168,7 @@ export class ObservableValue<T>
163
168
  newValue: this.value_,
164
169
  oldValue: undefined
165
170
  })
171
+ }
166
172
  return registerListener(this, listener)
167
173
  }
168
174
 
@@ -3,7 +3,8 @@ import {
3
3
  Annotation,
4
4
  hasProp,
5
5
  createDecoratorAnnotation,
6
- ObservableObjectAdministration
6
+ ObservableObjectAdministration,
7
+ MakeResult
7
8
  } from "../internal"
8
9
 
9
10
  const OVERRIDE = "override"
@@ -18,7 +19,7 @@ export function isOverride(annotation: Annotation): boolean {
18
19
  return annotation.annotationType_ === OVERRIDE
19
20
  }
20
21
 
21
- function make_(adm: ObservableObjectAdministration, key): void {
22
+ function make_(adm: ObservableObjectAdministration, key): MakeResult {
22
23
  // Must not be plain object
23
24
  if (__DEV__ && adm.isPlainObject_) {
24
25
  die(
@@ -33,6 +34,7 @@ function make_(adm: ObservableObjectAdministration, key): void {
33
34
  `but no such annotated member was found on prototype.`
34
35
  )
35
36
  }
37
+ return MakeResult.Cancel
36
38
  }
37
39
 
38
40
  function extend_(adm, key, descriptor, proxyTrap): boolean {
@@ -16,23 +16,35 @@ import {
16
16
  export function getAtom(thing: any, property?: PropertyKey): IDepTreeNode {
17
17
  if (typeof thing === "object" && thing !== null) {
18
18
  if (isObservableArray(thing)) {
19
- if (property !== undefined) die(23)
19
+ if (property !== undefined) {
20
+ die(23)
21
+ }
20
22
  return (thing as any)[$mobx].atom_
21
23
  }
22
24
  if (isObservableSet(thing)) {
23
- return (thing as any)[$mobx]
25
+ return thing.atom_
24
26
  }
25
27
  if (isObservableMap(thing)) {
26
- if (property === undefined) return thing.keysAtom_
28
+ if (property === undefined) {
29
+ return thing.keysAtom_
30
+ }
27
31
  const observable = thing.data_.get(property) || thing.hasMap_.get(property)
28
- if (!observable) die(25, property, getDebugName(thing))
32
+ if (!observable) {
33
+ die(25, property, getDebugName(thing))
34
+ }
29
35
  return observable
30
36
  }
31
- if (property && !thing[$mobx]) thing[property] // See #1072
37
+ if (property && !thing[$mobx]) {
38
+ thing[property]
39
+ } // See #1072
32
40
  if (isObservableObject(thing)) {
33
- if (!property) return die(26)
41
+ if (!property) {
42
+ return die(26)
43
+ }
34
44
  const observable = (thing as any)[$mobx].values_.get(property)
35
- if (!observable) die(27, property, getDebugName(thing))
45
+ if (!observable) {
46
+ die(27, property, getDebugName(thing))
47
+ }
36
48
  return observable
37
49
  }
38
50
  if (isAtom(thing) || isComputedValue(thing) || isReaction(thing)) {
@@ -48,11 +60,21 @@ export function getAtom(thing: any, property?: PropertyKey): IDepTreeNode {
48
60
  }
49
61
 
50
62
  export function getAdministration(thing: any, property?: string) {
51
- if (!thing) die(29)
52
- if (property !== undefined) return getAdministration(getAtom(thing, property))
53
- if (isAtom(thing) || isComputedValue(thing) || isReaction(thing)) return thing
54
- if (isObservableMap(thing) || isObservableSet(thing)) return thing
55
- if (thing[$mobx]) return thing[$mobx]
63
+ if (!thing) {
64
+ die(29)
65
+ }
66
+ if (property !== undefined) {
67
+ return getAdministration(getAtom(thing, property))
68
+ }
69
+ if (isAtom(thing) || isComputedValue(thing) || isReaction(thing)) {
70
+ return thing
71
+ }
72
+ if (isObservableMap(thing) || isObservableSet(thing)) {
73
+ return thing
74
+ }
75
+ if (thing[$mobx]) {
76
+ return thing[$mobx]
77
+ }
56
78
  die(24, thing)
57
79
  }
58
80
 
@@ -17,7 +17,11 @@ function shallowComparer(a: any, b: any): boolean {
17
17
  }
18
18
 
19
19
  function defaultComparer(a: any, b: any): boolean {
20
- return Object.is(a, b)
20
+ if (Object.is) {
21
+ return Object.is(a, b)
22
+ }
23
+
24
+ return a === b ? a !== 0 || 1 / a === 1 / b : a !== a && b !== b
21
25
  }
22
26
 
23
27
  export const comparer = {