Closed ORESoftware closed 6 years ago
For example, if I do this:
const vm = require('vm');
const fs = require('fs');
const sandBox = vm.createContext({foo:'bar'});
const file = fs.readFileSync(__dirname + '/adjacent-file.js');
vm.runInContext(file, sandBox);
I get an error:
evalmachine.<anonymous>:3
const foo = require('./some-other-file');
^
ReferenceError: require is not defined
at evalmachine.<anonymous>:3:15
at ContextifyScript.Script.runInContext (vm.js:32:29)
at Object.exports.runInContext (vm.js:64:17)
Is this the best way to do it:
and if so, why don't the Node.js docs demonstrate an example of this?
If you need to access parts of the current scope, why do you use the vm
module at all? (Just out of curiousity).
If you really want to do this, you will need to put a wrapper function around your code, which provides implementations of require
, module
etc. You might want to take a look at this function.
For more, hah, context: require()
loads code in its home context, you can't use it with vm.runInNewContext()
(well, you can, but it won't do what you want.)
what's wrong with adding require
to the sandbox?
> var sandBox1 = vm.createContext({foo:'bar', require});
undefined
> vm.runInNewContext('const path2 = require("path"); path2.join(foo, "b")', sandBox1);
'bar\\b'
> path2
ReferenceError: path2 is not defined
@tniessen I am looking to isolate code for the purposes of testing. I have multiple tests in the same process, and as opposed to forking processes, I am looking to the vm module to see if I can isolate shared scope.
@tniessen I am looking to isolate code for the purposes of testing. I have multiple tests in the same process, and as opposed to forking processes, I am looking to the vm module to see if I can isolate shared scope.
@ORESoftware If you manage please share, I'm looking into improving core's test harness https://github.com/nodejs/node/issues/14214
@refack yeah I will share - they are attempting to do the same thing over at AVA. Not sure how much success they have had so far.
https://github.com/avajs/ava/issues/1332
I'd like to be notified if anyone "gets this working" :)
Got the same problem. I am creating a simple package manager for one of my nw.js apps - Qilin. I need to load plugins from user desktop directly into nw.js context. Basically it tries to require plugins from the app whereas it should look directly into plugin directories.
You can find the manager itself here, but here are some core parts. The lifecycle is very basic:
npm i
, npm prepare
, …);const data:Object = await readPackage(dir);
const file:string = await readFile(exe, "utf8");
const script = new vm.Script(file, {
filename: exe,
});
return {
createContext: (ctx) => {
return vm.createContext({
...ctx,
__filename: exe,
__dirname: dir,
exports: exports,
require: require,
module: module,
});
},
runInContext: (ctx) => script.runInContext(ctx),
};
Error:
{ module.js:529
throw err;
^
Error: Cannot find module 'merge-descriptors'
at Function.Module._resolveFilename (module.js:527:15)
at Function.Module._load (module.js:476:23)
at Module.require (module.js:568:17)
at require (internal/module.js:11:18)
at /Users/Bartek/Documents/GitHub/qilin-manager/demo/packages/plugins/crawlerr-master/dist/index.js:7:25
at ContextifyScript.Script.runInContext (vm.js:59:29)
at Object.runInContext (/Users/Bartek/Documents/GitHub/qilin-manager/dist/lib/load.js:44:23)
at Manager.load.then (/Users/Bartek/Documents/GitHub/qilin-manager/demo/index.js:21:24)
at <anonymous> code: 'MODULE_NOT_FOUND' }
is this still outstanding?
closing due to inactivity, please re-open if it is still outstanding.
Don't know if this will help anyone else, I'm using the following for an interactive shell tool I'm making:
const vm = require('vm');
// Create the VM context.
const context = vm.createContext(global);
// Bind require to the parent's require.
context.require = function(moduleName) {
return eval(`require`)(moduleName);
}.bind(global);
// Run some code.
vm.runInContext(`
const fs = require('fs');
console.log(
fs.readdirSync('/'),
);
`, context);
This script can also require other JS files with both absolute and relative paths, and those scripts can require their own things as well.
I am looking at the VM module https://nodejs.org/api/vm.html
I'd like to essentially run this code in a sandbox:
my question is - how do load another JS file and run that new JS file in a new global context? My guess is that require() is not available in the VM string code, so how can I load the code and pass the appropriate values to the file? (filename, dirname, module, etc).