UNPKG

4.08 kBJavaScriptView Raw
1var 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};
8var 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
17var 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
24var 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
42var 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
48function Context() {}
49Context.prototype = {};
50
51var Script = exports.Script = function NodeScript (code) {
52 if (!(this instanceof Script)) return new Script(code);
53 this.code = code;
54};
55
56Script.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
109Script.prototype.runInThisContext = function () {
110 return eval(this.code); // maybe...
111};
112
113Script.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
126forEach(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
133exports.isContext = function (context) {
134 return context instanceof Context;
135};
136
137exports.createScript = function (code) {
138 return exports.Script(code);
139};
140
141exports.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};