-
Notifications
You must be signed in to change notification settings - Fork 20
/
index.js
121 lines (101 loc) · 2.87 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
'use strict'
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
}
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, '__wrapped', 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