├── .github └── FUNDING.yml ├── .npmrc ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── example └── run │ ├── bundle.js │ ├── entry.js │ ├── index.html │ └── server.js ├── index.js ├── package.json ├── readme.markdown ├── security.md └── test └── vm.js /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: npm/vm-browserify 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | dist: xenial 3 | node_js: 4 | - "stable" 5 | script: 6 | - xvfb-run --auto-servernum npm test 7 | services: 8 | - xvfb 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # vm-browserify Change Log 2 | All notable changes to this project will be documented in this file. 3 | This project adheres to [Semantic Versioning](http://semver.org/). 4 | 5 | ## 1.1.2 - 2019-11-04 6 | * Update another jQuery reference in the readme. (https://github.com/browserify/vm-browserify/pull/27) 7 | * Get rid of jQuery references altogether from samples and readme. (https://github.com/browserify/vm-browserify/commit/d509e8e5afb7b1ead191cbbd49c37a3fb934b2dc) 8 | 9 | ## 1.1.1 - 2019-11-04 10 | * Update a reference to jQuery in an example file that was setting off some security software. (https://github.com/browserify/vm-browserify/pull/22) 11 | 12 | ## 1.1.0 - 2018-06-15 13 | * Add `vm.isContext(sandbox)`. (https://github.com/browserify/vm-browserify/commit/038c3cb33edcad9eec33aa8a8beae31b15c1a006) 14 | 15 | ## 1.0.1 - 2018-04-13 16 | * Remove the `component-indexof` dependency. (https://github.com/browserify/vm-browserify/commit/0d9bd4c99f80db12c5c45e260a23ebfc51ec850d) 17 | 18 | ## 1.0.0 - 2018-03-23 19 | 20 | (This is not a breaking change.) 21 | 22 | * Make the `sandbox` argument to `runInNewContext` optional, like in Node. (https://github.com/browserify/vm-browserify/pull/13) 23 | * Substituting `component-indexof` for deprecated `indexof`. (https://github.com/browserify/vm-browserify/pull/14) 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so, 8 | subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | -------------------------------------------------------------------------------- /example/run/bundle.js: -------------------------------------------------------------------------------- 1 | (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i 2 | 3 | 4 | 5 | 6 | result = 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/run/server.js: -------------------------------------------------------------------------------- 1 | var ecstatic = require('ecstatic')(__dirname); 2 | var http = require('http'); 3 | http.createServer(ecstatic).listen(8000); 4 | 5 | console.log('listening on :8000'); 6 | console.log('# remember to run browserify entry.js -o bundle.js'); 7 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var indexOf = function (xs, item) { 2 | if (xs.indexOf) return xs.indexOf(item); 3 | else for (var i = 0; i < xs.length; i++) { 4 | if (xs[i] === item) return i; 5 | } 6 | return -1; 7 | }; 8 | var Object_keys = function (obj) { 9 | if (Object.keys) return Object.keys(obj) 10 | else { 11 | var res = []; 12 | for (var key in obj) res.push(key) 13 | return res; 14 | } 15 | }; 16 | 17 | var forEach = function (xs, fn) { 18 | if (xs.forEach) return xs.forEach(fn) 19 | else for (var i = 0; i < xs.length; i++) { 20 | fn(xs[i], i, xs); 21 | } 22 | }; 23 | 24 | var defineProp = (function() { 25 | try { 26 | Object.defineProperty({}, '_', {}); 27 | return function(obj, name, value) { 28 | Object.defineProperty(obj, name, { 29 | writable: true, 30 | enumerable: false, 31 | configurable: true, 32 | value: value 33 | }) 34 | }; 35 | } catch(e) { 36 | return function(obj, name, value) { 37 | obj[name] = value; 38 | }; 39 | } 40 | }()); 41 | 42 | var globals = ['Array', 'Boolean', 'Date', 'Error', 'EvalError', 'Function', 43 | 'Infinity', 'JSON', 'Math', 'NaN', 'Number', 'Object', 'RangeError', 44 | 'ReferenceError', 'RegExp', 'String', 'SyntaxError', 'TypeError', 'URIError', 45 | 'decodeURI', 'decodeURIComponent', 'encodeURI', 'encodeURIComponent', 'escape', 46 | 'eval', 'isFinite', 'isNaN', 'parseFloat', 'parseInt', 'undefined', 'unescape']; 47 | 48 | function Context() {} 49 | Context.prototype = {}; 50 | 51 | var Script = exports.Script = function NodeScript (code) { 52 | if (!(this instanceof Script)) return new Script(code); 53 | this.code = code; 54 | }; 55 | 56 | Script.prototype.runInContext = function (context) { 57 | if (!(context instanceof Context)) { 58 | throw new TypeError("needs a 'context' argument."); 59 | } 60 | 61 | var iframe = document.createElement('iframe'); 62 | if (!iframe.style) iframe.style = {}; 63 | iframe.style.display = 'none'; 64 | 65 | document.body.appendChild(iframe); 66 | 67 | var win = iframe.contentWindow; 68 | var wEval = win.eval, wExecScript = win.execScript; 69 | 70 | if (!wEval && wExecScript) { 71 | // win.eval() magically appears when this is called in IE: 72 | wExecScript.call(win, 'null'); 73 | wEval = win.eval; 74 | } 75 | 76 | forEach(Object_keys(context), function (key) { 77 | win[key] = context[key]; 78 | }); 79 | forEach(globals, function (key) { 80 | if (context[key]) { 81 | win[key] = context[key]; 82 | } 83 | }); 84 | 85 | var winKeys = Object_keys(win); 86 | 87 | var res = wEval.call(win, this.code); 88 | 89 | forEach(Object_keys(win), function (key) { 90 | // Avoid copying circular objects like `top` and `window` by only 91 | // updating existing context properties or new properties in the `win` 92 | // that was only introduced after the eval. 93 | if (key in context || indexOf(winKeys, key) === -1) { 94 | context[key] = win[key]; 95 | } 96 | }); 97 | 98 | forEach(globals, function (key) { 99 | if (!(key in context)) { 100 | defineProp(context, key, win[key]); 101 | } 102 | }); 103 | 104 | document.body.removeChild(iframe); 105 | 106 | return res; 107 | }; 108 | 109 | Script.prototype.runInThisContext = function () { 110 | return eval(this.code); // maybe... 111 | }; 112 | 113 | Script.prototype.runInNewContext = function (context) { 114 | var ctx = Script.createContext(context); 115 | var res = this.runInContext(ctx); 116 | 117 | if (context) { 118 | forEach(Object_keys(ctx), function (key) { 119 | context[key] = ctx[key]; 120 | }); 121 | } 122 | 123 | return res; 124 | }; 125 | 126 | forEach(Object_keys(Script.prototype), function (name) { 127 | exports[name] = Script[name] = function (code) { 128 | var s = Script(code); 129 | return s[name].apply(s, [].slice.call(arguments, 1)); 130 | }; 131 | }); 132 | 133 | exports.isContext = function (context) { 134 | return context instanceof Context; 135 | }; 136 | 137 | exports.createScript = function (code) { 138 | return exports.Script(code); 139 | }; 140 | 141 | exports.createContext = Script.createContext = function (context) { 142 | var copy = new Context(); 143 | if(typeof context === 'object') { 144 | forEach(Object_keys(context), function (key) { 145 | copy[key] = context[key]; 146 | }); 147 | } 148 | return copy; 149 | }; 150 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vm-browserify", 3 | "version": "1.1.2", 4 | "description": "vm module for the browser", 5 | "main": "index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "http://github.com/browserify/vm-browserify.git" 9 | }, 10 | "keywords": [ 11 | "vm", 12 | "browser", 13 | "eval" 14 | ], 15 | "dependencies": {}, 16 | "devDependencies": { 17 | "browserify": "^16.1.1", 18 | "tape": "^4.11.0", 19 | "tape-run": "^6.0.1" 20 | }, 21 | "author": { 22 | "name": "James Halliday", 23 | "email": "mail@substack.net", 24 | "url": "http://substack.net" 25 | }, 26 | "scripts": { 27 | "test": "browserify test/vm.js | tape-run" 28 | }, 29 | "license": "MIT" 30 | } 31 | -------------------------------------------------------------------------------- /readme.markdown: -------------------------------------------------------------------------------- 1 | # vm-browserify 2 | 3 | emulate node's vm module for the browser 4 | 5 | [![Build Status](https://travis-ci.org/browserify/vm-browserify.svg?branch=master)](https://travis-ci.org/browserify/vm-browserify) 6 | 7 | # example 8 | 9 | Just write some client-side javascript: 10 | 11 | ``` js 12 | var vm = require('vm'); 13 | 14 | window.addEventListener('load', function () { 15 | var res = vm.runInNewContext('a + 5', { a : 100 }); 16 | document.querySelector('#res').textContent = res; 17 | }); 18 | ``` 19 | 20 | compile it with [browserify](http://github.com/substack/node-browserify): 21 | 22 | ``` 23 | browserify entry.js -o bundle.js 24 | ``` 25 | 26 | then whip up some html: 27 | 28 | ``` html 29 | 30 | 31 | 32 | 33 | 34 | result = 35 | 36 | 37 | ``` 38 | 39 | and when you load the page you should see: 40 | 41 | ``` 42 | result = 105 43 | ``` 44 | 45 | # methods 46 | 47 | ## vm.runInNewContext(code, context={}) 48 | 49 | Evaluate some `code` in a new iframe with a `context`. 50 | 51 | Contexts are like wrapping your code in a `with()` except slightly less terrible 52 | because the code is sandboxed into a new iframe. 53 | 54 | # install 55 | 56 | This module is depended upon by browserify, so you should just be able to 57 | `require('vm')` and it will just work. However if you want to use this module 58 | directly you can install it with [npm](http://npmjs.org): 59 | 60 | ``` 61 | npm install vm-browserify 62 | ``` 63 | 64 | # license 65 | 66 | MIT 67 | -------------------------------------------------------------------------------- /security.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | Only the latest major version is supported at any given time. 5 | 6 | ## Reporting a Vulnerability 7 | 8 | To report a security vulnerability, please use the 9 | [Tidelift security contact](https://tidelift.com/security). 10 | Tidelift will coordinate the fix and disclosure. 11 | -------------------------------------------------------------------------------- /test/vm.js: -------------------------------------------------------------------------------- 1 | var test = require('tape'); 2 | var vm = require('../'); 3 | 4 | test('vmRunInNewContext', function (t) { 5 | t.plan(6); 6 | 7 | t.equal(vm.runInNewContext('a + 5', { a : 100 }), 105); 8 | 9 | (function () { 10 | var vars = { x : 10 }; 11 | t.equal(vm.runInNewContext('x++', vars), 10); 12 | t.equal(vars.x, 11); 13 | })(); 14 | 15 | (function () { 16 | var vars = { x : 10 }; 17 | t.equal(vm.runInNewContext('var y = 3; y + x++', vars), 13); 18 | t.equal(vars.x, 11); 19 | t.equal(vars.y, 3); 20 | })(); 21 | 22 | t.end(); 23 | }); 24 | 25 | test('vmRunInContext', function (t) { 26 | t.plan(2); 27 | 28 | var context = vm.createContext({ foo: 1 }); 29 | 30 | vm.runInContext('var x = 1', context); 31 | t.deepEqual(context, { foo: 1, x: 1 }); 32 | 33 | vm.runInContext('var y = 1', context); 34 | t.deepEqual(context, { foo: 1, x: 1, y: 1 }); 35 | }); 36 | --------------------------------------------------------------------------------