11var indexOf = require ( 'indexof' ) ;
22
3+ // cached iFrame instance, re-use for each runInContext Call.
4+ var iFrame = null ;
5+
36var Object_keys = function ( obj ) {
47 if ( Object . keys ) return Object . keys ( obj )
58 else {
@@ -45,37 +48,43 @@ Context.prototype = {};
4548
4649var Script = exports . Script = function NodeScript ( code ) {
4750 if ( ! ( this instanceof Script ) ) return new Script ( code ) ;
51+ if ( ! iFrame ) {
52+ iFrame = document . createElement ( 'iframe' ) ;
53+ if ( ! iFrame . style ) iFrame . style = { } ;
54+ iFrame . style . display = 'none' ;
55+
56+ document . body . appendChild ( iFrame ) ;
57+ }
4858 this . code = code ;
59+ this . iFrame = iFrame ;
4960} ;
5061
5162Script . prototype . runInContext = function ( context ) {
5263 if ( ! ( context instanceof Context ) ) {
5364 throw new TypeError ( "needs a 'context' argument." ) ;
5465 }
55-
56- var iframe = document . createElement ( 'iframe' ) ;
57- if ( ! iframe . style ) iframe . style = { } ;
58- iframe . style . display = 'none' ;
59-
60- document . body . appendChild ( iframe ) ;
61-
62- var win = iframe . contentWindow ;
66+ var win = this . iFrame . contentWindow ;
67+ var winOriginal = Object_keys ( win ) ;
68+ let originalToRestore = [ ] ;
6369 var wEval = win . eval , wExecScript = win . execScript ;
6470
65- if ( ! wEval && wExecScript ) {
66- // win.eval() magically appears when this is called in IE:
67- wExecScript . call ( win , 'null' ) ;
68- wEval = win . eval ;
69- }
70-
7171 forEach ( Object_keys ( context ) , function ( key ) {
72- win [ key ] = context [ key ] ;
73- } ) ;
74- forEach ( globals , function ( key ) {
75- if ( context [ key ] ) {
76- win [ key ] = context [ key ] ;
77- }
72+ if ( win [ key ] !== undefined ) {
73+ let restore = {
74+ 'key' : key ,
75+ 'value' : win [ key ]
76+ } ;
77+ originalToRestore . push ( restore ) ;
78+ }
79+ win [ key ] = context [ key ] ;
7880 } ) ;
81+
82+ if ( ! wEval && wExecScript ) {
83+ // win.eval() magically appears when this is called in IE:
84+ wExecScript . call ( win , 'null' ) ;
85+ wEval = win . eval ;
86+ }
87+
7988
8089 var winKeys = Object_keys ( win ) ;
8190
@@ -86,18 +95,18 @@ Script.prototype.runInContext = function (context) {
8695 // updating existing context properties or new properties in the `win`
8796 // that was only introduced after the eval.
8897 if ( key in context || indexOf ( winKeys , key ) === - 1 ) {
89- context [ key ] = win [ key ] ;
98+ if ( indexOf ( globals , key ) === - 1 ) context [ key ] = win [ key ] ;
99+ else defineProp ( context , key , win [ key ] ) ;
90100 }
101+ // delete win context of extra fields
102+ if ( indexOf ( winOriginal , key ) === - 1 ) delete win [ key ] ;
91103 } ) ;
92104
93- forEach ( globals , function ( key ) {
94- if ( ! ( key in context ) ) {
95- defineProp ( context , key , win [ key ] ) ;
96- }
105+ // restore context to original field values
106+ forEach ( originalToRestore , function ( orig ) {
107+ win [ orig . key ] = orig . value ;
97108 } ) ;
98-
99- document . body . removeChild ( iframe ) ;
100-
109+
101110 return res ;
102111} ;
103112
0 commit comments