Выполнить js-код в отдельном контексте и получить доступ к его глобальной переменной
Я хотел бы запустить сторонний файл JavaScript (у меня нет большого контроля над его содержимым) в node и получить доступ к глобальной переменной, созданной этим файловым кодом в его контексте.
Есть две вещи, которые я рассмотрел:
-
Запуск кода в vm
песочнице. Проблема в том, что я не знаю, как правильно создать контекст, потому что vm.createContext([sandbox])
не будет автоматически предоставлять основные вещи, такие как console
или require
или что-то еще в script, который я хочу запустить.
Это немного облом, потому что в документации явно указано (внимание мое):
Если задан объект песочницы, он будет "контекстуализировать" эту песочницу, чтобы ее можно было использовать в вызовах vm.runInContext() или script.runInContext(). Внутренние скрипты запускаются как таковые, песочница будет глобальным объектом, сохраняя все существующие свойства , но также имея встроенные объекты и функции любого стандартного глобального объекта.
Что такое "встроенные объекты и функции любого стандартного глобального объекта"? Я наивно полагаю, что это такие вещи, как console
, process
, require
и т.д. Но если так, API не работает, потому что они не установлены. Возможно, я что-то не понимаю.
var sandbox = vm.createContext({foo: 'foo'});
var code = 'console.log(foo);';
vm.runInContext(code, sandbox);
Результат:
evalmachine.:1
console.log(Foo);
^
ReferenceError: консоль не определена
-
Выполнение кода в дочернем процессе . Но я не могу найти документацию о доступе к глобальным переменным дочерних процессов. Я предполагаю, что единственный способ общаться с дочерним процессом - это передача сообщения, но даже это кажется от родителя к ребенку, а не наоборот...
В принципе, я застрял. Halp.
Ответы
Ответ 1
Вы можете использовать расширенный vm/песочницу для 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);
Ответ 2
Как просто передать родительский 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);
Ответ 3
В этом коде мы можем отправить любой ответ и получить доступ к глобальной переменной с помощью глобальной функции, а также получить доступ ко всем данным, возвращаемым из 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);
}