-
Notifications
You must be signed in to change notification settings - Fork 25
/
sandbox.js
58 lines (51 loc) · 2.14 KB
/
sandbox.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
/**
* Inject dependencies into a module.
* @param {function} parentRequire Your require.
* @param {String} sandboxId The module id to load
* @param {Object} sandboxDependencies An object mapping from module ids
* relative to the sandboxId module, to the exports that should be returned.
* @return {Promise} A promise for the exports
* @example
* var mockFileReader = sandbox(require, "./file-reader", {
* "fs": {
* "readFile": function () { return "content"; }
* }
* });
*/
module.exports = function (parentRequire, sandboxId, sandboxDependencies) {
var topId = parentRequire.resolve(sandboxId);
var originalModule = parentRequire.getModuleDescriptor(topId);
while (originalModule.redirect || originalModule.mappingRedirect) {
if (originalModule.redirect) {
topId = originalModule.redirect;
} else {
parentRequire = originalModule.mappingRequire;
topId = originalModule.mappingRedirect;
}
originalModule = parentRequire.getModuleDescriptor(topId);
}
return parentRequire.deepLoad(topId)
.then(function () {
// delete the exports to cause the factory to get called again
var originalExports = originalModule.exports;
delete originalModule.exports;
// wrap the factory to work our magic
var originalFactory = originalModule.factory;
originalModule.factory = function (require, exports, module) {
var sandboxRequire = function (id) {
if (id in sandboxDependencies) {
return sandboxDependencies[id];
}
return require(id);
};
var sandboxModule = JSON.parse(JSON.stringify(module));
var sandboxExports = sandboxModule.exports;
return originalFactory(sandboxRequire, sandboxExports, sandboxModule) || sandboxModule.exports;
};
var sandboxExports = parentRequire(topId);
// restore normality
originalModule.exports = originalExports;
originalModule.factory = originalFactory;
return sandboxExports;
});
};