Spec-Zone.ru › Node.js 4 LTS

Виртуальная машина (выполнение JavaScript)

Стабильность: 2 — Стабильно

Вы можете получить доступ к этому модулю следующим образом:

const vm = require('vm');

Код JavaScript можно компилировать и запускать немедленно или компилировать, сохранять и запускать позже.

Класс: Script

Добавлен в: v0.3.1

Класс для хранения предварительно скомпилированных скриптов и их запуска в определённых защищённых средах.

new vm.Script(code, options)

Добавлен в: v0.3.1

Создание нового Script компилирует code но не запускает его. Вместо этого созданный vm.Script объект представляет этот скомпилированный код. Этот скрипт можно запустить многократно позже с помощью методов ниже. Возвращаемый скрипт не привязан к какому-либо глобальному объекту. Он привязывается перед каждым запуском только для этого запуска.

Параметры при создании скрипта:

  • filename: позволяет управлять именем файла, отображаемым в любых трассировках стека, сгенерированных этим скриптом.
  • columnOffset: позволяет добавить смещение к номеру столбца, отображаемому в трассировках стека
  • lineOffset: позволяет добавить смещение к номеру строки, отображаемому в трассировках стека
  • displayErrors: указывает, нужно ли выводить ошибки в stderr с выделением строки кода, вызвавшей ошибку, перед выбросом исключения. Применяется только к синтаксическим ошибкам при компиляции кода; ошибки во время выполнения кода контролируются параметрами методов скрипта.
  • timeout: количество миллисекунд для выполнения code перед завершением выполнения. Если выполнение завершится преждевременно, будет выброшено исключение Error.

script.runInContext(contextifiedSandbox[, options])

Добавлен в: v0.3.1

Аналогично vm.runInContext(), но является методом предварительно скомпилированного Script объекта. script.runInContext() выполняет скомпилированный код script в contextifiedSandbox и возвращает результат. Выполняемый код не имеет доступа к локальному пространству имён.

script.runInContext() принимает те же параметры, что и script.runInThisContext().

Пример: компилируется код, который увеличивает глобальную переменную и устанавливает новую, а затем код выполняется несколько раз. Эти глобальные переменные содержатся в защищённой среде.

const util = require('util');
const vm = require('vm');

var sandbox = {
  animal: 'cat',
  count: 2
};

var context = new vm.createContext(sandbox);
var script = new vm.Script('count += 1; name = "kitty"');

for (var i = 0; i < 10; ++i) {
  script.runInContext(context);
}

console.log(util.inspect(sandbox));

// { animal: 'cat', count: 12, name: 'kitty' }

Обратите внимание, что выполнение недоверенного кода — это сложная задача, требующая большой осторожности. script.runInContext() весьма полезно, но для безопасного выполнения недоверенного кода требуется отдельный процесс.

script.runInNewContext([sandbox][, options])

Добавлен в: v0.3.1

Аналогично vm.runInNewContext(), но является методом предварительно скомпилированного Script объекта. script.runInNewContext() контекстуализирует sandbox (если передан) или создаёт новую контекстуализированную защищённую среду (если параметр опущен), а затем выполняет скомпилированный код script с защищённой средой в качестве глобального объекта и возвращает результат. Выполняемый код не имеет доступа к локальному пространству имён.

script.runInNewContext() принимает те же параметры, что и script.runInThisContext().

Пример: компилируется код, который устанавливает глобальную переменную, а затем код выполняется несколько раз в разных контекстах. Эти глобальные переменные устанавливаются и содержатся в защищённых средах.

const util = require('util');
const vm = require('vm');

const sandboxes = [{}, {}, {}];

const script = new vm.Script('globalVar = "set"');

sandboxes.forEach((sandbox) => {
  script.runInNewContext(sandbox);
});

console.log(util.inspect(sandboxes));

// [{ globalVar: 'set' }, { globalVar: 'set' }, { globalVar: 'set' }]

Обратите внимание, что выполнение недоверенного кода — это сложная задача, требующая большой осторожности. script.runInNewContext() весьма полезно, но для безопасного выполнения недоверенного кода требуется отдельный процесс.

script.runInThisContext([options])

Добавлен в: v0.3.1

