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
package/src/mobx.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * (c) Michel Weststrate 2015 - 2020
3
3
  * MIT Licensed
4
4
  *
5
- * Welcome to the mobx sources! To get an global overview of how MobX internally works,
5
+ * Welcome to the mobx sources! To get a global overview of how MobX internally works,
6
6
  * this is a good place to start:
7
7
  * https://medium.com/@mweststrate/becoming-fully-reactive-an-in-depth-explanation-of-mobservable-55995262a254#.xvbh6qd74
8
8
  *
@@ -17,7 +17,7 @@
17
17
  */
18
18
  import { die } from "./errors"
19
19
  import { getGlobal } from "./utils/global"
20
- ;["Symbol", "Map", "Set", "Symbol"].forEach(m => {
20
+ ;["Symbol", "Map", "Set"].forEach(m => {
21
21
  let g = getGlobal()
22
22
  if (typeof g[m] === "undefined") {
23
23
  die(`MobX requires global '${m}' to be available or polyfilled`)
@@ -75,6 +75,7 @@ export {
75
75
  IObservableFactory,
76
76
  CreateObservableOptions,
77
77
  computed,
78
+ IComputedFactory,
78
79
  isObservable,
79
80
  isObservableProp,
80
81
  isComputed,
@@ -99,10 +100,13 @@ export {
99
100
  remove,
100
101
  has,
101
102
  get,
103
+ apiOwnKeys as ownKeys,
104
+ apiDefineProperty as defineProperty,
102
105
  configure,
103
106
  onBecomeObserved,
104
107
  onBecomeUnobserved,
105
108
  flow,
109
+ isFlow,
106
110
  flowResult,
107
111
  FlowCancellationError,
108
112
  isFlowCancellationError,
@@ -3,14 +3,11 @@ import {
3
3
  createAction,
4
4
  isAction,
5
5
  defineProperty,
6
- getDescriptor,
7
- objectPrototype,
8
6
  die,
9
7
  isFunction,
10
8
  Annotation,
11
- recordAnnotationApplied,
12
9
  globalState,
13
- storedAnnotationsSymbol
10
+ MakeResult
14
11
  } from "../internal"
15
12
 
16
13
  export function createActionAnnotation(name: string, options?: object): Annotation {
@@ -22,54 +19,33 @@ export function createActionAnnotation(name: string, options?: object): Annotati
22
19
  }
23
20
  }
24
21
 
25
- function make_(adm: ObservableObjectAdministration, key: PropertyKey): void {
26
- let annotated = false
27
- let source = adm.target_
28
- let bound = this.options_?.bound ?? false
29
- while (source && source !== objectPrototype) {
30
- const descriptor = getDescriptor(source, key)
31
- if (descriptor) {
32
- // Instance or bound
33
- // Keep first because the operation can be intercepted
34
- // and we don't want to end up with partially annotated proto chain
35
- if (source === adm.target_ || bound) {
36
- const actionDescriptor = createActionDescriptor(adm, this, key, descriptor)
37
- const definePropertyOutcome = adm.defineProperty_(key, actionDescriptor)
38
- if (!definePropertyOutcome) {
39
- // Intercepted
40
- return
41
- }
42
- annotated = true
43
- // Don't annotate protos if bound
44
- if (bound) {
45
- break
46
- }
47
- }
48
- // Prototype
49
- if (source !== adm.target_) {
50
- if (isAction(descriptor.value)) {
51
- // A prototype could have been annotated already by other constructor,
52
- // rest of the proto chain must be annotated already
53
- annotated = true
54
- break
55
- }
56
- const actionDescriptor = createActionDescriptor(adm, this, key, descriptor, false)
57
- defineProperty(source, key, actionDescriptor)
58
- annotated = true
59
- }
60
- }
61
- source = Object.getPrototypeOf(source)
22
+ function make_(
23
+ adm: ObservableObjectAdministration,
24
+ key: PropertyKey,
25
+ descriptor: PropertyDescriptor,
26
+ source: object
27
+ ): MakeResult {
28
+ // bound
29
+ if (this.options_?.bound) {
30
+ return this.extend_(adm, key, descriptor, false) === null
31
+ ? MakeResult.Cancel
32
+ : MakeResult.Break
33
+ }
34
+ // own
35
+ if (source === adm.target_) {
36
+ return this.extend_(adm, key, descriptor, false) === null
37
+ ? MakeResult.Cancel
38
+ : MakeResult.Continue
62
39
  }
63
- if (annotated) {
64
- recordAnnotationApplied(adm, this, key)
65
- } else if (!adm.target_[storedAnnotationsSymbol]?.[key]) {
66
- // Throw on missing key, except for decorators:
67
- // Decorator annotations are collected from whole prototype chain.
68
- // When called from super() some props may not exist yet.
69
- // However we don't have to worry about missing prop,
70
- // because the decorator must have been applied to something.
71
- die(1, this.annotationType_, `${adm.name_}.${key.toString()}`)
40
+ // prototype
41
+ if (isAction(descriptor.value)) {
42
+ // A prototype could have been annotated already by other constructor,
43
+ // rest of the proto chain must be annotated already
44
+ return MakeResult.Break
72
45
  }
46
+ const actionDescriptor = createActionDescriptor(adm, this, key, descriptor, false)
47
+ defineProperty(source, key, actionDescriptor)
48
+ return MakeResult.Continue
73
49
  }
74
50
 
75
51
  function extend_(
@@ -96,7 +72,7 @@ function assertActionDescriptor(
96
72
  }
97
73
  }
98
74
 
99
- function createActionDescriptor(
75
+ export function createActionDescriptor(
100
76
  adm: ObservableObjectAdministration,
101
77
  annotation: Annotation,
102
78
  key: PropertyKey,
@@ -113,7 +89,9 @@ function createActionDescriptor(
113
89
  value: createAction(
114
90
  annotation.options_?.name ?? key.toString(),
115
91
  value,
116
- annotation.options_?.autoAction ?? false
92
+ annotation.options_?.autoAction ?? false,
93
+ // https://github.com/mobxjs/mobx/discussions/3140
94
+ annotation.options_?.bound ? adm.proxy_ ?? adm.target_ : undefined
117
95
  ),
118
96
  // Non-configurable for classes
119
97
  // prevents accidental field redefinition in subclass
@@ -0,0 +1,107 @@
1
+ import {
2
+ ObservableObjectAdministration,
3
+ observable,
4
+ Annotation,
5
+ defineProperty,
6
+ createAction,
7
+ globalState,
8
+ flow,
9
+ computed,
10
+ autoAction,
11
+ isGenerator,
12
+ MakeResult
13
+ } from "../internal"
14
+
15
+ const AUTO = "true"
16
+
17
+ export const autoAnnotation: Annotation = createAutoAnnotation()
18
+
19
+ export function createAutoAnnotation(options?: object): Annotation {
20
+ return {
21
+ annotationType_: AUTO,
22
+ options_: options,
23
+ make_,
24
+ extend_
25
+ }
26
+ }
27
+
28
+ function make_(
29
+ adm: ObservableObjectAdministration,
30
+ key: PropertyKey,
31
+ descriptor: PropertyDescriptor,
32
+ source: object
33
+ ): MakeResult {
34
+ // getter -> computed
35
+ if (descriptor.get) {
36
+ return computed.make_(adm, key, descriptor, source)
37
+ }
38
+ // lone setter -> action setter
39
+ if (descriptor.set) {
40
+ // TODO make action applicable to setter and delegate to action.make_
41
+ const set = createAction(key.toString(), descriptor.set) as (v: any) => void
42
+ // own
43
+ if (source === adm.target_) {
44
+ return adm.defineProperty_(key, {
45
+ configurable: globalState.safeDescriptors ? adm.isPlainObject_ : true,
46
+ set
47
+ }) === null
48
+ ? MakeResult.Cancel
49
+ : MakeResult.Continue
50
+ }
51
+ // proto
52
+ defineProperty(source, key, {
53
+ configurable: true,
54
+ set
55
+ })
56
+ return MakeResult.Continue
57
+ }
58
+ // function on proto -> autoAction/flow
59
+ if (source !== adm.target_ && typeof descriptor.value === "function") {
60
+ if (isGenerator(descriptor.value)) {
61
+ const flowAnnotation = this.options_?.autoBind ? flow.bound : flow
62
+ return flowAnnotation.make_(adm, key, descriptor, source)
63
+ }
64
+ const actionAnnotation = this.options_?.autoBind ? autoAction.bound : autoAction
65
+ return actionAnnotation.make_(adm, key, descriptor, source)
66
+ }
67
+ // other -> observable
68
+ // Copy props from proto as well, see test:
69
+ // "decorate should work with Object.create"
70
+ let observableAnnotation = this.options_?.deep === false ? observable.ref : observable
71
+ // if function respect autoBind option
72
+ if (typeof descriptor.value === "function" && this.options_?.autoBind) {
73
+ descriptor.value = descriptor.value.bind(adm.proxy_ ?? adm.target_)
74
+ }
75
+ return observableAnnotation.make_(adm, key, descriptor, source)
76
+ }
77
+
78
+ function extend_(
79
+ adm: ObservableObjectAdministration,
80
+ key: PropertyKey,
81
+ descriptor: PropertyDescriptor,
82
+ proxyTrap: boolean
83
+ ): boolean | null {
84
+ // getter -> computed
85
+ if (descriptor.get) {
86
+ return computed.extend_(adm, key, descriptor, proxyTrap)
87
+ }
88
+ // lone setter -> action setter
89
+ if (descriptor.set) {
90
+ // TODO make action applicable to setter and delegate to action.extend_
91
+ return adm.defineProperty_(
92
+ key,
93
+ {
94
+ configurable: globalState.safeDescriptors ? adm.isPlainObject_ : true,
95
+ set: createAction(key.toString(), descriptor.set) as (v: any) => void
96
+ },
97
+ proxyTrap
98
+ )
99
+ }
100
+ // other -> observable
101
+ // if function respect autoBind option
102
+ if (typeof descriptor.value === "function" && this.options_?.autoBind) {
103
+ descriptor.value = descriptor.value.bind(adm.proxy_ ?? adm.target_)
104
+ }
105
+ let observableAnnotation = this.options_?.deep === false ? observable.ref : observable
106
+ return observableAnnotation.extend_(adm, key, descriptor, proxyTrap)
107
+ }
@@ -1,12 +1,4 @@
1
- import {
2
- ObservableObjectAdministration,
3
- getDescriptor,
4
- objectPrototype,
5
- die,
6
- Annotation,
7
- recordAnnotationApplied,
8
- storedAnnotationsSymbol
9
- } from "../internal"
1
+ import { ObservableObjectAdministration, die, Annotation, MakeResult } from "../internal"
10
2
 
11
3
  export function createComputedAnnotation(name: string, options?: object): Annotation {
12
4
  return {
@@ -17,34 +9,12 @@ export function createComputedAnnotation(name: string, options?: object): Annota
17
9
  }
18
10
  }
19
11
 
20
- function make_(adm: ObservableObjectAdministration, key: PropertyKey): void {
21
- let source = adm.target_
22
- while (source && source !== objectPrototype) {
23
- const descriptor = getDescriptor(source, key)
24
- if (descriptor) {
25
- assertComputedDescriptor(adm, this, key, descriptor)
26
- const definePropertyOutcome = adm.defineComputedProperty_(key, {
27
- ...this.options_,
28
- get: descriptor.get,
29
- set: descriptor.set
30
- })
31
- if (!definePropertyOutcome) {
32
- // Intercepted
33
- return
34
- }
35
- recordAnnotationApplied(adm, this, key)
36
- return
37
- }
38
- source = Object.getPrototypeOf(source)
39
- }
40
- if (!adm.target_[storedAnnotationsSymbol]?.[key]) {
41
- // Throw on missing key, except for decorators:
42
- // Decorator annotations are collected from whole prototype chain.
43
- // When called from super() some props may not exist yet.
44
- // However we don't have to worry about missing prop,
45
- // because the decorator must have been applied to something.
46
- die(1, this.annotationType_, `${adm.name_}.${key.toString()}`)
47
- }
12
+ function make_(
13
+ adm: ObservableObjectAdministration,
14
+ key: PropertyKey,
15
+ descriptor: PropertyDescriptor
16
+ ): MakeResult {
17
+ return this.extend_(adm, key, descriptor, false) === null ? MakeResult.Cancel : MakeResult.Break
48
18
  }
49
19
 
50
20
  function extend_(
@@ -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
  },
@@ -61,11 +66,12 @@ const objectProxyTraps: ProxyHandler<any> = {
61
66
  // null (intercepted) -> true (success)
62
67
  return getAdm(target).defineProperty_(name, descriptor) ?? true
63
68
  },
64
- ownKeys(target: IIsObservableObject): PropertyKey[] {
65
- if (__DEV__ && globalState.trackingDerivation)
69
+ ownKeys(target: IIsObservableObject): ArrayLike<string | symbol> {
70
+ if (__DEV__ && globalState.trackingDerivation) {
66
71
  warnAboutProxyRequirement(
67
- "iterate keys to detect added / removed properties. Use `keys` from 'mobx' instead."
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) {
@@ -2,15 +2,13 @@ import {
2
2
  ObservableObjectAdministration,
3
3
  Annotation,
4
4
  defineProperty,
5
- getDescriptor,
6
- objectPrototype,
7
5
  die,
8
6
  flow,
9
7
  isFlow,
10
- recordAnnotationApplied,
11
8
  isFunction,
12
9
  globalState,
13
- storedAnnotationsSymbol
10
+ MakeResult,
11
+ hasProp
14
12
  } from "../internal"
15
13
 
16
14
  export function createFlowAnnotation(name: string, options?: object): Annotation {
@@ -22,44 +20,33 @@ export function createFlowAnnotation(name: string, options?: object): Annotation
22
20
  }
23
21
  }
24
22
 
25
- function make_(adm: ObservableObjectAdministration, key: PropertyKey): void {
26
- let annotated = false
27
- let source = adm.target_
28
- while (source && source !== objectPrototype) {
29
- const descriptor = getDescriptor(source, key)
30
- if (descriptor) {
31
- if (source !== adm.target_) {
32
- // Prototype
33
- if (isFlow(descriptor.value)) {
34
- // A prototype could have been annotated already by other constructor,
35
- // rest of the proto chain must be annotated already
36
- annotated = true
37
- break
38
- }
39
- const flowDescriptor = createFlowDescriptor(adm, this, key, descriptor, false)
40
- defineProperty(source, key, flowDescriptor)
41
- } else {
42
- const flowDescriptor = createFlowDescriptor(adm, this, key, descriptor)
43
- const definePropertyOutcome = adm.defineProperty_(key, flowDescriptor)
44
- if (!definePropertyOutcome) {
45
- // Intercepted
46
- return
47
- }
48
- }
49
- annotated = true
23
+ function make_(
24
+ adm: ObservableObjectAdministration,
25
+ key: PropertyKey,
26
+ descriptor: PropertyDescriptor,
27
+ source: object
28
+ ): MakeResult {
29
+ // own
30
+ if (source === adm.target_) {
31
+ return this.extend_(adm, key, descriptor, false) === null
32
+ ? MakeResult.Cancel
33
+ : MakeResult.Continue
34
+ }
35
+ // prototype
36
+ // bound - must annotate protos to support super.flow()
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
50
40
  }
51
- source = Object.getPrototypeOf(source)
52
41
  }
53
- if (annotated) {
54
- recordAnnotationApplied(adm, this, key)
55
- } else if (!adm.target_[storedAnnotationsSymbol]?.[key]) {
56
- // Throw on missing key, except for decorators:
57
- // Decorator annotations are collected from whole prototype chain.
58
- // When called from super() some props may not exist yet.
59
- // However we don't have to worry about missing prop,
60
- // because the decorator must have been applied to something.
61
- die(1, this.annotationType_, `${adm.name_}.${key.toString()}`)
42
+ if (isFlow(descriptor.value)) {
43
+ // A prototype could have been annotated already by other constructor,
44
+ // rest of the proto chain must be annotated already
45
+ return MakeResult.Break
62
46
  }
47
+ const flowDescriptor = createFlowDescriptor(adm, this, key, descriptor, false, false)
48
+ defineProperty(source, key, flowDescriptor)
49
+ return MakeResult.Continue
63
50
  }
64
51
 
65
52
  function extend_(
@@ -68,7 +55,7 @@ function extend_(
68
55
  descriptor: PropertyDescriptor,
69
56
  proxyTrap: boolean
70
57
  ): boolean | null {
71
- const flowDescriptor = createFlowDescriptor(adm, this, key, descriptor)
58
+ const flowDescriptor = createFlowDescriptor(adm, this, key, descriptor, this.options_?.bound)
72
59
  return adm.defineProperty_(key, flowDescriptor, proxyTrap)
73
60
  }
74
61
 
@@ -91,12 +78,24 @@ function createFlowDescriptor(
91
78
  annotation: Annotation,
92
79
  key: PropertyKey,
93
80
  descriptor: PropertyDescriptor,
81
+ bound: boolean,
94
82
  // provides ability to disable safeDescriptors for prototypes
95
83
  safeDescriptors: boolean = globalState.safeDescriptors
96
84
  ): PropertyDescriptor {
97
85
  assertFlowDescriptor(adm, annotation, key, descriptor)
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
+ }
91
+ if (bound) {
92
+ // We do not keep original function around, so we bind the existing flow
93
+ value = value.bind(adm.proxy_ ?? adm.target_)
94
+ // This is normally set by `flow`, but `bind` returns new function...
95
+ value.isMobXFlow = true
96
+ }
98
97
  return {
99
- value: flow(descriptor.value),
98
+ value,
100
99
  // Non-configurable for classes
101
100
  // prevents accidental field redefinition in subclass
102
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 {
@@ -14,6 +14,21 @@ import {
14
14
  defineProperty
15
15
  } from "../internal"
16
16
 
17
+ // Bug in safari 9.* (or iOS 9 safari mobile). See #364
18
+ const ENTRY_0 = createArrayEntryDescriptor(0)
19
+
20
+ const safariPrototypeSetterInheritanceBug = (() => {
21
+ let v = false
22
+ const p = {}
23
+ Object.defineProperty(p, "0", {
24
+ set: () => {
25
+ v = true
26
+ }
27
+ })
28
+ Object.create(p)["0"] = 1
29
+ return v === false
30
+ })()
31
+
17
32
  /**
18
33
  * This array buffer contains two lists of properties, so that all arrays
19
34
  * can recycle their property definitions, which significantly improves performance of creating
@@ -57,6 +72,12 @@ class LegacyObservableArray<T> extends StubArray {
57
72
  this.spliceWithArray(0, 0, initialValues)
58
73
  allowStateChangesEnd(prev)
59
74
  }
75
+
76
+ if (safariPrototypeSetterInheritanceBug) {
77
+ // Seems that Safari won't use numeric prototype setter untill any * numeric property is
78
+ // defined on the instance. After that it works fine, even if this property is deleted.
79
+ Object.defineProperty(this, "0", ENTRY_0)
80
+ }
60
81
  }
61
82
 
62
83
  concat(...arrays: T[][]): T[] {
@@ -85,7 +106,6 @@ class LegacyObservableArray<T> extends StubArray {
85
106
  let nextIndex = 0
86
107
  return makeIterable({
87
108
  next() {
88
- // @ts-ignore
89
109
  return nextIndex < self.length
90
110
  ? { value: self[nextIndex++], done: false }
91
111
  : { done: true, value: undefined }
@@ -95,7 +115,9 @@ class LegacyObservableArray<T> extends StubArray {
95
115
  }
96
116
 
97
117
  Object.entries(arrayExtensions).forEach(([prop, fn]) => {
98
- if (prop !== "concat") addHiddenProp(LegacyObservableArray.prototype, prop, fn)
118
+ if (prop !== "concat") {
119
+ addHiddenProp(LegacyObservableArray.prototype, prop, fn)
120
+ }
99
121
  })
100
122
 
101
123
  function createArrayEntryDescriptor(index: number) {
@@ -117,8 +139,9 @@ function createArrayBufferItem(index: number) {
117
139
 
118
140
  export function reserveArrayBuffer(max: number) {
119
141
  if (max > OBSERVABLE_ARRAY_BUFFER_SIZE) {
120
- for (let index = OBSERVABLE_ARRAY_BUFFER_SIZE; index < max + 100; index++)
142
+ for (let index = OBSERVABLE_ARRAY_BUFFER_SIZE; index < max + 100; index++) {
121
143
  createArrayBufferItem(index)
144
+ }
122
145
  OBSERVABLE_ARRAY_BUFFER_SIZE = max
123
146
  }
124
147
  }
@@ -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)