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
@@ -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,9 +145,15 @@ 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
@@ -156,7 +166,9 @@ export class ObservableSet<T = any> implements Set<T>, IInterceptable<ISetWillCh
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,13 +184,19 @@ 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
@@ -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
 
@@ -61,7 +61,8 @@ const CREATE = "create"
61
61
 
62
62
  export class ObservableValue<T>
63
63
  extends Atom
64
- implements IObservableValue<T>, IInterceptable<IValueWillChange<T>>, IListenable {
64
+ implements IObservableValue<T>, IInterceptable<IValueWillChange<T>>, IListenable
65
+ {
65
66
  hasUnreportedChange_ = false
66
67
  interceptors_
67
68
  changeListeners_
@@ -90,7 +91,9 @@ export class ObservableValue<T>
90
91
  }
91
92
 
92
93
  private dehanceValue(value: T): T {
93
- if (this.dehancer !== undefined) return this.dehancer(value)
94
+ if (this.dehancer !== undefined) {
95
+ return this.dehancer(value)
96
+ }
94
97
  return value
95
98
  }
96
99
 
@@ -110,7 +113,9 @@ export class ObservableValue<T>
110
113
  })
111
114
  }
112
115
  this.setNewValue_(newValue)
113
- if (__DEV__ && notifySpy) spyReportEnd()
116
+ if (__DEV__ && notifySpy) {
117
+ spyReportEnd()
118
+ }
114
119
  }
115
120
  }
116
121
 
@@ -122,7 +127,9 @@ export class ObservableValue<T>
122
127
  type: UPDATE,
123
128
  newValue
124
129
  })
125
- if (!change) return globalState.UNCHANGED
130
+ if (!change) {
131
+ return globalState.UNCHANGED
132
+ }
126
133
  newValue = change.newValue
127
134
  }
128
135
  // apply modifier
@@ -154,7 +161,7 @@ export class ObservableValue<T>
154
161
  }
155
162
 
156
163
  observe_(listener: (change: IValueDidChange<T>) => void, fireImmediately?: boolean): Lambda {
157
- if (fireImmediately)
164
+ if (fireImmediately) {
158
165
  listener({
159
166
  observableKind: "value",
160
167
  debugObjectName: this.name_,
@@ -163,6 +170,7 @@ export class ObservableValue<T>
163
170
  newValue: this.value_,
164
171
  oldValue: undefined
165
172
  })
173
+ }
166
174
  return registerListener(this, listener)
167
175
  }
168
176
 
@@ -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
25
  return (thing as any)[$mobx]
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,11 +17,11 @@ function shallowComparer(a: any, b: any): boolean {
17
17
  }
18
18
 
19
19
  function defaultComparer(a: any, b: any): boolean {
20
- if (Object.is) return Object.is(a, b)
20
+ if (Object.is) {
21
+ return Object.is(a, b)
22
+ }
21
23
 
22
- return a === b
23
- ? a !== 0 || 1 / a === 1 / b
24
- : a !== a && b !== b
24
+ return a === b ? a !== 0 || 1 / a === 1 / b : a !== a && b !== b
25
25
  }
26
26
 
