1 | import {
|
2 | isObservable,
|
3 | isObservableArray,
|
4 | isObservableValue,
|
5 | isObservableMap,
|
6 | isObservableSet,
|
7 | isComputedValue,
|
8 | die,
|
9 | apiOwnKeys,
|
10 | objectPrototype
|
11 | } from "../internal"
|
12 |
|
13 | function cache<K, V>(map: Map<any, any>, key: K, value: V): V {
|
14 | map.set(key, value)
|
15 | return value
|
16 | }
|
17 |
|
18 | function toJSHelper(source, __alreadySeen: Map<any, any>) {
|
19 | if (
|
20 | source == null ||
|
21 | typeof source !== "object" ||
|
22 | source instanceof Date ||
|
23 | !isObservable(source)
|
24 | )
|
25 | return source
|
26 |
|
27 | if (isObservableValue(source) || isComputedValue(source))
|
28 | return toJSHelper(source.get(), __alreadySeen)
|
29 | if (__alreadySeen.has(source)) {
|
30 | return __alreadySeen.get(source)
|
31 | }
|
32 | if (isObservableArray(source)) {
|
33 | const res = cache(__alreadySeen, source, new Array(source.length))
|
34 | source.forEach((value, idx) => {
|
35 | res[idx] = toJSHelper(value, __alreadySeen)
|
36 | })
|
37 | return res
|
38 | }
|
39 | if (isObservableSet(source)) {
|
40 | const res = cache(__alreadySeen, source, new Set())
|
41 | source.forEach(value => {
|
42 | res.add(toJSHelper(value, __alreadySeen))
|
43 | })
|
44 | return res
|
45 | }
|
46 | if (isObservableMap(source)) {
|
47 | const res = cache(__alreadySeen, source, new Map())
|
48 | source.forEach((value, key) => {
|
49 | res.set(key, toJSHelper(value, __alreadySeen))
|
50 | })
|
51 | return res
|
52 | } else {
|
53 |
|
54 | const res = cache(__alreadySeen, source, {})
|
55 | apiOwnKeys(source).forEach((key: any) => {
|
56 | if (objectPrototype.propertyIsEnumerable.call(source, key)) {
|
57 | res[key] = toJSHelper(source[key], __alreadySeen)
|
58 | }
|
59 | })
|
60 | return res
|
61 | }
|
62 | }
|
63 |
|
64 |
|
65 |
|
66 |
|
67 | export function toJS<T>(source: T, options?: any): T {
|
68 | if (__DEV__ && options) die("toJS no longer supports options")
|
69 | return toJSHelper(source, new Map())
|
70 | }
|