3
3
using System . Runtime . CompilerServices ;
4
4
using Esprima ;
5
5
using Esprima . Ast ;
6
+ using Jint . Collections ;
6
7
using Jint . Native ;
7
8
using Jint . Native . Argument ;
8
9
using Jint . Native . Array ;
@@ -215,8 +216,8 @@ public Engine(Action<Engine, Options> options)
215
216
}
216
217
217
218
218
- internal LexicalEnvironment GlobalEnvironment { get ; }
219
- public GlobalObject Global { get ; }
219
+ internal LexicalEnvironment GlobalEnvironment { get ; set ; }
220
+ public GlobalObject Global { get ; internal set ; }
220
221
public ObjectConstructor Object { get ; }
221
222
public FunctionConstructor Function { get ; }
222
223
public ArrayConstructor Array { get ; }
@@ -255,7 +256,6 @@ public ref readonly ExecutionContext ExecutionContext
255
256
256
257
internal Options Options { [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ] get ; private set ; }
257
258
258
- #region Debugger
259
259
public delegate StepMode DebugStepDelegate ( object sender , DebugInformation e ) ;
260
260
public delegate StepMode BreakDelegate ( object sender , DebugInformation e ) ;
261
261
public event DebugStepDelegate Step ;
@@ -274,7 +274,6 @@ public ref readonly ExecutionContext ExecutionContext
274
274
{
275
275
return Break ? . Invoke ( this , info ) ;
276
276
}
277
- #endregion
278
277
279
278
public ExecutionContext EnterExecutionContext (
280
279
LexicalEnvironment lexicalEnvironment ,
@@ -288,6 +287,72 @@ public ExecutionContext EnterExecutionContext(
288
287
return context ;
289
288
}
290
289
290
+ public IDisposable EnterIsolatedContext ( )
291
+ {
292
+ var originalGlobalEnvironment = GlobalEnvironment ;
293
+ if ( originalGlobalEnvironment . _record . GetType ( ) != typeof ( GlobalEnvironmentRecord ) )
294
+ {
295
+ ExceptionHelper . ThrowInvalidOperationException ( "Cannot enter isolated context when global environment is not default, did you already enter?" ) ;
296
+ }
297
+
298
+ if ( _executionContexts . Count != 1 )
299
+ {
300
+ ExceptionHelper . ThrowInvalidOperationException ( "Cannot enter isolated context when execution context stack is not on root level" ) ;
301
+ }
302
+
303
+ if ( ! _isStrict )
304
+ {
305
+ ExceptionHelper . ThrowInvalidOperationException ( "Cannot enter isolated context when engine is not in strict mode" ) ;
306
+ }
307
+
308
+ var originalGlobal = Global ;
309
+ var propertyLessGlobal = new GlobalObject ( this )
310
+ {
311
+ _properties = new PropertyDictionary ( )
312
+ } ;
313
+ var globalEnvironmentRecord = ( GlobalEnvironmentRecord ) originalGlobalEnvironment . _record ;
314
+
315
+ var newGlobal = new LexicalEnvironment ( this , new IsolatedEnvironmentRecord ( this , propertyLessGlobal , globalEnvironmentRecord ) , null ) ;
316
+ GlobalEnvironment = newGlobal ;
317
+ Global = propertyLessGlobal ;
318
+
319
+ var context = new ExecutionContext ( newGlobal , newGlobal ) ;
320
+ _executionContexts . Push ( context ) ;
321
+
322
+ return new ContextRestorer ( this , originalGlobalEnvironment , originalGlobal ) ;
323
+ }
324
+
325
+ private readonly struct ContextRestorer : IDisposable
326
+ {
327
+ private readonly Engine _engine ;
328
+ private readonly LexicalEnvironment _originalGlobalEnvironment ;
329
+ private readonly GlobalObject _originalGlobal ;
330
+
331
+ public ContextRestorer ( Engine engine , LexicalEnvironment originalGlobalEnvironment , GlobalObject originalGlobal )
332
+ {
333
+ _engine = engine ;
334
+ _originalGlobalEnvironment = originalGlobalEnvironment ;
335
+ _originalGlobal = originalGlobal ;
336
+ }
337
+
338
+ public void Dispose ( )
339
+ {
340
+ if ( _engine . GlobalEnvironment . _record . GetType ( ) != typeof ( IsolatedEnvironmentRecord ) )
341
+ {
342
+ ExceptionHelper . ThrowInvalidOperationException ( "Cannot leave isolated context when global environment is not isolated, did you already dispose?" ) ;
343
+ }
344
+
345
+ if ( _engine . _executionContexts . Count != 2 )
346
+ {
347
+ ExceptionHelper . ThrowInvalidOperationException ( "Cannot enter isolated context when execution context stack is not on root level" ) ;
348
+ }
349
+
350
+ _engine . GlobalEnvironment = _originalGlobalEnvironment ;
351
+ _engine . Global = _originalGlobal ;
352
+ _engine . _executionContexts . Pop ( ) ;
353
+ }
354
+ }
355
+
291
356
public Engine SetValue ( JsValue name , Delegate value )
292
357
{
293
358
Global . FastAddProperty ( name , new DelegateWrapper ( this , value ) , true , false , true ) ;
0 commit comments