-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathapplyPatchFactory.js
More file actions
73 lines (65 loc) · 2.54 KB
/
applyPatchFactory.js
File metadata and controls
73 lines (65 loc) · 2.54 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
62
63
64
65
66
67
68
69
70
71
72
73
import { isPlainObject, isPlain } from '../util/is'
import { setDeep } from '../util/getset'
import { mergeCore } from '../util/merge'
export default function applyPatchFactory(patchers) {
return function applyPatch(target, patch) {
const mutations = []
const target_root = { '': target } // a trick to allow top level patches
const patch_root = { '': patch } // a trick to allow top level patches
const unpatch_root = { '': {} }
function addMutation(target, prop, old_value, path) {
mutations.push({
target,
prop,
old_value,
path,
})
}
mergeCore(patch_root, target_root, ({ patch, target, prop, path }) => {
const patch_value = patch[prop]
const target_value = target[prop]
if (
!target.hasOwnProperty(prop) ||
(patch_value !== target_value &&
!(isPlainObject(patch_value) && isPlain(target_value)))
) {
const length = target.length
// Applying patches
const old_value = patchers.reduce(
(old_value, patcher) =>
patcher({
patch,
target,
prop,
old_value,
applyPatch,
}),
target_value
)
// We register the mutation if old_value is different to the new value
if (target[prop] !== old_value) {
addMutation(target, prop, old_value, path.slice(1))
if (target.length !== length) {
addMutation(
target,
'length',
length,
path.slice(1, path.length - 1).concat('length')
)
}
}
return false // we don't go deeper
}
})
// Creating unpatch
for (let index = mutations.length - 1; index >= 0; --index) {
const { path, old_value } = mutations[index]
setDeep(unpatch_root, [''].concat(path), old_value)
}
return {
result: target_root[''],
unpatch: unpatch_root[''],
mutations,
}
}
}