Аналогично vm.runInThisContext(), но является методом предварительно скомпилированного Script объекта. script.runInThisContext() выполняет скомпилированный код script и возвращает результат. Выполняемый код не имеет доступа к локальному пространству имён, но имеет доступ к текущему global объекту.

Пример использования script.runInThisContext() для компиляции кода один раз и его многократного выполнения:

const vm = require('vm');

global.globalVar = 0;

const script = new vm.Script('globalVar += 1', { filename: 'myfile.vm' });

for (var i = 0; i < 1000; ++i) {
  script.runInThisContext();
}

console.log(globalVar);

// 1000

Параметры для запуска скрипта:

  • filename: позволяет управлять именем файла, отображаемым в любых трассировках стека, сгенерированных этим скриптом.
  • lineOffset: позволяет добавить смещение к номеру строки, отображаемому в трассировках стека
  • columnOffset: позволяет добавить смещение к номеру столбца, отображаемому в трассировках стека
  • displayErrors: указывает, нужно ли выводить ошибки в stderr с выделением строки кода, вызвавшей ошибку, перед выбросом исключения. Применяется только к ошибкам во время выполнения кода; невозможно создать экземпляр Script с синтаксическими ошибками, так как конструктор выбросит исключение.
  • timeout: количество миллисекунд для выполнения скрипта перед завершением выполнения. Если выполнение завершится преждевременно, будет выброшено исключение Error.

vm.createContext([sandbox])

Добавлен в: v0.3.1

Если задан объект sandbox, он "контекстуализирует" эту защищённую среду, чтобы её можно было использовать в вызовах vm.runInContext() или script.runInContext(). Внутри скриптов, запущенных таким образом, sandbox будет глобальным объектом, сохраняя все свои существующие свойства, а также встроенные объекты и функции, имеющиеся у стандартного глобального объекта. Вне скриптов, выполняемых модулем vm, sandbox останется без изменений.

Если объект защищённой среды не передан, возвращается новый пустой контекстуализированный объект защищённой среды, который можно использовать.

Эта функция полезна для создания защищённой среды, которая может использоваться для запуска нескольких скриптов, например, если вы эмулируете веб-браузер, она может быть использована для создания одной защищённой среды, представляющей глобальный объект окна, а затем для запуска всех <script> тегов вместе внутри этой защищённой среды.

vm.isContext(sandbox)

Добавлен в: v0.11.7

Возвращает значение true, если объект защищённой среды был контекстуализирован путём вызова vm.createContext() на нём.

vm.runInContext(code, contextifiedSandbox[, options])

vm.runInContext() компилирует code, затем выполняет его в contextifiedSandbox и возвращает результат. Выполняемый код не имеет доступа к локальному пространству имён. Объект contextifiedSandbox должен быть предварительно контекстуализирован с помощью vm.createContext(); он будет использован в качестве глобального объекта для code.

vm.runInContext() принимает те же параметры, что и vm.runInThisContext().

Пример: компиляция и выполнение различных скриптов в одном существующем контексте.

const util = require('util');
const vm = require('vm');

const sandbox = { globalVar: 1 };
vm.createContext(sandbox);

for (var i = 0; i < 10; ++i) {
    vm.runInContext('globalVar *= 2;', sandbox);
}
console.log(util.inspect(sandbox));

// { globalVar: 1024 }

Обратите внимание, что выполнение недоверенного кода — это сложная задача, требующая большой осторожности. vm.runInContext() весьма полезно, но для безопасного выполнения недоверенного кода требуется отдельный процесс.

vm.runInDebugContext(code)

Добавлен в: v0.11.14

vm.runInDebugContext() компилирует и выполняет code в контексте отладки V8. Основной случай использования — получение доступа к объекту отладки V8:

const vm = require('vm');
const Debug = vm.runInDebugContext('Debug');
console.log(Debug.findScript(process.emit).name);  // 'events.js'
console.log(Debug.findScript(process.exit).name);  // 'internal/process.js'

Обратите внимание, что контекст и объект отладки тесно связаны с реализацией отладчика V8 и могут измениться (или даже быть удалены) без предварительного предупреждения.

Объект отладки также может быть доступен с помощью ключа --expose_debug_as=.

