Skip to content

File tree

1 file changed

+36
-25
lines changed

1 file changed

+36
-25
lines changed

index.js

+36-25
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ var indexOf = function (xs, item) {
55
}
66
return -1;
77
};
8+
89
var Object_keys = function (obj) {
910
if (Object.keys) return Object.keys(obj)
1011
else {
@@ -39,6 +40,9 @@ var defineProp = (function() {
3940
}
4041
}());
4142

43+
// cached iFrame instance, re-use for each runInContext Call.
44+
var iFrame = null;
45+
4246
var globals = ['Array', 'Boolean', 'Date', 'Error', 'EvalError', 'Function',
4347
'Infinity', 'JSON', 'Math', 'NaN', 'Number', 'Object', 'RangeError',
4448
'ReferenceError', 'RegExp', 'String', 'SyntaxError', 'TypeError', 'URIError',
@@ -50,59 +54,66 @@ Context.prototype = {};
5054

5155
var Script = exports.Script = function NodeScript (code) {
5256
if (!(this instanceof Script)) return new Script(code);
57+
if(!iFrame) {
58+
iFrame = document.createElement('iframe');
59+
if (!iFrame.style) iFrame.style = {};
60+
iFrame.style.display = 'none';
61+
62+
document.body.appendChild(iFrame);
63+
}
5364
this.code = code;
65+
this.iFrame = iFrame;
5466
};
5567

5668
Script.prototype.runInContext = function (context) {
5769
if (!(context instanceof Context)) {
5870
throw new TypeError("needs a 'context' argument.");
5971
}
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;
72+
73+
var win = this.iFrame.contentWindow;
74+
var winOriginal = Object_keys(win);
75+
var originalToRestore = [];
6876
var wEval = win.eval, wExecScript = win.execScript;
6977

7078
if (!wEval && wExecScript) {
7179
// win.eval() magically appears when this is called in IE:
7280
wExecScript.call(win, 'null');
7381
wEval = win.eval;
7482
}
75-
83+
7684
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-
}
85+
if(win[key] !== undefined) {
86+
let restore = {
87+
'key': key,
88+
'value': win[key]
89+
};
90+
originalToRestore.push(restore);
91+
}
92+
win[key] = context[key];
8393
});
84-
94+
8595
var winKeys = Object_keys(win);
8696

8797
var res = wEval.call(win, this.code);
88-
98+
8999
forEach(Object_keys(win), function (key) {
90100
// Avoid copying circular objects like `top` and `window` by only
91101
// updating existing context properties or new properties in the `win`
92102
// that was only introduced after the eval.
93103
if (key in context || indexOf(winKeys, key) === -1) {
94-
context[key] = win[key];
104+
if (indexOf(globals, key) === -1) context[key] = win[key];
105+
else defineProp(context, key, win[key]);
95106
}
107+
108+
// delete win context of extra fields
109+
if (indexOf(winOriginal, key) === -1) delete win[key];
96110
});
97111

98-
forEach(globals, function (key) {
99-
if (!(key in context)) {
100-
defineProp(context, key, win[key]);
101-
}
112+
// restore context to original field values
113+
forEach(originalToRestore, function (orig) {
114+
win[orig.key] = orig.value;
102115
});
103-
104-
document.body.removeChild(iframe);
105-
116+
106117
return res;
107118
};
108119

0 commit comments

Comments
 (0)