Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Run js code in a separate context and access its global variable

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:

  1. 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

  2. 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.

like image 655
Oleg Avatar asked Apr 26 '16 10:04

Oleg


1 Answers

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);
like image 175
stdob-- Avatar answered Nov 02 '22 23:11

stdob--