Browse Source

Internalize Environment services and use Key as name (#1735)

* make Environment and GlobalEnvironment internal, use Key as lookup
Marko Lahma 1 year ago
parent
commit
fbe0f6b09c

+ 1 - 3
Jint.Tests.PublicInterface/RavenApiUsageTests.cs

@@ -34,9 +34,7 @@ public class RavenApiUsageTests
         var functionObject = new ScriptFunction(
             engine,
             functionExp,
-            engine.Advanced.CreateDeclarativeEnvironment(),
-            strict: false
-        );
+            strict: false);
 
         Assert.NotNull(functionObject);
     }

+ 0 - 1
Jint.Tests/Runtime/InteropTests.cs

@@ -3,7 +3,6 @@ using System.Globalization;
 using System.Reflection;
 using System.Runtime.CompilerServices;
 using Jint.Native;
-using Jint.Native.Object;
 using Jint.Native.Symbol;
 using Jint.Runtime;
 using Jint.Runtime.Interop;

+ 0 - 10
Jint/Engine.Advanced.cs

@@ -1,6 +1,4 @@
 using Jint.Native.Promise;
-using Jint.Runtime.Environments;
-using Environment = Jint.Runtime.Environments.Environment;
 
 namespace Jint;
 
@@ -51,14 +49,6 @@ public class AdvancedOperations
         _engine.RunAvailableContinuations();
     }
 
-    /// <summary>
-    /// Creates a new declarative environment that has current lexical environment as outer scope.
-    /// </summary>
-    public Environment CreateDeclarativeEnvironment()
-    {
-        return JintEnvironment.NewDeclarativeEnvironment(_engine, _engine.ExecutionContext.LexicalEnvironment);
-    }
-
     /// <summary>
     /// EXPERIMENTAL! Subject to change.
     ///

+ 3 - 1
Jint/Engine.Ast.cs

@@ -1,3 +1,4 @@
+using System.Runtime.InteropServices;
 using Esprima;
 using Esprima.Ast;
 using Jint.Native;
@@ -126,7 +127,8 @@ internal sealed class CachedHoistingScope
         }
     }
 
-    internal readonly record struct CachedLexicalName(string Name, bool Constant);
+    [StructLayout(LayoutKind.Auto)]
+    internal readonly record struct CachedLexicalName(Key Name, bool Constant);
 
     public HoistingScope Scope { get; }
     public List<string> VarNames { get; }

+ 9 - 10
Jint/Engine.cs

