current.ts
1.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import {
die,
isDraft,
shallowCopy,
each,
DRAFT_STATE,
get,
set,
ImmerState,
isDraftable,
ArchtypeMap,
ArchtypeSet,
getArchtype,
getPlugin
} from "../internal"
/** Takes a snapshot of the current state of a draft and finalizes it (but without freezing). This is a great utility to print the current state during debugging (no Proxies in the way). The output of current can also be safely leaked outside the producer. */
export function current<T>(value: T): T
export function current(value: any): any {
if (!isDraft(value)) die(22, value)
return currentImpl(value)
}
function currentImpl(value: any): any {
if (!isDraftable(value)) return value
const state: ImmerState | undefined = value[DRAFT_STATE]
let copy: any
const archType = getArchtype(value)
if (state) {
if (
!state.modified_ &&
(state.type_ < 4 || !getPlugin("ES5").hasChanges_(state as any))
)
return state.base_
// Optimization: avoid generating new drafts during copying
state.finalized_ = true
copy = copyHelper(value, archType)
state.finalized_ = false
} else {
copy = copyHelper(value, archType)
}
each(copy, (key, childValue) => {
if (state && get(state.base_, key) === childValue) return // no need to copy or search in something that didn't change
set(copy, key, currentImpl(childValue))
})
// In the future, we might consider freezing here, based on the current settings
return archType === ArchtypeSet ? new Set(copy) : copy
}
function copyHelper(value: any, archType: number): any {
// creates a shallow copy, even if it is a map or set
switch (archType) {
case ArchtypeMap:
return new Map(value)
case ArchtypeSet:
// Set will be cloned as array temporarily, so that we can replace individual items
return Array.from(value)
}
return shallowCopy(value)
}