Permalink
Browse files

initial implementation taken from browserify with some testling tests

  • Loading branch information...
substack committed Feb 25, 2012
0 parents commit 2a59d220569e7985d6a0f4649da5c5e5a9653196
Showing with 172 additions and 0 deletions.
  1. +117 −0 index.js
  2. +33 −0 package.json
  3. +22 −0 testling/run.js
117 index.js
@@ -0,0 +1,117 @@
+var Object_keys = function (obj) {
+ if (Object.keys) return Object.keys(obj)
+ else {
+ var res = [];
+ for (var key in obj) res.push(key)
+ return res;
+ }
+};
+
+var forEach = function (xs, fn) {
+ if (xs.forEach) return xs.forEach(fn)
+ else for (var i = 0; i < xs.length; i++) {
+ fn(xs[i], i, xs);
+ }
+};
+
+var Script = exports.Script = function NodeScript (code) {
+ if (!(this instanceof Script)) return new Script(code);
+ this.code = code;
+};
+
+var iframe = document.createElement('iframe');
+if (!iframe.style) iframe.style = {};
+iframe.style.display = 'none';
+
+var iframeCapable = true; // until proven otherwise
+if (navigator.appName === 'Microsoft Internet Explorer') {
+ var m = navigator.appVersion.match(/\bMSIE (\d+\.\d+);/);
+ if (m && parseFloat(m[1]) <= 9.0) {
+ iframeCapable = false;
+ }
+}
+
+Script.prototype.runInNewContext = function (context) {
+ if (!context) context = {};
+
+ if (!iframeCapable) {
+ var keys = Object_keys(context);
+ var args = [];
+ for (var i = 0; i < keys.length; i++) {
+ args.push(context[keys[i]]);
+ }
+
+ var fn = new Function(keys, 'return ' + this.code);
+ return fn.apply(null, args);
+ }
+
+ document.body.appendChild(iframe);
+
+ var win = iframe.contentWindow
+ || (window.frames && window.frames[window.frames.length - 1])
+ || window[window.length - 1]
+ ;
+
+ forEach(Object_keys(context), function (key) {
+ win[key] = context[key];
+ iframe[key] = context[key];
+ });
+
+ if (win.eval) {
+ // chrome and ff can just .eval()
+ var res = win.eval(this.code);
+ }
+ else {
+ // this works in IE9 but not anything newer
+ iframe.setAttribute('src',
+ 'javascript:__browserifyVmResult=(' + this.code + ')'
+ );
+ if ('__browserifyVmResult' in win) {
+ var res = win.__browserifyVmResult;
+ }
+ else {
+ iframeCapable = false;
+ res = this.runInThisContext(context);
+ }
+ }
+
+ forEach(Object_keys(win), function (key) {
+ context[key] = win[key];
+ });
+
+ document.body.removeChild(iframe);
+
+ return res;
+};
+
+Script.prototype.runInThisContext = function () {
+ return eval(this.code); // maybe...
+};
+
+Script.prototype.runInContext = function (context) {
+ // seems to be just runInNewContext on magical context objects which are
+ // otherwise indistinguishable from objects except plain old objects
+ // for the parameter segfaults node
+ return this.runInNewContext(context);
+};
+
+forEach(Object_keys(Script.prototype), function (name) {
+ exports[name] = Script[name] = function (code) {
+ var s = Script(code);
+ return s[name].apply(s, [].slice.call(arguments, 1));
+ };
+});
+
+exports.createScript = function (code) {
+ return exports.Script(code);
+};
+
+exports.createContext = Script.createContext = function (context) {
+ // not really sure what this one does
+ // seems to just make a shallow copy
+ var copy = {};
+ forEach(Object_keys(context), function (key) {
+ copy[key] = context[key];
+ });
+ return copy;
+};
@@ -0,0 +1,33 @@
+{
+ "name" : "vm-browserify",
+ "version" : "0.0.0",
+ "description" : "vm module for the browser",
+ "main" : "index.js",
+ "directories" : {
+ "example" : "example",
+ "test" : "test"
+ },
+ "repository" : {
+ "type" : "git",
+ "url" : "http://github.com/substack/vm-browserify.git"
+ },
+ "keywords" : [
+ "vm",
+ "browser",
+ "eval"
+ ],
+ "devDependencies" : {
+ "tap" : "~0.2.1",
+ "browserify" : "1.9.x"
+ },
+ "author" : {
+ "name" : "James Halliday",
+ "email" : "mail@substack.net",
+ "url" : "http://substack.net"
+ },
+ "scripts" : {
+ "test" : "tap test/*.js"
+ },
+ "license" : "MIT/X11",
+ "engine" : { "node" : ">=0.4.0" }
+}
@@ -0,0 +1,22 @@
+var test = require('testling');
+var vm = require('./');
+
+test('vmRunInNewContext', function (t) {
+ //t.plan(4);
+
+ t.equal(vm.runInNewContext('a + 5', { a : 100 }), 105);
+
+ (function () {
+ var vars = { x : 10 };
+ t.equal(vm.runInNewContext('x++', vars), 10);
+ t.equal(vars.x, 11);
+ })();
+
+ (function () {
+ var vars = { x : 10 };
+ t.equal(vm.runInNewContext('var y = 3; y + x++', vars), 13);
+ t.equal(vars.x, 11);
+ })();
+
+ t.end();
+});

0 comments on commit 2a59d22

Please sign in to comment.