From 46dffd54228e5eb53928a4ef82dc7efaf3df5964 Mon Sep 17 00:00:00 2001 From: James Talmage Date: Mon, 9 Nov 2015 20:09:45 -0500 Subject: [PATCH] Allow intercept of transitive require calls files. This paves the way for https://github.com/sindresorhus/ava/issues/156 --- index.js | 5 +++ test/fixture/depth0.js | 2 ++ test/fixture/depth1/depth2/index.js | 1 + test/fixture/depth1/index.js | 1 + test/fixture/greet-james.js | 3 ++ test/fixture/james.js | 1 + test/index.js | 55 +++++++++++++++++++++++++---- 7 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 test/fixture/depth0.js create mode 100644 test/fixture/depth1/depth2/index.js create mode 100644 test/fixture/depth1/index.js create mode 100644 test/fixture/greet-james.js create mode 100644 test/fixture/james.js diff --git a/index.js b/index.js index 69da662..bebb9e4 100644 --- a/index.js +++ b/index.js @@ -21,6 +21,11 @@ module.exports = function requireFromString(code, filename, opts) { var paths = Module._nodeModulePaths(path.dirname(filename)); var m = new Module(filename, module.parent); + if (opts.require) { + m.require = function (path) { + return opts.require.call(this, path); + } + } m.filename = filename; m.paths = [].concat(opts.prependPaths).concat(paths).concat(opts.appendPaths); m._compile(code, filename); diff --git a/test/fixture/depth0.js b/test/fixture/depth0.js new file mode 100644 index 0000000..d812491 --- /dev/null +++ b/test/fixture/depth0.js @@ -0,0 +1,2 @@ + +module.exports = require('./depth1'); diff --git a/test/fixture/depth1/depth2/index.js b/test/fixture/depth1/depth2/index.js new file mode 100644 index 0000000..f13355e --- /dev/null +++ b/test/fixture/depth1/depth2/index.js @@ -0,0 +1 @@ +module.exports = 'FOO - depth2'; diff --git a/test/fixture/depth1/index.js b/test/fixture/depth1/index.js new file mode 100644 index 0000000..f5b6081 --- /dev/null +++ b/test/fixture/depth1/index.js @@ -0,0 +1 @@ +module.exports = require('./depth2'); diff --git a/test/fixture/greet-james.js b/test/fixture/greet-james.js new file mode 100644 index 0000000..36f51c7 --- /dev/null +++ b/test/fixture/greet-james.js @@ -0,0 +1,3 @@ +module.exports = function() { + return 'Hello ' + require('./james'); +}; diff --git a/test/fixture/james.js b/test/fixture/james.js new file mode 100644 index 0000000..852a223 --- /dev/null +++ b/test/fixture/james.js @@ -0,0 +1 @@ +module.exports = 'James'; diff --git a/test/index.js b/test/index.js index 05b197a..46c6b70 100644 --- a/test/index.js +++ b/test/index.js @@ -7,6 +7,13 @@ var fs = require('fs'); var path = require('path'); var requireFromString = require('../'); +function getFixture(file) { + file = path.join(__dirname, 'fixture', file); + var code = fs.readFileSync(file, 'utf8'); + + return {file: file, code: code}; +} + it('should accept only string as code', function () { assert.throws(function () { requireFromString(); @@ -24,18 +31,16 @@ it('should accept filename', function () { }); it('should work with relative require in file', function () { - var file = path.join(__dirname, '/fixture/module.js'); - var code = fs.readFileSync(file, 'utf8'); - var result = requireFromString(code, file); + var fixture = getFixture('module.js'); + var result = requireFromString(fixture.code, fixture.file); assert.ok(result); assert.ok(module === result.parent.parent); }); it('should have appended and preppended paths', function () { - var file = path.join(__dirname, '/fixture/submodule.js'); - var code = fs.readFileSync(file, 'utf8'); - var result = requireFromString(code, file, { + var fixture = getFixture('submodule.js'); + var result = requireFromString(fixture.code, fixture.file, { appendPaths: ['append'], prependPaths: ['prepend'] }); @@ -44,3 +49,41 @@ it('should have appended and preppended paths', function () { assert.equal(result.paths.indexOf('append'), result.paths.length - 1); assert.equal(result.paths.indexOf('prepend'), 0); }); + +it('should allow modification of other required modules via callback', function () { + var fixture = getFixture('greet-james.js'); + var Module = module.constructor; + + function transform(code) { + return code.replace('James', 'Jim'); + } + + function requireHook(path) { + var file = Module._resolveFilename(path, this); + var code = fs.readFileSync(file, 'utf8'); + return requireFromString(transform(code), file, {require: requireHook}); + } + + var result = requireFromString(fixture.code, fixture.file, {require: requireHook}); + + assert.equal(result(), 'Hello Jim'); +}); + +it('transforms should be doable even as relative directory changes', function () { + var fixture = getFixture('depth0.js'); + var Module = module.constructor; + + function transform(code) { + return code.replace('FOO', 'BAR'); + } + + function requireHook(path) { + var file = Module._resolveFilename(path, this); + var code = fs.readFileSync(file, 'utf8'); + return requireFromString(transform(code), file, {require: requireHook}); + } + + var result = requireFromString(fixture.code, fixture.file, {require: requireHook}); + + assert.equal(result, 'BAR - depth2'); +});