Reputation: 9359
I would like to run a third-party JavaScript file (I don't have much control over its contents) in node and access a global variable created by that file's code in its context.
There are two things I've considered:
Running the code in a vm
sandbox. The problem is that I don't know how to properly create the context, because vm.createContext([sandbox])
won't automatically provide basic things such as console
or require
or whatever to the script I want to run.
This is a bit of a bummer, because the documentation explicitly states (emphasis mine):
If given a sandbox object, will "contextify" that sandbox so that it can be used in calls to vm.runInContext() or script.runInContext(). Inside scripts run as such, sandbox will be the global object, retaining all its existing properties but also having the built-in objects and functions any standard global object has.
What are "the built-in objects and functions any standard global object has"? I'm naively assuming it's things like console
, process
, require
, etc. But if so, the API doesn't work, because those are not set. I'm probably misunderstanding something here.
var sandbox = vm.createContext({foo: 'foo'});
var code = 'console.log(foo);';
vm.runInContext(code, sandbox);
Which results in:
evalmachine.:1
console.log(foo);
^
ReferenceError: console is not defined
Running the code in a child process. But I can't find any documentation on accessing global variables of child processes. I'm assuming the only way to communicate with a child process is by message passing, but even that seems to be from parent to child, not the other way round...
Basically, I'm stuck. Halp.
Upvotes: 13
Views: 3777
Reputation: 764
In this code, we can send any of the response and can access the global variable with global function and can access the whole data returning from VM Sandbox.
function compiler(){
let add = x*y
Return (add);
}
compiler();
const vm = new NodeVM({
sandbox: {
Return(data) {
console.log('Data:', data);
},
x : 10,=
y : 20
},
require: {
external: true,
builtin: ["fs", "path"],
root: "./",
mock: {
fs: {
readFileSync() {
return "Nice try!";
}
}
}
}
});
try {
vm.run(req.query.code);
} catch (error) {
console.log("error: ", error);
}
Upvotes: 0
Reputation: 22099
How about just passing the parent's console
in a context?
const vm = require('vm');
var sandbox = {
console: console
};
var context = new vm.createContext(sandbox);
var script = new vm.Script('console.log("foo")');
script.runInContext(context);
Upvotes: 0
Reputation: 29172
You can use advanced vm/sandbox for Node.js
var VM = require('vm2').NodeVM; // https://github.com/patriksimek/vm2#nodevm
var options = {
console: 'inherit',
sandbox: {
foo: 'foo'
}
}
vm = new VM(options);
var code = `
console.log(foo);
oldFoo = foo;
foo = Math.random();
`;
vm.run(code);
console.log(vm.context.oldFoo, vm.context.foo);
Upvotes: 5