11

My Problem

I'm writing a node module called a, which require()s a module b (written by a stranger). Unfortunately, a doesn't only need to access the public members - it also needs to access local variables declared in the scope of the module.

// a
var b = require('b');

console.log(b.public);
console.log(b.private); // undefined


// b
var c = require('c');
var stdin = process.stdin;

exports.public = true;
var private = true;

My Solution

// a
var b = require('b');
var srcPath = require.resolve('b');

console.log(b.public);
fs.readFile(srcPath, 'utf-8', function (err, src) {
    var box = {};
    var res = vm.runInNewContext(src, box, srcPath);
    console.log(box.private);
});

But vm doesn't run b as a module, so require() etc. aren't accessible from the context of the vm. So there are ReferenceErrors like:

    var res = vm.runInNewContext(src, box, scPath);
                 ^
ReferenceError: require is not defined
    at <module b>
    at <module a>
    at fs.readFile (fs.js:176:14)
    at Object.oncomplete (fs.js:297:15)

My Question

Which is the cleanest way to get the value of a local variable declared in another module? Ideas?

Thanks for your help.

5
  • Export getters / setters? You surely don't want others to freely mess with all of your local variables, do you? Commented Dec 24, 2012 at 10:40
  • Edit b to export the data you want access to. Don't try to hack into it from the outside. Commented Dec 24, 2012 at 10:41
  • Thanks for your ideas. But module b was written by a stranger and not by me (and I don't want to get my hands dirty). - Any other ideas? Commented Dec 24, 2012 at 10:56
  • @fridojet, did you manage to discover a solution? Commented Nov 17, 2013 at 22:14
  • One of the best questions i have saw on stackoverflow. This should be a node module. +1 Commented Feb 11, 2017 at 2:29

3 Answers 3

5

you should probably mostly never have to do this, but there might be reasons.

you can hook the loader and inject javascript code to export what you want.

// let's say you have node_modules/foreignmodule/index.js
// and in that script there is a local (not-exported) function foreignfunction().

var path = require('path');
_oldLoader = require.extensions['.js'];
require.extensions['.js'] = function(mod, filename) {
    if (filename == path.resolve(path.dirname(module.filename), 'node_modules/foreignmodule/index.js')) {
        var content = require('fs').readFileSync(filename, 'utf8');
        content += "module.exports.foreignfunction=foreignfunction;\n";
        mod._compile(content, filename);
    } else {
        _oldLoader(mod, filename);
    }
};

require('foreignmodule').foreignfunction();
Sign up to request clarification or add additional context in comments.

Comments

1

Check out my module import-locals

const patcher = new Patcher();
patcher.export("yourmodule", "Foo");
const { Foo } = require("yourmodule");

Comments

-2

Just export the values properly

Module B

// b.js

// some local var
var foo = 'Bar';

exports.Foo = foo;
exports.Hello = 'World';

Module A

// a .js
b = require('./b');
console.log(b.Foo); //=> 'Bar'
console.log(b.Hello); // => 'World'

Read more about nodejs module.exports here

2 Comments

I'm writing a node module called a, which require()s a module b (written by a stranger). - That means: b isn't written by me (and I don't want to get my hands dirty).
It'd be nice if all strangers wrote their modules properly. But that isn't the case. Sometimes, you need to help them export the things they should've done.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.