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.
- package/CHANGELOG.md +224 -7
- package/README.md +54 -52
- package/dist/api/annotation.d.ts +6 -12
- package/dist/api/autorun.d.ts +4 -4
- package/dist/api/flow.d.ts +1 -0
- package/dist/api/intercept.d.ts +5 -5
- package/dist/api/object-api.d.ts +2 -0
- package/dist/api/observable.d.ts +5 -1
- package/dist/api/observe.d.ts +4 -4
- package/dist/api/tojs.d.ts +4 -1
- package/dist/api/when.d.ts +8 -0
- package/dist/core/atom.d.ts +1 -1
- package/dist/core/computedvalue.d.ts +0 -1
- package/dist/core/globalstate.d.ts +4 -0
- package/dist/core/reaction.d.ts +2 -2
- package/dist/errors.d.ts +4 -2
- package/dist/internal.d.ts +1 -0
- package/dist/mobx.cjs.development.js +1477 -1719
- package/dist/mobx.cjs.development.js.map +1 -1
- package/dist/mobx.cjs.production.min.js +1 -1
- package/dist/mobx.cjs.production.min.js.map +1 -1
- package/dist/mobx.d.ts +1 -1
- package/dist/mobx.esm.development.js +1475 -1720
- package/dist/mobx.esm.development.js.map +1 -1
- package/dist/mobx.esm.js +1492 -1726
- package/dist/mobx.esm.js.map +1 -1
- package/dist/mobx.esm.production.min.js +1 -1
- package/dist/mobx.esm.production.min.js.map +1 -1
- package/dist/mobx.umd.development.js +1477 -1719
- package/dist/mobx.umd.development.js.map +1 -1
- package/dist/mobx.umd.production.min.js +1 -1
- package/dist/mobx.umd.production.min.js.map +1 -1
- package/dist/types/actionannotation.d.ts +7 -1
- package/dist/types/autoannotation.d.ts +3 -0
- package/dist/types/observablemap.d.ts +5 -4
- package/dist/types/observableobject.d.ts +6 -9
- package/dist/types/observableset.d.ts +4 -4
- package/dist/types/observablevalue.d.ts +3 -5
- package/dist/utils/utils.d.ts +4 -4
- package/package.json +1 -1
- package/src/api/action.ts +8 -3
- package/src/api/annotation.ts +14 -44
- package/src/api/autorun.ts +38 -17
- package/src/api/computed.ts +5 -2
- package/src/api/configure.ts +6 -2
- package/src/api/decorators.ts +1 -1
- package/src/api/extendobservable.ts +12 -6
- package/src/api/extras.ts +4 -2
- package/src/api/flow.ts +17 -5
- package/src/api/intercept-read.ts +4 -2
- package/src/api/intercept.ts +10 -7
- package/src/api/iscomputed.ts +14 -8
- package/src/api/isobservable.ts +10 -4
- package/src/api/makeObservable.ts +35 -36
- package/src/api/object-api.ts +42 -14
- package/src/api/observable.ts +39 -25
- package/src/api/observe.ts +9 -6
- package/src/api/tojs.ts +20 -10
- package/src/api/trace.ts +6 -2
- package/src/api/when.ts +34 -9
- package/src/core/action.ts +11 -5
- package/src/core/atom.ts +9 -2
- package/src/core/computedvalue.ts +48 -27
- package/src/core/derivation.ts +34 -12
- package/src/core/globalstate.ts +25 -7
- package/src/core/observable.ts +23 -13
- package/src/core/reaction.ts +16 -7
- package/src/core/spy.ts +20 -7
- package/src/errors.ts +16 -3
- package/src/internal.ts +1 -0
- package/src/mobx.ts +6 -2
- package/src/types/actionannotation.ts +30 -52
- package/src/types/autoannotation.ts +107 -0
- package/src/types/computedannotation.ts +7 -37
- package/src/types/dynamicobject.ts +12 -6
- package/src/types/flowannotation.ts +40 -41
- package/src/types/intercept-utils.ts +9 -3
- package/src/types/legacyobservablearray.ts +26 -3
- package/src/types/listen-utils.ts +6 -2
- package/src/types/modifiers.ts +52 -16
- package/src/types/observableannotation.ts +7 -34
- package/src/types/observablearray.ts +106 -45
- package/src/types/observablemap.ts +71 -35
- package/src/types/observableobject.ts +88 -82
- package/src/types/observableset.ts +32 -13
- package/src/types/observablevalue.ts +16 -10
- package/src/types/overrideannotation.ts +4 -2
- package/src/types/type-utils.ts +34 -12
- package/src/utils/comparer.ts +5 -1
- package/src/utils/eq.ts +45 -15
- 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
|
-
|
|
47
|
-
getDebugName,
|
|
45
|
+
autoAnnotation,
|
|
48
46
|
getAdministration,
|
|
49
|
-
|
|
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 =
|
|
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)
|
|
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)
|
|
163
|
+
if (__DEV__ && notifySpy) {
|
|
164
|
+
spyReportStart(change!)
|
|
165
|
+
}
|
|
169
166
|
;(observable as ObservableValue<any>).setNewValue_(newValue)
|
|
170
|
-
if (notify)
|
|
171
|
-
|
|
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 -
|
|
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 -
|
|
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.
|
|
244
|
+
annotation = this.defaultAnnotation_
|
|
244
245
|
}
|
|
245
246
|
if (annotation === false) {
|
|
246
247
|
return
|
|
247
248
|
}
|
|
248
249
|
assertAnnotable(this, annotation, key)
|
|
249
|
-
|
|
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 -
|
|
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 =
|
|
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)
|
|
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)
|
|
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)
|
|
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)
|
|
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)
|
|
570
|
-
|
|
571
|
-
|
|
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)
|
|
611
|
-
|
|
612
|
-
|
|
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_():
|
|
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
|
|
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
|
-
|
|
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())
|
|
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)
|
|
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__)
|
|
145
|
-
|
|
146
|
-
|
|
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:
|
|
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)
|
|
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__)
|
|
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)
|
|
181
|
-
|
|
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:
|
|
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:
|
|
41
|
-
oldValue:
|
|
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:
|
|
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)
|
|
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)
|
|
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)
|
|
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):
|
|
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 {
|
package/src/types/type-utils.ts
CHANGED
|
@@ -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)
|
|
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
|
|
25
|
+
return thing.atom_
|
|
24
26
|
}
|
|
25
27
|
if (isObservableMap(thing)) {
|
|
26
|
-
if (property === undefined)
|
|
28
|
+
if (property === undefined) {
|
|
29
|
+
return thing.keysAtom_
|
|
30
|
+
}
|
|
27
31
|
const observable = thing.data_.get(property) || thing.hasMap_.get(property)
|
|
28
|
-
if (!observable)
|
|
32
|
+
if (!observable) {
|
|
33
|
+
die(25, property, getDebugName(thing))
|
|
34
|
+
}
|
|
29
35
|
return observable
|
|
30
36
|
}
|
|
31
|
-
if (property && !thing[$mobx])
|
|
37
|
+
if (property && !thing[$mobx]) {
|
|
38
|
+
thing[property]
|
|
39
|
+
} // See #1072
|
|
32
40
|
if (isObservableObject(thing)) {
|
|
33
|
-
if (!property)
|
|
41
|
+
if (!property) {
|
|
42
|
+
return die(26)
|
|
43
|
+
}
|
|
34
44
|
const observable = (thing as any)[$mobx].values_.get(property)
|
|
35
|
-
if (!observable)
|
|
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)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (
|
|
55
|
-
|
|
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
|
|
package/src/utils/comparer.ts
CHANGED
|
@@ -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
|
-
|
|
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 = {
|