mobx 6.16.1 → 7.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/README.md +9 -13
  3. package/dist/api/action.d.ts +6 -4
  4. package/dist/api/annotation.d.ts +0 -1
  5. package/dist/api/computed.d.ts +4 -7
  6. package/dist/api/configure.d.ts +0 -1
  7. package/dist/api/decoratorannotation.d.ts +3 -0
  8. package/dist/api/decorators.d.ts +0 -19
  9. package/dist/api/flow.d.ts +4 -5
  10. package/dist/api/makeObservable.d.ts +2 -3
  11. package/dist/api/observable.d.ts +9 -15
  12. package/dist/core/atom.d.ts +1 -4
  13. package/dist/core/computedvalue.d.ts +5 -33
  14. package/dist/core/derivation.d.ts +1 -7
  15. package/dist/core/globalstate.d.ts +7 -2
  16. package/dist/core/observable.d.ts +9 -1
  17. package/dist/core/reaction.d.ts +1 -9
  18. package/dist/errors.d.ts +6 -4
  19. package/dist/internal.d.ts +1 -4
  20. package/dist/mobx.cjs.development.js +1704 -2484
  21. package/dist/mobx.cjs.development.js.map +1 -1
  22. package/dist/mobx.cjs.production.min.js +1 -1
  23. package/dist/mobx.cjs.production.min.js.map +1 -1
  24. package/dist/mobx.d.ts +2 -2
  25. package/dist/mobx.esm.development.js +1693 -2483
  26. package/dist/mobx.esm.development.js.map +1 -1
  27. package/dist/mobx.esm.js +1643 -2436
  28. package/dist/mobx.esm.js.map +1 -1
  29. package/dist/mobx.esm.production.min.js +1 -1
  30. package/dist/mobx.esm.production.min.js.map +1 -1
  31. package/dist/mobx.mjs +5308 -0
  32. package/dist/mobx.mjs.map +1 -0
  33. package/dist/mobx.umd.development.js +1707 -2487
  34. package/dist/mobx.umd.development.js.map +1 -1
  35. package/dist/mobx.umd.production.min.js +1 -1
  36. package/dist/mobx.umd.production.min.js.map +1 -1
  37. package/dist/types/actionannotation.d.ts +1 -0
  38. package/dist/types/computedannotation.d.ts +1 -0
  39. package/dist/types/decorator_fills.d.ts +2 -0
  40. package/dist/types/flowannotation.d.ts +1 -0
  41. package/dist/types/observableannotation.d.ts +5 -0
  42. package/dist/types/observablearray.d.ts +2 -5
  43. package/dist/types/observablemap.d.ts +1 -8
  44. package/dist/types/observableobject.d.ts +2 -13
  45. package/dist/types/observableset.d.ts +1 -3
  46. package/dist/types/observablevalue.d.ts +4 -6
  47. package/dist/types/overrideannotation.d.ts +1 -2
  48. package/dist/utils/comparer.d.ts +4 -11
  49. package/dist/utils/utils.d.ts +0 -2
  50. package/package.json +25 -15
  51. package/src/api/action.ts +27 -35
  52. package/src/api/annotation.ts +0 -1
  53. package/src/api/autorun.ts +2 -4
  54. package/src/api/computed.ts +21 -28
  55. package/src/api/configure.ts +1 -15
  56. package/src/api/decoratorannotation.ts +20 -0
  57. package/src/api/decorators.ts +1 -85
  58. package/src/api/extras.ts +1 -1
  59. package/src/api/flow.ts +26 -29
  60. package/src/api/intercept.ts +4 -3
  61. package/src/api/makeObservable.ts +45 -17
  62. package/src/api/object-api.ts +1 -1
  63. package/src/api/observable.ts +34 -67
  64. package/src/api/observe.ts +82 -3
  65. package/src/api/when.ts +4 -3
  66. package/src/core/action.ts +12 -5
  67. package/src/core/atom.ts +16 -14
  68. package/src/core/computedvalue.ts +36 -69
  69. package/src/core/derivation.ts +16 -15
  70. package/src/core/globalstate.ts +16 -13
  71. package/src/core/observable.ts +65 -73
  72. package/src/core/reaction.ts +19 -25
  73. package/src/core/spy.ts +3 -3
  74. package/src/errors.ts +23 -12
  75. package/src/internal.ts +1 -4
  76. package/src/mobx.ts +21 -10
  77. package/src/types/actionannotation.ts +5 -9
  78. package/src/types/autoannotation.ts +8 -11
  79. package/src/types/computedannotation.ts +13 -11
  80. package/src/types/decorator_fills.ts +4 -0
  81. package/src/types/dynamicobject.ts +0 -29
  82. package/src/types/flowannotation.ts +7 -4
  83. package/src/types/modifiers.ts +5 -0
  84. package/src/types/observableannotation.ts +6 -7
  85. package/src/types/observablearray.ts +8 -61
  86. package/src/types/observablemap.ts +4 -29
  87. package/src/types/observableobject.ts +5 -70
  88. package/src/types/observableset.ts +9 -52
  89. package/src/types/observablevalue.ts +7 -29
  90. package/src/types/overrideannotation.ts +7 -22
  91. package/src/types/type-utils.ts +4 -2
  92. package/src/utils/comparer.ts +4 -17
  93. package/src/utils/iterable.ts +3 -4
  94. package/src/utils/utils.ts +4 -46
  95. package/dist/api/trace.d.ts +0 -3
  96. package/dist/types/legacyobservablearray.d.ts +0 -14
  97. package/dist/utils/global.d.ts +0 -1
  98. package/src/api/trace.ts +0 -35
  99. package/src/types/legacyobservablearray.ts +0 -155
  100. package/src/utils/global.ts +0 -20