@@ -942,10 +942,9 @@ namespace Jint
         {
             var hoistingScope = script.GetHoistingScope();
             var functionDeclarations = hoistingScope._functionDeclarations;
-            var lexDeclarations = hoistingScope._lexicalDeclarations;
 
             var functionToInitialize = new List<JintFunctionDefinition>();
-            var declaredFunctionNames = new HashSet<string>(StringComparer.Ordinal);
+            var declaredFunctionNames = new HashSet<Key>();
             var declaredVarNames = new List<string>();
 
             var realm = Realm;
@@ -955,7 +954,7 @@ namespace Jint
                 for (var i = functionDeclarations.Count - 1; i >= 0; i--)
                 {
                     var d = functionDeclarations[i];
-                    var fn = d.Id!.Name;
+                    var fn = (Key) d.Id!.Name;
                     if (!declaredFunctionNames.Contains(fn))
                     {
                         var fnDefinable = env.CanDeclareGlobalFunction(fn);
@@ -973,7 +972,7 @@ namespace Jint
             var varNames = script.GetVarNames(hoistingScope);
             for (var j = 0; j < varNames.Count; j++)
             {
-                var vn = varNames[j];
+                Key vn = varNames[j];
                 if (env.HasLexicalDeclaration(vn))
                 {
                     ExceptionHelper.ThrowSyntaxError(realm, $"Identifier '{vn}' has already been declared");
@@ -1144,7 +1143,7 @@ namespace Jint
                 {
                     for (var j = 0; j < d.BoundNames.Count; j++)
                     {
-                        var dn = d.BoundNames[j];
+                        Key dn = d.BoundNames[j];
                         if (d.IsConstantDeclaration)
                         {
                             lexEnv.CreateImmutableBinding(dn, strict: true);
@@ -1260,14 +1259,14 @@ namespace Jint
 
             var functionDeclarations = hoistingScope._functionDeclarations;
             var functionsToInitialize = new LinkedList<JintFunctionDefinition>();
-            var declaredFunctionNames = new HashSet<string>(StringComparer.Ordinal);
+            var declaredFunctionNames = new HashSet<Key>();
 
             if (functionDeclarations != null)
             {
                 for (var i = functionDeclarations.Count - 1; i >= 0; i--)
                 {
                     var d = functionDeclarations[i];
-                    var fn = d.Id!.Name;
+                    Key fn = d.Id!.Name;
                     if (!declaredFunctionNames.Contains(fn))
                     {
                         if (varEnvRec is GlobalEnvironment ger)
@@ -1286,7 +1285,7 @@ namespace Jint
             }
 
             var boundNames = new List<string>();
-            var declaredVarNames = new List<string>();
+            var declaredVarNames = new List<Key>();
             var variableDeclarations = hoistingScope._variablesDeclarations;
             var variableDeclarationsCount = variableDeclarations?.Count;
             for (var i = 0; i < variableDeclarationsCount; i++)
@@ -1322,7 +1321,7 @@ namespace Jint
                 d.GetBoundNames(boundNames);
                 for (var j = 0; j < boundNames.Count; j++)
                 {
-                    var dn = boundNames[j];
+                    Key dn = boundNames[j];
                     if (d.IsConstantDeclaration())
                     {
                         lexEnvRec.CreateImmutableBinding(dn, strict: true);
@@ -1336,7 +1335,7 @@ namespace Jint
 
             foreach (var f in functionsToInitialize)
             {
-                var fn = f.Name!;
+                Key fn = f.Name!;
                 var fo = realm.Intrinsics.Function.InstantiateFunctionObject(f, lexEnv, privateEnv);
                 if (varEnvRec is GlobalEnvironment ger)
                 {

+ 4 - 4
Jint/Key.cs

@@ -10,6 +10,7 @@ namespace Jint
     [DebuggerDisplay("{" + nameof(Name) + "}")]
     internal readonly struct Key : IEquatable<Key>
     {
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         private Key(string name)
         {
             Name = name;
@@ -19,11 +20,10 @@ namespace Jint
         internal readonly string Name;
         internal readonly int HashCode;
 
-        public static implicit operator Key(string name)
-        {
-            return new Key(name);
-        }
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static implicit operator Key(string name) => new(name);
 
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static implicit operator string(Key key) => key.Name;
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]

+ 1 - 1
Jint/Native/Argument/JsArguments.cs

@@ -15,7 +15,7 @@ namespace Jint.Native.Argument
     public sealed class JsArguments : ObjectInstance
     {
         // cache property container for array iteration for less allocations
-        private static readonly ThreadLocal<HashSet<string>> _mappedNamed = new(() => new HashSet<string>(StringComparer.Ordinal));
+        private static readonly ThreadLocal<HashSet<Key>> _mappedNamed = new(() => []);
 
         private Function.Function _func = null!;
         private Key[] _names = null!;

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

@@ -21,7 +21,7 @@ namespace Jint.Native.Function
         protected internal PropertyDescriptor? _length;
         internal PropertyDescriptor? _nameDescriptor;
 
-        protected internal Environment? _environment;
+        internal Environment? _environment;
         internal readonly JintFunctionDefinition _functionDefinition = null!;
         internal readonly FunctionThisMode _thisMode;
         internal JsValue _homeObject = Undefined;

+ 1 - 2
Jint/Native/Function/ScriptFunction.cs

@@ -23,13 +23,12 @@ namespace Jint.Native.Function
         public ScriptFunction(
             Engine engine,
             IFunction functionDeclaration,
-            Environment env,
             bool strict,
             ObjectInstance? proto = null)
             : this(
                 engine,
                 new JintFunctionDefinition(functionDeclaration),
-                env,
+                JintEnvironment.NewDeclarativeEnvironment(engine, engine.ExecutionContext.LexicalEnvironment),
                 strict ? FunctionThisMode.Strict : FunctionThisMode.Global,
                 proto)
         {

+ 1 - 19
Jint/Native/Global/GlobalObject.cs

@@ -673,19 +673,7 @@ uriError:
             return GetOwnProperty(property) != PropertyDescriptor.Undefined;
         }
 
-        internal PropertyDescriptor GetProperty(Key property) => GetOwnProperty(property);
-
-        internal bool DefinePropertyOrThrow(Key property, PropertyDescriptor desc)
-        {
-            if (!DefineOwnProperty(property, desc))
-            {
-                ExceptionHelper.ThrowTypeError(_realm);
-            }
-
-            return true;
-        }
-
-        internal bool DefineOwnProperty(Key property, PropertyDescriptor desc)
+        private bool DefineOwnProperty(Key property, PropertyDescriptor desc)
         {
             var current = GetOwnProperty(property);
             if (current == desc)
@@ -752,11 +740,5 @@ uriError:
 
             return true;
         }
-
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal void SetOwnProperty(Key property, PropertyDescriptor desc)
-        {
-            SetProperty(property, desc);
-        }
     }
 }

+ 0 - 1
Jint/Native/Promise/JsPromise.cs

@@ -1,4 +1,3 @@
-using Jint.Native.Function;
 using Jint.Native.Object;
 using Jint.Runtime;
 using Jint.Runtime.Descriptors;

+ 0 - 1
Jint/Native/ShadowRealm/ShadowRealm.cs

@@ -1,7 +1,6 @@
 using Esprima;
 using Esprima.Ast;
 using Esprima.Utils;
-using Jint.Native.Function;
 using Jint.Native.Object;
 using Jint.Native.Promise;
 using Jint.Runtime;

+ 1 - 1
Jint/Runtime/Descriptors/Specialized/ClrAccessDescriptor.cs

@@ -38,7 +38,7 @@ namespace Jint.Runtime.Descriptors.Specialized
 
         private void DoSet(JsValue n, JsValue o)
         {
-            _env.SetMutableBinding(_name.Key.Name, o, true);
+            _env.SetMutableBinding(_name.Key, o, true);
         }
     }
 }

+ 17 - 27
Jint/Runtime/Environments/DeclarativeEnvironment.cs

@@ -19,15 +19,9 @@ namespace Jint.Runtime.Environments
             _catchEnvironment = catchEnvironment;
         }
 
-        public sealed override bool HasBinding(string name)
-        {
-            return _dictionary is not null && _dictionary.ContainsKey(name);
-        }
+        internal sealed override bool HasBinding(BindingName name) => HasBinding(name.Key);
 
-        internal sealed override bool HasBinding(BindingName name)
-        {
-            return _dictionary is not null &&_dictionary.ContainsKey(name.Key);
-        }
+        internal sealed override bool HasBinding(Key name) => _dictionary is not null && _dictionary.ContainsKey(name);
 
         internal override bool TryGetBinding(
             BindingName name,
@@ -53,39 +47,35 @@ namespace Jint.Runtime.Environments
             _dictionary[name] = new Binding(value, canBeDeleted: false, mutable: false, strict);
         }
 
-        public sealed override void CreateMutableBinding(string name, bool canBeDeleted = false)
+        internal sealed override void CreateMutableBinding(Key name, bool canBeDeleted = false)
         {
             _dictionary ??= new HybridDictionary<Binding>();
             _dictionary[name] = new Binding(null!, canBeDeleted, mutable: true, strict: false);
         }
 
-        public sealed override void CreateImmutableBinding(string name, bool strict = true)
+        internal sealed override void CreateImmutableBinding(Key name, bool strict = true)
         {
             _dictionary ??= new HybridDictionary<Binding>();
             _dictionary[name] = new Binding(null!, canBeDeleted: false, mutable: false, strict);
         }
 
-        public sealed override void InitializeBinding(string name, JsValue value)
+        internal sealed override void InitializeBinding(Key name, JsValue value)
         {
             _dictionary ??= new HybridDictionary<Binding>();
             _dictionary.SetOrUpdateValue(name, static (current, value) => current.ChangeValue(value), value);
         }
 
-        internal sealed override void SetMutableBinding(BindingName name, JsValue value, bool strict)
-        {
-            SetMutableBinding(name.Key.Name, value, strict);
-        }
+        internal sealed override void SetMutableBinding(BindingName name, JsValue value, bool strict) => SetMutableBinding(name.Key, value, strict);
 
-        public sealed override void SetMutableBinding(string name, JsValue value, bool strict)
+        internal sealed override void SetMutableBinding(Key name, JsValue value, bool strict)
         {
-            var key = (Key) name;
-            if (_dictionary is null || !_dictionary.TryGetValue(key, out var binding))
+            if (_dictionary is null || !_dictionary.TryGetValue(name, out var binding))
             {
                 if (strict)
                 {
                     ExceptionHelper.ThrowReferenceNameError(_engine.Realm, name);
                 }
-                CreateMutableBindingAndInitialize(key, canBeDeleted: true, value);
+                CreateMutableBindingAndInitialize(name, canBeDeleted: true, value);
                 return;
             }
 
@@ -102,7 +92,7 @@ namespace Jint.Runtime.Environments
 
             if (binding.Mutable)
             {
-                _dictionary[key] = binding.ChangeValue(value);
+                _dictionary[name] = binding.ChangeValue(value);
             }
             else
             {
@@ -113,7 +103,7 @@ namespace Jint.Runtime.Environments
             }
         }
 
-        public override JsValue GetBindingValue(string name, bool strict)
+        internal override JsValue GetBindingValue(Key name, bool strict)
         {
             if (_dictionary is not null && _dictionary.TryGetValue(name, out var binding) && binding.IsInitialized())
             {
@@ -130,7 +120,7 @@ namespace Jint.Runtime.Environments
             ExceptionHelper.ThrowReferenceError(_engine.Realm, $"Cannot access '{name}' before initialization");
         }
 
-        public sealed override bool DeleteBinding(string name)
+        internal sealed override bool DeleteBinding(Key name)
         {
             if (_dictionary is null || !_dictionary.TryGetValue(name, out var binding))
             {
@@ -147,13 +137,13 @@ namespace Jint.Runtime.Environments
             return true;
         }
 
-        public override bool HasThisBinding() => false;
+        internal override bool HasThisBinding() => false;
 
-        public override bool HasSuperBinding() => false;
+        internal override bool HasSuperBinding() => false;
 
-        public sealed override JsValue WithBaseObject() => Undefined;
+        internal sealed override JsValue WithBaseObject() => Undefined;
 
-        public sealed override bool HasBindings()
+        internal sealed override bool HasBindings()
         {
             return _dictionary?.Count > 0;
         }
@@ -176,7 +166,7 @@ namespace Jint.Runtime.Environments
             return keys;
         }
 
-        public override JsValue GetThisBinding()
+        internal override JsValue GetThisBinding()
         {
             return Undefined;
         }

+ 14 - 14
Jint/Runtime/Environments/Environment.cs

@@ -9,7 +9,7 @@ namespace Jint.Runtime.Environments
     /// https://tc39.es/ecma262/#sec-environment-records
     /// </summary>
     [DebuggerTypeProxy(typeof(EnvironmentDebugView))]
-    public abstract class Environment : JsValue
+    internal abstract class Environment : JsValue
     {
         protected internal readonly Engine _engine;
         protected internal Environment? _outerEnv;
@@ -24,7 +24,7 @@ namespace Jint.Runtime.Environments
         /// </summary>
         /// <param name="name">The identifier of the binding</param>
         /// <returns><c>true</c> if it does and <c>false</c> if it does not.</returns>
-        public abstract bool HasBinding(string name);
+        internal abstract bool HasBinding(Key name);
 
         internal abstract bool HasBinding(BindingName name);
 
@@ -39,21 +39,21 @@ namespace Jint.Runtime.Environments
         /// </summary>
         /// <param name="name">The identifier of the binding.</param>
         /// <param name="canBeDeleted"><c>true</c> if the binding may be subsequently deleted.</param>
-        public abstract void CreateMutableBinding(string name, bool canBeDeleted = false);
+        internal abstract void CreateMutableBinding(Key name, bool canBeDeleted = false);
 
         /// <summary>
         /// Creates a new but uninitialized immutable binding in an environment record.
         /// </summary>
         /// <param name="name">The identifier of the binding.</param>
         /// <param name="strict"><c>false</c> if the binding may used before it's been initialized.</param>
-        public abstract void CreateImmutableBinding(string name, bool strict = true);
+        internal abstract void CreateImmutableBinding(Key name, bool strict = true);
 
         /// <summary>
         /// Set the value of an already existing but uninitialized binding in an Environment Record.
         /// </summary>
         /// <param name="name">The text of the bound name</param>
         /// <param name="value">The value for the binding.</param>
-        public abstract void InitializeBinding(string name, JsValue value);
+        internal abstract void InitializeBinding(Key name, JsValue value);
 
         /// <summary>
         /// Sets the value of an already existing mutable binding in an environment record.
@@ -61,7 +61,7 @@ namespace Jint.Runtime.Environments
         /// <param name="name">The identifier of the binding</param>
         /// <param name="value">The value of the binding.</param>
         /// <param name="strict">The identify strict mode references.</param>
-        public abstract void SetMutableBinding(string name, JsValue value, bool strict);
+        internal abstract void SetMutableBinding(Key name, JsValue value, bool strict);
 
         internal abstract void SetMutableBinding(BindingName name, JsValue value, bool strict);
 
@@ -71,22 +71,22 @@ namespace Jint.Runtime.Environments
         /// <param name="name">The identifier of the binding</param>
         /// <param name="strict">The identify strict mode references.</param>
         /// <return>The value of an already existing binding from an environment record.</return>
-        public abstract JsValue GetBindingValue(string name, bool strict);
+        internal abstract JsValue GetBindingValue(Key name, bool strict);
 
         /// <summary>
         /// Delete a binding from an environment record. The String value N is the text of the bound name If a binding for N exists, remove the binding and return true. If the binding exists but cannot be removed return false. If the binding does not exist return true.
         /// </summary>
         /// <param name="name">The identifier of the binding</param>
         /// <returns><true>true</true> if the deletion is successfull.</returns>
-        public abstract bool DeleteBinding(string name);
+        internal abstract bool DeleteBinding(Key name);
 
-        public abstract bool HasThisBinding();
+        internal abstract bool HasThisBinding();
 
-        public abstract bool HasSuperBinding();
+        internal abstract bool HasSuperBinding();
 
-        public abstract JsValue WithBaseObject();
+        internal abstract JsValue WithBaseObject();
 
-        public abstract bool HasBindings();
+        internal abstract bool HasBindings();
 
         /// <summary>
         /// Returns an array of all the defined binding names
@@ -106,9 +106,9 @@ namespace Jint.Runtime.Environments
             return false;
         }
 
-        public abstract JsValue GetThisBinding();
+        internal abstract JsValue GetThisBinding();
 
-        public JsValue? NewTarget { get; protected set; }
+        internal JsValue? NewTarget { get; set; }
 
         /// <summary>
         /// Helper to cache JsString/Key when environments use different lookups.

+ 3 - 3
Jint/Runtime/Environments/FunctionEnvironment.cs

@@ -44,9 +44,9 @@ namespace Jint.Runtime.Environments
         }
 
 
-        public override bool HasThisBinding() => _thisBindingStatus != ThisBindingStatus.Lexical;
+        internal override bool HasThisBinding() => _thisBindingStatus != ThisBindingStatus.Lexical;
 
-        public override bool HasSuperBinding() =>
+        internal override bool HasSuperBinding() =>
             _thisBindingStatus != ThisBindingStatus.Lexical && !_functionObject._homeObject.IsUndefined();
 
         public JsValue BindThisValue(JsValue value)
@@ -62,7 +62,7 @@ namespace Jint.Runtime.Environments
             return null!;
         }
 
-        public override JsValue GetThisBinding()
+        internal override JsValue GetThisBinding()
         {
             if (_thisBindingStatus != ThisBindingStatus.Uninitialized)
             {

+ 25 - 31
Jint/Runtime/Environments/GlobalEnvironment.cs

@@ -10,7 +10,7 @@ namespace Jint.Runtime.Environments
     /// <summary>
     /// https://tc39.es/ecma262/#sec-global-environment-records
     /// </summary>
-    public sealed class GlobalEnvironment : Environment
+    internal sealed class GlobalEnvironment : Environment
     {
         /// <summary>
         /// A sealed class for global usage.
@@ -40,7 +40,7 @@ namespace Jint.Runtime.Environments
 
         public ObjectInstance GlobalThisValue => _global;
 
-        public override bool HasBinding(string name)
+        internal override bool HasBinding(Key name)
         {
             if (_declarativeRecord.HasBinding(name))
             {
@@ -123,7 +123,7 @@ namespace Jint.Runtime.Environments
         /// <summary>
         /// https://tc39.es/ecma262/#sec-global-environment-records-createmutablebinding-n-d
         /// </summary>
-        public override void CreateMutableBinding(string name, bool canBeDeleted = false)
+        internal override void CreateMutableBinding(Key name, bool canBeDeleted = false)
         {
             if (_declarativeRecord.HasBinding(name))
             {
@@ -136,7 +136,7 @@ namespace Jint.Runtime.Environments
         /// <summary>
         /// https://tc39.es/ecma262/#sec-global-environment-records-createimmutablebinding-n-s
         /// </summary>
-        public override void CreateImmutableBinding(string name, bool strict = true)
+        internal override void CreateImmutableBinding(Key name, bool strict = true)
         {
             if (_declarativeRecord.HasBinding(name))
             {
@@ -147,12 +147,12 @@ namespace Jint.Runtime.Environments
         }
 
         [MethodImpl(MethodImplOptions.NoInlining)]
-        private void ThrowAlreadyDeclaredException(string name)
+        private void ThrowAlreadyDeclaredException(Key name)
         {
-            ExceptionHelper.ThrowTypeError(_engine.Realm, name + " has already been declared");
+            ExceptionHelper.ThrowTypeError(_engine.Realm, $"{name} has already been declared");
         }
 
-        public override void InitializeBinding(string name, JsValue value)
+        internal override void InitializeBinding(Key name, JsValue value)
         {
             if (_declarativeRecord.HasBinding(name))
             {
@@ -164,7 +164,7 @@ namespace Jint.Runtime.Environments
             }
         }
 
-        public override void SetMutableBinding(string name, JsValue value, bool strict)
+        internal override void SetMutableBinding(Key name, JsValue value, bool strict)
         {
             if (_declarativeRecord.HasBinding(name))
             {
@@ -205,15 +205,15 @@ namespace Jint.Runtime.Environments
                 }
                 else
                 {
-                    SetMutableBindingUnlikely(name.Key.Name, value, strict);
+                    SetMutableBindingUnlikely(name.Key, value, strict);
                 }
             }
         }
 
-        private void SetMutableBindingUnlikely(string name, JsValue value, bool strict)
+        private void SetMutableBindingUnlikely(Key name, JsValue value, bool strict)
         {
             // see ObjectEnvironmentRecord.SetMutableBinding
-            var jsString = new JsString(name);
+            var jsString = new JsString(name.Name);
             if (strict && !_global.HasProperty(jsString))
             {
                 ExceptionHelper.ThrowReferenceNameError(_engine.Realm, name);
@@ -222,7 +222,7 @@ namespace Jint.Runtime.Environments
             _global.Set(jsString, value);
         }
 
-        public override JsValue GetBindingValue(string name, bool strict)
+        internal override JsValue GetBindingValue(Key name, bool strict)
         {
             if (_declarativeRecord.HasBinding(name))
             {
@@ -240,7 +240,7 @@ namespace Jint.Runtime.Environments
             }
             else
             {
-                desc = _global.GetProperty(name);
+                desc = _global.GetProperty(name.Name);
             }
 
             if (strict && desc == PropertyDescriptor.Undefined)
@@ -251,16 +251,16 @@ namespace Jint.Runtime.Environments
             return ObjectInstance.UnwrapJsValue(desc, _global);
         }
 
-        public override bool DeleteBinding(string name)
+        internal override bool DeleteBinding(Key name)
         {
             if (_declarativeRecord.HasBinding(name))
             {
                 return _declarativeRecord.DeleteBinding(name);
             }
 
-            if (_global.HasOwnProperty(name))
+            if (_global.HasOwnProperty(name.Name))
             {
-                var status = _global.Delete(name);
+                var status = _global.Delete(name.Name);
                 if (status)
                 {
                     _varNames.Remove(name);
@@ -272,37 +272,31 @@ namespace Jint.Runtime.Environments
             return true;
         }
 
-        public override bool HasThisBinding()
+        internal override bool HasThisBinding()
         {
             return true;
         }
 
-        public override bool HasSuperBinding()
+        internal override bool HasSuperBinding()
         {
             return false;
         }
 
-        public override JsValue WithBaseObject()
+        internal override JsValue WithBaseObject()
         {
             return Undefined;
         }
 
-        public override JsValue GetThisBinding()
+        internal override JsValue GetThisBinding()
         {
             return _global;
         }
 
-        public bool HasVarDeclaration(string name)
-        {
-            return _varNames.Contains(name);
-        }
+        internal bool HasVarDeclaration(Key name) => _varNames.Contains(name);
 
-        public bool HasLexicalDeclaration(string name)
-        {
-            return _declarativeRecord.HasBinding(name);
-        }
+        internal bool HasLexicalDeclaration(Key name) => _declarativeRecord.HasBinding(name);
 
-        public bool HasRestrictedGlobalProperty(string name)
+        internal bool HasRestrictedGlobalProperty(Key name)
         {
             if (_globalObject is not null)
             {
@@ -310,7 +304,7 @@ namespace Jint.Runtime.Environments
                        && !desc.Configurable;
             }
 
-            var existingProp = _global.GetOwnProperty(name);
+            var existingProp = _global.GetOwnProperty(name.Name);
             if (existingProp == PropertyDescriptor.Undefined)
             {
                 return false;
@@ -403,7 +397,7 @@ namespace Jint.Runtime.Environments
             _varNames.Add(name);
         }
 
-        public sealed override bool HasBindings()
+        internal sealed override bool HasBindings()
         {
             return _declarativeRecord.HasBindings() || _globalObject?._properties?.Count > 0 || _global._properties?.Count > 0;
         }

+ 3 - 3
Jint/Runtime/Environments/ModuleEnvironment.cs

@@ -20,7 +20,7 @@ internal sealed class ModuleEnvironment : DeclarativeEnvironment
     /// <summary>
     /// https://tc39.es/ecma262/#sec-module-environment-records-getthisbinding
     /// </summary>
-    public override JsValue GetThisBinding()
+    internal override JsValue GetThisBinding()
     {
         return Undefined;
     }
@@ -37,7 +37,7 @@ internal sealed class ModuleEnvironment : DeclarativeEnvironment
     /// <summary>
     /// https://tc39.es/ecma262/#sec-module-environment-records-getbindingvalue-n-s
     /// </summary>
-    public override JsValue GetBindingValue(string name, bool strict)
+    internal override JsValue GetBindingValue(Key name, bool strict)
     {
         if (_importBindings.TryGetValue(name, out var indirectBinding))
         {
@@ -62,7 +62,7 @@ internal sealed class ModuleEnvironment : DeclarativeEnvironment
     /// <summary>
     /// https://tc39.es/ecma262/#sec-module-environment-records-hasthisbinding
     /// </summary>
-    public override bool HasThisBinding() => true;
+    internal override bool HasThisBinding() => true;
 
     private readonly record struct IndirectBinding(Module Module, string BindingName);
 }

+ 16 - 25
Jint/Runtime/Environments/ObjectEnvironment.cs

@@ -27,9 +27,9 @@ namespace Jint.Runtime.Environments
             _withEnvironment = withEnvironment;
         }
 
-        public override bool HasBinding(string name)
+        internal override bool HasBinding(Key name)
         {
-            var property = new JsString(name);
+            var property = new JsString(name.Name);
             var foundBinding = HasProperty(property);
 
             if (!foundBinding)
@@ -42,7 +42,7 @@ namespace Jint.Runtime.Environments
                 return true;
             }
 
-            return !IsBlocked(name);
+            return !IsBlocked(property);
         }
 
         internal override bool HasBinding(BindingName name)
@@ -111,9 +111,9 @@ namespace Jint.Runtime.Environments
         /// <summary>
         /// http://www.ecma-international.org/ecma-262/6.0/#sec-object-environment-records-createmutablebinding-n-d
         /// </summary>
-        public override void CreateMutableBinding(string name, bool canBeDeleted = false)
+        internal override void CreateMutableBinding(Key name, bool canBeDeleted = false)
         {
-            _bindingObject.DefinePropertyOrThrow(name, new PropertyDescriptor(Undefined, canBeDeleted
+            _bindingObject.DefinePropertyOrThrow(name.Name, new PropertyDescriptor(Undefined, canBeDeleted
                 ? PropertyFlag.ConfigurableEnumerableWritable | PropertyFlag.MutableBinding
                 : PropertyFlag.NonConfigurable | PropertyFlag.MutableBinding));
         }
@@ -121,7 +121,7 @@ namespace Jint.Runtime.Environments
         /// <summary>
         /// https://tc39.es/ecma262/#sec-object-environment-records-createimmutablebinding-n-s
         /// </summary>
-        public override void CreateImmutableBinding(string name, bool strict = true)
+        internal override void CreateImmutableBinding(Key name, bool strict = true)
         {
             ExceptionHelper.ThrowInvalidOperationException("The concrete Environment Record method CreateImmutableBinding is never used within this specification in association with Object Environment Records.");
         }
@@ -129,12 +129,9 @@ namespace Jint.Runtime.Environments
         /// <summary>
         /// https://tc39.es/ecma262/#sec-object-environment-records-initializebinding-n-v
         /// </summary>
-        public override void InitializeBinding(string name, JsValue value)
-        {
-            SetMutableBinding(name, value, false);
-        }
+        internal override void InitializeBinding(Key name, JsValue value) => SetMutableBinding(name, value, strict: false);
 
-        public override void SetMutableBinding(string name, JsValue value, bool strict)
+        internal override void SetMutableBinding(Key name, JsValue value, bool strict)
         {
             var jsString = new JsString(name);
             if (strict && !_bindingObject.HasProperty(jsString))
@@ -155,9 +152,9 @@ namespace Jint.Runtime.Environments
             _bindingObject.Set(name.Value, value);
         }
 
-        public override JsValue GetBindingValue(string name, bool strict)
+        internal override JsValue GetBindingValue(Key name, bool strict)
         {
-            var desc = _bindingObject.GetProperty(name);
+            var desc = _bindingObject.GetProperty(name.Name);
             if (strict && desc == PropertyDescriptor.Undefined)
             {
                 ExceptionHelper.ThrowReferenceNameError(_engine.Realm, name);
@@ -166,21 +163,15 @@ namespace Jint.Runtime.Environments
             return ObjectInstance.UnwrapJsValue(desc, _bindingObject);
         }
 
-        public override bool DeleteBinding(string name)
-        {
-            return _bindingObject.Delete(name);
-        }
+        internal override bool DeleteBinding(Key name) => _bindingObject.Delete(name.Name);
 
-        public override bool HasThisBinding() => false;
+        internal override bool HasThisBinding() => false;
 
-        public override bool HasSuperBinding() => false;
+        internal override bool HasSuperBinding() => false;
 
-        public override JsValue WithBaseObject() => _withEnvironment ? _bindingObject : Undefined;
+        internal override JsValue WithBaseObject() => _withEnvironment ? _bindingObject : Undefined;
 
-        public sealed override bool HasBindings()
-        {
-            return _bindingObject._properties?.Count > 0;
-        }
+        internal override bool HasBindings() => _bindingObject._properties?.Count > 0;
 
         internal override string[] GetAllBindingNames()
         {
@@ -202,7 +193,7 @@ namespace Jint.Runtime.Environments
             return ReferenceEquals(_bindingObject, other);
         }
 
-        public override JsValue GetThisBinding()
+        internal override JsValue GetThisBinding()
         {
             throw new NotImplementedException();
         }

+ 1 - 1
Jint/Runtime/Host.cs

@@ -59,7 +59,7 @@ namespace Jint.Runtime
             Engine.EnterExecutionContext(newContext);
         }
 
-        protected virtual GlobalEnvironment CreateGlobalEnvironment(ObjectInstance globalObject)
+        internal virtual GlobalEnvironment CreateGlobalEnvironment(ObjectInstance globalObject)
         {
             return JintEnvironment.NewGlobalEnvironment(Engine, globalObject, globalObject);
         }

+ 3 - 0
Jint/Runtime/KnownKeys.cs

@@ -1,3 +1,5 @@
+using Environment = Jint.Runtime.Environments.Environment;
+
 namespace Jint.Runtime;
 
 internal static class KnownKeys
@@ -5,6 +7,7 @@ internal static class KnownKeys
     internal static readonly Key Arguments = "arguments";
     internal static readonly Key Caller = "caller";
     internal static readonly Key Constructor = "constructor";
+    internal static readonly Key Default = "default";
     internal static readonly Key Done = "done";
     internal static readonly Key Eval = "eval";
     internal static readonly Key Length = "length";

+ 2 - 2
Jint/Runtime/Modules/SyntheticModule.cs

@@ -49,7 +49,7 @@ internal sealed class SyntheticModule : Module
         // 7.Suspend the currently running execution context.
         _engine.EnterExecutionContext(moduleContext);
 
-        _environment.SetMutableBinding("default", _obj, strict: true);
+        _environment.SetMutableBinding(KnownKeys.Default, _obj, strict: true);
 
         _engine.LeaveExecutionContext();
 
@@ -70,7 +70,7 @@ internal sealed class SyntheticModule : Module
 
     protected internal override Completion InnerModuleEvaluation(Stack<CyclicModule> stack, int index, ref int asyncEvalOrder)
     {
-        _environment.SetMutableBinding("default", _obj, strict: true);
+        _environment.SetMutableBinding(KnownKeys.Default, _obj, strict: true);
         return new Completion(CompletionType.Normal, index, new Identifier(""));
     }
 }

+ 1 - 1
Jint/Runtime/Realm.cs

@@ -35,7 +35,7 @@ namespace Jint.Runtime
         /// <summary>
         /// The global environment for this realm.
         /// </summary>
-        public GlobalEnvironment GlobalEnv { get; internal set; } = null!;
+        internal GlobalEnvironment GlobalEnv { get; set; } = null!;
 
         /// <summary>
         /// Field reserved for use by hosts that need to associate additional information with a Realm Record.