| var indexOf = function (xs, item) { | |
| if (xs.indexOf) return xs.indexOf(item); | |
| else for (var i = 0; i < xs.length; i++) { | |
| if (xs[i] === item) return i; | |
| } | |
| return -1; | |
| }; | |
| 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 defineProp = (function() { | |
| try { | |
| Object.defineProperty({}, '_', {}); | |
| return function(obj, name, value) { | |
| Object.defineProperty(obj, name, { | |
| writable: true, | |
| enumerable: false, | |
| configurable: true, | |
| value: value | |
| }) | |
| }; | |
| } catch(e) { | |
| return function(obj, name, value) { | |
| obj[name] = value; | |
| }; | |
| } | |
| }()); | |
| var globals = ['Array', 'Boolean', 'Date', 'Error', 'EvalError', 'Function', | |
| 'Infinity', 'JSON', 'Math', 'NaN', 'Number', 'Object', 'RangeError', | |
| 'ReferenceError', 'RegExp', 'String', 'SyntaxError', 'TypeError', 'URIError', | |
| 'decodeURI', 'decodeURIComponent', 'encodeURI', 'encodeURIComponent', 'escape', | |
| 'eval', 'isFinite', 'isNaN', 'parseFloat', 'parseInt', 'undefined', 'unescape']; | |
| function Context() {} | |
| Context.prototype = {}; | |
| var Script = exports.Script = function NodeScript (code) { | |
| if (!(this instanceof Script)) return new Script(code); | |
| this.code = code; | |
| }; | |
| Script.prototype.runInContext = function (context) { | |
| if (!(context instanceof Context)) { | |
| throw new TypeError("needs a 'context' argument."); | |
| } | |
| var iframe = document.createElement('iframe'); | |
| if (!iframe.style) iframe.style = {}; | |
| iframe.style.display = 'none'; | |
| document.body.appendChild(iframe); | |
| var win = iframe.contentWindow; | |
| var wEval = win.eval, wExecScript = win.execScript; | |
| if (!wEval && wExecScript) { | |
| // win.eval() magically appears when this is called in IE: | |
| wExecScript.call(win, 'null'); | |
| wEval = win.eval; | |
| } | |
| forEach(Object_keys(context), function (key) { | |
| win[key] = context[key]; | |
| }); | |
| forEach(globals, function (key) { | |
| if (context[key]) { | |
| win[key] = context[key]; | |
| } | |
| }); | |
| var winKeys = Object_keys(win); | |
| var res = wEval.call(win, this.code); | |
| forEach(Object_keys(win), function (key) { | |
| // Avoid copying circular objects like `top` and `window` by only | |
| // updating existing context properties or new properties in the `win` | |
| // that was only introduced after the eval. | |
| if (key in context || indexOf(winKeys, key) === -1) { | |
| context[key] = win[key]; | |
| } | |
| }); | |
| forEach(globals, function (key) { | |
| if (!(key in context)) { | |
| defineProp(context, key, win[key]); | |
| } | |
| }); | |
| document.body.removeChild(iframe); | |
| return res; | |
| }; | |
| Script.prototype.runInThisContext = function () { | |
| return eval(this.code); // maybe... | |
| }; | |
| Script.prototype.runInNewContext = function (context) { | |
| var ctx = Script.createContext(context); | |
| var res = this.runInContext(ctx); | |
| if (context) { | |
| forEach(Object_keys(ctx), function (key) { | |
| context[key] = ctx[key]; | |
| }); | |
| } | |
| return res; | |
| }; | |
| 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.isContext = function (context) { | |
| return context instanceof Context; | |
| }; | |
| exports.createScript = function (code) { | |
| return exports.Script(code); | |
| }; | |
| exports.createContext = Script.createContext = function (context) { | |
| var copy = new Context(); | |
| if(typeof context === 'object') { | |
| forEach(Object_keys(context), function (key) { | |
| copy[key] = context[key]; | |
| }); | |
| } | |
| return copy; | |
| }; |