-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathindex.js
93 lines (77 loc) · 2.74 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
'use strict'
var Module = require('module')
var path = require('path')
var caller = require('caller')
try {
require('readable-stream')
} catch (_) {
// ignore error, just doing the require to work around weirdness in readable-stream
}
exports = module.exports = function (toLoad, mocks) {
return requireInject(toLoad, mocks)
}
exports.withEmptyCache = function (toLoad, mocks) {
return requireInject(toLoad, mocks, true)
}
exports.installGlobally = installGlobally
exports.installGlobally.andClearCache = function (toLoad, mocks) {
var callerFilename = getCallerFilename()
Object.keys(require.cache).forEach(function (name) {
if (name !== callerFilename) delete require.cache[name]
})
return installGlobally(toLoad, mocks)
}
var requireInject = function (toLoad, mocks, withEmptyCache) {
mocks = mocks || {}
// Copy the existing cache
var originalCache = {}
Object.keys(require.cache).forEach(function (name) {
originalCache[name] = require.cache[name]
})
var mocked = withEmptyCache
? installGlobally.andClearCache(toLoad, mocks)
: installGlobally(toLoad, mocks)
// restore the cache, we can't just assign originalCache to require.cache as the require
// object is unique to each module, even though require.cache is shared
Object.keys(require.cache).forEach(function (name) { delete require.cache[name] })
Object.keys(originalCache).forEach(function (name) { require.cache[name] = originalCache[name] })
return mocked
}
function resolve (callerFilename, name) {
if (/^[.][.]?\//.test(name)) {
name = path.resolve(path.dirname(callerFilename), name)
}
return require.resolve(name)
}
function getCallerFilename () {
var callerFilename
for (var ii = 1; ii <= 10; ++ii) {
callerFilename = caller(ii)
if (callerFilename !== module.filename) return callerFilename
}
throw new Error("Couldn't find caller that wasn't " + module.filename + ' in most recent 10 stackframes')
}
function installGlobally (toLoad, mocks) {
var callerFilename = getCallerFilename()
var parent = require.cache[toLoadPath] || null
// Inject all of our mocks
Object.keys(mocks).forEach(function (name) {
var namePath = resolve(callerFilename, name)
if (mocks[name] == null) {
delete require.cache[namePath]
} else {
var old = require.cache[namePath]
var mod = new Module(namePath, null)
mod.filename = namePath
mod.exports = mocks[name]
mod.loaded = true
mod.parent = old ? old.parent : parent
require.cache[namePath] = mod
}
})
var toLoadPath = resolve(callerFilename, toLoad)
// remove any unmocked version previously loaded
delete require.cache[toLoadPath]
// load our new version using our mocks
return require.cache[callerFilename].require(toLoadPath)
}