UNPKG

2.02 kBPlain TextView Raw
1import {
2 isObservable,
3 isObservableArray,
4 isObservableValue,
5 isObservableMap,
6 isObservableSet,
7 isComputedValue,
8 die,
9 apiOwnKeys,
10 objectPrototype
11} from "../internal"
12
13function cache<K, V>(map: Map<any, any>, key: K, value: V): V {
14 map.set(key, value)
15 return value
16}
17
18function 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 // must be observable object
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 * Basically, a deep clone, so that no reactive property will exist anymore.
66 */
67export 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}