|
@ -4,7 +4,8 @@ |
|
|
|
|
|
|
|
|
<!--name=vm--> |
|
|
<!--name=vm--> |
|
|
|
|
|
|
|
|
You can access this module with: |
|
|
The `vm` module provides APIs for compiling and running code within V8 Virtual |
|
|
|
|
|
Machine contexts. It can be accessed using: |
|
|
|
|
|
|
|
|
```js |
|
|
```js |
|
|
const vm = require('vm'); |
|
|
const vm = require('vm'); |
|
@ -13,66 +14,81 @@ const vm = require('vm'); |
|
|
JavaScript code can be compiled and run immediately or compiled, saved, and run |
|
|
JavaScript code can be compiled and run immediately or compiled, saved, and run |
|
|
later. |
|
|
later. |
|
|
|
|
|
|
|
|
## Class: Script |
|
|
## Class: vm.Script |
|
|
|
|
|
|
|
|
A class for holding precompiled scripts, and running them in specific sandboxes. |
|
|
Instances of the `vm.Script` class contain precompiled scripts that can be |
|
|
|
|
|
executed in specific sandboxes (or "contexts"). |
|
|
|
|
|
|
|
|
### new vm.Script(code, options) |
|
|
### new vm.Script(code, options) |
|
|
|
|
|
|
|
|
Creating a new `Script` compiles `code` but does not run it. Instead, the |
|
|
* `code` {string} The JavaScript code to compile. |
|
|
created `vm.Script` object represents this compiled code. This script can be run |
|
|
* `options` |
|
|
later many times using methods below. The returned script is not bound to any |
|
|
* `filename` {string} Specifies the filename used in stack traces produced |
|
|
global object. It is bound before each run, just for that run. |
|
|
by this script. |
|
|
|
|
|
* `lineOffset` {number} Specifies the line number offset that is displayed |
|
|
The options when creating a script are: |
|
|
in stack traces produced by this script. |
|
|
|
|
|
* `columnOffset` {number} Specifies the column number offset that is displayed |
|
|
- `filename`: allows you to control the filename that shows up in any stack |
|
|
in stack traces produced by this script. |
|
|
traces produced from this script. |
|
|
* `displayErrors` {boolean} When `true`, if an [`Error`][] error occurs |
|
|
- `lineOffset`: allows you to add an offset to the line number that is |
|
|
while compiling the `code`, the line of code causing the error is attached |
|
|
displayed in stack traces |
|
|
to the stack trace. |
|
|
- `columnOffset`: allows you to add an offset to the column number that is |
|
|
* `timeout` {number} Specifies the number of milliseconds to execute `code` |
|
|
displayed in stack traces |
|
|
before terminating execution. If execution is terminated, an [`Error`][] |
|
|
- `displayErrors`: if `true`, on error, attach the line of code that caused |
|
|
will be thrown. |
|
|
the error to the stack trace. Applies only to syntax errors compiling the |
|
|
* `cachedData` {Buffer} Provides an optional `Buffer` with V8's code cache |
|
|
code; errors while running the code are controlled by the options to the |
|
|
data for the supplied source. When supplied, the `cachedDataRejected` value |
|
|
script's methods. |
|
|
will be set to either `true` or `false` depending on acceptance of the data |
|
|
- `timeout`: a number of milliseconds to execute `code` before terminating |
|
|
by V8. |
|
|
execution. If execution is terminated, an [`Error`][] will be thrown. |
|
|
* `produceCachedData` {boolean} When `true` and no `cachedData` is present, V8 |
|
|
- `cachedData`: an optional `Buffer` with V8's code cache data for the supplied |
|
|
will attempt to produce code cache data for `code`. Upon success, a |
|
|
source. When supplied `cachedDataRejected` value will be set to either |
|
|
`Buffer` with V8's code cache data will be produced and stored in the |
|
|
`true` or `false` depending on acceptance of the data by V8. |
|
|
`cachedData` property of the returned `vm.Script` instance. |
|
|
- `produceCachedData`: if `true` and no `cachedData` is present - V8 tries to |
|
|
The `cachedDataProduced` value will be set to either `true` or `false` |
|
|
produce code cache data for `code`. Upon success, a `Buffer` with V8's code |
|
|
depending on whether code cache data is produced successfully. |
|
|
cache data will be produced and stored in `cachedData` property of the |
|
|
|
|
|
returned `vm.Script` instance. `cachedDataProduced` value will be set to |
|
|
Creating a new `vm.Script` object compiles `code` but does not run it. The |
|
|
either `true` or `false` depending on whether code cache data is produced |
|
|
compiled `vm.Script` can be run later multiple times. It is important to note |
|
|
successfully. |
|
|
that the `code` is not bound to any global object; rather, it is bound before |
|
|
|
|
|
each run, just for that run. |
|
|
|
|
|
|
|
|
### script.runInContext(contextifiedSandbox[, options]) |
|
|
### script.runInContext(contextifiedSandbox[, options]) |
|
|
|
|
|
|
|
|
Similar to [`vm.runInContext()`][] but a method of a precompiled `Script` |
|
|
* `contextifiedSandbox` {Object} A [contextified][] object as returned by the |
|
|
object. `script.runInContext()` runs `script`'s compiled code in |
|
|
`vm.createContext()` method. |
|
|
|
|
|
* `options` {Object} |
|
|
|
|
|
* `filename` {string} Specifies the filename used in stack traces produced |
|
|
|
|
|
by this script. |
|
|
|
|
|
* `lineOffset` {number} Specifies the line number offset that is displayed |
|
|
|
|
|
in stack traces produced by this script. |
|
|
|
|
|
* `columnOffset` {number} Specifies the column number offset that is displayed |
|
|
|
|
|
in stack traces produced by this script. |
|
|
|
|
|
* `displayErrors` {boolean} When `true`, if an [`Error`][] error occurs |
|
|
|
|
|
while compiling the `code`, the line of code causing the error is attached |
|
|
|
|
|
to the stack trace. |
|
|
|
|
|
* `timeout` {number} Specifies the number of milliseconds to execute `code` |
|
|
|
|
|
before terminating execution. If execution is terminated, an [`Error`][] |
|
|
|
|
|
will be thrown. |
|
|
|
|
|
|
|
|
|
|
|
Runs the compiled code contained by the `vm.Script` object within the given |
|
|
`contextifiedSandbox` and returns the result. Running code does not have access |
|
|
`contextifiedSandbox` and returns the result. Running code does not have access |
|
|
to local scope. |
|
|
to local scope. |
|
|
|
|
|
|
|
|
`script.runInContext()` takes the same options as |
|
|
The following example compiles code that increments a global variable, sets |
|
|
[`script.runInThisContext()`][]. |
|
|
the value of another global variable, then execute the code multiple times. |
|
|
|
|
|
The globals are contained in the `sandbox` object. |
|
|
Example: compile code that increments a global variable and sets one, then |
|
|
|
|
|
execute the code multiple times. These globals are contained in the sandbox. |
|
|
|
|
|
|
|
|
|
|
|
```js |
|
|
```js |
|
|
const util = require('util'); |
|
|
const util = require('util'); |
|
|
const vm = require('vm'); |
|
|
const vm = require('vm'); |
|
|
|
|
|
|
|
|
var sandbox = { |
|
|
const sandbox = { |
|
|
animal: 'cat', |
|
|
animal: 'cat', |
|
|
count: 2 |
|
|
count: 2 |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
var context = new vm.createContext(sandbox); |
|
|
const script = new vm.Script('count += 1; name = "kitty";'); |
|
|
var script = new vm.Script('count += 1; name = "kitty"'); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const context = new vm.createContext(sandbox); |
|
|
for (var i = 0; i < 10; ++i) { |
|
|
for (var i = 0; i < 10; ++i) { |
|
|
script.runInContext(context); |
|
|
script.runInContext(context); |
|
|
} |
|
|
} |
|
@ -82,33 +98,39 @@ console.log(util.inspect(sandbox)); |
|
|
// { animal: 'cat', count: 12, name: 'kitty' } |
|
|
// { animal: 'cat', count: 12, name: 'kitty' } |
|
|
``` |
|
|
``` |
|
|
|
|
|
|
|
|
Note that running untrusted code is a tricky business requiring great care. |
|
|
|
|
|
`script.runInContext()` is quite useful, but safely running untrusted code |
|
|
|
|
|
requires a separate process. |
|
|
|
|
|
|
|
|
|
|
|
### script.runInNewContext([sandbox][, options]) |
|
|
### script.runInNewContext([sandbox][, options]) |
|
|
|
|
|
|
|
|
Similar to [`vm.runInNewContext()`][] but a method of a precompiled `Script` |
|
|
* `sandbox` {Object} An object that will be [contextified][]. If `undefined`, a |
|
|
object. `script.runInNewContext()` contextifies `sandbox` if passed or creates a |
|
|
new object will be created. |
|
|
new contextified sandbox if it's omitted, and then runs `script`'s compiled code |
|
|
* `options` {Object} |
|
|
with the sandbox as the global object and returns the result. Running code does |
|
|
* `filename` {string} Specifies the filename used in stack traces produced |
|
|
not have access to local scope. |
|
|
by this script. |
|
|
|
|
|
* `lineOffset` {number} Specifies the line number offset that is displayed |
|
|
`script.runInNewContext()` takes the same options as |
|
|
in stack traces produced by this script. |
|
|
[`script.runInThisContext()`][]. |
|
|
* `columnOffset` {number} Specifies the column number offset that is displayed |
|
|
|
|
|
in stack traces produced by this script. |
|
|
Example: compile code that sets a global variable, then execute the code |
|
|
* `displayErrors` {boolean} When `true`, if an [`Error`][] error occurs |
|
|
multiple times in different contexts. These globals are set on and contained in |
|
|
while compiling the `code`, the line of code causing the error is attached |
|
|
the sandboxes. |
|
|
to the stack trace. |
|
|
|
|
|
* `timeout` {number} Specifies the number of milliseconds to execute `code` |
|
|
|
|
|
before terminating execution. If execution is terminated, an [`Error`][] |
|
|
|
|
|
will be thrown. |
|
|
|
|
|
|
|
|
|
|
|
First contextifies the given `sandbox`, runs the compiled code contained by |
|
|
|
|
|
the `vm.Script` object within the created sandbox, and returns the result. |
|
|
|
|
|
Running code does not have access to local scope. |
|
|
|
|
|
|
|
|
|
|
|
The following example compiles code that sets a global variable, then executes |
|
|
|
|
|
the code multiple times in different contexts. The globals are set on and |
|
|
|
|
|
contained within each individual `sandbox`. |
|
|
|
|
|
|
|
|
```js |
|
|
```js |
|
|
const util = require('util'); |
|
|
const util = require('util'); |
|
|
const vm = require('vm'); |
|
|
const vm = require('vm'); |
|
|
|
|
|
|
|
|
const sandboxes = [{}, {}, {}]; |
|
|
|
|
|
|
|
|
|
|
|
const script = new vm.Script('globalVar = "set"'); |
|
|
const script = new vm.Script('globalVar = "set"'); |
|
|
|
|
|
|
|
|
|
|
|
const sandboxes = [{}, {}, {}]; |
|
|
sandboxes.forEach((sandbox) => { |
|
|
sandboxes.forEach((sandbox) => { |
|
|
script.runInNewContext(sandbox); |
|
|
script.runInNewContext(sandbox); |
|
|
}); |
|
|
}); |
|
@ -118,19 +140,28 @@ console.log(util.inspect(sandboxes)); |
|
|
// [{ globalVar: 'set' }, { globalVar: 'set' }, { globalVar: 'set' }] |
|
|
// [{ globalVar: 'set' }, { globalVar: 'set' }, { globalVar: 'set' }] |
|
|
``` |
|
|
``` |
|
|
|
|
|
|
|
|
Note that running untrusted code is a tricky business requiring great care. |
|
|
|
|
|
`script.runInNewContext()` is quite useful, but safely running untrusted code |
|
|
|
|
|
requires a separate process. |
|
|
|
|
|
|
|
|
|
|
|
### script.runInThisContext([options]) |
|
|
### script.runInThisContext([options]) |
|
|
|
|
|
|
|
|
Similar to [`vm.runInThisContext()`][] but a method of a precompiled `Script` |
|
|
* `options` {Object} |
|
|
object. `script.runInThisContext()` runs `script`'s compiled code and returns |
|
|
* `filename` {string} Specifies the filename used in stack traces produced |
|
|
the result. Running code does not have access to local scope, but does have |
|
|
by this script. |
|
|
access to the current `global` object. |
|
|
* `lineOffset` {number} Specifies the line number offset that is displayed |
|
|
|
|
|
in stack traces produced by this script. |
|
|
Example of using `script.runInThisContext()` to compile code once and run it |
|
|
* `columnOffset` {number} Specifies the column number offset that is displayed |
|
|
multiple times: |
|
|
in stack traces produced by this script. |
|
|
|
|
|
* `displayErrors` {boolean} When `true`, if an [`Error`][] error occurs |
|
|
|
|
|
while compiling the `code`, the line of code causing the error is attached |
|
|
|
|
|
to the stack trace. |
|
|
|
|
|
* `timeout` {number} Specifies the number of milliseconds to execute `code` |
|
|
|
|
|
before terminating execution. If execution is terminated, an [`Error`][] |
|
|
|
|
|
will be thrown. |
|
|
|
|
|
|
|
|
|
|
|
Runs the compiled code contained by the `vm.Script` within the context of the |
|
|
|
|
|
current `global` object. Running code does not have access to local scope, but |
|
|
|
|
|
*does* have access to the current `global` object. |
|
|
|
|
|
|
|
|
|
|
|
The following example compiles code that increments a `global` variable then |
|
|
|
|
|
executes that code multiple times: |
|
|
|
|
|
|
|
|
```js |
|
|
```js |
|
|
const vm = require('vm'); |
|
|
const vm = require('vm'); |
|
@ -148,53 +179,60 @@ console.log(globalVar); |
|
|
// 1000 |
|
|
// 1000 |
|
|
``` |
|
|
``` |
|
|
|
|
|
|
|
|
The options for running a script are: |
|
|
|
|
|
|
|
|
|
|
|
- `filename`: allows you to control the filename that shows up in any stack |
|
|
|
|
|
traces produced. |
|
|
|
|
|
- `lineOffset`: allows you to add an offset to the line number that is |
|
|
|
|
|
displayed in stack traces |
|
|
|
|
|
- `columnOffset`: allows you to add an offset to the column number that is |
|
|
|
|
|
displayed in stack traces |
|
|
|
|
|
- `displayErrors`: if `true`, on error, attach the line of code that caused |
|
|
|
|
|
the error to the stack trace. Applies only to runtime errors executing the |
|
|
|
|
|
code; it is impossible to create a `Script` instance with syntax errors, as |
|
|
|
|
|
the constructor will throw. |
|
|
|
|
|
- `timeout`: a number of milliseconds to execute the script before terminating |
|
|
|
|
|
execution. If execution is terminated, an [`Error`][] will be thrown. |
|
|
|
|
|
|
|
|
|
|
|
## vm.createContext([sandbox]) |
|
|
## vm.createContext([sandbox]) |
|
|
|
|
|
|
|
|
If given a `sandbox` object, will "contextify" that sandbox so that it can be |
|
|
* `sandbox` {Object} |
|
|
|
|
|
|
|
|
|
|
|
If given a `sandbox` object, the `vm.createContext()` method will [prepare |
|
|
|
|
|
that sandbox][#vm_what_does_it_mean_to_contextify_an_object] so that it can be |
|
|
used in calls to [`vm.runInContext()`][] or [`script.runInContext()`][]. Inside |
|
|
used in calls to [`vm.runInContext()`][] or [`script.runInContext()`][]. Inside |
|
|
scripts run as such, `sandbox` will be the global object, retaining all its |
|
|
such scripts, the `sandbox` object will be the global object, retaining all of |
|
|
existing properties but also having the built-in objects and functions any |
|
|
its existing properties but also having the built-in objects and functions any |
|
|
standard [global object][] has. Outside of scripts run by the vm module, |
|
|
standard [global object][] has. Outside of scripts run by the vm module, |
|
|
`sandbox` will be unchanged. |
|
|
`sandbox` will remain unchanged. |
|
|
|
|
|
|
|
|
If not given a sandbox object, returns a new, empty contextified sandbox object |
|
|
If `sandbox` is omitted (or passed explicitly as `undefined`), a new, empty |
|
|
you can use. |
|
|
[contextified][] sandbox object will be returned. |
|
|
|
|
|
|
|
|
This function is useful for creating a sandbox that can be used to run multiple |
|
|
The `vm.createContext()` method is primarily useful for creating a single |
|
|
scripts, e.g. if you were emulating a web browser it could be used to create a |
|
|
sandbox that can be used to run multiple scripts. For instance, if emulating a |
|
|
single sandbox representing a window's global object, then run all `<script>` |
|
|
web browser, the method can be used to create a single sandbox representing a |
|
|
tags together inside that sandbox. |
|
|
window's global object, then run all `<script>` tags together within the context |
|
|
|
|
|
of that sandbox. |
|
|
|
|
|
|
|
|
## vm.isContext(sandbox) |
|
|
## vm.isContext(sandbox) |
|
|
|
|
|
|
|
|
Returns whether or not a sandbox object has been contextified by calling |
|
|
* `sandbox` {Object} |
|
|
[`vm.createContext()`][] on it. |
|
|
|
|
|
|
|
|
|
|
|
## vm.runInContext(code, contextifiedSandbox[, options]) |
|
|
|
|
|
|
|
|
|
|
|
`vm.runInContext()` compiles `code`, then runs it in `contextifiedSandbox` and |
|
|
Returns `true` if the given `sandbox` object has been [contextified][] using |
|
|
returns the result. Running code does not have access to local scope. The |
|
|
[`vm.createContext()`][]. |
|
|
`contextifiedSandbox` object must have been previously contextified via |
|
|
|
|
|
[`vm.createContext()`][]; it will be used as the global object for `code`. |
|
|
|
|
|
|
|
|
|
|
|
`vm.runInContext()` takes the same options as [`vm.runInThisContext()`][]. |
|
|
## vm.runInContext(code, contextifiedSandbox[, options]) |
|
|
|
|
|
|
|
|
Example: compile and execute different scripts in a single existing context. |
|
|
* `code` {string} The JavaScript code to compile and run. |
|
|
|
|
|
* `contextifiedSandbox` {Object} The [contextified][] object that will be used |
|
|
|
|
|
as the `global` when the `code` is compiled and run. |
|
|
|
|
|
* `options` |
|
|
|
|
|
* `filename` {string} Specifies the filename used in stack traces produced |
|
|
|
|
|
by this script. |
|
|
|
|
|
* `lineOffset` {number} Specifies the line number offset that is displayed |
|
|
|
|
|
in stack traces produced by this script. |
|
|
|
|
|
* `columnOffset` {number} Specifies the column number offset that is displayed |
|
|
|
|
|
in stack traces produced by this script. |
|
|
|
|
|
* `displayErrors` {boolean} When `true`, if an [`Error`][] error occurs |
|
|
|
|
|
while compiling the `code`, the line of code causing the error is attached |
|
|
|
|
|
to the stack trace. |
|
|
|
|
|
* `timeout` {number} Specifies the number of milliseconds to execute `code` |
|
|
|
|
|
before terminating execution. If execution is terminated, an [`Error`][] |
|
|
|
|
|
will be thrown. |
|
|
|
|
|
|
|
|
|
|
|
The `vm.runInContext()` method compiles `code`, runs it within the context of |
|
|
|
|
|
the `contextifiedSandbox`, then returns the result. Running code does not have |
|
|
|
|
|
access to the local scope. The `contextifiedSandbox` object *must* have been |
|
|
|
|
|
previously [contextified][] using the [`vm.createContext()`][] method. |
|
|
|
|
|
|
|
|
|
|
|
The following example compiles and executes different scripts using a single |
|
|
|
|
|
[contextified][] object: |
|
|
|
|
|
|
|
|
```js |
|
|
```js |
|
|
const util = require('util'); |
|
|
const util = require('util'); |
|
@ -204,21 +242,19 @@ const sandbox = { globalVar: 1 }; |
|
|
vm.createContext(sandbox); |
|
|
vm.createContext(sandbox); |
|
|
|
|
|
|
|
|
for (var i = 0; i < 10; ++i) { |
|
|
for (var i = 0; i < 10; ++i) { |
|
|
vm.runInContext('globalVar *= 2;', sandbox); |
|
|
vm.runInContext('globalVar *= 2;', sandbox); |
|
|
} |
|
|
} |
|
|
console.log(util.inspect(sandbox)); |
|
|
console.log(util.inspect(sandbox)); |
|
|
|
|
|
|
|
|
// { globalVar: 1024 } |
|
|
// { globalVar: 1024 } |
|
|
``` |
|
|
``` |
|
|
|
|
|
|
|
|
Note that running untrusted code is a tricky business requiring great care. |
|
|
|
|
|
`vm.runInContext()` is quite useful, but safely running untrusted code requires |
|
|
|
|
|
a separate process. |
|
|
|
|
|
|
|
|
|
|
|
## vm.runInDebugContext(code) |
|
|
## vm.runInDebugContext(code) |
|
|
|
|
|
|
|
|
`vm.runInDebugContext()` compiles and executes `code` inside the V8 debug |
|
|
* `code` {string} The JavaScript code to compile and run. |
|
|
context. The primary use case is to get access to the V8 debug object: |
|
|
|
|
|
|
|
|
The `vm.runInDebugContext()` method compiles and executes `code` inside the V8 |
|
|
|
|
|
debug context. The primary use case is to gain access to the V8 `Debug` object: |
|
|
|
|
|
|
|
|
```js |
|
|
```js |
|
|
const vm = require('vm'); |
|
|
const vm = require('vm'); |
|
@ -227,21 +263,38 @@ console.log(Debug.findScript(process.emit).name); // 'events.js' |
|
|
console.log(Debug.findScript(process.exit).name); // 'internal/process.js' |
|
|
console.log(Debug.findScript(process.exit).name); // 'internal/process.js' |
|
|
``` |
|
|
``` |
|
|
|
|
|
|
|
|
Note that the debug context and object are intrinsically tied to V8's debugger |
|
|
*Note*: The debug context and object are intrinsically tied to V8's debugger |
|
|
implementation and may change (or even get removed) without prior warning. |
|
|
implementation and may change (or even be removed) without prior warning. |
|
|
|
|
|
|
|
|
The debug object can also be exposed with the `--expose_debug_as=` switch. |
|
|
The `Debug` object can also be made available using the V8-specific |
|
|
|
|
|
`--expose_debug_as=` [command line option][cli.md]. |
|
|
|
|
|
|
|
|
## vm.runInNewContext(code[, sandbox][, options]) |
|
|
## vm.runInNewContext(code[, sandbox][, options]) |
|
|
|
|
|
|
|
|
`vm.runInNewContext()` compiles `code`, contextifies `sandbox` if passed or |
|
|
* `code` {string} The JavaScript code to compile and run. |
|
|
creates a new contextified sandbox if it's omitted, and then runs the code with |
|
|
* `sandbox` {Object} An object that will be [contextified][]. If `undefined`, a |
|
|
the sandbox as the global object and returns the result. |
|
|
new object will be created. |
|
|
|
|
|
* `options` |
|
|
`vm.runInNewContext()` takes the same options as [`vm.runInThisContext()`][]. |
|
|
* `filename` {string} Specifies the filename used in stack traces produced |
|
|
|
|
|
by this script. |
|
|
Example: compile and execute code that increments a global variable and sets a |
|
|
* `lineOffset` {number} Specifies the line number offset that is displayed |
|
|
new one. These globals are contained in the sandbox. |
|
|
in stack traces produced by this script. |
|
|
|
|
|
* `columnOffset` {number} Specifies the column number offset that is displayed |
|
|
|
|
|
in stack traces produced by this script. |
|
|
|
|
|
* `displayErrors` {boolean} When `true`, if an [`Error`][] error occurs |
|
|
|
|
|
while compiling the `code`, the line of code causing the error is attached |
|
|
|
|
|
to the stack trace. |
|
|
|
|
|
* `timeout` {number} Specifies the number of milliseconds to execute `code` |
|
|
|
|
|
before terminating execution. If execution is terminated, an [`Error`][] |
|
|
|
|
|
will be thrown. |
|
|
|
|
|
|
|
|
|
|
|
The `vm.runInContext()` first contextifies the given `sandbox` object (or |
|
|
|
|
|
creates a new `sandbox` if passed as `undefined`), compiles the `code`, runs it |
|
|
|
|
|
within the context of the created context, then returns the result. Running code |
|
|
|
|
|
does not have access to the local scope. |
|
|
|
|
|
|
|
|
|
|
|
The following example compiles and executes code that increments a global |
|
|
|
|
|
variable and sets a new one. These globals are contained in the `sandbox`. |
|
|
|
|
|
|
|
|
```js |
|
|
```js |
|
|
const util = require('util'); |
|
|
const util = require('util'); |
|
@ -258,17 +311,29 @@ console.log(util.inspect(sandbox)); |
|
|
// { animal: 'cat', count: 3, name: 'kitty' } |
|
|
// { animal: 'cat', count: 3, name: 'kitty' } |
|
|
``` |
|
|
``` |
|
|
|
|
|
|
|
|
Note that running untrusted code is a tricky business requiring great care. |
|
|
|
|
|
`vm.runInNewContext()` is quite useful, but safely running untrusted code requires |
|
|
|
|
|
a separate process. |
|
|
|
|
|
|
|
|
|
|
|
## vm.runInThisContext(code[, options]) |
|
|
## vm.runInThisContext(code[, options]) |
|
|
|
|
|
|
|
|
`vm.runInThisContext()` compiles `code`, runs it and returns the result. Running |
|
|
* `code` {string} The JavaScript code to compile and run. |
|
|
code does not have access to local scope, but does have access to the current |
|
|
* `options` |
|
|
`global` object. |
|
|
* `filename` {string} Specifies the filename used in stack traces produced |
|
|
|
|
|
by this script. |
|
|
Example of using `vm.runInThisContext()` and [`eval()`][] to run the same code: |
|
|
* `lineOffset` {number} Specifies the line number offset that is displayed |
|
|
|
|
|
in stack traces produced by this script. |
|
|
|
|
|
* `columnOffset` {number} Specifies the column number offset that is displayed |
|
|
|
|
|
in stack traces produced by this script. |
|
|
|
|
|
* `displayErrors` {boolean} When `true`, if an [`Error`][] error occurs |
|
|
|
|
|
while compiling the `code`, the line of code causing the error is attached |
|
|
|
|
|
to the stack trace. |
|
|
|
|
|
* `timeout` {number} Specifies the number of milliseconds to execute `code` |
|
|
|
|
|
before terminating execution. If execution is terminated, an [`Error`][] |
|
|
|
|
|
will be thrown. |
|
|
|
|
|
|
|
|
|
|
|
`vm.runInThisContext()` compiles `code`, runs it within the context of the |
|
|
|
|
|
current `global` and returns the result. Running code does not have access to |
|
|
|
|
|
local scope, but does have access to the current `global` object. |
|
|
|
|
|
|
|
|
|
|
|
The following example illustrates using both `vm.runInThisContext()` and |
|
|
|
|
|
the JavaScript [`eval()`][] function to run the same code: |
|
|
|
|
|
|
|
|
```js |
|
|
```js |
|
|
const vm = require('vm'); |
|
|
const vm = require('vm'); |
|
@ -286,33 +351,21 @@ console.log('localVar: ', localVar); |
|
|
// evalResult: 'eval', localVar: 'eval' |
|
|
// evalResult: 'eval', localVar: 'eval' |
|
|
``` |
|
|
``` |
|
|
|
|
|
|
|
|
`vm.runInThisContext()` does not have access to the local scope, so `localVar` |
|
|
Because `vm.runInThisContext()` does not have access to the local scope, |
|
|
is unchanged. [`eval()`][] does have access to the local scope, so `localVar` is |
|
|
`localVar` is unchanged. In contrast, [`eval()`][] *does* have access to the |
|
|
changed. |
|
|
local scope, so the value `localVar` is changed. In this way |
|
|
|
|
|
`vm.runInThisContext()` is much like an [indirect `eval()` call][], e.g. |
|
|
In this way `vm.runInThisContext()` is much like an [indirect `eval()` call][], |
|
|
`(0,eval)('code')`. |
|
|
e.g. `(0,eval)('code')`. However, it also has the following additional options: |
|
|
|
|
|
|
|
|
## Example: Running an HTTP Server within a VM |
|
|
- `filename`: allows you to control the filename that shows up in any stack |
|
|
|
|
|
traces produced. |
|
|
When using either `script.runInThisContext()` or `vm.runInThisContext()`, the |
|
|
- `lineOffset`: allows you to add an offset to the line number that is |
|
|
code is executed within the current V8 global context. The code passed |
|
|
displayed in stack traces |
|
|
to this VM context will have its own isolated scope. |
|
|
- `columnOffset`: allows you to add an offset to the column number that is |
|
|
|
|
|
displayed in stack traces |
|
|
In order to run a simple web server using the `http` module the code passed to |
|
|
- `displayErrors`: if `true`, on error, attach the line of code that caused |
|
|
the context must either call `require('http')` on its own, or have a reference |
|
|
the error to the stack trace. Will capture both syntax errors from compiling |
|
|
to the `http` module passed to it. For instance: |
|
|
`code` and runtime errors thrown by executing the compiled code. Defaults to |
|
|
|
|
|
`true`. |
|
|
|
|
|
- `timeout`: a number of milliseconds to execute `code` before terminating |
|
|
|
|
|
execution. If execution is terminated, an [`Error`][] will be thrown. |
|
|
|
|
|
|
|
|
|
|
|
## Example: Run a Server within a VM |
|
|
|
|
|
|
|
|
|
|
|
The context of `.runInThisContext()` refers to the V8 context. The code passed |
|
|
|
|
|
to this VM context will have it's own isolated scope. To run a simple web server |
|
|
|
|
|
using the `http` module, for instance, the code passed to the context must either |
|
|
|
|
|
call `require('http')` on its own, or have a reference to the `http` module passed |
|
|
|
|
|
to it. For instance: |
|
|
|
|
|
|
|
|
|
|
|
```js |
|
|
```js |
|
|
'use strict'; |
|
|
'use strict'; |
|
@ -334,10 +387,26 @@ let code = |
|
|
vm.runInThisContext(code)(require); |
|
|
vm.runInThisContext(code)(require); |
|
|
``` |
|
|
``` |
|
|
|
|
|
|
|
|
_Note: `require()` in the above case shares the state with context it is passed |
|
|
*Note*: The `require()` in the above case shares the state with context it is |
|
|
from. This might introduce risks when unknown code is executed, e.g. altering |
|
|
passed from. This may introduce risks when untrusted code is executed, e.g. |
|
|
objects from the calling thread's context in unwanted ways. It is advisable to |
|
|
altering objects from the calling thread's context in unwanted ways. |
|
|
run `vm` code in a separate process._ |
|
|
|
|
|
|
|
|
## What does it mean to "contextify" an object? |
|
|
|
|
|
|
|
|
|
|
|
All JavaScript executed within Node.js runs within the scope of a "context". |
|
|
|
|
|
According to the [V8 Embedder's Guide][]: |
|
|
|
|
|
|
|
|
|
|
|
> In V8, a context is an execution environment that allows separate, unrelated, |
|
|
|
|
|
> JavaScript applications to run in a single instance of V8. You must explicitly |
|
|
|
|
|
> specify the context in which you want any JavaScript code to be run. |
|
|
|
|
|
|
|
|
|
|
|
When the method `vm.createContext()` is called, the `sandbox` object that is |
|
|
|
|
|
passed in (or a newly created object if `sandbox` is `undefined`) is associated |
|
|
|
|
|
internally with a new instance of a V8 Context. This V8 Context provides the |
|
|
|
|
|
`code` run using the `vm` modules methods with an isolated global environment |
|
|
|
|
|
within which it can operate. The process of creating the V8 Context and |
|
|
|
|
|
associating it with the `sandbox` object is what this document refers to as |
|
|
|
|
|
"contextifying" the `sandbox`. |
|
|
|
|
|
|
|
|
[indirect `eval()` call]: https://es5.github.io/#x10.4.2 |
|
|
[indirect `eval()` call]: https://es5.github.io/#x10.4.2 |
|
|
[global object]: https://es5.github.io/#x15.1 |
|
|
[global object]: https://es5.github.io/#x15.1 |
|
@ -349,3 +418,5 @@ run `vm` code in a separate process._ |
|
|
[`vm.runInNewContext()`]: #vm_vm_runinnewcontext_code_sandbox_options |
|
|
[`vm.runInNewContext()`]: #vm_vm_runinnewcontext_code_sandbox_options |
|
|
[`vm.runInThisContext()`]: #vm_vm_runinthiscontext_code_options |
|
|
[`vm.runInThisContext()`]: #vm_vm_runinthiscontext_code_options |
|
|
[`eval()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval |
|
|
[`eval()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval |
|
|
|
|
|
[V8 Embedder's Guide]: https://developers.google.com/v8/embed#contexts |
|
|
|
|
|
[contextified]: #vm_what_does_it_mean_to_contextify_an_object |
|
|