summaryrefslogtreecommitdiff
path: root/doc/api/vm.md
diff options
context:
space:
mode:
authorJames M Snell <jasnell@gmail.com>2016-05-17 21:56:01 -0700
committerJames M Snell <jasnell@gmail.com>2016-05-19 17:40:00 -0700
commitbaeed8b3d93efb337a09c902e259c0695d179a15 (patch)
treef1e00b0817491ec65ce3ead78188bc2015eb0ede /doc/api/vm.md
parent395cc885f4eb21c2002dbfe405d31da275699aa8 (diff)
downloadandroid-node-v8-baeed8b3d93efb337a09c902e259c0695d179a15.tar.gz
android-node-v8-baeed8b3d93efb337a09c902e259c0695d179a15.tar.bz2
android-node-v8-baeed8b3d93efb337a09c902e259c0695d179a15.zip
doc: improve vm.md copy
General improvements to vm module documentation PR-URL: https://github.com/nodejs/node/pull/6827 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Diffstat (limited to 'doc/api/vm.md')
-rw-r--r--doc/api/vm.md397
1 files changed, 234 insertions, 163 deletions
diff --git a/doc/api/vm.md b/doc/api/vm.md
index b212cc6e29..8de2775dcc 100644
--- a/doc/api/vm.md
+++ b/doc/api/vm.md
@@ -4,7 +4,8 @@
<!--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
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
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)
-Creating a new `Script` compiles `code` but does not run it. Instead, the
-created `vm.Script` object represents this compiled code. This script can be run
-later many times using methods below. The returned script is not bound to any
-global object. It is bound before each run, just for that run.
-
-The options when creating a script are:
-
-- `filename`: allows you to control the filename that shows up in any stack
- traces produced from this script.
-- `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 syntax errors compiling the
- code; errors while running the code are controlled by the options to the
- script's methods.
-- `timeout`: a number of milliseconds to execute `code` before terminating
- execution. If execution is terminated, an [`Error`][] will be thrown.
-- `cachedData`: an optional `Buffer` with V8's code cache data for the supplied
- source. When supplied `cachedDataRejected` value will be set to either
- `true` or `false` depending on acceptance of the data by V8.
-- `produceCachedData`: if `true` and no `cachedData` is present - V8 tries to
- produce code cache data for `code`. Upon success, a `Buffer` with V8's code
- cache data will be produced and stored in `cachedData` property of the
- returned `vm.Script` instance. `cachedDataProduced` value will be set to
- either `true` or `false` depending on whether code cache data is produced
- successfully.
+* `code` {string} The JavaScript code to compile.
+* `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.
+ * `cachedData` {Buffer} Provides an optional `Buffer` with V8's code cache
+ data for the supplied source. When supplied, the `cachedDataRejected` value
+ will be set to either `true` or `false` depending on acceptance of the data
+ by V8.
+ * `produceCachedData` {boolean} When `true` and no `cachedData` is present, V8
+ will attempt to produce code cache data for `code`. Upon success, a
+ `Buffer` with V8's code cache data will be produced and stored in the
+ `cachedData` property of the returned `vm.Script` instance.
+ The `cachedDataProduced` value will be set to either `true` or `false`
+ depending on whether code cache data is produced successfully.
+
+Creating a new `vm.Script` object compiles `code` but does not run it. The
+compiled `vm.Script` can be run later multiple times. It is important to note
+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])
-Similar to [`vm.runInContext()`][] but a method of a precompiled `Script`
-object. `script.runInContext()` runs `script`'s compiled code in
+* `contextifiedSandbox` {Object} A [contextified][] object as returned by the
+ `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
to local scope.
-`script.runInContext()` takes the same options as
-[`script.runInThisContext()`][].
-
-Example: compile code that increments a global variable and sets one, then
-execute the code multiple times. These globals are contained in the sandbox.
+The following example compiles code that increments a global variable, sets
+the value of another global variable, then execute the code multiple times.
+The globals are contained in the `sandbox` object.
```js
const util = require('util');
const vm = require('vm');
-var sandbox = {
+const sandbox = {
animal: 'cat',
count: 2
};
-var context = new vm.createContext(sandbox);
-var script = new vm.Script('count += 1; name = "kitty"');
+const script = new vm.Script('count += 1; name = "kitty";');
+const context = new vm.createContext(sandbox);
for (var i = 0; i < 10; ++i) {
script.runInContext(context);
}
@@ -82,33 +98,39 @@ console.log(util.inspect(sandbox));
// { 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])
-Similar to [`vm.runInNewContext()`][] but a method of a precompiled `Script`
-object. `script.runInNewContext()` contextifies `sandbox` if passed or creates a
-new contextified sandbox if it's omitted, and then runs `script`'s compiled code
-with the sandbox as the global object and returns the result. Running code does
-not have access to local scope.
-
-`script.runInNewContext()` takes the same options as
-[`script.runInThisContext()`][].
-
-Example: compile code that sets a global variable, then execute the code
-multiple times in different contexts. These globals are set on and contained in
-the sandboxes.
+* `sandbox` {Object} An object that will be [contextified][]. If `undefined`, a
+ new object will be created.
+* `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.
+
+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
const util = require('util');
const vm = require('vm');
-const sandboxes = [{}, {}, {}];
-
const script = new vm.Script('globalVar = "set"');
+const sandboxes = [{}, {}, {}];
sandboxes.forEach((sandbox) => {
script.runInNewContext(sandbox);
});
@@ -118,19 +140,28 @@ console.log(util.inspect(sandboxes));
// [{ 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])
-Similar to [`vm.runInThisContext()`][] but a method of a precompiled `Script`
-object. `script.runInThisContext()` runs `script`'s compiled code and returns
-the result. Running code does not have access to local scope, but does have
-access to the current `global` object.
-
-Example of using `script.runInThisContext()` to compile code once and run it
-multiple times:
+* `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` 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
const vm = require('vm');
@@ -148,53 +179,60 @@ console.log(globalVar);
// 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])
-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
-scripts run as such, `sandbox` will be the global object, retaining all its
-existing properties but also having the built-in objects and functions any
+such scripts, the `sandbox` object will be the global object, retaining all of
+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,
-`sandbox` will be unchanged.
+`sandbox` will remain unchanged.
-If not given a sandbox object, returns a new, empty contextified sandbox object
-you can use.
+If `sandbox` is omitted (or passed explicitly as `undefined`), a new, empty
+[contextified][] sandbox object will be returned.
-This function is useful for creating a sandbox that can be used to run multiple
-scripts, e.g. if you were emulating a web browser it could be used to create a
-single sandbox representing a window's global object, then run all `<script>`
-tags together inside that sandbox.
+The `vm.createContext()` method is primarily useful for creating a single
+sandbox that can be used to run multiple scripts. For instance, if emulating a
+web browser, the method can be used to create a single sandbox representing a
+window's global object, then run all `<script>` tags together within the context
+of that sandbox.
## vm.isContext(sandbox)
-Returns whether or not a sandbox object has been contextified by calling
-[`vm.createContext()`][] on it.
-
-## vm.runInContext(code, contextifiedSandbox[, options])
+* `sandbox` {Object}
-`vm.runInContext()` compiles `code`, then runs it in `contextifiedSandbox` and
-returns the result. Running code does not have access to local scope. The
-`contextifiedSandbox` object must have been previously contextified via
-[`vm.createContext()`][]; it will be used as the global object for `code`.
+Returns `true` if the given `sandbox` object has been [contextified][] using
+[`vm.createContext()`][].
-`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
const util = require('util');
@@ -204,21 +242,19 @@ const sandbox = { globalVar: 1 };
vm.createContext(sandbox);
for (var i = 0; i < 10; ++i) {
- vm.runInContext('globalVar *= 2;', sandbox);
+ vm.runInContext('globalVar *= 2;', sandbox);
}
console.log(util.inspect(sandbox));
// { 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()` compiles and executes `code` inside the V8 debug
-context. The primary use case is to get access to the V8 debug object:
+* `code` {string} The JavaScript code to compile and run.
+
+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
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'
```
-Note that the debug context and object are intrinsically tied to V8's debugger
-implementation and may change (or even get removed) without prior warning.
+*Note*: The debug context and object are intrinsically tied to V8's debugger
+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()` compiles `code`, contextifies `sandbox` if passed or
-creates a new contextified sandbox if it's omitted, and then runs the code with
-the sandbox as the global object and returns the result.
-
-`vm.runInNewContext()` takes the same options as [`vm.runInThisContext()`][].
-
-Example: compile and execute code that increments a global variable and sets a
-new one. These globals are contained in the sandbox.
+* `code` {string} The JavaScript code to compile and run.
+* `sandbox` {Object} An object that will be [contextified][]. If `undefined`, a
+ new object will be created.
+* `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()` 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
const util = require('util');
@@ -258,17 +311,29 @@ console.log(util.inspect(sandbox));
// { 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()` compiles `code`, runs it and returns the result. Running
-code does not have access to local scope, but does have access to the current
-`global` object.
-
-Example of using `vm.runInThisContext()` and [`eval()`][] to run the same code:
+* `code` {string} The JavaScript code to compile 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.
+
+`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
const vm = require('vm');
@@ -286,33 +351,21 @@ console.log('localVar: ', localVar);
// evalResult: 'eval', localVar: 'eval'
```
-`vm.runInThisContext()` does not have access to the local scope, so `localVar`
-is unchanged. [`eval()`][] does have access to the local scope, so `localVar` is
-changed.
-
-In this way `vm.runInThisContext()` is much like an [indirect `eval()` call][],
-e.g. `(0,eval)('code')`. However, it also has the following additional options:
-
-- `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. Will capture both syntax errors from compiling
- `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:
+Because `vm.runInThisContext()` does not have access to the local scope,
+`localVar` is unchanged. In contrast, [`eval()`][] *does* have access to the
+local scope, so the value `localVar` is changed. In this way
+`vm.runInThisContext()` is much like an [indirect `eval()` call][], e.g.
+`(0,eval)('code')`.
+
+## Example: Running an HTTP Server within a VM
+
+When using either `script.runInThisContext()` or `vm.runInThisContext()`, the
+code is executed within the current V8 global context. The code passed
+to this VM context will have its own isolated scope.
+
+In order to run a simple web server using the `http` module 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
'use strict';
@@ -334,10 +387,26 @@ let code =
vm.runInThisContext(code)(require);
```
-_Note: `require()` in the above case shares the state with context it is passed
-from. This might introduce risks when unknown code is executed, e.g. altering
-objects from the calling thread's context in unwanted ways. It is advisable to
-run `vm` code in a separate process._
+*Note*: The `require()` in the above case shares the state with context it is
+passed from. This may introduce risks when untrusted code is executed, e.g.
+altering objects from the calling thread's context in unwanted ways.
+
+## 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
[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.runInThisContext()`]: #vm_vm_runinthiscontext_code_options
[`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