package/src/api/flow.ts CHANGED
@@ -4,13 +4,11 @@ import {
4
4
  die,
5
5
  isFunction,
6
6
  Annotation,
7
- isStringish,
8
- storeAnnotation,
9
7
  createFlowAnnotation,
10
- createDecoratorAnnotation,
11
- is20223Decorator
8
+ decorateFlow20223_,
9
+ assign
12
10
  } from "../internal"
13
-
11
+ import { createDecoratorAnnotation, type DecoratorAnnotation } from "./decoratorannotation"
14
12
  import type { ClassMethodDecorator } from "../types/decorator_fills"
15
13
 
16
14
  export const FLOW = "flow"
@@ -35,46 +33,44 @@ export function isFlowCancellationError(error: Error) {
35
33
 
36
34
  export type CancellablePromise<T> = Promise<T> & { cancel(): void }
37
35
 
38
- type FlowGenerator = (...args: any[]) => Generator<any, any, any> | AsyncGenerator<any, any, any>
36
+ function createFlowDecoratorAnnotation(
37
+ annotation: Annotation
38
+ ): DecoratorAnnotation<ClassMethodDecorator> {
39
+ return createDecoratorAnnotation(annotation, decorateFlow20223_)
40
+ }
39
41
 
40
- // PropertyDecorator is only for legacy decorators
41
- interface Flow extends Annotation, PropertyDecorator {
42
- <This, Value extends FlowGenerator>(
43
- value: Value,
44
- context: ClassMethodDecoratorContext<This, Value>
45
- ): Value | void
42
+ interface Flow extends Annotation, ClassMethodDecorator {
46
43
  <R, Args extends any[]>(
47
- generator: (...args: Args) => Generator<any, R, any> | AsyncGenerator<any, R, any>
44
+ generator: (...args: Args) => Generator<any, R, any> | AsyncGenerator<any, R, any>,
45
+ context?: never
48
46
  ): (...args: Args) => CancellablePromise<R>
49
- bound: Annotation & PropertyDecorator & ClassMethodDecorator
50
47
  }
51
48
 
52
49
  const flowAnnotation = createFlowAnnotation("flow")
53
50
  const flowBoundAnnotation = createFlowAnnotation("flow.bound", { bound: true })
54
51
 
55
- export const flow: Flow = Object.assign(
52
+ export const flow: Flow = assign(
56
53
  function flow(arg1, arg2?) {
57
- // @flow (2022.3 Decorators)
58
- if (is20223Decorator(arg2)) {
59
- return flowAnnotation.decorate_20223_(arg1, arg2)
60
- }
61
- // @flow
62
- if (isStringish(arg2)) {
63
- return storeAnnotation(arg1, arg2, flowAnnotation)
54
+ if (arg2 && typeof arg2.kind === "string") {
55
+ return decorateFlow20223_(flowAnnotation, arg1, arg2)
64
56
  }
57
+
65
58
  // flow(fn)
66
59
  if (__DEV__ && arguments.length !== 1) {
67
60
  die(`Flow expects single argument with generator function`)
68
61
  }
69
62
  const generator = arg1
70
- const name = generator.name || "<unnamed flow>"
63
+ const name = generator.name || (__DEV__ ? "<unnamed flow>" : "flow")
71
64
 
72
65
  // Implementation based on https://github.com/tj/co/blob/master/index.js
73
66
  const res = function () {
74
67
  const ctx = this
75
68
  const args = arguments
76
- const runId = ++generatorId
77
- const gen = action(`${name} - runid: ${runId} - init`, generator).apply(ctx, args)
69
+ const runId = __DEV__ ? ++generatorId : 0
70
+ const gen = action(
71
+ __DEV__ ? `${name} - runid: ${runId} - init` : name,
72
+ generator
73
+ ).apply(ctx, args)
78
74
  let rejector: (error: any) => void
79
75
  let pendingPromise: CancellablePromise<any> | undefined = undefined
80
76
 
@@ -87,7 +83,7 @@ export const flow: Flow = Object.assign(
87
83
  let ret
88
84
  try {
89
85
  ret = action(
90
- `${name} - runid: ${runId} - yield ${stepId++}`,
86
+ __DEV__ ? `${name} - runid: ${runId} - yield ${stepId++}` : name,
91
87
  gen.next
92
88
  ).call(gen, res)
93
89
  } catch (e) {
@@ -102,7 +98,7 @@ export const flow: Flow = Object.assign(
102
98
  let ret
103
99
  try {
104
100
  ret = action(
105
- `${name} - runid: ${runId} - yield ${stepId++}`,
101
+ __DEV__ ? `${name} - runid: ${runId} - yield ${stepId++}` : name,
106
102
  gen.throw!
107
103
  ).call(gen, err)
108
104
  } catch (e) {
@@ -127,7 +123,8 @@ export const flow: Flow = Object.assign(
127
123
  onFulfilled(undefined) // kick off the process
128
124
  }) as any
129
125
 
130
- promise.cancel = action(`${name} - runid: ${runId} - cancel`, function () {
126
+ const cancelActionName = __DEV__ ? `${name} - runid: ${runId} - cancel` : name
127
+ promise.cancel = action(cancelActionName, function () {
131
128
  try {
132
129
  if (pendingPromise) {
133
130
  cancelPromise(pendingPromise)
@@ -152,7 +149,7 @@ export const flow: Flow = Object.assign(
152
149
  flowAnnotation
153
150
  )
154
151
 
155
- flow.bound = createDecoratorAnnotation(flowBoundAnnotation)
152
+ export const flowBound = createFlowDecoratorAnnotation(flowBoundAnnotation)
156
153
 
157
154
  function cancelPromise(promise) {
158
155
  if (isFunction(promise.cancel)) {
@@ -12,7 +12,8 @@ import {
12
12
  getAdministration,
13
13
  ObservableSet,
14
14
  ISetWillChange,
15
- isFunction
15
+ isFunction,
16
+ registerInterceptor
16
17
  } from "../internal"
17
18
 
18
19
  export function intercept<T>(
@@ -51,9 +52,9 @@ export function intercept(thing, propOrHandler?, handler?): Lambda {
51
52
  }
52
53
 
53
54
  function interceptInterceptable(thing, handler) {
54
- return getAdministration(thing).intercept_(handler)
55
+ return registerInterceptor(getAdministration(thing), handler)
55
56
  }
56
57
 
57
58
  function interceptProperty(thing, property, handler) {
58
- return getAdministration(thing, property).intercept_(handler)
59
+ return registerInterceptor(getAdministration(thing, property), handler)
59
60
  }
@@ -4,15 +4,19 @@ import {
4
4
  AnnotationsMap,
5
5
  CreateObservableOptions,
6
6
  ObservableObjectAdministration,
7
- collectStoredAnnotations,
8
7
  isPlainObject,
9
8
  isObservableObject,
10
9
  die,
11
10
  ownKeys,
12
11
  extendObservable,
13
12
  addHiddenProp,
14
- storedAnnotationsSymbol,
15
- initObservable
13
+ initObservable,
14
+ Annotation,
15
+ assertAnnotable,
16
+ getDescriptor,
17
+ MakeResult,
18
+ objectPrototype,
19
+ recordAnnotationApplied
16
20
  } from "../internal"
17
21
 
18
22
  // Hack based on https://github.com/Microsoft/TypeScript/issues/14829#issuecomment-322267089
@@ -22,25 +26,16 @@ import {
22
26
  // Fixes: https://github.com/mobxjs/mobx/issues/2325#issuecomment-691070022
23
27
  type NoInfer<T> = [T][T extends any ? 0 : never]
24
28
 
25
- type MakeObservableOptions = Omit<CreateObservableOptions, "proxy">
26
-
27
29
  export function makeObservable<T extends object, AdditionalKeys extends PropertyKey = never>(
28
30
  target: T,
29
- annotations?: AnnotationsMap<T, NoInfer<AdditionalKeys>>,
30
- options?: MakeObservableOptions
31
+ annotations: AnnotationsMap<T, NoInfer<AdditionalKeys>>,
32
+ options?: CreateObservableOptions
31
33
  ): T {
32
34
  initObservable(() => {
33
35
  const adm: ObservableObjectAdministration = asObservableObject(target, options)[$mobx]
34
- if (__DEV__ && annotations && target[storedAnnotationsSymbol]) {
35
- die(
36
- `makeObservable second arg must be nullish when using decorators. Mixing @decorator syntax with annotations is not supported.`
37
- )
38
- }
39
- // Default to decorators
40
- annotations ??= collectStoredAnnotations(target)
41
36
 
42
37
  // Annotate
43
- ownKeys(annotations).forEach(key => adm.make_(key, annotations![key]))
38
+ ownKeys(annotations).forEach(key => make_(adm, key, annotations[key]))
44
39
  })
45
40
  return target
46
41
  }
@@ -51,7 +46,7 @@ const keysSymbol = Symbol("mobx-keys")
51
46
  export function makeAutoObservable<T extends object, AdditionalKeys extends PropertyKey = never>(
52
47
  target: T,
53
48
  overrides?: AnnotationsMap<T, NoInfer<AdditionalKeys>>,
54
- options?: MakeObservableOptions
49
+ options?: CreateObservableOptions
55
50
  ): T {
56
51
  if (__DEV__) {
57
52
  if (!isPlainObject(target) && !isPlainObject(Object.getPrototypeOf(target))) {
@@ -82,7 +77,8 @@ export function makeAutoObservable<T extends object, AdditionalKeys extends Prop
82
77
  }
83
78
 
84
79
  target[keysSymbol].forEach(key =>
85
- adm.make_(
80
+ make_(
81
+ adm,
86
82
  key,
87
83
  // must pass "undefined" for { key: undefined }
88
84
  !overrides ? true : key in overrides ? overrides[key] : true
@@ -92,3 +88,35 @@ export function makeAutoObservable<T extends object, AdditionalKeys extends Prop
92
88
 
93
89
  return target
94
90
  }
91
+
92
+ function make_(
93
+ adm: ObservableObjectAdministration,
94
+ key: PropertyKey,
95
+ annotation: Annotation | boolean
96
+ ) {
97
+ if (annotation === true) {
98
+ annotation = adm.defaultAnnotation_
99
+ }
100
+ if (annotation === false) {
101
+ return
102
+ }
103
+ assertAnnotable(adm, annotation, key)
104
+ if (!(key in adm.target_)) {
105
+ die(1, annotation.annotationType_, `${adm.name_}.${key.toString()}`)
106
+ }
107
+ let source = adm.target_
108
+ while (source && source !== objectPrototype) {
109
+ const descriptor = getDescriptor(source, key)
110
+ if (descriptor) {
111
+ const outcome = annotation.make_(adm, key, descriptor, source)
112
+ if (outcome === MakeResult.Cancel) {
113
+ return
114
+ }
115
+ if (outcome === MakeResult.Break) {
116
+ break
117
+ }
118
+ }
119
+ source = Object.getPrototypeOf(source)
120
+ }
121
+ recordAnnotationApplied(adm, annotation, key)
122
+ }
@@ -105,7 +105,7 @@ export function set(obj: any, key: any, value?: any): void {
105
105
  key = parseInt(key, 10)
106
106
  }
107
107
  if (key < 0) {
108
- die(`Invalid index: '${key}'`)
108
+ die(42, key)
109
109
  }
110
110
  startBatch()
111
111
  if (key >= obj.length) {
@@ -24,20 +24,14 @@ import {
24
24
  shallowEnhancer,
25
25
  refStructEnhancer,
26
26
  AnnotationsMap,
27
- asObservableObject,
28
- storeAnnotation,
29
- createDecoratorAnnotation,
30
- createLegacyArray,
31
- globalState,
32
27
  assign,
33
- isStringish,
34
28
  createObservableAnnotation,
35
29
  createAutoAnnotation,
36
- is20223Decorator,
37
- initObservable
30
+ initObservable,
31
+ decorateObservable20223_
38
32
  } from "../internal"
39
-
40
- import type { ClassAccessorDecorator, ClassFieldDecorator } from "../types/decorator_fills"
33
+ import { createDecoratorAnnotation, type DecoratorAnnotation } from "./decoratorannotation"
34
+ import type { ClassAccessorAndFieldDecorator } from "../types/decorator_fills"
41
35
 
42
36
  export const OBSERVABLE = "observable"
43
37
  export const OBSERVABLE_REF = "observable.ref"
@@ -49,7 +43,6 @@ export type CreateObservableOptions = {
49
43
  equals?: IEqualsComparer<any>
50
44
  deep?: boolean
51
45
  defaultDecorator?: Annotation
52
- proxy?: boolean
53
46
  autoBind?: boolean
54
47
  }
55
48
 
@@ -58,8 +51,7 @@ export type CreateObservableOptions = {
58
51
  export const defaultCreateObservableOptions: CreateObservableOptions = {
59
52
  deep: true,
60
53
  name: undefined,
61
- defaultDecorator: undefined,
62
- proxy: true
54
+ defaultDecorator: undefined
63
55
  }
64
56
  Object.freeze(defaultCreateObservableOptions)
65
57
 
@@ -69,16 +61,20 @@ export function asCreateObservableOptions(thing: any): CreateObservableOptions {
69
61
 
70
62
  const observableAnnotation = createObservableAnnotation(OBSERVABLE)
71
63
  const observableRefAnnotation = createObservableAnnotation(OBSERVABLE_REF, {
72
- enhancer: referenceEnhancer
64
+ enhancer_: referenceEnhancer
73
65
  })
74
66
  const observableShallowAnnotation = createObservableAnnotation(OBSERVABLE_SHALLOW, {
75
- enhancer: shallowEnhancer
67
+ enhancer_: shallowEnhancer
76
68
  })
77
69
  const observableStructAnnotation = createObservableAnnotation(OBSERVABLE_STRUCT, {
78
- enhancer: refStructEnhancer
70
+ enhancer_: refStructEnhancer
79
71
  })
80
- const observableDecoratorAnnotation =
81
- createDecoratorAnnotation<ClassAccessorDecorator>(observableAnnotation)
72
+
73
+ function createObservableDecoratorAnnotation(
74
+ annotation: Annotation
75
+ ): DecoratorAnnotation<ClassAccessorAndFieldDecorator> {
76
+ return createDecoratorAnnotation(annotation, decorateObservable20223_)
77
+ }
82
78
 
83
79
  export function getEnhancerFromOptions(options: CreateObservableOptions): IEnhancer<any> {
84
80
  return options.deep === true
@@ -95,7 +91,7 @@ export function getAnnotationFromOptions(
95
91
  }
96
92
 
97
93
  export function getEnhancerFromAnnotation(annotation?: Annotation): IEnhancer<any> {
98
- return !annotation ? deepEnhancer : annotation.options_?.enhancer ?? deepEnhancer
94
+ return !annotation ? deepEnhancer : annotation.options_?.enhancer_ ?? deepEnhancer
99
95
  }
100
96
 
101
97
  /**
@@ -103,15 +99,8 @@ export function getEnhancerFromAnnotation(annotation?: Annotation): IEnhancer<an
103
99
  * @param v the value which should become observable.
104
100
  */
105
101
  function createObservable(v: any, arg2?: any, arg3?: any) {
106
- // @observable someProp; (2022.3 Decorators)
107
- if (is20223Decorator(arg2)) {
108
- return observableAnnotation.decorate_20223_(v, arg2)
109
- }
110
-
111
- // @observable someProp;
112
- if (isStringish(arg2)) {
113
- storeAnnotation(v, arg2, observableAnnotation)
114
- return
102
+ if (arg2 && typeof arg2.kind === "string") {
103
+ return decorateObservable20223_(observableAnnotation, v, arg2)
115
104
  }
116
105
 
117
106
  // already observable - ignore
@@ -147,7 +136,6 @@ function createObservable(v: any, arg2?: any, arg3?: any) {
147
136
  // anything else
148
137
  return observable.box(v, arg2)
149
138
  }
150
- assign(createObservable, observableDecoratorAnnotation)
151
139
 
152
140
  export interface IObservableValueFactory {
153
141
  <T>(value: T, options?: CreateObservableOptions): IObservableValue<T>
@@ -172,18 +160,13 @@ export interface IObservableMapFactory {
172
160
  >
173
161
  }
174
162
 
175
- export interface IObservableFactory
176
- extends Annotation,
177
- PropertyDecorator,
178
- ClassAccessorDecorator,
179
- ClassFieldDecorator {
180
- // TODO: remove ClassFieldDecorator, this is only temporarily support for legacy decorators
163
+ export interface IObservableFactory extends Annotation, ClassAccessorAndFieldDecorator {
181
164
  <T = any>(value: T[], options?: CreateObservableOptions): IObservableArray<T>
182
165
  <T = any>(value: Set<T>, options?: CreateObservableOptions): ObservableSet<T>
183
166
  <K = any, V = any>(value: Map<K, V>, options?: CreateObservableOptions): ObservableMap<K, V>
184
167
  <T extends object>(
185
168
  value: T,
186
- decorators?: AnnotationsMap<T, never>,
169
+ annotations?: AnnotationsMap<T, never>,
187
170
  options?: CreateObservableOptions
188
171
  ): T
189
172
 
@@ -196,20 +179,9 @@ export interface IObservableFactory
196
179
  map: IObservableMapFactory
197
180
  object: <T = any>(
198
181
  props: T,
199
- decorators?: AnnotationsMap<T, never>,
182
+ annotations?: AnnotationsMap<T, never>,
200
183
  options?: CreateObservableOptions
201
184
  ) => T
202
-
203
- /**
204
- * Decorator that creates an observable that only observes the references, but doesn't try to turn the assigned value into an observable.ts.
205
- */
206
- ref: Annotation & PropertyDecorator & ClassAccessorDecorator & ClassFieldDecorator
207
- /**
208
- * Decorator that creates an observable converts its value (objects, maps or arrays) into a shallow observable structure
209
- */
210
- shallow: Annotation & PropertyDecorator & ClassAccessorDecorator & ClassFieldDecorator
211
- deep: Annotation & PropertyDecorator & ClassAccessorDecorator & ClassFieldDecorator
212
- struct: Annotation & PropertyDecorator & ClassAccessorDecorator & ClassFieldDecorator
213
185
  }
214
186
 
215
187
  const observableFactories: IObservableFactory = {
@@ -219,11 +191,7 @@ const observableFactories: IObservableFactory = {
219
191
  },
220
192
  array<T = any>(initialValues?: T[], options?: CreateObservableOptions): IObservableArray<T> {
221
193
  const o = asCreateObservableOptions(options)
222
- return (
223
- globalState.useProxies === false || o.proxy === false
224
- ? createLegacyArray
225
- : createObservableArray
226
- )(initialValues, getEnhancerFromOptions(o), o.name)
194
+ return createObservableArray(initialValues, getEnhancerFromOptions(o), o.name)
227
195
  },
228
196
  map<K = any, V = any>(
229
197
  initialValues?: IObservableMapInitialValues<K, V>,
@@ -241,24 +209,23 @@ const observableFactories: IObservableFactory = {
241
209
  },
242
210
  object<T extends object = any>(
243
211
  props: T,
244
- decorators?: AnnotationsMap<T, never>,
212
+ annotations?: AnnotationsMap<T, never>,
245
213
  options?: CreateObservableOptions
246
214
  ): T {
247
215
  return initObservable(() =>
248
- extendObservable(
249
- globalState.useProxies === false || options?.proxy === false
250
- ? asObservableObject({}, options)
251
- : asDynamicObservableObject({}, options),
252
- props,
253
- decorators
254
- )
216
+ extendObservable(asDynamicObservableObject({}, options), props, annotations)
255
217
  )
256
- },
257
- ref: createDecoratorAnnotation(observableRefAnnotation),
258
- shallow: createDecoratorAnnotation(observableShallowAnnotation),
259
- deep: observableDecoratorAnnotation,
260
- struct: createDecoratorAnnotation(observableStructAnnotation)
218
+ }
261
219
  } as any
262
220
 
221
+ export const observableRef = createObservableDecoratorAnnotation(observableRefAnnotation)
222
+ export const observableShallow = createObservableDecoratorAnnotation(observableShallowAnnotation)
223
+ export const observableDeep = createObservableDecoratorAnnotation(observableAnnotation)
224
+ export const observableStruct = createObservableDecoratorAnnotation(observableStructAnnotation)
225
+
263
226
  // eslint-disable-next-line
264
- export var observable: IObservableFactory = assign(createObservable, observableFactories)
227
+ export var observable: IObservableFactory = assign(
228
+ createObservable,
229
+ observableAnnotation,
230
+ observableFactories
231
+ )
@@ -11,7 +11,18 @@ import {
11
11
  getAdministration,
12
12
  ObservableSet,
13
13
  ISetDidChange,
14
- isFunction
14
+ isFunction,
15
+ isComputedValue,
16
+ isObservableArray,
17
+ isObservableMap,
18
+ isObservableObject,
19
+ isObservableSet,
20
+ autorun,
21
+ registerListener,
22
+ untrackedEnd,
23
+ untrackedStart,
24
+ UPDATE,
25
+ die
15
26
  } from "../internal"
16
27
 
17
28
  export function observe<T>(
@@ -61,9 +72,77 @@ export function observe(thing, propOrCb?, cbOrFire?, fireImmediately?): Lambda {
61
72
  }
62
73
 
63
74
  function observeObservable(thing, listener, fireImmediately: boolean) {
64
- return getAdministration(thing).observe_(listener, fireImmediately)
75
+ const adm = getAdministration(thing)
76
+
77
+ if (isObservableArray(thing)) {
78
+ if (fireImmediately) {
79
+ listener({
80
+ observableKind: "array",
81
+ object: adm.proxy_,
82
+ debugObjectName: adm.atom_.name_,
83
+ type: "splice",
84
+ index: 0,
85
+ added: adm.values_.slice(),
86
+ addedCount: adm.values_.length,
87
+ removed: [],
88
+ removedCount: 0
89
+ })
90
+ }
91
+ } else if (isObservableMap(thing)) {
92
+ if (__DEV__ && fireImmediately === true) {
93
+ die("`observe` doesn't support fireImmediately=true in combination with maps.")
94
+ }
95
+ } else if (isObservableSet(thing)) {
96
+ if (__DEV__ && fireImmediately === true) {
97
+ die("`observe` doesn't support fireImmediately=true in combination with sets.")
98
+ }
99
+ } else if (isObservableObject(thing)) {
100
+ if (__DEV__ && fireImmediately === true) {
101
+ die("`observe` doesn't support the fire immediately property for observable objects.")
102
+ }
103
+ } else {
104
+ return observeValue(adm, listener, fireImmediately)
105
+ }
106
+
107
+ return registerListener(adm, listener)
65
108
  }
66
109
 
67
110
  function observeObservableProperty(thing, property, listener, fireImmediately: boolean) {
68
- return getAdministration(thing, property).observe_(listener, fireImmediately)
111
+ return observeValue(getAdministration(thing, property), listener, fireImmediately)
112
+ }
113
+
114
+ function observeValue(adm, listener, fireImmediately: boolean) {
115
+ if (isComputedValue(adm)) {
116
+ let firstTime = true
117
+ let prevValue: any = undefined
118
+ return autorun(() => {
119
+ const newValue = adm.get()
120
+ if (!firstTime || fireImmediately) {
121
+ const prevU = untrackedStart()
122
+ listener({
123
+ observableKind: "computed",
124
+ debugObjectName: adm.name_,
125
+ type: UPDATE,
126
+ object: adm,
127
+ newValue,
128
+ oldValue: prevValue
129
+ })
130
+ untrackedEnd(prevU)
131
+ }
132
+ firstTime = false
133
+ prevValue = newValue
134
+ })
135
+ }
136
+
137
+ if (fireImmediately) {
138
+ listener({
139
+ observableKind: "value",
140
+ debugObjectName: adm.name_,
141
+ object: adm,
142
+ type: UPDATE,
143
+ newValue: adm.value_,
144
+ oldValue: undefined
145
+ })
146
+ }
147
+ return registerListener(adm, listener)
69
148
  }
package/src/api/when.ts CHANGED
@@ -7,7 +7,8 @@ import {
7
7
  getNextId,
8
8
  die,
9
9
  allowStateChanges,
10
- GenericAbortSignal
10
+ GenericAbortSignal,
11
+ assign
11
12
  } from "../internal"
12
13
 
13
14
  export interface IWhenOptions {
@@ -77,12 +78,12 @@ function whenPromise(
77
78
  return die(`the options 'onError' and 'promise' cannot be combined`)
78
79
  }
79
80
  if (opts?.signal?.aborted) {
80
- return Object.assign(Promise.reject(new Error("WHEN_ABORTED")), { cancel: () => null })
81
+ return assign(Promise.reject(new Error("WHEN_ABORTED")), { cancel: () => null })
81
82
  }
82
83
  let cancel
83
84
  let abort
84
85
  const res = new Promise((resolve, reject) => {
85
- let disposer = _when(predicate, resolve as Lambda, { ...opts, onError: reject })
86
+ let disposer = _when(predicate, resolve as Lambda, assign({}, opts, { onError: reject }))
86
87
  cancel = () => {
87
88
  disposer()
88
89
  reject(new Error("WHEN_CANCELLED"))
@@ -96,7 +96,7 @@ export function _startAction(
96
96
  ): IActionRunInfo {
97
97
  const notifySpy_ = __DEV__ && isSpyEnabled() && !!actionName
98
98
  let startTime_: number = 0
99
- if (__DEV__ && notifySpy_) {
99
+ if (notifySpy_) {
100
100
  startTime_ = Date.now()
101
101
  const flattenedArgs = args ? Array.from(args) : EMPTY_ARRAY
102
102
  spyReportStart({
@@ -112,9 +112,14 @@ export function _startAction(
112
112
  let prevAllowStateChanges_ = globalState.allowStateChanges // by default preserve previous allow
113
113
  if (runAsAction) {
114
114
  untrackedStart()
115
- prevAllowStateChanges_ = allowStateChangesStart(true)
115
+ if (__DEV__) {
116
+ prevAllowStateChanges_ = allowStateChangesStart(true)
117
+ }
118
+ }
119
+ const prevAllowStateReads_ = globalState.allowStateReads
120
+ if (__DEV__) {
121
+ allowStateReadsStart(true)
116
122
  }
117
- const prevAllowStateReads_ = allowStateReadsStart(true)
118
123
  const runInfo = {
119
124
  runAsAction_: runAsAction,
120
125
  prevDerivation_,
@@ -138,8 +143,10 @@ export function _endAction(runInfo: IActionRunInfo) {
138
143
  if (runInfo.error_ !== undefined) {
139
144
  globalState.suppressReactionErrors = true
140
145
  }
141
- allowStateChangesEnd(runInfo.prevAllowStateChanges_)
142
- allowStateReadsEnd(runInfo.prevAllowStateReads_)
146
+ if (__DEV__) {
147
+ allowStateChangesEnd(runInfo.prevAllowStateChanges_)
148
+ allowStateReadsEnd(runInfo.prevAllowStateReads_)
149
+ }
143
150
  endBatch()
144
151
  if (runInfo.runAsAction_) {
145
152
  untrackedEnd(runInfo.prevDerivation_)