UNPKG

1.85 kBJavaScriptView Raw
1var vm = require('vm');
2
3module.exports = function (cfg, wrapper, callback) {
4
5 // Hook into Node's `require(...)`
6 updateHooks();
7
8 // Patch the vm module to watch files executed via one of these methods:
9 if (cfg.vm) {
10 patch(vm, 'createScript', 1);
11 patch(vm, 'runInThisContext', 1);
12 patch(vm, 'runInNewContext', 2);
13 patch(vm, 'runInContext', 2);
14 }
15
16 /**
17 * Patch the specified method to watch the file at the given argument
18 * index.
19 */
20 function patch(obj, method, optionsArgIndex) {
21 var orig = obj[method];
22 if (!orig) return;
23 obj[method] = function () {
24 var opts = arguments[optionsArgIndex];
25 var file = null;
26 if (opts) {
27 file = typeof opts == 'string' ? opts : opts.filename;
28 }
29 if (file) callback(file);
30 return orig.apply(this, arguments);
31 };
32 }
33
34 /**
35 * (Re-)install hooks for all registered file extensions.
36 */
37 function updateHooks() {
38 Object.keys(require.extensions).forEach(function (ext) {
39 var fn = require.extensions[ext];
40 if (typeof fn === 'function' && fn.name !== 'nodeDevHook') {
41 require.extensions[ext] = createHook(fn);
42 }
43 });
44 }
45
46 /**
47 * Returns a function that can be put into `require.extensions` in order to
48 * invoke the callback when a module is required for the first time.
49 */
50 function createHook(handler) {
51 return function nodeDevHook(module, filename) {
52 if (module.parent === wrapper) {
53 // If the main module is required conceal the wrapper
54 module.id = '.';
55 module.parent = null;
56 process.mainModule = module;
57 }
58 if (!module.loaded) callback(module.filename);
59
60 // Invoke the original handler
61 handler(module, filename);
62
63 // Make sure the module did not hijack the handler
64 updateHooks();
65 };
66 }
67};