1 | import {
|
2 | ObservableObjectAdministration,
|
3 | Annotation,
|
4 | defineProperty,
|
5 | die,
|
6 | flow,
|
7 | isFlow,
|
8 | isFunction,
|
9 | globalState,
|
10 | MakeResult
|
11 | } from "../internal"
|
12 |
|
13 | export function createFlowAnnotation(name: string, options?: object): Annotation {
|
14 | return {
|
15 | annotationType_: name,
|
16 | options_: options,
|
17 | make_,
|
18 | extend_
|
19 | }
|
20 | }
|
21 |
|
22 | function make_(
|
23 | adm: ObservableObjectAdministration,
|
24 | key: PropertyKey,
|
25 | descriptor: PropertyDescriptor,
|
26 | source: object
|
27 | ): MakeResult {
|
28 |
|
29 | if (source === adm.target_) {
|
30 | return this.extend_(adm, key, descriptor, false) === null
|
31 | ? MakeResult.Cancel
|
32 | : MakeResult.Continue
|
33 | }
|
34 |
|
35 |
|
36 | if (this.options_?.bound && !isFlow(adm.target_[key])) {
|
37 | if (this.extend_(adm, key, descriptor, false) === null) return MakeResult.Cancel
|
38 | }
|
39 | if (isFlow(descriptor.value)) {
|
40 |
|
41 |
|
42 | return MakeResult.Break
|
43 | }
|
44 | const flowDescriptor = createFlowDescriptor(adm, this, key, descriptor, false, false)
|
45 | defineProperty(source, key, flowDescriptor)
|
46 | return MakeResult.Continue
|
47 | }
|
48 |
|
49 | function extend_(
|
50 | adm: ObservableObjectAdministration,
|
51 | key: PropertyKey,
|
52 | descriptor: PropertyDescriptor,
|
53 | proxyTrap: boolean
|
54 | ): boolean | null {
|
55 | const flowDescriptor = createFlowDescriptor(adm, this, key, descriptor, this.options_?.bound)
|
56 | return adm.defineProperty_(key, flowDescriptor, proxyTrap)
|
57 | }
|
58 |
|
59 | function assertFlowDescriptor(
|
60 | adm: ObservableObjectAdministration,
|
61 | { annotationType_ }: Annotation,
|
62 | key: PropertyKey,
|
63 | { value }: PropertyDescriptor
|
64 | ) {
|
65 | if (__DEV__ && !isFunction(value)) {
|
66 | die(
|
67 | `Cannot apply '${annotationType_}' to '${adm.name_}.${key.toString()}':` +
|
68 | `\n'${annotationType_}' can only be used on properties with a generator function value.`
|
69 | )
|
70 | }
|
71 | }
|
72 |
|
73 | function createFlowDescriptor(
|
74 | adm: ObservableObjectAdministration,
|
75 | annotation: Annotation,
|
76 | key: PropertyKey,
|
77 | descriptor: PropertyDescriptor,
|
78 | bound: boolean,
|
79 |
|
80 | safeDescriptors: boolean = globalState.safeDescriptors
|
81 | ): PropertyDescriptor {
|
82 | assertFlowDescriptor(adm, annotation, key, descriptor)
|
83 | let { value } = descriptor
|
84 | if (bound) {
|
85 | value = value.bind(adm.proxy_ ?? adm.target_)
|
86 | }
|
87 | return {
|
88 | value: flow(value),
|
89 |
|
90 |
|
91 | configurable: safeDescriptors ? adm.isPlainObject_ : true,
|
92 |
|
93 | enumerable: false,
|
94 |
|
95 |
|
96 | writable: safeDescriptors ? false : true
|
97 | }
|
98 | }
|