vm.runInNewContext(code[, sandbox][, options])

Добавлен в: v0.3.1

vm.runInNewContext() компилирует code, контекстуализирует sandbox (если передан) или создаёт новую контекстуализированную защищённую среду (если параметр опущен), а затем выполняет код с защищённой средой в качестве глобального объекта и возвращает результат.

vm.runInNewContext() принимает те же параметры, что и vm.runInThisContext().

Пример: компиляция и выполнение кода, который увеличивает глобальную переменную и устанавливает новую. Эти глобальные переменные содержатся в защищённой среде.

const util = require('util');
const vm = require('vm');

const sandbox = {
  animal: 'cat',
  count: 2
};

vm.runInNewContext('count += 1; name = "kitty"', sandbox);
console.log(util.inspect(sandbox));

// { animal: 'cat', count: 3, name: 'kitty' }

Обратите внимание, что выполнение недоверенного кода — это сложная задача, требующая большой осторожности. vm.runInNewContext() весьма полезно, но для безопасного выполнения недоверенного кода требуется отдельный процесс.

vm.runInThisContext(code[, options])

Добавлен в: v0.3.1

vm.runInThisContext() компилирует code, выполняет его и возвращает результат. Выполняемый код не имеет доступа к локальному пространству имён, но имеет доступ к текущему global объекту.

Пример использования vm.runInThisContext() и eval() для запуска одного и того же кода:

const vm = require('vm');
var localVar = 'initial value';

const vmResult = vm.runInThisContext('localVar = "vm";');
console.log('vmResult:', vmResult);
console.log('localVar:', localVar);

const evalResult = eval('localVar = "eval";');
console.log('evalResult:', evalResult);
console.log('localVar:', localVar);

// vmResult: 'vm', localVar: 'initial value'
// evalResult: 'eval', localVar: 'eval'

vm.runInThisContext() не имеет доступа к локальному пространству имён, поэтому localVar остаётся без изменений. eval() имеет доступ к локальному пространству имён, поэтому localVar меняется.

Таким образом, vm.runInThisContext() очень похож на непрямой eval() вызов, например, (0,eval)('code'). Однако у него также есть следующие дополнительные параметры:

  • filename: позволяет управлять именем файла, отображаемым в любых трассировках стека, сгенерированных этим скриптом.
  • lineOffset: позволяет добавить смещение к номеру строки, отображаемому в трассировках стека
  • columnOffset: позволяет добавить смещение к номеру столбца, отображаемому в трассировках стека
  • displayErrors: указывает, нужно ли выводить ошибки в stderr с выделением строки кода, вызвавшей ошибку, перед выбросом исключения. Будет захватывать как синтаксические ошибки при компиляции code, так и ошибки выполнения, выброшенные при выполнении скомпилированного кода. По умолчанию true.
  • timeout: количество миллисекунд для выполнения code перед завершением выполнения. Если выполнение завершится преждевременно, будет выброшено исключение Error.

Пример: запуск сервера внутри виртуальной машины

Контекст .runInThisContext() относится к контексту V8. Код, переданный в этот контекст виртуальной машины, будет иметь свой изолированный объем. Например, для запуска простого веб-сервера с помощью модуля http, код, переданный в контекст, должен либо вызвать require('http'), либо иметь ссылку на модуль http.

'use strict';
const vm = require('vm');

let code =
`(function(require) {

   const http = require('http');

   http.createServer( (request, response) => {
     response.writeHead(200, {'Content-Type': 'text/plain'});
     response.end('Hello World\\n');
   }).listen(8124);

   console.log('Server running at http://127.0.0.1:8124/');
 })`;

 vm.runInThisContext(code)(require);

Примечание: require() в приведенном выше случае разделяет состояние с контекстом, из которого он передан. Это может создать риски при выполнении неизвестного кода, например, при изменении объектов из контекста вызывающей нити нежелательными способами. Рекомендуется запускать код vm в отдельном процессе.

© Joyent, Inc. and other Node contributors
Licensed under the MIT License.
Node.js is a trademark of Joyent, Inc. and is used with its permission.
We are not endorsed by or affiliated with Joyent.
https://nodejs.org/dist/latest-v4.x/docs/api/vm.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API