Browse Source

Remove LexicalEnvironment (#901)

Marko Lahma 4 years ago
parent
commit
978d31900f
34 changed files with 242 additions and 227 deletions
  1. 44 40
      Jint/Engine.cs
  2. 2 2
      Jint/EsprimaExtensions.cs
  3. 1 1
      Jint/Native/Array/ArrayInstance.cs
  4. 4 4
      Jint/Native/Function/ClassDefinition.cs
  5. 4 4
      Jint/Native/Function/EvalFunctionInstance.cs
  6. 1 1
      Jint/Native/Function/FunctionConstructor.cs
  7. 5 6
      Jint/Native/Function/FunctionInstance.cs
  8. 3 3
      Jint/Native/Function/ScriptFunctionInstance.cs
  9. 1 1
      Jint/Native/Object/ObjectConstructor.cs
  10. 1 1
      Jint/Native/Proxy/ProxyInstance.cs
  11. 1 1
      Jint/Runtime/Debugger/CallFrame.cs
  12. 5 5
      Jint/Runtime/Debugger/DebugScopes.cs
  13. 6 3
      Jint/Runtime/Environments/EnvironmentRecord.cs
  14. 18 17
      Jint/Runtime/Environments/ExecutionContext.cs
  15. 2 2
      Jint/Runtime/Environments/FunctionEnvironmentRecord.cs
  16. 1 1
      Jint/Runtime/Environments/GlobalEnvironmentRecord.cs
  17. 92 0
      Jint/Runtime/Environments/JintEnvironment.cs
  18. 0 87
      Jint/Runtime/Environments/LexicalEnvironment.cs
  19. 2 2
      Jint/Runtime/ExecutionContextStack.cs
  20. 6 6
      Jint/Runtime/Interpreter/Expressions/BindingPatternAssignmentExpression.cs
  21. 2 1
      Jint/Runtime/Interpreter/Expressions/JintAssignmentExpression.cs
  22. 2 3
      Jint/Runtime/Interpreter/Expressions/JintFunctionExpression.cs
  23. 3 2
      Jint/Runtime/Interpreter/Expressions/JintIdentifierExpression.cs
  24. 2 1
      Jint/Runtime/Interpreter/Expressions/JintMemberExpression.cs
  25. 2 1
      Jint/Runtime/Interpreter/Expressions/JintUpdateExpression.cs
  26. 2 2
      Jint/Runtime/Interpreter/JintStatementList.cs
  27. 3 3
      Jint/Runtime/Interpreter/Statements/JintBlockStatement.cs
  28. 2 2
      Jint/Runtime/Interpreter/Statements/JintClassDeclarationStatement.cs
  29. 6 6
      Jint/Runtime/Interpreter/Statements/JintForInForOfStatement.cs
  30. 9 9
      Jint/Runtime/Interpreter/Statements/JintForStatement.cs
  31. 1 1
      Jint/Runtime/Interpreter/Statements/JintStatement.cs
  32. 6 6
      Jint/Runtime/Interpreter/Statements/JintSwitchBlock.cs
  33. 2 2
      Jint/Runtime/Interpreter/Statements/JintTryStatement.cs
  34. 1 1
      Jint/Runtime/Interpreter/Statements/JintWithStatement.cs

+ 44 - 40
Jint/Engine.cs

@@ -186,7 +186,7 @@ namespace Jint
             Object._prototype = Function.PrototypeObject;
             Object._prototype = Function.PrototypeObject;
 
 
             // create the global environment http://www.ecma-international.org/ecma-262/5.1/#sec-10.2.3
             // create the global environment http://www.ecma-international.org/ecma-262/5.1/#sec-10.2.3
-            GlobalEnvironment = LexicalEnvironment.NewGlobalEnvironment(this, Global);
+            GlobalEnvironment = JintEnvironment.NewGlobalEnvironment(this, Global, Global);
 
 
             // create the global execution context http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.1.1
             // create the global execution context http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.1.1
             EnterExecutionContext(GlobalEnvironment, GlobalEnvironment);
             EnterExecutionContext(GlobalEnvironment, GlobalEnvironment);
@@ -213,7 +213,7 @@ namespace Jint
             Options.Apply(this);
             Options.Apply(this);
         }
         }
 
 
-        internal LexicalEnvironment GlobalEnvironment { get; }
+        internal GlobalEnvironmentRecord GlobalEnvironment { get; }
         public GlobalObject Global { get; }
         public GlobalObject Global { get; }
         public ObjectConstructor Object { get; }
         public ObjectConstructor Object { get; }
         public FunctionConstructor Function { get; }
         public FunctionConstructor Function { get; }
