在单独的上下文中运行 js 代码并访问其全局变量

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

本文关键字:代码 访问 全局变量 js 运行 单独 上下文      更新时间:2023-09-26

我想在节点中运行一个第三方JavaScript文件(我对它的内容没有太多控制权),并在其上下文中访问该文件代码创建的全局变量。

我考虑了两件事:

  1. vm沙盒中运行代码。问题是我不知道如何正确创建上下文,因为vm.createContext([sandbox])不会自动为我要运行的脚本提供基本内容,例如consolerequire或任何内容。

    这有点令人沮丧,因为文档明确指出(强调我的):

    如果给定一个沙盒对象,则将"上下文化"该沙箱,以便它可以用于调用vm.runInContext()或script.runInContext()。在脚本中以这种方式运行,沙盒将是全局对象,保留其所有现有属性,但也具有任何标准全局对象具有的内置对象和函数

    什么是"任何标准全局对象具有的内置对象和函数"?我天真地假设它是像consoleprocessrequire等。但如果是这样,API 将不起作用,因为这些未设置。我可能在这里误解了什么。

    var sandbox = vm.createContext({foo: 'foo'});
    var code = 'console.log(foo);';
    vm.runInContext(code, sandbox);
    

    这导致:

    评估机:1
    console.log(foo);

    ^ 引用错误:未定义控制台

  2. 在子进程中运行代码。但是我找不到任何有关访问子进程的全局变量的文档。我假设与子进程通信的唯一方法是通过消息传递,但即使这样似乎也是从父级到子级,而不是相反......

基本上,我被困住了。哈尔普。

您可以将高级虚拟机/沙盒用于 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);

在上下文中传递父级console怎么样?

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);

在此代码中,我们可以发送任何响应,并且可以访问具有全局函数的全局变量,并且可以访问从 VM 沙箱返回的整个数据。

 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);
 }