node.js: Accessing local variables from another module
Asked Answered
T

3

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.

Transcendent answered 24/12, 2012 at 10:37 Comment(5)
Export getters / setters? You surely don't want others to freely mess with all of your local variables, do you?Apple
Edit b to export the data you want access to. Don't try to hack into it from the outside.Empurple
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?Transcendent
@fridojet, did you manage to discover a solution?Esra
One of the best questions i have saw on stackoverflow. This should be a node module. +1Comradery
S
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();
Slater answered 26/8, 2014 at 14:25 Comment(0)
H
1

Check out my module import-locals

const patcher = new Patcher();
patcher.export("yourmodule", "Foo");
const { Foo } = require("yourmodule");
Horvath answered 10/3, 2019 at 17:19 Comment(0)
S
-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

Stillage answered 24/12, 2012 at 10:43 Comment(2)
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).Transcendent
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.Austroasiatic

© 2022 - 2024 — McMap. All rights reserved.