| # Executing JavaScript |
| |
| Stability: 2 - Unstable. See Caveats, below. |
| |
| <!--name=vm--> |
| |
| You can access this module with: |
| |
| var vm = require('vm'); |
| |
| JavaScript code can be compiled and run immediately or compiled, saved, and run later. |
| |
| ## Caveats |
| |
| The `vm` module has many known issues and edge cases. If you run into |
| issues or unexpected behavior, please consult [the open issues on |
| GitHub](https://github.com/joyent/node/issues?labels=vm&state=open). |
| Some of the biggest problems are described below. |
| |
| ### Sandboxes |
| |
| The `sandbox` argument to `vm.runInNewContext` and `vm.createContext`, |
| along with the `initSandbox` argument to `vm.createContext`, do not |
| behave as one might normally expect and their behavior varies |
| between different versions of Node. |
| |
| The key issue to be aware of is that V8 provides no way to directly |
| control the global object used within a context. As a result, while |
| properties of your `sandbox` object will be available in the context, |
| any properties from the `prototype`s of the `sandbox` may not be |
| available. Furthermore, the `this` expression within the global scope |
| of the context evaluates to the empty object (`{}`) instead of to |
| your sandbox. |
| |
| Your sandbox's properties are also not shared directly with the script. |
| Instead, the properties of the sandbox are copied into the context at |
| the beginning of execution, and then after execution, the properties |
| are copied back out in an attempt to propagate any changes. |
| |
| ### Globals |
| |
| Properties of the global object, like `Array` and `String`, have |
| different values inside of a context. This means that common |
| expressions like `[] instanceof Array` or |
| `Object.getPrototypeOf([]) === Array.prototype` may not produce |
| expected results when used inside of scripts evaluated via the `vm` module. |
| |
| Some of these problems have known workarounds listed in the issues for |
| `vm` on GitHub. for example, `Array.isArray` works around |
| the example problem with `Array`. |
| |
| ## vm.runInThisContext(code, [filename]) |
| |
| `vm.runInThisContext()` compiles `code`, runs it and returns the result. Running |
| code does not have access to local scope. `filename` is optional, it's used only |
| in stack traces. |
| |
| Example of using `vm.runInThisContext` and `eval` to run the same code: |
| |
| var localVar = 123, |
| usingscript, evaled, |
| vm = require('vm'); |
| |
| usingscript = vm.runInThisContext('localVar = 1;', |
| 'myfile.vm'); |
| console.log('localVar: ' + localVar + ', usingscript: ' + |
| usingscript); |
| evaled = eval('localVar = 1;'); |
| console.log('localVar: ' + localVar + ', evaled: ' + |
| evaled); |
| |
| // localVar: 123, usingscript: 1 |
| // localVar: 1, evaled: 1 |
| |
| `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 case of syntax error in `code`, `vm.runInThisContext` emits the syntax error to stderr |
| and throws an exception. |
| |
| |
| ## vm.runInNewContext(code, [sandbox], [filename]) |
| |
| `vm.runInNewContext` compiles `code`, then runs it in `sandbox` and returns the |
| result. Running code does not have access to local scope. The object `sandbox` |
| will be used as the global object for `code`. |
| `sandbox` and `filename` are optional, `filename` is only used in stack traces. |
| |
| Example: compile and execute code that increments a global variable and sets a new one. |
| These globals are contained in the sandbox. |
| |
| var util = require('util'), |
| vm = require('vm'), |
| sandbox = { |
| animal: 'cat', |
| count: 2 |
| }; |
| |
| vm.runInNewContext('count += 1; name = "kitty"', sandbox, 'myfile.vm'); |
| console.log(util.inspect(sandbox)); |
| |
| // { animal: 'cat', count: 3, name: 'kitty' } |
| |
| Note that running untrusted code is a tricky business requiring great care. To prevent accidental |
| global variable leakage, `vm.runInNewContext` is quite useful, but safely running untrusted code |
| requires a separate process. |
| |
| In case of syntax error in `code`, `vm.runInNewContext` emits the syntax error to stderr |
| and throws an exception. |
| |
| ## vm.runInContext(code, context, [filename]) |
| |
| `vm.runInContext` compiles `code`, then runs it in `context` and returns the |
| result. A (V8) context comprises a global object, together with a set of |
| built-in objects and functions. Running code does not have access to local scope |
| and the global object held within `context` will be used as the global object |
| for `code`. |
| `filename` is optional, it's used only in stack traces. |
| |
| Example: compile and execute code in a existing context. |
| |
| var util = require('util'), |
| vm = require('vm'), |
| initSandbox = { |
| animal: 'cat', |
| count: 2 |
| }, |
| context = vm.createContext(initSandbox); |
| |
| vm.runInContext('count += 1; name = "CATT"', context, 'myfile.vm'); |
| console.log(util.inspect(context)); |
| |
| // { animal: 'cat', count: 3, name: 'CATT' } |
| |
| Note that `createContext` will perform a shallow clone of the supplied sandbox object in order to |
| initialize the global object of the freshly constructed context. |
| |
| Note that running untrusted code is a tricky business requiring great care. To prevent accidental |
| global variable leakage, `vm.runInContext` is quite useful, but safely running untrusted code |
| requires a separate process. |
| |
| In case of syntax error in `code`, `vm.runInContext` emits the syntax error to stderr |
| and throws an exception. |
| |
| ## vm.createContext([initSandbox]) |
| |
| `vm.createContext` creates a new context which is suitable for use as the 2nd argument of a subsequent |
| call to `vm.runInContext`. A (V8) context comprises a global object together with a set of |
| build-in objects and functions. The optional argument `initSandbox` will be shallow-copied |
| to seed the initial contents of the global object used by the context. |
| |
| ## vm.createScript(code, [filename]) |
| |
| `createScript` compiles `code` but does not run it. Instead, it returns a |
| `vm.Script` object representing 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. `filename` is |
| optional, it's only used in stack traces. |
| |
| In case of syntax error in `code`, `createScript` prints the syntax error to stderr |
| and throws an exception. |
| |
| |
| ## Class: Script |
| |
| A class for running scripts. Returned by vm.createScript. |
| |
| ### script.runInThisContext() |
| |
| Similar to `vm.runInThisContext` but a method of a precompiled `Script` object. |
| `script.runInThisContext` runs the code of `script` and returns the result. |
| Running code does not have access to local scope, but does have access to the `global` object |
| (v8: in actual context). |
| |
| Example of using `script.runInThisContext` to compile code once and run it multiple times: |
| |
| var vm = require('vm'); |
| |
| globalVar = 0; |
| |
| var script = vm.createScript('globalVar += 1', 'myfile.vm'); |
| |
| for (var i = 0; i < 1000 ; i += 1) { |
| script.runInThisContext(); |
| } |
| |
| console.log(globalVar); |
| |
| // 1000 |
| |
| |
| ### script.runInNewContext([sandbox]) |
| |
| Similar to `vm.runInNewContext` a method of a precompiled `Script` object. |
| `script.runInNewContext` runs the code of `script` with `sandbox` as the global object and returns the result. |
| Running code does not have access to local scope. `sandbox` is optional. |
| |
| Example: compile code that increments a global variable and sets one, then execute this code multiple times. |
| These globals are contained in the sandbox. |
| |
| var util = require('util'), |
| vm = require('vm'), |
| sandbox = { |
| animal: 'cat', |
| count: 2 |
| }; |
| |
| var script = vm.createScript('count += 1; name = "kitty"', 'myfile.vm'); |
| |
| for (var i = 0; i < 10 ; i += 1) { |
| script.runInNewContext(sandbox); |
| } |
| |
| console.log(util.inspect(sandbox)); |
| |
| // { animal: 'cat', count: 12, name: 'kitty' } |
| |
| Note that running untrusted code is a tricky business requiring great care. To prevent accidental |
| global variable leakage, `script.runInNewContext` is quite useful, but safely running untrusted code |
| requires a separate process. |