Is it possible to make all of Node.js Globals available in Node's VM context?

904 Views Asked by At

Consider the following code:

vm = require('vm');
context = vm.createContext({});
vm.runInContext("Buffer.from('abc').toString()", context);

Observe that this produces ReferenceError: Buffer is not defined as Buffer is a Node.js specific construct that Node.js has added as a Node Specific Global Object. (Note that other JS globals like Math and Array do not share this problem.) This particular problem can be solved by modifying the above code to

vm = require('vm');
context = vm.createContext({Buffer});
vm.runInContext("Buffer.from('abc').toString()", context);

However, if I want every single Node Specific Global to be imported, then it appears as though I must list them one by one. Given that Node.js adds Global objects relatively frequetly, is there a way I can pass all of Node.JS' global objects to a vm context? Alternatively, is there a programatic way to construct a list of all of Node Globals?

Note: Using global isn't consistent across different node versions: e.g. Buffer is in global for node v8 and v10 but not v12.

2

There are 2 best solutions below

2
On

I got this.


const cloneGlobal = () => Object.defineProperties(
    {...global},
    Object.getOwnPropertyDescriptors(global)
)

Test:

> const nG = cloneGlobal()
> nG.myVar = 'a';
'a'
> myVar
Uncaught ReferenceError: myVar is not defined
> 'myVar' in global
false
> 'myVar' in nG
true
> 'Buffer' in nG
true

Edit: add Example code for the author's example:

vm = require('vm');

const cloneGlobal = () => Object.defineProperties(
    {...global},
    Object.getOwnPropertyDescriptors(global)
)

context = vm.createContext(cloneGlobal());
const ret = vm.runInContext("Buffer.from('abc').toString()", context);

console.log(ret); // abc
1
On

The whole reason to use the "vm" module is to isolate the context of the running program from the code being executed.

If you want to execute arbitrary JavaScript inside the current context you can just use eval. No reason to use vm.createContext.

eval("Buffer.from('abc').toString()");