27
27
  export const comparer = {
package/src/utils/eq.ts CHANGED
@@ -21,18 +21,28 @@ export function deepEqual(a: any, b: any, depth: number = -1): boolean {
21
21
  function eq(a: any, b: any, depth: number, aStack?: any[], bStack?: any[]) {
22
22
  // Identical objects are equal. `0 === -0`, but they aren't identical.
23
23
  // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
24
- if (a === b) return a !== 0 || 1 / a === 1 / b
24
+ if (a === b) {
25
+ return a !== 0 || 1 / a === 1 / b
26
+ }
25
27
  // `null` or `undefined` only equal to itself (strict comparison).
26
- if (a == null || b == null) return false
28
+ if (a == null || b == null) {
29
+ return false
30
+ }
27
31
  // `NaN`s are equivalent, but non-reflexive.
28
- if (a !== a) return b !== b
32
+ if (a !== a) {
33
+ return b !== b
34
+ }
29
35
  // Exhaust primitive checks
30
36
  const type = typeof a
31
- if (type !== "function" && type !== "object" && typeof b != "object") return false
37
+ if (type !== "function" && type !== "object" && typeof b != "object") {
38
+ return false
39
+ }
32
40
 
33
41
  // Compare `[[Class]]` names.
34
42
  const className = toString.call(a)
35
- if (className !== toString.call(b)) return false
43
+ if (className !== toString.call(b)) {
44
+ return false
45
+ }
36
46
  switch (className) {
37
47
  // Strings, numbers, regular expressions, dates, and booleans are compared by value.
38
48
  case "[object RegExp]":
@@ -44,7 +54,9 @@ function eq(a: any, b: any, depth: number, aStack?: any[], bStack?: any[]) {
44
54
  case "[object Number]":
45
55
  // `NaN`s are equivalent, but non-reflexive.
46
56
  // Object(NaN) is equivalent to NaN.
47
- if (+a !== +a) return +b !== +b
57
+ if (+a !== +a) {
58
+ return +b !== +b
59
+ }
48
60
  // An `egal` comparison is performed for other numeric values.
49
61
  return +a === 0 ? 1 / +a === 1 / b : +a === +b
50
62
  case "[object Date]":
@@ -72,7 +84,9 @@ function eq(a: any, b: any, depth: number, aStack?: any[], bStack?: any[]) {
72
84
 
73
85
  const areArrays = className === "[object Array]"
74
86
  if (!areArrays) {
75
- if (typeof a != "object" || typeof b != "object") return false
87
+ if (typeof a != "object" || typeof b != "object") {
88
+ return false
89
+ }
76
90
 
77
91
  // Objects with different constructors are not equivalent, but `Object`s or `Array`s
78
92
  // from different frames are.
@@ -110,7 +124,9 @@ function eq(a: any, b: any, depth: number, aStack?: any[], bStack?: any[]) {
110
124
  while (length--) {
111
125
  // Linear search. Performance is inversely proportional to the number of
112
126
  // unique nested structures.
113
- if (aStack[length] === a) return bStack[length] === b
127
+ if (aStack[length] === a) {
128
+ return bStack[length] === b
129
+ }
114
130
  }
115
131
 
116
132
  // Add the first object to the stack of traversed objects.
@@ -121,10 +137,14 @@ function eq(a: any, b: any, depth: number, aStack?: any[], bStack?: any[]) {
121
137
  if (areArrays) {
122
138
  // Compare array lengths to determine if a deep comparison is necessary.
123
139
  length = a.length
124
- if (length !== b.length) return false
140
+ if (length !== b.length) {
141
+ return false
142
+ }
125
143
  // Deep compare the contents, ignoring non-numeric properties.
126
144
  while (length--) {
127
- if (!eq(a[length], b[length], depth - 1, aStack, bStack)) return false
145
+ if (!eq(a[length], b[length], depth - 1, aStack, bStack)) {
146
+ return false
147
+ }
128
148
  }
129
149
  } else {
130
150
  // Deep compare objects.
@@ -132,11 +152,15 @@ function eq(a: any, b: any, depth: number, aStack?: any[], bStack?: any[]) {
132
152
  let key
133
153
  length = keys.length
134
154
  // Ensure that both objects contain the same number of properties before comparing deep equality.
135
- if (Object.keys(b).length !== length) return false
155
+ if (Object.keys(b).length !== length) {
156
+ return false
157
+ }
136
158
  while (length--) {
137
159
  // Deep compare each member
138
160
  key = keys[length]
139
- if (!(hasProp(b, key) && eq(a[key], b[key], depth - 1, aStack, bStack))) return false
161
+ if (!(hasProp(b, key) && eq(a[key], b[key], depth - 1, aStack, bStack))) {
162
+ return false
163
+ }
140
164
  }
141
165
  }
142
166
  // Remove the first object from the stack of traversed objects.
@@ -146,8 +170,14 @@ function eq(a: any, b: any, depth: number, aStack?: any[], bStack?: any[]) {
146
170
  }
147
171
 
148
172
  function unwrap(a: any) {
149
- if (isObservableArray(a)) return a.slice()
150
- if (isES6Map(a) || isObservableMap(a)) return Array.from(a.entries())
151
- if (isES6Set(a) || isObservableSet(a)) return Array.from(a.entries())
173
+ if (isObservableArray(a)) {
174
+ return a.slice()
175
+ }
176
+ if (isES6Map(a) || isObservableMap(a)) {
177
+ return Array.from(a.entries())
178
+ }
179
+ if (isES6Set(a) || isObservableSet(a)) {
180
+ return Array.from(a.entries())
181
+ }
152
182
  return a
153
183
  }
@@ -34,7 +34,7 @@ export function warnAboutProxyRequirement(msg: string) {
34
34
  if (__DEV__ && globalState.verifyProxies) {
35
35
  die(
36
36
  "MobX is currently configured to be able to run in ES5 mode, but in ES5 MobX won't be able to " +
37
- msg
37
+ msg
38
38
  )
39
39
  }
40
40
  }
@@ -49,13 +49,15 @@ export function getNextId() {
49
49
  export function once(func: Lambda): Lambda {
50
50
  let invoked = false
51
51
  return function () {
52
- if (invoked) return
52
+ if (invoked) {
53
+ return
54
+ }
53
55
  invoked = true
54
56
  return (func as any).apply(this, arguments)
55
57
  }
56
58
  }
57
59
 
58
- export const noop = () => { }
60
+ export const noop = () => {}
59
61
 
60
62
  export function isFunction(fn: any): fn is Function {
61
63
  return typeof fn === "function"
@@ -80,20 +82,32 @@ export function isObject(value: any): value is Object {
80
82
  return value !== null && typeof value === "object"
81
83
  }
82
84
 
83
- export function isPlainObject(value) {
84
- if (!isObject(value)) return false
85
+ export function isPlainObject(value: any) {
86
+ if (!isObject(value)) {
87
+ return false
88
+ }
85
89
  const proto = Object.getPrototypeOf(value)
86
- if (proto == null) return true
87
- const protoConstructor = Object.hasOwnProperty.call(proto, "constructor") && proto.constructor;
88
- return typeof protoConstructor === "function" && protoConstructor.toString() === plainObjectString
90
+ if (proto == null) {
91
+ return true
92
+ }
93
+ const protoConstructor = Object.hasOwnProperty.call(proto, "constructor") && proto.constructor
94
+ return (
95
+ typeof protoConstructor === "function" && protoConstructor.toString() === plainObjectString
96
+ )
89
97
  }
90
98
 
91
99
  // https://stackoverflow.com/a/37865170
92
100
  export function isGenerator(obj: any): boolean {
93
101
  const constructor = obj?.constructor
94
- if (!constructor) return false
95
- if ("GeneratorFunction" === constructor.name || "GeneratorFunction" === constructor.displayName)
102
+ if (!constructor) {
103
+ return false
104
+ }
105
+ if (
106
+ "GeneratorFunction" === constructor.name ||
107
+ "GeneratorFunction" === constructor.displayName
108
+ ) {
96
109
  return true
110
+ }
97
111
  return false
98
112
  }
99
113
 
@@ -126,11 +140,11 @@ export function createInstanceofPredicate<T>(
126
140
  } as any
127
141
  }
128
142
 
129
- export function isES6Map(thing): boolean {
143
+ export function isES6Map(thing: any): thing is Map<any, any> {
130
144
  return thing instanceof Map
131
145
  }
132
146
 
133
- export function isES6Set(thing): thing is Set<any> {
147
+ export function isES6Set(thing: any): thing is Set<any> {
134
148
  return thing instanceof Set
135
149
  }
136
150
 
@@ -139,12 +153,16 @@ const hasGetOwnPropertySymbols = typeof Object.getOwnPropertySymbols !== "undefi
139
153
  /**
140
154
  * Returns the following: own enumerable keys and symbols.
141
155
  */
142
- export function getPlainObjectKeys(object) {
156
+ export function getPlainObjectKeys(object: any) {
143
157
  const keys = Object.keys(object)
144
158
  // Not supported in IE, so there are not going to be symbol props anyway...
145
- if (!hasGetOwnPropertySymbols) return keys
159
+ if (!hasGetOwnPropertySymbols) {
160
+ return keys
161
+ }
146
162
  const symbols = Object.getOwnPropertySymbols(object)
147
- if (!symbols.length) return keys
163
+ if (!symbols.length) {
164
+ return keys
165
+ }
148
166
  return [...keys, ...symbols.filter(s => objectPrototype.propertyIsEnumerable.call(object, s))]
149
167
  }
150
168
 
@@ -154,16 +172,20 @@ export const ownKeys: (target: any) => Array<string | symbol> =
154
172
  typeof Reflect !== "undefined" && Reflect.ownKeys
155
173
  ? Reflect.ownKeys
156
174
  : hasGetOwnPropertySymbols
157
- ? obj => Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertySymbols(obj) as any)
158
- : /* istanbul ignore next */ Object.getOwnPropertyNames
175
+ ? obj => Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertySymbols(obj) as any)
176
+ : /* istanbul ignore next */ Object.getOwnPropertyNames
159
177
 
160
178
  export function stringifyKey(key: any): string {
161
- if (typeof key === "string") return key
162
- if (typeof key === "symbol") return key.toString()
179
+ if (typeof key === "string") {
180
+ return key
181
+ }
182
+ if (typeof key === "symbol") {
183
+ return key.toString()
184
+ }
163
185
  return new String(key).toString()
164
186
  }
165
187
 
166
- export function toPrimitive(value) {
188
+ export function toPrimitive(value: any) {
167
189
  return value === null ? null : typeof value === "object" ? "" + value : value
168
190
  }
169
191