-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdissect.js
88 lines (66 loc) · 2.21 KB
/
dissect.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
const Module = require('module');
const shebangRe = /^\#\!.*/;
const CONFIGURATIONS = {
replaceConstWithVar: false,
clearCache: false
};
var toDissect = null;
function replaceConst(content) {
/**
* Nasty way of replacing block scope declaration. Needs a better way.
*/
return CONFIGURATIONS.replaceConstWithVar === true ? content.replace(/const |let /g, 'var ') : content;
}
function wrap(content) {
return `
const vm = require('vm');
/**
* Serves as the context for the module to be dissected. Not that the module's content is not
* wrappered inside a function as NodeJS usually does. Instead, the contents are executed directly
* without any outer functional scope.
*/
const context = { exports, require, module, __filename, __dirname, global, __proto__: global };
const code = ${JSON.stringify(content)};
vm.runInContext(code, vm.createContext(context), {
filename: __filename,
displayErrors: true
});
if (!Object.isExtensible(module.exports)) {
module.exports = {
exports: module.exports
};
}
module.exports.__get = key => context.hasOwnProperty(key) ? context[key] : undefined,
module.exports.__set = (key, value) => context[key] = value;
`;
}
const originalCompile = Module.prototype._compile;
Module.prototype._compile = function(content, filename) {
content = content.replace(shebangRe, '');
if (filename === toDissect) {
content = replaceConst(wrap(content));
}
originalCompile.call(this, content, filename);
};
const originalRequire = Module.prototype.require;
Module.prototype.require = function(request) {
/**
* Dissect only those modules which are required with the "dissect"
* extension. Very unintuitive. Needs a better solution.
*/
if (request.endsWith('.dissect')) {
request = `${request.slice(0, -8)}.js`;
try {
toDissect = Module._resolveFilename(request, this);
} catch(e) { toDissect = null; }
}
const temp = originalRequire.call(this, request);
if (CONFIGURATIONS.clearCache) {
delete Module._cache[toDissect];
}
toDissect = null;
return temp;
};
module.exports = function(configurations) {
Object.assign(CONFIGURATIONS, configurations);
};