@@ -274,8 +274,8 @@ namespace Jint
         public DebugHandler DebugHandler => _debugHandler ??= new DebugHandler(this);
         public DebugHandler DebugHandler => _debugHandler ??= new DebugHandler(this);
 
 
         public ExecutionContext EnterExecutionContext(
         public ExecutionContext EnterExecutionContext(
-            LexicalEnvironment lexicalEnvironment,
-            LexicalEnvironment variableEnvironment)
+            EnvironmentRecord lexicalEnvironment,
+            EnvironmentRecord variableEnvironment)
         {
         {
             var context = new ExecutionContext(
             var context = new ExecutionContext(
                 lexicalEnvironment,
                 lexicalEnvironment,
@@ -285,6 +285,12 @@ namespace Jint
             return context;
             return context;
         }
         }
 
 
+        internal ExecutionContext EnterExecutionContext(ExecutionContext context)
+        {
+            _executionContexts.Push(context);
+            return context;
+        }
+
         public Engine SetValue(JsValue name, Delegate value)
         public Engine SetValue(JsValue name, Delegate value)
         {
         {
             Global.FastAddProperty(name, new DelegateWrapper(this, value), true, false, true);
             Global.FastAddProperty(name, new DelegateWrapper(this, value), true, false, true);
@@ -791,26 +797,26 @@ namespace Jint
         /// <summary>
         /// <summary>
         /// https://tc39.es/ecma262/#sec-resolvebinding
         /// https://tc39.es/ecma262/#sec-resolvebinding
         /// </summary>
         /// </summary>
-        internal Reference ResolveBinding(string name, LexicalEnvironment env = null)
+        internal Reference ResolveBinding(string name, EnvironmentRecord env = null)
         {
         {
             env ??= ExecutionContext.LexicalEnvironment;
             env ??= ExecutionContext.LexicalEnvironment;
             return GetIdentifierReference(env, name, StrictModeScope.IsStrictModeCode);
             return GetIdentifierReference(env, name, StrictModeScope.IsStrictModeCode);
         }
         }
 
 
-        private Reference GetIdentifierReference(LexicalEnvironment env, string name, bool strict)
+        private Reference GetIdentifierReference(EnvironmentRecord env, string name, bool strict)
         {
         {
             if (env is null)
             if (env is null)
             {
             {
                 return new Reference(JsValue.Undefined, name, strict);
                 return new Reference(JsValue.Undefined, name, strict);
             }
             }
 
 
-            var envRec = env._record;
+            var envRec = env;
             if (envRec.HasBinding(name))
             if (envRec.HasBinding(name))
             {
             {
                 return new Reference(envRec, name, strict);
                 return new Reference(envRec, name, strict);
             }
             }
 
 
-            return GetIdentifierReference(env._outer, name, strict);
+            return GetIdentifierReference(env._outerEnv, name, strict);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -837,10 +843,8 @@ namespace Jint
         /// </summary>
         /// </summary>
         private void GlobalDeclarationInstantiation(
         private void GlobalDeclarationInstantiation(
             Script script,
             Script script,
-            LexicalEnvironment env)
+            GlobalEnvironmentRecord env)
         {
         {
-            var envRec = (GlobalEnvironmentRecord) env._record;
-
             var hoistingScope = HoistingScope.GetProgramLevelDeclarations(script);
             var hoistingScope = HoistingScope.GetProgramLevelDeclarations(script);
             var functionDeclarations = hoistingScope._functionDeclarations;
             var functionDeclarations = hoistingScope._functionDeclarations;
             var varDeclarations = hoistingScope._variablesDeclarations;
             var varDeclarations = hoistingScope._variablesDeclarations;
@@ -858,7 +862,7 @@ namespace Jint
                     var fn = d.Id.Name;
                     var fn = d.Id.Name;
                     if (!declaredFunctionNames.Contains(fn))
                     if (!declaredFunctionNames.Contains(fn))
                     {
                     {
-                        var fnDefinable = envRec.CanDeclareGlobalFunction(fn);
+                        var fnDefinable = env.CanDeclareGlobalFunction(fn);
                         if (!fnDefinable)
                         if (!fnDefinable)
                         {
                         {
                             ExceptionHelper.ThrowTypeError(this);
                             ExceptionHelper.ThrowTypeError(this);
@@ -882,14 +886,14 @@ namespace Jint
                     {
                     {
                         var vn = boundNames[j];
                         var vn = boundNames[j];
 
 
-                        if (envRec.HasLexicalDeclaration(vn))
+                        if (env.HasLexicalDeclaration(vn))
                         {
                         {
                             ExceptionHelper.ThrowSyntaxError(this, $"Identifier '{vn}' has already been declared");
                             ExceptionHelper.ThrowSyntaxError(this, $"Identifier '{vn}' has already been declared");
                         }
                         }
 
 
                         if (!declaredFunctionNames.Contains(vn))
                         if (!declaredFunctionNames.Contains(vn))
                         {
                         {
-                            var vnDefinable = envRec.CanDeclareGlobalVar(vn);
+                            var vnDefinable = env.CanDeclareGlobalVar(vn);
                             if (!vnDefinable)
                             if (!vnDefinable)
                             {
                             {
                                 ExceptionHelper.ThrowTypeError(this);
                                 ExceptionHelper.ThrowTypeError(this);
@@ -911,20 +915,20 @@ namespace Jint
                     for (var j = 0; j < boundNames.Count; j++)
                     for (var j = 0; j < boundNames.Count; j++)
                     {
                     {
                         var dn = boundNames[j];
                         var dn = boundNames[j];
-                        if (envRec.HasVarDeclaration(dn)
-                            || envRec.HasLexicalDeclaration(dn)
-                            || envRec.HasRestrictedGlobalProperty(dn))
+                        if (env.HasVarDeclaration(dn)
+                            || env.HasLexicalDeclaration(dn)
+                            || env.HasRestrictedGlobalProperty(dn))
                         {
                         {
                             ExceptionHelper.ThrowSyntaxError(this, $"Identifier '{dn}' has already been declared");
                             ExceptionHelper.ThrowSyntaxError(this, $"Identifier '{dn}' has already been declared");
                         }
                         }
 
 
                         if (d.Kind == VariableDeclarationKind.Const)
                         if (d.Kind == VariableDeclarationKind.Const)
                         {
                         {
-                            envRec.CreateImmutableBinding(dn, strict: true);
+                            env.CreateImmutableBinding(dn, strict: true);
                         }
                         }
                         else
                         else
                         {
                         {
-                            envRec.CreateMutableBinding(dn, canBeDeleted: false);
+                            env.CreateMutableBinding(dn, canBeDeleted: false);
                         }
                         }
                     }
                     }
                 }
                 }
@@ -934,19 +938,19 @@ namespace Jint
             {
             {
                 var fn = f.Id!.Name;
                 var fn = f.Id!.Name;
 
 
-                if (envRec.HasLexicalDeclaration(fn))
+                if (env.HasLexicalDeclaration(fn))
                 {
                 {
                     ExceptionHelper.ThrowSyntaxError(this, $"Identifier '{fn}' has already been declared");
                     ExceptionHelper.ThrowSyntaxError(this, $"Identifier '{fn}' has already been declared");
                 }
                 }
 
 
                 var fo = Function.InstantiateFunctionObject(f, env);
                 var fo = Function.InstantiateFunctionObject(f, env);
-                envRec.CreateGlobalFunctionBinding(fn, fo, canBeDeleted: false);
+                env.CreateGlobalFunctionBinding(fn, fo, canBeDeleted: false);
             }
             }
 
 
             for (var i = 0; i < declaredVarNames.Count; i++)
             for (var i = 0; i < declaredVarNames.Count; i++)
             {
             {
                 var vn = declaredVarNames[i];
                 var vn = declaredVarNames[i];
-                envRec.CreateGlobalVarBinding(vn, canBeDeleted: false);
+                env.CreateGlobalVarBinding(vn, canBeDeleted: false);
             }
             }
         }
         }
 
 
@@ -956,11 +960,11 @@ namespace Jint
         internal ArgumentsInstance FunctionDeclarationInstantiation(
         internal ArgumentsInstance FunctionDeclarationInstantiation(
             FunctionInstance functionInstance,
             FunctionInstance functionInstance,
             JsValue[] argumentsList,
             JsValue[] argumentsList,
-            LexicalEnvironment env)
+            EnvironmentRecord env)
         {
         {
             var func = functionInstance._functionDefinition;
             var func = functionInstance._functionDefinition;
 
 
-            var envRec = (FunctionEnvironmentRecord) env._record;
+            var envRec = (FunctionEnvironmentRecord) env;
             var strict = StrictModeScope.IsStrictModeCode;
             var strict = StrictModeScope.IsStrictModeCode;
 
 
             var configuration = func.Initialize(this, functionInstance);
             var configuration = func.Initialize(this, functionInstance);
@@ -1010,7 +1014,7 @@ namespace Jint
             // Else,
             // Else,
             //     Perform ? IteratorBindingInitialization for formals with iteratorRecord and env as arguments.
             //     Perform ? IteratorBindingInitialization for formals with iteratorRecord and env as arguments.
 
 
-            LexicalEnvironment varEnv;
+            EnvironmentRecord varEnv;
             DeclarativeEnvironmentRecord varEnvRec;
             DeclarativeEnvironmentRecord varEnvRec;
             if (!hasParameterExpressions)
             if (!hasParameterExpressions)
             {
             {
@@ -1028,8 +1032,8 @@ namespace Jint
             {
             {
                 // NOTE: A separate Environment Record is needed to ensure that closures created by expressions
                 // NOTE: A separate Environment Record is needed to ensure that closures created by expressions
                 // in the formal parameter list do not have visibility of declarations in the function body.
                 // in the formal parameter list do not have visibility of declarations in the function body.
-                varEnv = LexicalEnvironment.NewDeclarativeEnvironment(this, env);
-                varEnvRec = (DeclarativeEnvironmentRecord) varEnv._record;
+                varEnv = JintEnvironment.NewDeclarativeEnvironment(this, env);
+                varEnvRec = (DeclarativeEnvironmentRecord) varEnv;
 
 
                 UpdateVariableEnvironment(varEnv);
                 UpdateVariableEnvironment(varEnv);
 
 
@@ -1044,10 +1048,10 @@ namespace Jint
             // NOTE: Annex B.3.3.1 adds additional steps at this point. 
             // NOTE: Annex B.3.3.1 adds additional steps at this point. 
             // A https://tc39.es/ecma262/#sec-web-compat-functiondeclarationinstantiation
             // A https://tc39.es/ecma262/#sec-web-compat-functiondeclarationinstantiation
 
 
-            LexicalEnvironment lexEnv;
+            EnvironmentRecord lexEnv;
             if (!strict)
             if (!strict)
             {
             {
-                lexEnv = LexicalEnvironment.NewDeclarativeEnvironment(this, varEnv);
+                lexEnv = JintEnvironment.NewDeclarativeEnvironment(this, varEnv);
                 // NOTE: Non-strict functions use a separate lexical Environment Record for top-level lexical declarations
                 // NOTE: Non-strict functions use a separate lexical Environment Record for top-level lexical declarations
                 // so that a direct eval can determine whether any var scoped declarations introduced by the eval code conflict
                 // so that a direct eval can determine whether any var scoped declarations introduced by the eval code conflict
                 // with pre-existing top-level lexically scoped declarations. This is not needed for strict functions
                 // with pre-existing top-level lexically scoped declarations. This is not needed for strict functions
@@ -1058,7 +1062,7 @@ namespace Jint
                 lexEnv = varEnv;
                 lexEnv = varEnv;
             }
             }
 
 
-            var lexEnvRec = lexEnv._record;
+            var lexEnvRec = lexEnv;
 
 
             UpdateLexicalEnvironment(lexEnv);
             UpdateLexicalEnvironment(lexEnv);
 
 
@@ -1077,7 +1081,7 @@ namespace Jint
 
 
         private void InitializeFunctions(
         private void InitializeFunctions(
             LinkedList<FunctionDeclaration> functionsToInitialize,
             LinkedList<FunctionDeclaration> functionsToInitialize,
-            LexicalEnvironment lexEnv,
+            EnvironmentRecord lexEnv,
             DeclarativeEnvironmentRecord varEnvRec)
             DeclarativeEnvironmentRecord varEnvRec)
         {
         {
             foreach (var f in functionsToInitialize)
             foreach (var f in functionsToInitialize)
@@ -1129,14 +1133,14 @@ namespace Jint
         /// </summary>
         /// </summary>
         internal void EvalDeclarationInstantiation(
         internal void EvalDeclarationInstantiation(
             Script script,
             Script script,
-            LexicalEnvironment varEnv,
-            LexicalEnvironment lexEnv,
+            EnvironmentRecord varEnv,
+            EnvironmentRecord lexEnv,
             bool strict)
             bool strict)
         {
         {
             var hoistingScope = HoistingScope.GetProgramLevelDeclarations(script);
             var hoistingScope = HoistingScope.GetProgramLevelDeclarations(script);
 
 
-            var lexEnvRec = (DeclarativeEnvironmentRecord) lexEnv._record;
-            var varEnvRec = varEnv._record;
+            var lexEnvRec = (DeclarativeEnvironmentRecord) lexEnv;
+            var varEnvRec = varEnv;
 
 
             if (!strict && hoistingScope._variablesDeclarations != null)
             if (!strict && hoistingScope._variablesDeclarations != null)
             {
             {
@@ -1156,9 +1160,9 @@ namespace Jint
                 }
                 }
 
 
                 var thisLex = lexEnv;
                 var thisLex = lexEnv;
-                while (thisLex != varEnv)
+                while (!ReferenceEquals(thisLex, varEnv))
                 {
                 {
-                    var thisEnvRec = thisLex._record;
+                    var thisEnvRec = thisLex;
                     if (!(thisEnvRec is ObjectEnvironmentRecord))
                     if (!(thisEnvRec is ObjectEnvironmentRecord))
                     {
                     {
                         ref readonly var nodes = ref hoistingScope._variablesDeclarations;
                         ref readonly var nodes = ref hoistingScope._variablesDeclarations;
@@ -1173,7 +1177,7 @@ namespace Jint
                         }
                         }
                     }
                     }
 
 
-                    thisLex = thisLex._outer;
+                    thisLex = thisLex._outerEnv;
                 }
                 }
             }
             }
 
 
@@ -1295,13 +1299,13 @@ namespace Jint
         }
         }
 
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal void UpdateLexicalEnvironment(LexicalEnvironment newEnv)
+        internal void UpdateLexicalEnvironment(EnvironmentRecord newEnv)
         {
         {
             _executionContexts.ReplaceTopLexicalEnvironment(newEnv);
             _executionContexts.ReplaceTopLexicalEnvironment(newEnv);
         }
         }
 
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal void UpdateVariableEnvironment(LexicalEnvironment newEnv)
+        internal void UpdateVariableEnvironment(EnvironmentRecord newEnv)
         {
         {
             _executionContexts.ReplaceTopVariableEnvironment(newEnv);
             _executionContexts.ReplaceTopVariableEnvironment(newEnv);
         }
         }

+ 2 - 2
Jint/EsprimaExtensions.cs

@@ -179,11 +179,11 @@ namespace Jint
             this Expression? expression, 
             this Expression? expression, 
             Engine engine,
             Engine engine,
             JsValue value,
             JsValue value,
-            LexicalEnvironment env)
+            EnvironmentRecord env)
         {
         {
             if (expression is Identifier identifier)
             if (expression is Identifier identifier)
             {
             {
-                var catchEnvRecord = (DeclarativeEnvironmentRecord) env._record;
+                var catchEnvRecord = (DeclarativeEnvironmentRecord) env;
                 catchEnvRecord.CreateMutableBindingAndInitialize(identifier.Name, canBeDeleted: false, value);
                 catchEnvRecord.CreateMutableBindingAndInitialize(identifier.Name, canBeDeleted: false, value);
             }
             }
             else if (expression is BindingPattern bindingPattern)
             else if (expression is BindingPattern bindingPattern)

+ 1 - 1
Jint/Native/Array/ArrayInstance.cs

@@ -880,7 +880,7 @@ namespace Jint.Native.Array
                         ? sourceDense[i]
                         ? sourceDense[i]
                         : source.GetProperty(i);
                         : source.GetProperty(i);
 
 
-                    dense[targetStartIndex + j] = sourcePropertyDescriptor?._value != null
+                    dense[targetStartIndex + j] = sourcePropertyDescriptor?._value is not null
                         ? new PropertyDescriptor(sourcePropertyDescriptor._value, PropertyFlag.ConfigurableEnumerableWritable)
                         ? new PropertyDescriptor(sourcePropertyDescriptor._value, PropertyFlag.ConfigurableEnumerableWritable)
                         : null;
                         : null;
                 }
                 }

+ 4 - 4
Jint/Native/Function/ClassDefinition.cs

@@ -48,16 +48,16 @@ namespace Jint.Native.Function
         /// </summary>
         /// </summary>
         public ScriptFunctionInstance BuildConstructor(
         public ScriptFunctionInstance BuildConstructor(
             Engine engine,
             Engine engine,
-            LexicalEnvironment env)
+            EnvironmentRecord env)
         {
         {
             // A class definition is always strict mode code.
             // A class definition is always strict mode code.
             using var _ = (new StrictModeScope(true, true));
             using var _ = (new StrictModeScope(true, true));
             
             
-            var classScope = LexicalEnvironment.NewDeclarativeEnvironment(engine, env);
+            var classScope = JintEnvironment.NewDeclarativeEnvironment(engine, env);
 
 
             if (_className is not null)
             if (_className is not null)
             {
             {
-                classScope._record.CreateImmutableBinding(_className, true);
+                classScope.CreateImmutableBinding(_className, true);
             }
             }
 
 
             ObjectInstance? protoParent = null;
             ObjectInstance? protoParent = null;
@@ -158,7 +158,7 @@ namespace Jint.Native.Function
 
 
             if (_className is not null)
             if (_className is not null)
             {
             {
-                classScope._record.InitializeBinding(_className, F);
+                classScope.InitializeBinding(_className, F);
             }
             }
 
 
             return F;
             return F;

+ 4 - 4
Jint/Native/Function/EvalFunctionInstance.cs

@@ -92,16 +92,16 @@ namespace Jint.Native.Function
 
 
             using (new StrictModeScope(strictEval))
             using (new StrictModeScope(strictEval))
             {
             {
-                LexicalEnvironment lexEnv;
-                LexicalEnvironment varEnv;
+                EnvironmentRecord lexEnv;
+                EnvironmentRecord varEnv;
                 if (direct)
                 if (direct)
                 {
                 {
-                    lexEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, ctx.LexicalEnvironment);
+                    lexEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, ctx.LexicalEnvironment);
                     varEnv = ctx.VariableEnvironment;
                     varEnv = ctx.VariableEnvironment;
                 }
                 }
                 else
                 else
                 {
                 {
-                    lexEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, Engine.GlobalEnvironment);
+                    lexEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, Engine.GlobalEnvironment);
                     varEnv = Engine.GlobalEnvironment;
                     varEnv = Engine.GlobalEnvironment;
                 }
                 }
 
 

+ 1 - 1
Jint/Native/Function/FunctionConstructor.cs

@@ -125,7 +125,7 @@ namespace Jint.Native.Function
         /// <summary>
         /// <summary>
         /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiatefunctionobject
         /// https://tc39.es/ecma262/#sec-runtime-semantics-instantiatefunctionobject
         /// </summary>
         /// </summary>
-        internal FunctionInstance InstantiateFunctionObject(FunctionDeclaration functionDeclaration, LexicalEnvironment env)
+        internal FunctionInstance InstantiateFunctionObject(FunctionDeclaration functionDeclaration, EnvironmentRecord env)
         {
         {
             var functionObject = new ScriptFunctionInstance(
             var functionObject = new ScriptFunctionInstance(
                 Engine,
                 Engine,

+ 5 - 6
Jint/Native/Function/FunctionInstance.cs

@@ -17,7 +17,7 @@ namespace Jint.Native.Function
         protected internal PropertyDescriptor _length;
         protected internal PropertyDescriptor _length;
         private PropertyDescriptor _nameDescriptor;
         private PropertyDescriptor _nameDescriptor;
 
 
-        protected internal LexicalEnvironment _environment;
+        protected internal EnvironmentRecord _environment;
         internal readonly JintFunctionDefinition _functionDefinition;
         internal readonly JintFunctionDefinition _functionDefinition;
         internal readonly FunctionThisMode _thisMode;
         internal readonly FunctionThisMode _thisMode;
         internal JsValue _homeObject = Undefined;
         internal JsValue _homeObject = Undefined;
@@ -26,7 +26,7 @@ namespace Jint.Native.Function
         internal FunctionInstance(
         internal FunctionInstance(
             Engine engine,
             Engine engine,
             JintFunctionDefinition function,
             JintFunctionDefinition function,
-            LexicalEnvironment scope,
+            EnvironmentRecord scope,
             FunctionThisMode thisMode)
             FunctionThisMode thisMode)
             : this(engine, !string.IsNullOrWhiteSpace(function.Name) ? new JsString(function.Name) : null, thisMode)
             : this(engine, !string.IsNullOrWhiteSpace(function.Name) ? new JsString(function.Name) : null, thisMode)
         {
         {
@@ -255,7 +255,7 @@ namespace Jint.Native.Function
 
 
             // Let calleeRealm be F.[[Realm]].
             // Let calleeRealm be F.[[Realm]].
 
 
-            var localEnv = (FunctionEnvironmentRecord) calleeContext.LexicalEnvironment._record;
+            var localEnv = (FunctionEnvironmentRecord) calleeContext.LexicalEnvironment;
 
 
             JsValue thisValue;
             JsValue thisValue;
             if (_thisMode == FunctionThisMode.Strict)
             if (_thisMode == FunctionThisMode.Strict)
@@ -268,8 +268,7 @@ namespace Jint.Native.Function
                 {
                 {
                     // Let globalEnv be calleeRealm.[[GlobalEnv]].
                     // Let globalEnv be calleeRealm.[[GlobalEnv]].
                     var globalEnv = _engine.GlobalEnvironment;
                     var globalEnv = _engine.GlobalEnvironment;
-                    var globalEnvRec = (GlobalEnvironmentRecord) globalEnv._record;
-                    thisValue = globalEnvRec.GlobalThisValue;
+                    thisValue = globalEnv.GlobalThisValue;
                 }
                 }
                 else
                 else
                 {
                 {
@@ -307,7 +306,7 @@ namespace Jint.Native.Function
             // Let calleeRealm be F.[[Realm]].
             // Let calleeRealm be F.[[Realm]].
             // Set the Realm of calleeContext to calleeRealm.
             // Set the Realm of calleeContext to calleeRealm.
             // Set the ScriptOrModule of calleeContext to F.[[ScriptOrModule]].
             // Set the ScriptOrModule of calleeContext to F.[[ScriptOrModule]].
-            var calleeContext = LexicalEnvironment.NewFunctionEnvironment(_engine, this, newTarget);
+            var calleeContext = JintEnvironment.NewFunctionEnvironment(_engine, this, newTarget);
             // If callerContext is not already suspended, suspend callerContext.
             // If callerContext is not already suspended, suspend callerContext.
             // Push calleeContext onto the execution context stack; calleeContext is now the running execution context.
             // Push calleeContext onto the execution context stack; calleeContext is now the running execution context.
             // NOTE: Any exception objects produced after this point are associated with calleeRealm.
             // NOTE: Any exception objects produced after this point are associated with calleeRealm.

+ 3 - 3
Jint/Native/Function/ScriptFunctionInstance.cs

@@ -19,7 +19,7 @@ namespace Jint.Native.Function
         public ScriptFunctionInstance(
         public ScriptFunctionInstance(
             Engine engine,
             Engine engine,
             IFunction functionDeclaration,
             IFunction functionDeclaration,
-            LexicalEnvironment scope,
+            EnvironmentRecord scope,
             bool strict,
             bool strict,
             ObjectInstance proto = null)
             ObjectInstance proto = null)
             : this(engine, new JintFunctionDefinition(engine, functionDeclaration), scope, strict ? FunctionThisMode.Strict : FunctionThisMode.Global, proto)
             : this(engine, new JintFunctionDefinition(engine, functionDeclaration), scope, strict ? FunctionThisMode.Strict : FunctionThisMode.Global, proto)
@@ -29,7 +29,7 @@ namespace Jint.Native.Function
         internal ScriptFunctionInstance(
         internal ScriptFunctionInstance(
             Engine engine,
             Engine engine,
             JintFunctionDefinition function,
             JintFunctionDefinition function,
-            LexicalEnvironment scope,
+            EnvironmentRecord scope,
             FunctionThisMode thisMode,
             FunctionThisMode thisMode,
             ObjectInstance proto = null)
             ObjectInstance proto = null)
             : base(engine, function, scope, thisMode)
             : base(engine, function, scope, thisMode)
@@ -122,7 +122,7 @@ namespace Jint.Native.Function
                 OrdinaryCallBindThis(calleeContext, thisArgument);
                 OrdinaryCallBindThis(calleeContext, thisArgument);
             }
             }
 
 
-            var constructorEnv = (FunctionEnvironmentRecord) calleeContext.LexicalEnvironment._record;
+            var constructorEnv = (FunctionEnvironmentRecord) calleeContext.LexicalEnvironment;
             
             
             var strict = _thisMode == FunctionThisMode.Strict || _engine._isStrict;
             var strict = _thisMode == FunctionThisMode.Strict || _engine._isStrict;
             using (new StrictModeScope(strict, force: true))
             using (new StrictModeScope(strict, force: true))

+ 1 - 1
Jint/Native/Object/ObjectConstructor.cs

@@ -242,7 +242,7 @@ namespace Jint.Native.Object
             {
             {
                 var desc = o.GetOwnProperty(key);
                 var desc = o.GetOwnProperty(key);
                 var descriptor = PropertyDescriptor.FromPropertyDescriptor(Engine, desc);
                 var descriptor = PropertyDescriptor.FromPropertyDescriptor(Engine, desc);
-                if (descriptor != Undefined)
+                if (!ReferenceEquals(descriptor, Undefined))
                 {
                 {
                     descriptors.CreateDataProperty(key, descriptor);
                     descriptors.CreateDataProperty(key, descriptor);
                 }
                 }

+ 1 - 1
Jint/Native/Proxy/ProxyInstance.cs

@@ -82,7 +82,7 @@ namespace Jint.Native.Proxy
         }
         }
 
 
         internal override bool IsConstructor => 
         internal override bool IsConstructor => 
-            _handler != null
+            _handler is not null
             && _handler.TryGetValue(TrapConstruct, out var handlerFunction) 
             && _handler.TryGetValue(TrapConstruct, out var handlerFunction) 
             && handlerFunction is IConstructor;
             && handlerFunction is IConstructor;
 
 

+ 1 - 1
Jint/Runtime/Debugger/CallFrame.cs

@@ -23,7 +23,7 @@ namespace Jint.Runtime.Debugger
             _scopeChain = new Lazy<DebugScopes>(() => new DebugScopes(Environment));
             _scopeChain = new Lazy<DebugScopes>(() => new DebugScopes(Environment));
         }
         }
 
 
-        private LexicalEnvironment Environment => _context.LexicalEnvironment;
+        private EnvironmentRecord Environment => _context.LexicalEnvironment;
 
 
         // TODO: CallFrameId
         // TODO: CallFrameId
         /// <summary>
         /// <summary>

+ 5 - 5
Jint/Runtime/Debugger/DebugScopes.cs

@@ -9,7 +9,7 @@ namespace Jint.Runtime.Debugger
         private readonly HashSet<string> _foundBindings = new HashSet<string>();
         private readonly HashSet<string> _foundBindings = new HashSet<string>();
         private readonly List<DebugScope> _scopes = new List<DebugScope>();
         private readonly List<DebugScope> _scopes = new List<DebugScope>();
 
 
-        internal DebugScopes(LexicalEnvironment environment)
+        internal DebugScopes(EnvironmentRecord environment)
         {
         {
             Populate(environment);
             Populate(environment);
         }
         }
@@ -28,12 +28,12 @@ namespace Jint.Runtime.Debugger
         public DebugScope this[int index] => _scopes[index];
         public DebugScope this[int index] => _scopes[index];
         public int Count => _scopes.Count;
         public int Count => _scopes.Count;
 
 
-        private void Populate(LexicalEnvironment environment)
+        private void Populate(EnvironmentRecord environment)
         {
         {
             bool inLocalScope = true;
             bool inLocalScope = true;
             while (environment != null)
             while (environment != null)
             {
             {
-                EnvironmentRecord record = environment._record;
+                EnvironmentRecord record = environment;
                 switch (record)
                 switch (record)
                 {
                 {
                     case GlobalEnvironmentRecord:
                     case GlobalEnvironmentRecord:
@@ -55,13 +55,13 @@ namespace Jint.Runtime.Debugger
                         }
                         }
                         else
                         else
                         {
                         {
-                            bool isTopLevel = environment._outer?._record is FunctionEnvironmentRecord;
+                            bool isTopLevel = environment._outerEnv is FunctionEnvironmentRecord;
                             AddScope(DebugScopeType.Block, record, isTopLevel);
                             AddScope(DebugScopeType.Block, record, isTopLevel);
                         }
                         }
                         break;
                         break;
                 }
                 }
 
 
-                environment = environment._outer;
+                environment = environment._outerEnv;
             }
             }
         }
         }
 
 

+ 6 - 3
Jint/Runtime/Environments/EnvironmentRecord.cs

@@ -1,4 +1,6 @@
-using Jint.Native;
+#nullable enable
+
+using Jint.Native;
 
 
 namespace Jint.Runtime.Environments
 namespace Jint.Runtime.Environments
 {
 {
@@ -8,7 +10,8 @@ namespace Jint.Runtime.Environments
     /// </summary>
     /// </summary>
     public abstract class EnvironmentRecord : JsValue
     public abstract class EnvironmentRecord : JsValue
     {
     {
-        protected readonly Engine _engine;
+        protected internal readonly Engine _engine;
+        protected internal EnvironmentRecord? _outerEnv;
 
 
         protected EnvironmentRecord(Engine engine) : base(InternalTypes.ObjectEnvironmentRecord)
         protected EnvironmentRecord(Engine engine) : base(InternalTypes.ObjectEnvironmentRecord)
         {
         {
@@ -98,7 +101,7 @@ namespace Jint.Runtime.Environments
 
 
         public abstract JsValue GetThisBinding();
         public abstract JsValue GetThisBinding();
 
 
-        public JsValue NewTarget { get; protected set; }
+        public JsValue? NewTarget { get; protected set; }
 
 
         /// <summary>
         /// <summary>
         /// Helper to cache JsString/Key when environments use different lookups.
         /// Helper to cache JsString/Key when environments use different lookups.

+ 18 - 17
Jint/Runtime/Environments/ExecutionContext.cs

@@ -1,24 +1,26 @@
-namespace Jint.Runtime.Environments
+#nullable enable
+
+namespace Jint.Runtime.Environments
 {
 {
     public readonly struct ExecutionContext
     public readonly struct ExecutionContext
     {
     {
-        public ExecutionContext(
-            LexicalEnvironment lexicalEnvironment,
-            LexicalEnvironment variableEnvironment)
+        internal ExecutionContext(
+            EnvironmentRecord lexicalEnvironment,
+            EnvironmentRecord variableEnvironment)
         {
         {
             LexicalEnvironment = lexicalEnvironment;
             LexicalEnvironment = lexicalEnvironment;
             VariableEnvironment = variableEnvironment;
             VariableEnvironment = variableEnvironment;
         }
         }
 
 
-        public readonly LexicalEnvironment LexicalEnvironment;
-        public readonly LexicalEnvironment VariableEnvironment;
+        public readonly EnvironmentRecord LexicalEnvironment;
+        public readonly EnvironmentRecord VariableEnvironment;
 
 
-        public ExecutionContext UpdateLexicalEnvironment(LexicalEnvironment lexicalEnvironment)
+        public ExecutionContext UpdateLexicalEnvironment(EnvironmentRecord lexicalEnvironment)
         {
         {
             return new ExecutionContext(lexicalEnvironment, VariableEnvironment);
             return new ExecutionContext(lexicalEnvironment, VariableEnvironment);
         }
         }
 
 
-        public ExecutionContext UpdateVariableEnvironment(LexicalEnvironment variableEnvironment)
+        public ExecutionContext UpdateVariableEnvironment(EnvironmentRecord variableEnvironment)
         {
         {
             return new ExecutionContext(LexicalEnvironment, variableEnvironment);
             return new ExecutionContext(LexicalEnvironment, variableEnvironment);
         }
         }
@@ -33,18 +35,17 @@
             var lex = LexicalEnvironment;
             var lex = LexicalEnvironment;
             while (true)
             while (true)
             {
             {
-                var envRec = lex._record;
-                var exists = envRec.HasThisBinding();
-                if (exists)
+                if (lex != null)
                 {
                 {
-                    return envRec;
-                }
+                    if (lex.HasThisBinding())
+                    {
+                        return lex;
+                        
+                    }
 
 
-                var outer = lex._outer;
-                lex = outer;
+                    lex = lex._outerEnv;
+                }
             }
             }
         }
         }
-
-
     }
     }
 }
 }

+ 2 - 2
Jint/Runtime/Environments/FunctionEnvironmentRecord.cs

@@ -182,7 +182,7 @@ namespace Jint.Runtime.Environments
             foreach (var property in objectPattern.Properties)
             foreach (var property in objectPattern.Properties)
             {
             {
                 var oldEnv = _engine.ExecutionContext.LexicalEnvironment;
                 var oldEnv = _engine.ExecutionContext.LexicalEnvironment;
-                var paramVarEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
+                var paramVarEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
                 _engine.EnterExecutionContext(paramVarEnv, paramVarEnv);
                 _engine.EnterExecutionContext(paramVarEnv, paramVarEnv);
 
 
                 try
                 try
@@ -327,7 +327,7 @@ namespace Jint.Runtime.Environments
                 var jintExpression = JintExpression.Build(_engine, expression);
                 var jintExpression = JintExpression.Build(_engine, expression);
 
 
                 var oldEnv = _engine.ExecutionContext.LexicalEnvironment;
                 var oldEnv = _engine.ExecutionContext.LexicalEnvironment;
-                var paramVarEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
+                var paramVarEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
 
 
                 _engine.EnterExecutionContext(paramVarEnv, paramVarEnv);
                 _engine.EnterExecutionContext(paramVarEnv, paramVarEnv);
                 try
                 try

+ 1 - 1
Jint/Runtime/Environments/GlobalEnvironmentRecord.cs

@@ -68,7 +68,7 @@ namespace Jint.Runtime.Environments
             value = default;
             value = default;
 
 
             var parent = _global._prototype;
             var parent = _global._prototype;
-            if (parent != null)
+            if (parent is not null)
             {
             {
                 property = parent.GetOwnProperty(name.StringValue);
                 property = parent.GetOwnProperty(name.StringValue);
             }
             }

+ 92 - 0
Jint/Runtime/Environments/JintEnvironment.cs

@@ -0,0 +1,92 @@
+#nullable enable
+
+using Jint.Native;
+using Jint.Native.Function;
+using Jint.Native.Global;
+using Jint.Native.Object;
+
+namespace Jint.Runtime.Environments
+{
+    internal static class JintEnvironment
+    {
+        internal static bool TryGetIdentifierEnvironmentWithBindingValue(
+            Engine engine,
+            EnvironmentRecord? lex,
+            in EnvironmentRecord.BindingName name,
+            bool strict,
+            out EnvironmentRecord? record,
+            out JsValue? value)
+        {
+            record = default;
+            value = default;
+
+            if (ReferenceEquals(lex, engine.GlobalEnvironment)
+                && lex.TryGetBinding(name, strict, out _, out value))
+            {
+                record = lex;
+                return true;
+            }
+
+            while (!ReferenceEquals(lex, null))
+            {
+                if (lex.TryGetBinding(
+                    name,
+                    strict,
+                    out _,
+                    out value))
+                {
+                    record = lex;
+                    return true;
+                }
+
+                lex = lex._outerEnv;
+            }
+
+            return false;
+        }
+
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-newdeclarativeenvironment
+        /// </summary>
+        internal static DeclarativeEnvironmentRecord NewDeclarativeEnvironment(Engine engine, EnvironmentRecord outer, bool catchEnvironment = false)
+        {
+            return new DeclarativeEnvironmentRecord(engine, catchEnvironment)
+            {
+                _outerEnv = outer
+            };
+        }
+
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-newfunctionenvironment
+        /// </summary>
+        internal static FunctionEnvironmentRecord NewFunctionEnvironment(Engine engine, FunctionInstance f, JsValue newTarget)
+        {
+            return new FunctionEnvironmentRecord(engine, f, newTarget)
+            {
+                _outerEnv = f._environment
+            };
+        }
+
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-newglobalenvironment
+        /// </summary>
+        internal static GlobalEnvironmentRecord NewGlobalEnvironment(Engine engine, GlobalObject objectInstance, JsValue thisValue)
+        {
+            return new GlobalEnvironmentRecord(engine, objectInstance)
+            {
+                _outerEnv = null
+            };
+        }
+
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-newobjectenvironment
+        /// </summary>
+        internal static ObjectEnvironmentRecord NewObjectEnvironment(Engine engine, ObjectInstance objectInstance, EnvironmentRecord outer, bool provideThis, bool withEnvironment = false)
+        {
+            return new ObjectEnvironmentRecord(engine, objectInstance, provideThis, withEnvironment)
+            {
+                _outerEnv = outer
+            };
+        } 
+    }
+}

+ 0 - 87
Jint/Runtime/Environments/LexicalEnvironment.cs

@@ -1,87 +0,0 @@
-using Jint.Native;
-using Jint.Native.Function;
-using Jint.Native.Global;
-using Jint.Native.Object;
-
-namespace Jint.Runtime.Environments
-{
-    /// <summary>
-    /// Represents a Lexical Environment (a.k.a Scope)
-    /// http://www.ecma-international.org/ecma-262/5.1/#sec-10.2
-    /// http://www.ecma-international.org/ecma-262/5.1/#sec-10.2.2
-    /// </summary>
-    public sealed class LexicalEnvironment
-    {
-        internal readonly Engine _engine;
-        internal EnvironmentRecord _record;
-        internal LexicalEnvironment _outer;
-
-        public LexicalEnvironment(Engine engine, EnvironmentRecord record, LexicalEnvironment outer)
-        {
-            _engine = engine;
-            _record = record;
-            _outer = outer;
-        }
-
-        internal static bool TryGetIdentifierEnvironmentWithBindingValue(
-            LexicalEnvironment lex,
-            in EnvironmentRecord.BindingName name,
-            bool strict,
-            out EnvironmentRecord record,
-            out JsValue value)
-        {
-            record = default;
-            value = default;
-
-            if (ReferenceEquals(lex, lex._engine.GlobalEnvironment)
-                && lex._record.TryGetBinding(name, strict, out _, out value))
-            {
-                record = lex._record;
-                return true;
-            }
-
-            while (lex != null)
-            {
-                if (lex._record.TryGetBinding(
-                    name,
-                    strict,
-                    out _,
-                    out value))
-                {
-                    record = lex._record;
-                    return true;
-                }
-
-                lex = lex._outer;
-            }
-
-            return false;
-        }
-
-        public static LexicalEnvironment NewDeclarativeEnvironment(Engine engine, LexicalEnvironment outer = null, bool catchEnvironment = false)
-        {
-            var environment = new LexicalEnvironment(engine, null, null)
-            {
-                _record = new DeclarativeEnvironmentRecord(engine, catchEnvironment),
-                _outer = outer
-            };
-
-            return environment;
-        }
-
-        public static LexicalEnvironment NewFunctionEnvironment(Engine engine, FunctionInstance f, JsValue newTarget)
-        {
-            return new LexicalEnvironment(engine, new FunctionEnvironmentRecord(engine, f, newTarget), f._environment);
-        }
-
-        internal static LexicalEnvironment NewGlobalEnvironment(Engine engine, GlobalObject objectInstance)
-        {
-            return new LexicalEnvironment(engine, new GlobalEnvironmentRecord(engine, objectInstance), null);
-        }
-
-        internal static LexicalEnvironment NewObjectEnvironment(Engine engine, ObjectInstance objectInstance, LexicalEnvironment outer, bool provideThis, bool withEnvironment = false)
-        {
-            return new LexicalEnvironment(engine, new ObjectEnvironmentRecord(engine, objectInstance, provideThis, withEnvironment), outer);
-        } 
-    }
-}

+ 2 - 2
Jint/Runtime/ExecutionContextStack.cs

@@ -15,14 +15,14 @@ namespace Jint.Runtime
             _stack = new RefStack<ExecutionContext>(capacity);
             _stack = new RefStack<ExecutionContext>(capacity);
         }
         }
 
 
-        public void ReplaceTopLexicalEnvironment(LexicalEnvironment newEnv)
+        public void ReplaceTopLexicalEnvironment(EnvironmentRecord newEnv)
         {
         {
             var array = _stack._array;
             var array = _stack._array;
             var size = _stack._size;
             var size = _stack._size;
             array[size - 1] = array[size - 1].UpdateLexicalEnvironment(newEnv);
             array[size - 1] = array[size - 1].UpdateLexicalEnvironment(newEnv);
         }
         }
 
 
-        public void ReplaceTopVariableEnvironment(LexicalEnvironment newEnv)
+        public void ReplaceTopVariableEnvironment(EnvironmentRecord newEnv)
         {
         {
             var array = _stack._array;
             var array = _stack._array;
             var size = _stack._size;
             var size = _stack._size;

+ 6 - 6
Jint/Runtime/Interpreter/Expressions/BindingPatternAssignmentExpression.cs

@@ -39,7 +39,7 @@ namespace Jint.Runtime.Interpreter.Expressions
             Engine engine,
             Engine engine,
             BindingPattern pattern,
             BindingPattern pattern,
             JsValue argument,
             JsValue argument,
-            LexicalEnvironment environment,
+            EnvironmentRecord environment,
             bool checkObjectPatternPropertyReference = true)
             bool checkObjectPatternPropertyReference = true)
         {
         {
             if (pattern is ArrayPattern ap)
             if (pattern is ArrayPattern ap)
@@ -67,7 +67,7 @@ namespace Jint.Runtime.Interpreter.Expressions
             return true;
             return true;
         }
         }
         
         
-        private static void HandleArrayPattern(Engine engine, ArrayPattern pattern, JsValue argument, LexicalEnvironment environment)
+        private static void HandleArrayPattern(Engine engine, ArrayPattern pattern, JsValue argument, EnvironmentRecord environment)
         {
         {
             var obj = TypeConverter.ToObject(engine, argument);
             var obj = TypeConverter.ToObject(engine, argument);
             ArrayOperations arrayOperations = null;
             ArrayOperations arrayOperations = null;
@@ -270,7 +270,7 @@ namespace Jint.Runtime.Interpreter.Expressions
             }
             }
         }
         }
 
 
-        private static void HandleObjectPattern(Engine engine, ObjectPattern pattern, JsValue argument, LexicalEnvironment environment, bool checkReference)
+        private static void HandleObjectPattern(Engine engine, ObjectPattern pattern, JsValue argument, EnvironmentRecord environment, bool checkReference)
         {
         {
             var processedProperties = pattern.Properties.Count > 0 && pattern.Properties[pattern.Properties.Count - 1] is RestElement
             var processedProperties = pattern.Properties.Count > 0 && pattern.Properties[pattern.Properties.Count - 1] is RestElement
                 ? new HashSet<JsValue>()
                 ? new HashSet<JsValue>()
@@ -370,7 +370,7 @@ namespace Jint.Runtime.Interpreter.Expressions
             Engine engine,
             Engine engine,
             Reference lhs,
             Reference lhs,
             JsValue v,
             JsValue v,
-            LexicalEnvironment environment)
+            EnvironmentRecord environment)
         {
         {
             if (environment is null)
             if (environment is null)
             {
             {
@@ -395,11 +395,11 @@ namespace Jint.Runtime.Interpreter.Expressions
             Engine engine,
             Engine engine,
             string name,
             string name,
             JsValue rval,
             JsValue rval,
-            LexicalEnvironment environment,
+            EnvironmentRecord environment,
             bool checkReference = true)
             bool checkReference = true)
         {
         {
             var lhs = engine.ResolveBinding(name, environment);
             var lhs = engine.ResolveBinding(name, environment);
-            if (environment != null)
+            if (environment is not null)
             {
             {
                 lhs.InitializeReferencedBinding(rval);
                 lhs.InitializeReferencedBinding(rval);
             }
             }

+ 2 - 1
Jint/Runtime/Interpreter/Expressions/JintAssignmentExpression.cs

@@ -196,7 +196,8 @@ namespace Jint.Runtime.Interpreter.Expressions
             {
             {
                 var env = engine.ExecutionContext.LexicalEnvironment;
                 var env = engine.ExecutionContext.LexicalEnvironment;
                 var strict = StrictModeScope.IsStrictModeCode;
                 var strict = StrictModeScope.IsStrictModeCode;
-                if (LexicalEnvironment.TryGetIdentifierEnvironmentWithBindingValue(
+                if (JintEnvironment.TryGetIdentifierEnvironmentWithBindingValue(
+                    engine,
                     env,
                     env,
                     left._expressionName,
                     left._expressionName,
                     strict,
                     strict,

+ 2 - 3
Jint/Runtime/Interpreter/Expressions/JintFunctionExpression.cs

@@ -16,7 +16,7 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
         protected override object EvaluateInternal()
         protected override object EvaluateInternal()
         {
         {
-            var funcEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, _engine.ExecutionContext.LexicalEnvironment);
+            var funcEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, _engine.ExecutionContext.LexicalEnvironment);
 
 
             var functionThisMode = _function.Strict || _engine._isStrict
             var functionThisMode = _function.Strict || _engine._isStrict
                 ? FunctionThisMode.Strict 
                 ? FunctionThisMode.Strict 
@@ -32,8 +32,7 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
             if (_function.Name != null)
             if (_function.Name != null)
             {
             {
-                var envRec = (DeclarativeEnvironmentRecord) funcEnv._record;
-                envRec.CreateMutableBindingAndInitialize(_function.Name, canBeDeleted: false, closure);
+                funcEnv.CreateMutableBindingAndInitialize(_function.Name, canBeDeleted: false, closure);
             }
             }
 
 
             return closure;
             return closure;

+ 3 - 2
Jint/Runtime/Interpreter/Expressions/JintIdentifierExpression.cs

@@ -25,7 +25,7 @@ namespace Jint.Runtime.Interpreter.Expressions
         {
         {
             var env = _engine.ExecutionContext.LexicalEnvironment;
             var env = _engine.ExecutionContext.LexicalEnvironment;
             var strict = StrictModeScope.IsStrictModeCode;
             var strict = StrictModeScope.IsStrictModeCode;
-            var identifierEnvironment = LexicalEnvironment.TryGetIdentifierEnvironmentWithBindingValue(env, _expressionName, strict, out var temp, out _)
+            var identifierEnvironment = JintEnvironment.TryGetIdentifierEnvironmentWithBindingValue(_engine, env, _expressionName, strict, out var temp, out _)
                 ? temp
                 ? temp
                 : JsValue.Undefined;
                 : JsValue.Undefined;
 
 
@@ -44,7 +44,8 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
             var strict = StrictModeScope.IsStrictModeCode;
             var strict = StrictModeScope.IsStrictModeCode;
             var env = _engine.ExecutionContext.LexicalEnvironment;
             var env = _engine.ExecutionContext.LexicalEnvironment;
-            return LexicalEnvironment.TryGetIdentifierEnvironmentWithBindingValue(
+            return JintEnvironment.TryGetIdentifierEnvironmentWithBindingValue(
+                _engine,
                 env,
                 env,
                 _expressionName,
                 _expressionName,
                 strict,
                 strict,

+ 2 - 1
Jint/Runtime/Interpreter/Expressions/JintMemberExpression.cs

@@ -52,7 +52,8 @@ namespace Jint.Runtime.Interpreter.Expressions
                 baseReferenceName = identifierExpression._expressionName.Key.Name;
                 baseReferenceName = identifierExpression._expressionName.Key.Name;
                 var strict = isStrictModeCode;
                 var strict = isStrictModeCode;
                 var env = _engine.ExecutionContext.LexicalEnvironment;
                 var env = _engine.ExecutionContext.LexicalEnvironment;
-                LexicalEnvironment.TryGetIdentifierEnvironmentWithBindingValue(
+                JintEnvironment.TryGetIdentifierEnvironmentWithBindingValue(
+                    _engine,
                     env,
                     env,
                     identifierExpression._expressionName,
                     identifierExpression._expressionName,
                     strict,
                     strict,

+ 2 - 1
Jint/Runtime/Interpreter/Expressions/JintUpdateExpression.cs

@@ -94,7 +94,8 @@ namespace Jint.Runtime.Interpreter.Expressions
             var strict = StrictModeScope.IsStrictModeCode;
             var strict = StrictModeScope.IsStrictModeCode;
             var name = _leftIdentifier._expressionName;
             var name = _leftIdentifier._expressionName;
             var env = _engine.ExecutionContext.LexicalEnvironment;
             var env = _engine.ExecutionContext.LexicalEnvironment;
-            if (LexicalEnvironment.TryGetIdentifierEnvironmentWithBindingValue(
+            if (JintEnvironment.TryGetIdentifierEnvironmentWithBindingValue(
+                _engine,
                 env,
                 env,
                 name,
                 name,
                 strict,
                 strict,

+ 2 - 2
Jint/Runtime/Interpreter/JintStatementList.cs

@@ -112,10 +112,10 @@ namespace Jint.Runtime.Interpreter
         /// https://tc39.es/ecma262/#sec-blockdeclarationinstantiation
         /// https://tc39.es/ecma262/#sec-blockdeclarationinstantiation
         /// </summary>
         /// </summary>
         internal static void BlockDeclarationInstantiation(
         internal static void BlockDeclarationInstantiation(
-            LexicalEnvironment env,
+            EnvironmentRecord env,
             List<Declaration> declarations)
             List<Declaration> declarations)
         {
         {
-            var envRec = env._record;
+            var envRec = env;
             var boundNames = new List<string>();
             var boundNames = new List<string>();
             for (var i = 0; i < declarations.Count; i++)
             for (var i = 0; i < declarations.Count; i++)
             {
             {

+ 3 - 3
Jint/Runtime/Interpreter/Statements/JintBlockStatement.cs

@@ -23,18 +23,18 @@ namespace Jint.Runtime.Interpreter.Statements
         // http://www.ecma-international.org/ecma-262/6.0/#sec-blockdeclarationinstantiation
         // http://www.ecma-international.org/ecma-262/6.0/#sec-blockdeclarationinstantiation
         protected override Completion ExecuteInternal()
         protected override Completion ExecuteInternal()
         {
         {
-            LexicalEnvironment oldEnv = null;
+            EnvironmentRecord oldEnv = null;
             if (_lexicalDeclarations != null)
             if (_lexicalDeclarations != null)
             {
             {
                 oldEnv = _engine.ExecutionContext.LexicalEnvironment;
                 oldEnv = _engine.ExecutionContext.LexicalEnvironment;
-                var blockEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, _engine.ExecutionContext.LexicalEnvironment);
+                var blockEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, _engine.ExecutionContext.LexicalEnvironment);
                 JintStatementList.BlockDeclarationInstantiation(blockEnv, _lexicalDeclarations);
                 JintStatementList.BlockDeclarationInstantiation(blockEnv, _lexicalDeclarations);
                 _engine.UpdateLexicalEnvironment(blockEnv);
                 _engine.UpdateLexicalEnvironment(blockEnv);
             }
             }
 
 
             var blockValue = _statementList.Execute();
             var blockValue = _statementList.Execute();
 
 
-            if (oldEnv != null)
+            if (oldEnv is not null)
             {
             {
                 _engine.UpdateLexicalEnvironment(oldEnv);
                 _engine.UpdateLexicalEnvironment(oldEnv);
             }
             }

+ 2 - 2
Jint/Runtime/Interpreter/Statements/JintClassDeclarationStatement.cs

@@ -22,8 +22,8 @@ namespace Jint.Runtime.Interpreter.Statements
             var classBinding = _classDefinition._className;
             var classBinding = _classDefinition._className;
             if (classBinding != null)
             if (classBinding != null)
             {
             {
-                env._record.CreateMutableBinding(classBinding);
-                env._record.InitializeBinding(classBinding, F);
+                env.CreateMutableBinding(classBinding);
+                env.InitializeBinding(classBinding, F);
             }
             }
 
 
             return new Completion(CompletionType.Normal, null, null, Location);
             return new Completion(CompletionType.Normal, null, null, Location);

+ 6 - 6
Jint/Runtime/Interpreter/Statements/JintForInForOfStatement.cs

@@ -112,10 +112,10 @@ namespace Jint.Runtime.Interpreter.Statements
         private bool HeadEvaluation(out IIterator result)
         private bool HeadEvaluation(out IIterator result)
         {
         {
             var oldEnv = _engine.ExecutionContext.LexicalEnvironment;
             var oldEnv = _engine.ExecutionContext.LexicalEnvironment;
-            var tdz = LexicalEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
+            var tdz = JintEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
             if (_tdzNames != null)
             if (_tdzNames != null)
             {
             {
-                var TDZEnvRec = tdz._record;
+                var TDZEnvRec = tdz;
                 foreach (var name in _tdzNames)
                 foreach (var name in _tdzNames)
                 {
                 {
                     TDZEnvRec.CreateMutableBinding(name);
                     TDZEnvRec.CreateMutableBinding(name);
@@ -169,7 +169,7 @@ namespace Jint.Runtime.Interpreter.Statements
             {
             {
                 while (true)
                 while (true)
                 {
                 {
-                    LexicalEnvironment iterationEnv = null;
+                    EnvironmentRecord iterationEnv = null;
                     if (!iteratorRecord.TryIteratorStep(out var nextResult))
                     if (!iteratorRecord.TryIteratorStep(out var nextResult))
                     {
                     {
                         close = true;
                         close = true;
@@ -194,7 +194,7 @@ namespace Jint.Runtime.Interpreter.Statements
                     }
                     }
                     else
                     else
                     {
                     {
-                        iterationEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
+                        iterationEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
                         if (_tdzNames != null)
                         if (_tdzNames != null)
                         {
                         {
                             BindingInstantiation(iterationEnv);
                             BindingInstantiation(iterationEnv);
@@ -295,9 +295,9 @@ namespace Jint.Runtime.Interpreter.Statements
             }
             }
         }
         }
 
 
-        private void BindingInstantiation(LexicalEnvironment environment)
+        private void BindingInstantiation(EnvironmentRecord environment)
         {
         {
-            var envRec = (DeclarativeEnvironmentRecord) environment._record;
+            var envRec = (DeclarativeEnvironmentRecord) environment;
             var variableDeclaration = (VariableDeclaration) _leftNode;
             var variableDeclaration = (VariableDeclaration) _leftNode;
             var boundNames = new List<string>();
             var boundNames = new List<string>();
             variableDeclaration.GetBoundNames(boundNames);
             variableDeclaration.GetBoundNames(boundNames);

+ 9 - 9
Jint/Runtime/Interpreter/Statements/JintForStatement.cs

@@ -63,13 +63,13 @@ namespace Jint.Runtime.Interpreter.Statements
 
 
         protected override Completion ExecuteInternal()
         protected override Completion ExecuteInternal()
         {
         {
-            LexicalEnvironment oldEnv = null;
-            LexicalEnvironment loopEnv = null;
+            EnvironmentRecord oldEnv = null;
+            EnvironmentRecord loopEnv = null;
             if (_boundNames != null)
             if (_boundNames != null)
             {
             {
                 oldEnv = _engine.ExecutionContext.LexicalEnvironment;
                 oldEnv = _engine.ExecutionContext.LexicalEnvironment;
-                loopEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
-                var loopEnvRec = loopEnv._record;
+                loopEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
+                var loopEnvRec = loopEnv;
                 var kind = _initStatement._statement.Kind;
                 var kind = _initStatement._statement.Kind;
                 for (var i = 0; i < _boundNames.Count; i++)
                 for (var i = 0; i < _boundNames.Count; i++)
                 {
                 {
@@ -102,7 +102,7 @@ namespace Jint.Runtime.Interpreter.Statements
             }
             }
             finally
             finally
             {
             {
-                if (oldEnv != null)
+                if (oldEnv is not null)
                 {
                 {
                     _engine.UpdateLexicalEnvironment(oldEnv);
                     _engine.UpdateLexicalEnvironment(oldEnv);
                 }
                 }
@@ -167,10 +167,10 @@ namespace Jint.Runtime.Interpreter.Statements
             }
             }
             
             
             var lastIterationEnv = _engine.ExecutionContext.LexicalEnvironment;
             var lastIterationEnv = _engine.ExecutionContext.LexicalEnvironment;
-            var lastIterationEnvRec = lastIterationEnv._record;
-            var outer = lastIterationEnv._outer;
-            var thisIterationEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, outer);
-            var thisIterationEnvRec = (DeclarativeEnvironmentRecord) thisIterationEnv._record;
+            var lastIterationEnvRec = lastIterationEnv;
+            var outer = lastIterationEnv._outerEnv;
+            var thisIterationEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, outer);
+            var thisIterationEnvRec = (DeclarativeEnvironmentRecord) thisIterationEnv;
             
             
             for (var j = 0; j < _boundNames.Count; j++)
             for (var j = 0; j < _boundNames.Count; j++)
             {
             {

+ 1 - 1
Jint/Runtime/Interpreter/Statements/JintStatement.cs

@@ -93,7 +93,7 @@ namespace Jint.Runtime.Interpreter.Statements
             if (statement is ReturnStatement rs && rs.Argument is Literal l)
             if (statement is ReturnStatement rs && rs.Argument is Literal l)
             {
             {
                 var jsValue = JintLiteralExpression.ConvertToJsValue(l);
                 var jsValue = JintLiteralExpression.ConvertToJsValue(l);
-                if (jsValue != null)
+                if (jsValue is not null)
                 {
                 {
                     return new Completion(CompletionType.Return, jsValue, null, rs.Location);
                     return new Completion(CompletionType.Return, jsValue, null, rs.Location);
                 }
                 }

+ 6 - 6
Jint/Runtime/Interpreter/Statements/JintSwitchBlock.cs

@@ -46,11 +46,11 @@ namespace Jint.Runtime.Interpreter.Statements
             {
             {
                 var clause = _jintSwitchBlock[i];
                 var clause = _jintSwitchBlock[i];
 
 
-                LexicalEnvironment oldEnv = null;
+                EnvironmentRecord oldEnv = null;
                 if (clause.LexicalDeclarations != null)
                 if (clause.LexicalDeclarations != null)
                 {
                 {
                     oldEnv = _engine.ExecutionContext.LexicalEnvironment;
                     oldEnv = _engine.ExecutionContext.LexicalEnvironment;
-                    var blockEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
+                    var blockEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
                     JintStatementList.BlockDeclarationInstantiation(blockEnv, clause.LexicalDeclarations);
                     JintStatementList.BlockDeclarationInstantiation(blockEnv, clause.LexicalDeclarations);
                     _engine.UpdateLexicalEnvironment(blockEnv);
                     _engine.UpdateLexicalEnvironment(blockEnv);
                 }
                 }
@@ -72,7 +72,7 @@ namespace Jint.Runtime.Interpreter.Statements
                 {
                 {
                     var r = clause.Consequent.Execute();
                     var r = clause.Consequent.Execute();
 
 
-                    if (oldEnv != null)
+                    if (oldEnv is not null)
                     {
                     {
                         _engine.UpdateLexicalEnvironment(oldEnv);
                         _engine.UpdateLexicalEnvironment(oldEnv);
                     }
                     }
@@ -90,18 +90,18 @@ namespace Jint.Runtime.Interpreter.Statements
             // do we need to execute the default case ?
             // do we need to execute the default case ?
             if (hit == false && defaultCase != null)
             if (hit == false && defaultCase != null)
             {
             {
-                LexicalEnvironment oldEnv = null;
+                EnvironmentRecord oldEnv = null;
                 if (defaultCase.LexicalDeclarations != null)
                 if (defaultCase.LexicalDeclarations != null)
                 {
                 {
                     oldEnv = _engine.ExecutionContext.LexicalEnvironment;
                     oldEnv = _engine.ExecutionContext.LexicalEnvironment;
-                    var blockEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
+                    var blockEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
                     JintStatementList.BlockDeclarationInstantiation(blockEnv, defaultCase.LexicalDeclarations);
                     JintStatementList.BlockDeclarationInstantiation(blockEnv, defaultCase.LexicalDeclarations);
                     _engine.UpdateLexicalEnvironment(blockEnv);
                     _engine.UpdateLexicalEnvironment(blockEnv);
                 }
                 }
 
 
                 var r = defaultCase.Consequent.Execute();
                 var r = defaultCase.Consequent.Execute();
 
 
-                if (oldEnv != null)
+                if (oldEnv is not null)
                 {
                 {
                     _engine.UpdateLexicalEnvironment(oldEnv);
                     _engine.UpdateLexicalEnvironment(oldEnv);
                 }
                 }

+ 2 - 2
Jint/Runtime/Interpreter/Statements/JintTryStatement.cs

@@ -53,14 +53,14 @@ namespace Jint.Runtime.Interpreter.Statements
 
 
                     var thrownValue = b.Value;
                     var thrownValue = b.Value;
                     var oldEnv = _engine.ExecutionContext.LexicalEnvironment;
                     var oldEnv = _engine.ExecutionContext.LexicalEnvironment;
-                    var catchEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, oldEnv, catchEnvironment: true);
+                    var catchEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, oldEnv, catchEnvironment: true);
 
 
                     var boundNames = new List<string>();
                     var boundNames = new List<string>();
                     _statement.Handler.Param.GetBoundNames(boundNames);
                     _statement.Handler.Param.GetBoundNames(boundNames);
 
 
                     foreach (var argName in boundNames)
                     foreach (var argName in boundNames)
                     {
                     {
-                        catchEnv._record.CreateMutableBinding(argName, false);
+                        catchEnv.CreateMutableBinding(argName, false);
                     }
                     }
 
 
                     _engine.UpdateLexicalEnvironment(catchEnv);
                     _engine.UpdateLexicalEnvironment(catchEnv);

+ 1 - 1
Jint/Runtime/Interpreter/Statements/JintWithStatement.cs

@@ -23,7 +23,7 @@ namespace Jint.Runtime.Interpreter.Statements
             var jsValue = _object.GetValue();
             var jsValue = _object.GetValue();
             var obj = TypeConverter.ToObject(_engine, jsValue);
             var obj = TypeConverter.ToObject(_engine, jsValue);
             var oldEnv = _engine.ExecutionContext.LexicalEnvironment;
             var oldEnv = _engine.ExecutionContext.LexicalEnvironment;
-            var newEnv = LexicalEnvironment.NewObjectEnvironment(_engine, obj, oldEnv, provideThis: true, withEnvironment: true);
+            var newEnv = JintEnvironment.NewObjectEnvironment(_engine, obj, oldEnv, provideThis: true, withEnvironment: true);
             _engine.UpdateLexicalEnvironment(newEnv);
             _engine.UpdateLexicalEnvironment(newEnv);
 
 
             Completion c;
             Completion c;