forked from othiym23/shimmer
-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
127 lines (105 loc) · 2.96 KB
/
index.js
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
'use strict'
const isWrapped = Symbol('__wrapped')
function isFunction (funktion) {
return typeof funktion === 'function'
}
// Default to complaining loudly when things don't go according to plan.
var logger = console.error.bind(console)
// Sets a property on an object, preserving its enumerability.
// This function assumes that the property is already writable.
function defineProperty (obj, name, value) {
var enumerable = !!obj[name] && obj.propertyIsEnumerable(name)
Object.defineProperty(obj, name, {
configurable: true,
enumerable: enumerable,
writable: true,
value: value
})
}
// Keep initialization idempotent.
function shimmer (options) {
if (options && options.logger) {
if (!isFunction(options.logger)) logger("new logger isn't a function, not replacing")
else logger = options.logger
}
}
function wrap (nodule, name, wrapper) {
if (!nodule || !nodule[name]) {
logger('no original function ' + name + ' to wrap')
return
}
if (!wrapper) {
logger('no wrapper function')
logger((new Error()).stack)
return
}
if (!isFunction(nodule[name]) || !isFunction(wrapper)) {
logger('original object and wrapper must be functions')
return
}
if (nodule[name][isWrapped]) {
return
}
var original = nodule[name]
var wrapped = wrapper(original, name)
defineProperty(wrapped, '__original', original)
defineProperty(wrapped, '__unwrap', function () {
if (nodule[name] === wrapped) defineProperty(nodule, name, original)
})
defineProperty(wrapped, isWrapped, true)
defineProperty(nodule, name, wrapped)
return wrapped
}
function massWrap (nodules, names, wrapper) {
if (!nodules) {
logger('must provide one or more modules to patch')
logger((new Error()).stack)
return
} else if (!Array.isArray(nodules)) {
nodules = [nodules]
}
if (!(names && Array.isArray(names))) {
logger('must provide one or more functions to wrap on modules')
return
}
nodules.forEach(function (nodule) {
names.forEach(function (name) {
wrap(nodule, name, wrapper)
})
})
}
function unwrap (nodule, name) {
if (!nodule || !nodule[name]) {
logger('no function to unwrap.')
logger((new Error()).stack)
return
}
if (!nodule[name].__unwrap) {
logger('no original to unwrap to -- has ' + name + ' already been unwrapped?')
} else {
return nodule[name].__unwrap()
}
}
function massUnwrap (nodules, names) {
if (!nodules) {
logger('must provide one or more modules to patch')
logger((new Error()).stack)
return
} else if (!Array.isArray(nodules)) {
nodules = [nodules]
}
if (!(names && Array.isArray(names))) {
logger('must provide one or more functions to unwrap on modules')
return
}
nodules.forEach(function (nodule) {
names.forEach(function (name) {
unwrap(nodule, name)
})
})
}
shimmer.wrap = wrap
shimmer.massWrap = massWrap
shimmer.unwrap = unwrap
shimmer.massUnwrap = massUnwrap
module.exports = shimmer