Browse Source

Upgrade to Esprima 3.0.0-beta-7 (#1289)

Marko Lahma 2 years ago
parent
commit
03c31195bd
32 changed files with 204 additions and 127 deletions
  1. 20 5
      Jint.Benchmark/DromaeoBenchmark.cs
  2. 1 2
      Jint.Benchmark/SingleScriptBenchmark.cs
  3. 2 3
      Jint.Tests.Test262/TestHarness.cs
  4. 1 1
      Jint.Tests/Runtime/EngineTests.cs
  5. 58 0
      Jint/Engine.Ast.cs
  6. 4 4
      Jint/Engine.cs
  7. 1 1
      Jint/EsprimaExtensions.cs
  8. 6 10
      Jint/HoistingScope.cs
  9. 1 1
      Jint/Jint.csproj
  10. 1 1
      Jint/Native/Function/FunctionConstructor.cs
  11. 1 1
      Jint/Native/Function/FunctionInstance.cs
  12. 2 2
      Jint/Native/Function/ScriptFunctionInstance.cs
  13. 4 4
      Jint/Native/JsNumber.cs
  14. 3 3
      Jint/Native/RegExp/RegExpConstructor.cs
  15. 3 3
      Jint/Runtime/Environments/DeclarativeEnvironmentRecord.cs
  16. 13 5
      Jint/Runtime/Environments/EnvironmentRecord.cs
  17. 4 4
      Jint/Runtime/Environments/GlobalEnvironmentRecord.cs
  18. 1 1
      Jint/Runtime/Environments/ModuleEnvironmentRecord.cs
  19. 3 3
      Jint/Runtime/Environments/ObjectEnvironmentRecord.cs
  20. 1 1
      Jint/Runtime/Interpreter/Expressions/JintArrowFunctionExpression.cs
  21. 3 3
      Jint/Runtime/Interpreter/Expressions/JintAssignmentExpression.cs
  22. 1 1
      Jint/Runtime/Interpreter/Expressions/JintExpression.cs
  23. 2 2
      Jint/Runtime/Interpreter/Expressions/JintFunctionExpression.cs
  24. 22 17
      Jint/Runtime/Interpreter/Expressions/JintIdentifierExpression.cs
  25. 6 3
      Jint/Runtime/Interpreter/Expressions/JintLiteralExpression.cs
  26. 2 2
      Jint/Runtime/Interpreter/Expressions/JintMemberExpression.cs
  27. 3 3
      Jint/Runtime/Interpreter/Expressions/JintObjectExpression.cs
  28. 1 1
      Jint/Runtime/Interpreter/Expressions/JintUpdateExpression.cs
  29. 22 28
      Jint/Runtime/Interpreter/JintFunctionDefinition.cs
  30. 1 1
      Jint/Runtime/Interpreter/JintStatementList.cs
  31. 10 10
      Jint/Runtime/KnownKeys.cs
  32. 1 1
      Jint/Runtime/Modules/SourceTextModuleRecord.cs

+ 20 - 5
Jint.Benchmark/DromaeoBenchmark.cs

@@ -1,11 +1,12 @@
 using BenchmarkDotNet.Attributes;
 using BenchmarkDotNet.Attributes;
+using Esprima.Ast;
 
 
 namespace Jint.Benchmark;
 namespace Jint.Benchmark;
 
 
 [MemoryDiagnoser]
 [MemoryDiagnoser]
 public class DromaeoBenchmark
 public class DromaeoBenchmark
 {
 {
-    public static readonly Dictionary<string, string> files = new Dictionary<string, string>
+    private static readonly Dictionary<string, string> _files = new()
     {
     {
         {"dromaeo-3d-cube", null},
         {"dromaeo-3d-cube", null},
         {"dromaeo-core-eval", null},
         {"dromaeo-core-eval", null},
@@ -15,14 +16,18 @@ public class DromaeoBenchmark
         {"dromaeo-string-base64", null}
         {"dromaeo-string-base64", null}
     };
     };
 
 
+    private Dictionary<string, Script> _prepared = new();
+
     private Engine engine;
     private Engine engine;
 
 
     [GlobalSetup]
     [GlobalSetup]
     public void Setup()
     public void Setup()
     {
     {
-        foreach (var fileName in files.Keys.ToList())
+        foreach (var fileName in _files.Keys)
         {
         {
-            files[fileName] = File.ReadAllText($"Scripts/{fileName}.js");
+            var script = File.ReadAllText($"Scripts/{fileName}.js");
+            _files[fileName] = script;
+            _prepared[fileName] = Engine.PrepareScript(script);
         }
         }
 
 
         engine = new Engine()
         engine = new Engine()
@@ -40,9 +45,12 @@ var prep = function (fn) { fn(); };
     [ParamsSource(nameof(FileNames))]
     [ParamsSource(nameof(FileNames))]
     public string FileName { get; set; }
     public string FileName { get; set; }
 
 
+    [Params(true, false)]
+    public bool Prepared { get; set; }
+
     public IEnumerable<string> FileNames()
     public IEnumerable<string> FileNames()
     {
     {
-        foreach (var entry in files)
+        foreach (var entry in _files)
         {
         {
             yield return entry.Key;
             yield return entry.Key;
         }
         }
@@ -51,6 +59,13 @@ var prep = function (fn) { fn(); };
     [Benchmark]
     [Benchmark]
     public void Run()
     public void Run()
     {
     {
-        engine.Execute(files[FileName]);
+        if (Prepared)
+        {
+            engine.Execute(_prepared[FileName]);
+        }
+        else
+        {
+            engine.Execute(_files[FileName]);
+        }
     }
     }
 }
 }

+ 1 - 2
Jint.Benchmark/SingleScriptBenchmark.cs

@@ -1,5 +1,4 @@
 using BenchmarkDotNet.Attributes;
 using BenchmarkDotNet.Attributes;
-using Esprima;
 using Esprima.Ast;
 using Esprima.Ast;
 
 
 namespace Jint.Benchmark;
 namespace Jint.Benchmark;
@@ -16,7 +15,7 @@ public abstract class SingleScriptBenchmark
     public void Setup()
     public void Setup()
     {
     {
         _script = File.ReadAllText($"Scripts/{FileName}");
         _script = File.ReadAllText($"Scripts/{FileName}");
-        _parsedScript = new JavaScriptParser().ParseScript(_script);
+        _parsedScript = Engine.PrepareScript(_script);
     }
     }
 
 
     [Benchmark]
     [Benchmark]

+ 2 - 3
Jint.Tests.Test262/TestHarness.cs

@@ -1,5 +1,3 @@
-using Esprima;
-
 namespace Jint.Tests.Test262;
 namespace Jint.Tests.Test262;
 
 
 /// <summary>
 /// <summary>
@@ -12,7 +10,8 @@ public partial class TestHarness
         foreach (var file in State.HarnessFiles)
         foreach (var file in State.HarnessFiles)
         {
         {
             var source = file.Program;
             var source = file.Program;
-            State.Sources[Path.GetFileName(file.FileName)] = new JavaScriptParser().ParseScript(source, source: file.FileName);
+            var script = Engine.PrepareScript(source, source: file.FileName);
+            State.Sources[Path.GetFileName(file.FileName)] = script;
         }
         }
 
 
         return Task.CompletedTask;
         return Task.CompletedTask;

+ 1 - 1
Jint.Tests/Runtime/EngineTests.cs

@@ -1050,7 +1050,7 @@ namespace Jint.Tests.Runtime
             {
             {
                 Assert.Equal(1, e.LineNumber);
                 Assert.Equal(1, e.LineNumber);
                 Assert.Equal(9, e.Column);
                 Assert.Equal(9, e.Column);
-                Assert.Equal("jQuery.js", e.SourceText);
+                Assert.Equal("jQuery.js", e.SourceLocation);
             }
             }
         }
         }
         #region DateParsingAndStrings
         #region DateParsingAndStrings

+ 58 - 0
Jint/Engine.Ast.cs

@@ -0,0 +1,58 @@
+using Esprima;
+using Esprima.Ast;
+using Jint.Runtime.Environments;
+using Jint.Runtime.Interpreter;
+using Jint.Runtime.Interpreter.Expressions;
+
+namespace Jint;
+
+public partial class Engine
+{
+
+    /// <summary>
+    /// Prepares a script for the engine that includes static analysis data to speed up execution during run-time.
+    /// </summary>
+    /// <remarks>
+    /// Returned instance is reusable and thread-safe. You should prepare scripts only once and then reuse them.
+    /// </remarks>
+    public static Script PrepareScript(string script, string? source = null)
+    {
+        var astAnalyzer = new AstAnalyzer();
+        var options = ParserOptions.Default with { OnNodeCreated = astAnalyzer.NodeVisitor };
+
+        return new JavaScriptParser(options).ParseScript(script, source);
+    }
+
+    private sealed class AstAnalyzer
+    {
+        private readonly Dictionary<string, EnvironmentRecord.BindingName> _bindingNames = new();
+
+        public void NodeVisitor(Node node)
+        {
+            switch (node.Type)
+            {
+                case Nodes.Identifier:
+                    {
+                        var name = ((Identifier) node).Name;
+
+                        if (!_bindingNames.TryGetValue(name, out var bindingName))
+                        {
+                            _bindingNames[name] = bindingName = new EnvironmentRecord.BindingName(name);
+                        }
+
+                        node.AssociatedData = bindingName;
+                        break;
+                    }
+                case Nodes.Literal:
+                    node.AssociatedData = JintLiteralExpression.ConvertToJsValue((Literal) node);
+                    break;
+                case Nodes.ArrowFunctionExpression:
+                case Nodes.FunctionDeclaration:
+                case Nodes.FunctionExpression:
+                    var function = (IFunction) node;
+                    node.AssociatedData = JintFunctionDefinition.BuildState(function);
+                    break;
+            }
+        }
+    }
+}

+ 4 - 4
Jint/Engine.cs

@@ -832,7 +832,7 @@ namespace Jint
                         }
                         }
 
 
                         declaredFunctionNames.Add(fn);
                         declaredFunctionNames.Add(fn);
-                        functionToInitialize.AddFirst(new JintFunctionDefinition(this, d));
+                        functionToInitialize.AddFirst(new JintFunctionDefinition(d));
                     }
                     }
                 }
                 }
             }
             }
@@ -931,7 +931,7 @@ namespace Jint
             var env = (FunctionEnvironmentRecord) ExecutionContext.LexicalEnvironment;
             var env = (FunctionEnvironmentRecord) ExecutionContext.LexicalEnvironment;
             var strict = _isStrict || StrictModeScope.IsStrictModeCode;
             var strict = _isStrict || StrictModeScope.IsStrictModeCode;
 
 
-            var configuration = func.Initialize(functionInstance);
+            var configuration = func.Initialize();
             var parameterNames = configuration.ParameterNames;
             var parameterNames = configuration.ParameterNames;
             var hasDuplicates = configuration.HasDuplicates;
             var hasDuplicates = configuration.HasDuplicates;
             var simpleParameterList = configuration.IsSimpleParameterList;
             var simpleParameterList = configuration.IsSimpleParameterList;
@@ -942,7 +942,7 @@ namespace Jint
             env.InitializeParameters(parameterNames, hasDuplicates, arguments);
             env.InitializeParameters(parameterNames, hasDuplicates, arguments);
 
 
             ArgumentsInstance? ao = null;
             ArgumentsInstance? ao = null;
-            if (configuration.ArgumentsObjectNeeded)
+            if (configuration.ArgumentsObjectNeeded || _isDebugMode)
             {
             {
                 if (strict || !simpleParameterList)
                 if (strict || !simpleParameterList)
                 {
                 {
@@ -1153,7 +1153,7 @@ namespace Jint
                         }
                         }
 
 
                         declaredFunctionNames.Add(fn);
                         declaredFunctionNames.Add(fn);
-                        functionsToInitialize.AddFirst(new JintFunctionDefinition(this, d));
+                        functionsToInitialize.AddFirst(new JintFunctionDefinition(d));
                     }
                     }
                 }
                 }
             }
             }

+ 1 - 1
Jint/EsprimaExtensions.cs

@@ -288,7 +288,7 @@ namespace Jint
                 ExceptionHelper.ThrowSyntaxError(engine.Realm);
                 ExceptionHelper.ThrowSyntaxError(engine.Realm);
             }
             }
 
 
-            var definition = new JintFunctionDefinition(engine, function);
+            var definition = new JintFunctionDefinition(function);
             var closure = intrinsics.Function.OrdinaryFunctionCreate(prototype, definition, definition.ThisMode, scope, privateScope);
             var closure = intrinsics.Function.OrdinaryFunctionCreate(prototype, definition, definition.ThisMode, scope, privateScope);
             closure.MakeMethod(obj);
             closure.MakeMethod(obj);
 
 

+ 6 - 10
Jint/HoistingScope.cs

@@ -3,7 +3,7 @@ using Jint.Runtime.Modules;
 
 
 namespace Jint
 namespace Jint
 {
 {
-    internal readonly struct HoistingScope
+    internal sealed class HoistingScope
     {
     {
         internal readonly List<FunctionDeclaration>? _functionDeclarations;
         internal readonly List<FunctionDeclaration>? _functionDeclarations;
 
 
@@ -14,7 +14,8 @@ namespace Jint
         internal readonly List<string>? _lexicalNames;
         internal readonly List<string>? _lexicalNames;
         internal readonly bool _hasArgumentsReference;
         internal readonly bool _hasArgumentsReference;
 
 
-        private HoistingScope(List<FunctionDeclaration>? functionDeclarations,
+        private HoistingScope(
+            List<FunctionDeclaration>? functionDeclarations,
             List<Key>? varNames,
             List<Key>? varNames,
             List<VariableDeclaration>? variableDeclarations,
             List<VariableDeclaration>? variableDeclarations,
             List<Declaration>? lexicalDeclarations,
             List<Declaration>? lexicalDeclarations,
@@ -46,17 +47,12 @@ namespace Jint
                 false);
                 false);
         }
         }
 
 
-        public static HoistingScope GetFunctionLevelDeclarations(
-            bool strict,
-            IFunction node,
-            bool collectVarNames = false,
-            bool collectLexicalNames = false,
-            bool checkArgumentsReference = false)
+        public static HoistingScope GetFunctionLevelDeclarations(bool strict, IFunction node)
         {
         {
-            var treeWalker = new ScriptWalker(strict, collectVarNames, collectLexicalNames, checkArgumentsReference);
+            var treeWalker = new ScriptWalker(strict, collectVarNames: true, collectLexicalNames: true, checkArgumentsReference: true);
             treeWalker.Visit(node.Body, null);
             treeWalker.Visit(node.Body, null);
 
 
-            if (checkArgumentsReference && !treeWalker._hasArgumentsReference)
+            if (!treeWalker._hasArgumentsReference)
             {
             {
                 ref readonly var parameters = ref node.Params;
                 ref readonly var parameters = ref node.Params;
                 for (var i = 0; i < parameters.Count; ++i)
                 for (var i = 0; i < parameters.Count; ++i)

+ 1 - 1
Jint/Jint.csproj

@@ -11,7 +11,7 @@
   </PropertyGroup>
   </PropertyGroup>
 
 
   <ItemGroup>
   <ItemGroup>
-    <PackageReference Include="Esprima" Version="3.0.0-beta-6" />
+    <PackageReference Include="Esprima" Version="3.0.0-beta-7" />
     <PackageReference Include="IsExternalInit" Version="1.0.2" PrivateAssets="all" />
     <PackageReference Include="IsExternalInit" Version="1.0.2" PrivateAssets="all" />
     <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="all" />
     <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="all" />
     <PackageReference Include="Nullable" Version="1.3.0" PrivateAssets="all" />
     <PackageReference Include="Nullable" Version="1.3.0" PrivateAssets="all" />

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

@@ -187,7 +187,7 @@ namespace Jint.Native.Function
             var scope = realmF.GlobalEnv;
             var scope = realmF.GlobalEnv;
             PrivateEnvironmentRecord? privateScope = null;
             PrivateEnvironmentRecord? privateScope = null;
 
 
-            var definition = new JintFunctionDefinition(_engine, function);
+            var definition = new JintFunctionDefinition(function);
             FunctionInstance F = OrdinaryFunctionCreate(proto, definition, function.Strict ? FunctionThisMode.Strict : FunctionThisMode.Global, scope, privateScope);
             FunctionInstance F = OrdinaryFunctionCreate(proto, definition, function.Strict ? FunctionThisMode.Strict : FunctionThisMode.Global, scope, privateScope);
             F.SetFunctionName(_functionNameAnonymous, force: true);
             F.SetFunctionName(_functionNameAnonymous, force: true);
 
 

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

@@ -30,7 +30,7 @@ namespace Jint.Native.Function
             Engine engine,
             Engine engine,
             Realm realm,
             Realm realm,
             JsString? name)
             JsString? name)
-            : this(engine, realm, name, FunctionThisMode.Global, ObjectClass.Function)
+            : this(engine, realm, name, FunctionThisMode.Global)
         {
         {
         }
         }
 
 

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

@@ -23,7 +23,7 @@ namespace Jint.Native.Function
             ObjectInstance? proto = null)
             ObjectInstance? proto = null)
             : this(
             : this(
                 engine,
                 engine,
-                new JintFunctionDefinition(engine, functionDeclaration),
+                new JintFunctionDefinition(functionDeclaration),
                 scope,
                 scope,
                 strict ? FunctionThisMode.Strict : FunctionThisMode.Global,
                 strict ? FunctionThisMode.Strict : FunctionThisMode.Global,
                 proto)
                 proto)
@@ -39,7 +39,7 @@ namespace Jint.Native.Function
             : base(engine, engine.Realm, function, scope, thisMode)
             : base(engine, engine.Realm, function, scope, thisMode)
         {
         {
             _prototype = proto ?? _engine.Realm.Intrinsics.Function.PrototypeObject;
             _prototype = proto ?? _engine.Realm.Intrinsics.Function.PrototypeObject;
-            _length = new LazyPropertyDescriptor(null, _ => JsNumber.Create(function.Initialize(this).Length), PropertyFlag.Configurable);
+            _length = new LazyPropertyDescriptor(null, _ => JsNumber.Create(function.Initialize().Length), PropertyFlag.Configurable);
 
 
             if (!function.Strict
             if (!function.Strict
                 && !engine._isStrict
                 && !engine._isStrict

+ 4 - 4
Jint/Native/JsNumber.cs

@@ -93,7 +93,7 @@ namespace Jint.Native
         }
         }
 
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal static JsNumber Create(double value)
+        public static JsNumber Create(double value)
         {
         {
             // we expect zero to be on the fast path of integer mostly
             // we expect zero to be on the fast path of integer mostly
             var temp = _intToJsValue;
             var temp = _intToJsValue;
@@ -136,7 +136,7 @@ namespace Jint.Native
             return new JsNumber(value);
             return new JsNumber(value);
         }
         }
 
 
-        internal static JsNumber Create(byte value)
+        public static JsNumber Create(byte value)
         {
         {
             return _intToJsValue[value];
             return _intToJsValue[value];
         }
         }
@@ -151,7 +151,7 @@ namespace Jint.Native
             return new JsNumber(value);
             return new JsNumber(value);
         }
         }
 
 
-        internal static JsNumber Create(int value)
+        public static JsNumber Create(int value)
         {
         {
             var temp = _intToJsValue;
             var temp = _intToJsValue;
             if ((uint) value < (uint) temp.Length)
             if ((uint) value < (uint) temp.Length)
@@ -188,7 +188,7 @@ namespace Jint.Native
             return new JsNumber(value);
             return new JsNumber(value);
         }
         }
 
 
-        internal static JsNumber Create(long value)
+        public static JsNumber Create(long value)
         {
         {
             if ((ulong) value < (ulong) _intToJsValue.Length)
             if ((ulong) value < (ulong) _intToJsValue.Length)
             {
             {

+ 3 - 3
Jint/Native/RegExp/RegExpConstructor.cs

@@ -104,11 +104,11 @@ namespace Jint.Native.RegExp
 
 
             try
             try
             {
             {
-                var parserOptions = new ParserOptions();
-                var scanner = new Scanner("/" + p + "/" + flags, parserOptions);
+                var options = new ScannerOptions();
+                var scanner = new Scanner("/" + p + "/" + flags, options);
 
 
                 // seems valid
                 // seems valid
-                r.Value = scanner.ParseRegex(p, f, parserOptions.RegexTimeout);
+                r.Value = scanner.ParseRegex(p, f, options.RegexTimeout);
 
 
                 var timeout = _engine.Options.Constraints.RegexTimeout;
                 var timeout = _engine.Options.Constraints.RegexTimeout;
                 if (timeout.Ticks > 0)
                 if (timeout.Ticks > 0)

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

@@ -24,13 +24,13 @@ namespace Jint.Runtime.Environments
             return _dictionary is not null && _dictionary.ContainsKey(name);
             return _dictionary is not null && _dictionary.ContainsKey(name);
         }
         }
 
 
-        internal sealed override bool HasBinding(in BindingName name)
+        internal sealed override bool HasBinding(BindingName name)
         {
         {
             return _dictionary is not null &&_dictionary.ContainsKey(name.Key);
             return _dictionary is not null &&_dictionary.ContainsKey(name.Key);
         }
         }
 
 
         internal override bool TryGetBinding(
         internal override bool TryGetBinding(
-            in BindingName name,
+            BindingName name,
             bool strict,
             bool strict,
             out Binding binding,
             out Binding binding,
             [NotNullWhen(true)] out JsValue? value)
             [NotNullWhen(true)] out JsValue? value)
@@ -71,7 +71,7 @@ namespace Jint.Runtime.Environments
             _dictionary.SetOrUpdateValue(name, static (current, value) => current.ChangeValue(value), value);
             _dictionary.SetOrUpdateValue(name, static (current, value) => current.ChangeValue(value), value);
         }
         }
 
 
-        internal sealed override void SetMutableBinding(in BindingName name, JsValue value, bool strict)
+        internal sealed override void SetMutableBinding(BindingName name, JsValue value, bool strict)
         {
         {
             SetMutableBinding(name.Key.Name, value, strict);
             SetMutableBinding(name.Key.Name, value, strict);
         }
         }

+ 13 - 5
Jint/Runtime/Environments/EnvironmentRecord.cs

@@ -25,10 +25,10 @@ namespace Jint.Runtime.Environments
         /// <returns><c>true</c> if it does and <c>false</c> if it does not.</returns>
         /// <returns><c>true</c> if it does and <c>false</c> if it does not.</returns>
         public abstract bool HasBinding(string name);
         public abstract bool HasBinding(string name);
 
 
-        internal abstract bool HasBinding(in BindingName name);
+        internal abstract bool HasBinding(BindingName name);
 
 
         internal abstract bool TryGetBinding(
         internal abstract bool TryGetBinding(
-            in BindingName name,
+            BindingName name,
             bool strict,
             bool strict,
             out Binding binding,
             out Binding binding,
             [NotNullWhen(true)] out JsValue? value);
             [NotNullWhen(true)] out JsValue? value);
@@ -62,7 +62,7 @@ namespace Jint.Runtime.Environments
         /// <param name="strict">The identify strict mode references.</param>
         /// <param name="strict">The identify strict mode references.</param>
         public abstract void SetMutableBinding(string name, JsValue value, bool strict);
         public abstract void SetMutableBinding(string name, JsValue value, bool strict);
 
 
-        internal abstract void SetMutableBinding(in BindingName name, JsValue value, bool strict);
+        internal abstract void SetMutableBinding(BindingName name, JsValue value, bool strict);
 
 
         /// <summary>
         /// <summary>
         /// Returns the value of an already existing binding from an environment record.
         /// Returns the value of an already existing binding from an environment record.
@@ -122,15 +122,23 @@ namespace Jint.Runtime.Environments
         /// Helper to cache JsString/Key when environments use different lookups.
         /// Helper to cache JsString/Key when environments use different lookups.
         /// </summary>
         /// </summary>
         [DebuggerDisplay("\"{Key.Name}\"")]
         [DebuggerDisplay("\"{Key.Name}\"")]
-        internal readonly struct BindingName
+        internal sealed class BindingName
         {
         {
             public readonly Key Key;
             public readonly Key Key;
             public readonly JsString StringValue;
             public readonly JsString StringValue;
+            public readonly bool HasEvalOrArguments;
+            public readonly JsValue? CalculatedValue;
 
 
             public BindingName(string value)
             public BindingName(string value)
             {
             {
-                Key = (Key) value;
+                var key = (Key) value;
+                Key = key;
                 StringValue = JsString.Create(value);
                 StringValue = JsString.Create(value);
+                HasEvalOrArguments = key == KnownKeys.Eval || key == KnownKeys.Arguments;
+                if (key == KnownKeys.Undefined)
+                {
+                    CalculatedValue = Undefined;
+                }
             }
             }
         }
         }
     }
     }

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

@@ -45,7 +45,7 @@ namespace Jint.Runtime.Environments
             return _global.HasProperty(new JsString(name));
             return _global.HasProperty(new JsString(name));
         }
         }
 
 
-        internal override bool HasBinding(in BindingName name)
+        internal override bool HasBinding(BindingName name)
         {
         {
             if (_declarativeRecord.HasBinding(name))
             if (_declarativeRecord.HasBinding(name))
             {
             {
@@ -61,7 +61,7 @@ namespace Jint.Runtime.Environments
         }
         }
 
 
         internal override bool TryGetBinding(
         internal override bool TryGetBinding(
-            in BindingName name,
+            BindingName name,
             bool strict,
             bool strict,
             out Binding binding,
             out Binding binding,
             [NotNullWhen(true)] out JsValue? value)
             [NotNullWhen(true)] out JsValue? value)
@@ -93,7 +93,7 @@ namespace Jint.Runtime.Environments
 
 
         [MethodImpl(MethodImplOptions.NoInlining)]
         [MethodImpl(MethodImplOptions.NoInlining)]
         private bool TryGetBindingForGlobalParent(
         private bool TryGetBindingForGlobalParent(
-            in BindingName name,
+            BindingName name,
             [NotNullWhen(true)] out JsValue? value)
             [NotNullWhen(true)] out JsValue? value)
         {
         {
             value = default;
             value = default;
@@ -177,7 +177,7 @@ namespace Jint.Runtime.Environments
             }
             }
         }
         }
 
 
-        internal override void SetMutableBinding(in BindingName name, JsValue value, bool strict)
+        internal override void SetMutableBinding(BindingName name, JsValue value, bool strict)
         {
         {
             if (_declarativeRecord.HasBinding(name))
             if (_declarativeRecord.HasBinding(name))
             {
             {

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

@@ -47,7 +47,7 @@ internal sealed class ModuleEnvironmentRecord : DeclarativeEnvironmentRecord
         return base.GetBindingValue(name, strict);
         return base.GetBindingValue(name, strict);
     }
     }
 
 
-    internal override bool TryGetBinding(in BindingName name, bool strict, out Binding binding, [NotNullWhen(true)] out JsValue? value)
+    internal override bool TryGetBinding(BindingName name, bool strict, out Binding binding, [NotNullWhen(true)] out JsValue? value)
     {
     {
         if (_importBindings.TryGetValue(name.Key, out var indirectBinding))
         if (_importBindings.TryGetValue(name.Key, out var indirectBinding))
         {
         {

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

@@ -45,7 +45,7 @@ namespace Jint.Runtime.Environments
             return !IsBlocked(name);
             return !IsBlocked(name);
         }
         }
 
 
-        internal override bool HasBinding(in BindingName name)
+        internal override bool HasBinding(BindingName name)
         {
         {
             var foundBinding = HasProperty(name.StringValue);
             var foundBinding = HasProperty(name.StringValue);
 
 
@@ -68,7 +68,7 @@ namespace Jint.Runtime.Environments
         }
         }
 
 
         internal override bool TryGetBinding(
         internal override bool TryGetBinding(
-            in BindingName name,
+            BindingName name,
             bool strict,
             bool strict,
             out Binding binding,
             out Binding binding,
             [NotNullWhen(true)] out JsValue? value)
             [NotNullWhen(true)] out JsValue? value)
@@ -145,7 +145,7 @@ namespace Jint.Runtime.Environments
             _bindingObject.Set(jsString, value);
             _bindingObject.Set(jsString, value);
         }
         }
 
 
-        internal override void SetMutableBinding(in BindingName name, JsValue value, bool strict)
+        internal override void SetMutableBinding(BindingName name, JsValue value, bool strict)
         {
         {
             if (strict && !_bindingObject.HasProperty(name.StringValue))
             if (strict && !_bindingObject.HasProperty(name.StringValue))
             {
             {

+ 1 - 1
Jint/Runtime/Interpreter/Expressions/JintArrowFunctionExpression.cs

@@ -10,7 +10,7 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
         public JintArrowFunctionExpression(Engine engine, ArrowFunctionExpression function) : base(function)
         public JintArrowFunctionExpression(Engine engine, ArrowFunctionExpression function) : base(function)
         {
         {
-            _function = new JintFunctionDefinition(engine, function);
+            _function = new JintFunctionDefinition(function);
         }
         }
 
 
         protected override ExpressionResult EvaluateInternal(EvaluationContext context)
         protected override ExpressionResult EvaluateInternal(EvaluationContext context)

+ 3 - 3
Jint/Runtime/Interpreter/Expressions/JintAssignmentExpression.cs

@@ -393,7 +393,7 @@ namespace Jint.Runtime.Interpreter.Expressions
                 var strict = StrictModeScope.IsStrictModeCode;
                 var strict = StrictModeScope.IsStrictModeCode;
                 if (JintEnvironment.TryGetIdentifierEnvironmentWithBinding(
                 if (JintEnvironment.TryGetIdentifierEnvironmentWithBinding(
                     env,
                     env,
-                    left._expressionName,
+                    left.Identifier,
                     out var environmentRecord))
                     out var environmentRecord))
                 {
                 {
                     if (strict && hasEvalOrArguments)
                     if (strict && hasEvalOrArguments)
@@ -411,10 +411,10 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
                     if (right._expression.IsFunctionDefinition())
                     if (right._expression.IsFunctionDefinition())
                     {
                     {
-                        ((FunctionInstance) rval).SetFunctionName(left._expressionName.StringValue);
+                        ((FunctionInstance) rval).SetFunctionName(left.Identifier.StringValue);
                     }
                     }
 
 
-                    environmentRecord.SetMutableBinding(left._expressionName, rval, strict);
+                    environmentRecord.SetMutableBinding(left.Identifier, rval, strict);
                     return ExpressionResult.Normal(rval, completion._source);
                     return ExpressionResult.Normal(rval, completion._source);
                 }
                 }
 
 

+ 1 - 1
Jint/Runtime/Interpreter/Expressions/JintExpression.cs

@@ -177,7 +177,7 @@ namespace Jint.Runtime.Interpreter.Expressions
                 Nodes.BinaryExpression => JintBinaryExpression.Build(engine, (BinaryExpression) expression),
                 Nodes.BinaryExpression => JintBinaryExpression.Build(engine, (BinaryExpression) expression),
                 Nodes.CallExpression => new JintCallExpression((CallExpression) expression),
                 Nodes.CallExpression => new JintCallExpression((CallExpression) expression),
                 Nodes.ConditionalExpression => new JintConditionalExpression(engine, (ConditionalExpression) expression),
                 Nodes.ConditionalExpression => new JintConditionalExpression(engine, (ConditionalExpression) expression),
-                Nodes.FunctionExpression => new JintFunctionExpression(engine, (FunctionExpression) expression),
+                Nodes.FunctionExpression => new JintFunctionExpression((FunctionExpression) expression),
                 Nodes.Identifier => new JintIdentifierExpression((Identifier) expression),
                 Nodes.Identifier => new JintIdentifierExpression((Identifier) expression),
                 Nodes.Literal => JintLiteralExpression.Build((Literal) expression),
                 Nodes.Literal => JintLiteralExpression.Build((Literal) expression),
                 Nodes.LogicalExpression => ((BinaryExpression) expression).Operator switch
                 Nodes.LogicalExpression => ((BinaryExpression) expression).Operator switch

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

@@ -8,9 +8,9 @@ namespace Jint.Runtime.Interpreter.Expressions
     {
     {
         private readonly JintFunctionDefinition _function;
         private readonly JintFunctionDefinition _function;
 
 
-        public JintFunctionExpression(Engine engine, FunctionExpression function) : base(function)
+        public JintFunctionExpression(FunctionExpression function) : base(function)
         {
         {
-            _function = new JintFunctionDefinition(engine, function);
+            _function = new JintFunctionDefinition(function);
         }
         }
 
 
         protected override ExpressionResult EvaluateInternal(EvaluationContext context)
         protected override ExpressionResult EvaluateInternal(EvaluationContext context)

+ 22 - 17
Jint/Runtime/Interpreter/Expressions/JintIdentifierExpression.cs

@@ -1,3 +1,5 @@
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
 using Esprima.Ast;
 using Esprima.Ast;
 using Jint.Native;
 using Jint.Native;
 using Jint.Native.Argument;
 using Jint.Native.Argument;
@@ -7,31 +9,27 @@ namespace Jint.Runtime.Interpreter.Expressions
 {
 {
     internal sealed class JintIdentifierExpression : JintExpression
     internal sealed class JintIdentifierExpression : JintExpression
     {
     {
-        internal readonly EnvironmentRecord.BindingName _expressionName;
-        private readonly JsValue? _calculatedValue;
-
         public JintIdentifierExpression(Identifier expression) : base(expression)
         public JintIdentifierExpression(Identifier expression) : base(expression)
         {
         {
-            _expressionName = new EnvironmentRecord.BindingName(expression.Name);
-            if (expression.Name == "undefined")
-            {
-                _calculatedValue = JsValue.Undefined;
-            }
         }
         }
 
 
-        public bool HasEvalOrArguments
-            => _expressionName.Key == KnownKeys.Eval || _expressionName.Key == KnownKeys.Arguments;
+        internal EnvironmentRecord.BindingName Identifier
+        {
+            get => (EnvironmentRecord.BindingName) (_expression.AssociatedData ??= new EnvironmentRecord.BindingName(((Identifier) _expression).Name));
+        }
+
+        public bool HasEvalOrArguments => Identifier.HasEvalOrArguments;
 
 
         protected override ExpressionResult EvaluateInternal(EvaluationContext context)
         protected override ExpressionResult EvaluateInternal(EvaluationContext context)
         {
         {
             var engine = context.Engine;
             var engine = context.Engine;
             var env = engine.ExecutionContext.LexicalEnvironment;
             var env = engine.ExecutionContext.LexicalEnvironment;
             var strict = StrictModeScope.IsStrictModeCode;
             var strict = StrictModeScope.IsStrictModeCode;
-            var identifierEnvironment = JintEnvironment.TryGetIdentifierEnvironmentWithBinding(env, _expressionName, out var temp)
+            var identifierEnvironment = JintEnvironment.TryGetIdentifierEnvironmentWithBinding(env, Identifier, out var temp)
                 ? temp
                 ? temp
                 : JsValue.Undefined;
                 : JsValue.Undefined;
 
 
-            return NormalCompletion(engine._referencePool.Rent(identifierEnvironment, _expressionName.StringValue, strict, thisValue: null));
+            return NormalCompletion(engine._referencePool.Rent(identifierEnvironment, Identifier.StringValue, strict, thisValue: null));
         }
         }
 
 
         public override Completion GetValue(EvaluationContext context)
         public override Completion GetValue(EvaluationContext context)
@@ -39,9 +37,9 @@ namespace Jint.Runtime.Interpreter.Expressions
             // need to notify correct node when taking shortcut
             // need to notify correct node when taking shortcut
             context.LastSyntaxElement = _expression;
             context.LastSyntaxElement = _expression;
 
 
-            if (_calculatedValue is not null)
+            if (Identifier.CalculatedValue is not null)
             {
             {
-                return new(CompletionType.Normal, _calculatedValue, _expression);
+                return new(CompletionType.Normal, Identifier.CalculatedValue, _expression);
             }
             }
 
 
             var strict = StrictModeScope.IsStrictModeCode;
             var strict = StrictModeScope.IsStrictModeCode;
@@ -50,19 +48,19 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
             if (JintEnvironment.TryGetIdentifierEnvironmentWithBindingValue(
             if (JintEnvironment.TryGetIdentifierEnvironmentWithBindingValue(
                 env,
                 env,
-                _expressionName,
+                Identifier,
                 strict,
                 strict,
                 out _,
                 out _,
                 out var value))
                 out var value))
             {
             {
                 if (value is null)
                 if (value is null)
                 {
                 {
-                    ExceptionHelper.ThrowReferenceError(engine.Realm, _expressionName.Key.Name + " has not been initialized");
+                    ThrowNotInitialized(engine);
                 }
                 }
             }
             }
             else
             else
             {
             {
-                var reference = engine._referencePool.Rent(JsValue.Undefined, _expressionName.StringValue, strict, thisValue: null);
+                var reference = engine._referencePool.Rent(JsValue.Undefined, Identifier.StringValue, strict, thisValue: null);
                 value = engine.GetValue(reference, true);
                 value = engine.GetValue(reference, true);
             }
             }
 
 
@@ -74,5 +72,12 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
             return new(CompletionType.Normal, value, _expression);
             return new(CompletionType.Normal, value, _expression);
         }
         }
+
+        [DoesNotReturn]
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        private void ThrowNotInitialized(Engine engine)
+        {
+            ExceptionHelper.ThrowReferenceError(engine.Realm, Identifier.Key.Name + " has not been initialized");
+        }
     }
     }
 }
 }

+ 6 - 3
Jint/Runtime/Interpreter/Expressions/JintLiteralExpression.cs

@@ -7,16 +7,19 @@ namespace Jint.Runtime.Interpreter.Expressions
 {
 {
     internal sealed class JintLiteralExpression : JintExpression
     internal sealed class JintLiteralExpression : JintExpression
     {
     {
+        private static readonly object _nullMarker = new();
+
         private JintLiteralExpression(Literal expression) : base(expression)
         private JintLiteralExpression(Literal expression) : base(expression)
         {
         {
         }
         }
 
 
         internal static JintExpression Build(Literal expression)
         internal static JintExpression Build(Literal expression)
         {
         {
-            var constantValue = ConvertToJsValue(expression);
-            if (constantValue is not null)
+            var value = expression.AssociatedData ??= ConvertToJsValue(expression) ?? _nullMarker;
+
+            if (value is JsValue constant)
             {
             {
-                return new JintConstantExpression(expression, constantValue);
+                return new JintConstantExpression(expression, constant);
             }
             }
 
 
             return new JintLiteralExpression(expression);
             return new JintLiteralExpression(expression);

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

@@ -50,12 +50,12 @@ namespace Jint.Runtime.Interpreter.Expressions
             var engine = context.Engine;
             var engine = context.Engine;
             if (_objectExpression is JintIdentifierExpression identifierExpression)
             if (_objectExpression is JintIdentifierExpression identifierExpression)
             {
             {
-                baseReferenceName = identifierExpression._expressionName.Key.Name;
+                baseReferenceName = identifierExpression.Identifier.Key.Name;
                 var strict = isStrictModeCode;
                 var strict = isStrictModeCode;
                 var env = engine.ExecutionContext.LexicalEnvironment;
                 var env = engine.ExecutionContext.LexicalEnvironment;
                 JintEnvironment.TryGetIdentifierEnvironmentWithBindingValue(
                 JintEnvironment.TryGetIdentifierEnvironmentWithBindingValue(
                     env,
                     env,
-                    identifierExpression._expressionName,
+                    identifierExpression.Identifier,
                     strict,
                     strict,
                     out _,
                     out _,
                     out baseValue);
                     out baseValue);

+ 3 - 3
Jint/Runtime/Interpreter/Expressions/JintObjectExpression.cs

@@ -47,7 +47,7 @@ namespace Jint.Runtime.Interpreter.Expressions
                     ExceptionHelper.ThrowSyntaxError(engine.Realm);
                     ExceptionHelper.ThrowSyntaxError(engine.Realm);
                 }
                 }
 
 
-                _functionDefinition = new JintFunctionDefinition(engine, function);
+                _functionDefinition = new JintFunctionDefinition(function);
                 return _functionDefinition;
                 return _functionDefinition;
             }
             }
         }
         }
@@ -90,7 +90,7 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
                     _properties[i] = new ObjectProperty(propName, p);
                     _properties[i] = new ObjectProperty(propName, p);
 
 
-                    if (p.Kind is PropertyKind.Init or PropertyKind.Data)
+                    if (p.Kind is PropertyKind.Init)
                     {
                     {
                         var propertyValue = p.Value;
                         var propertyValue = p.Value;
                         _valueExpressions[i] = Build(engine, (Expression) propertyValue);
                         _valueExpressions[i] = Build(engine, (Expression) propertyValue);
@@ -193,7 +193,7 @@ namespace Jint.Runtime.Interpreter.Expressions
                     propName = TypeConverter.ToPropertyKey(completion.Value);
                     propName = TypeConverter.ToPropertyKey(completion.Value);
                 }
                 }
 
 
-                if (property.Kind == PropertyKind.Init || property.Kind == PropertyKind.Data)
+                if (property.Kind == PropertyKind.Init)
                 {
                 {
                     var expr = _valueExpressions[i];
                     var expr = _valueExpressions[i];
                     var completion = expr.GetValue(context);
                     var completion = expr.GetValue(context);

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

@@ -118,7 +118,7 @@ namespace Jint.Runtime.Interpreter.Expressions
         private JsValue? UpdateIdentifier(EvaluationContext context)
         private JsValue? UpdateIdentifier(EvaluationContext context)
         {
         {
             var strict = StrictModeScope.IsStrictModeCode;
             var strict = StrictModeScope.IsStrictModeCode;
-            var name = _leftIdentifier!._expressionName;
+            var name = _leftIdentifier!.Identifier;
             var engine = context.Engine;
             var engine = context.Engine;
             var env = engine.ExecutionContext.LexicalEnvironment;
             var env = engine.ExecutionContext.LexicalEnvironment;
             if (JintEnvironment.TryGetIdentifierEnvironmentWithBindingValue(
             if (JintEnvironment.TryGetIdentifierEnvironmentWithBindingValue(

+ 22 - 28
Jint/Runtime/Interpreter/JintFunctionDefinition.cs

@@ -11,28 +11,21 @@ namespace Jint.Runtime.Interpreter;
 /// </summary>
 /// </summary>
 internal sealed class JintFunctionDefinition
 internal sealed class JintFunctionDefinition
 {
 {
-    private readonly Engine _engine;
-
     private JintExpression? _bodyExpression;
     private JintExpression? _bodyExpression;
     private JintStatementList? _bodyStatementList;
     private JintStatementList? _bodyStatementList;
 
 
     public readonly string? Name;
     public readonly string? Name;
-    public readonly bool Strict;
     public readonly IFunction Function;
     public readonly IFunction Function;
 
 
-    private State? _state;
-
-    public JintFunctionDefinition(
-        Engine engine,
-        IFunction function)
+    public JintFunctionDefinition(IFunction function)
     {
     {
-        _engine = engine;
         Function = function;
         Function = function;
         Name = !string.IsNullOrEmpty(function.Id?.Name) ? function.Id!.Name : null;
         Name = !string.IsNullOrEmpty(function.Id?.Name) ? function.Id!.Name : null;
-        Strict = function.Strict;
     }
     }
 
 
-    public FunctionThisMode ThisMode => Strict ? FunctionThisMode.Strict : FunctionThisMode.Global;
+    public bool Strict => Function.Strict;
+
+    public FunctionThisMode ThisMode => Function.Strict ? FunctionThisMode.Strict : FunctionThisMode.Global;
 
 
     /// <summary>
     /// <summary>
     /// https://tc39.es/ecma262/#sec-ordinarycallevaluatebody
     /// https://tc39.es/ecma262/#sec-ordinarycallevaluatebody
@@ -41,11 +34,11 @@ internal sealed class JintFunctionDefinition
     internal Completion EvaluateBody(EvaluationContext context, FunctionInstance functionObject, JsValue[] argumentsList)
     internal Completion EvaluateBody(EvaluationContext context, FunctionInstance functionObject, JsValue[] argumentsList)
     {
     {
         Completion result;
         Completion result;
-        var argumentsInstance = _engine.FunctionDeclarationInstantiation(functionObject, argumentsList);
+        var argumentsInstance = context.Engine.FunctionDeclarationInstantiation(functionObject, argumentsList);
         if (Function.Expression)
         if (Function.Expression)
         {
         {
             // https://tc39.es/ecma262/#sec-runtime-semantics-evaluateconcisebody
             // https://tc39.es/ecma262/#sec-runtime-semantics-evaluateconcisebody
-            _bodyExpression ??= JintExpression.Build(_engine, (Expression) Function.Body);
+            _bodyExpression ??= JintExpression.Build(context.Engine, (Expression) Function.Body);
             var jsValue = _bodyExpression.GetValue(context).GetValueOrDefault().Clone();
             var jsValue = _bodyExpression.GetValue(context).GetValueOrDefault().Clone();
             result = new Completion(CompletionType.Return, jsValue, null, Function.Body);
             result = new Completion(CompletionType.Return, jsValue, null, Function.Body);
         }
         }
@@ -76,9 +69,11 @@ internal sealed class JintFunctionDefinition
         return default;
         return default;
     }
     }
 
 
-    internal State Initialize(FunctionInstance functionInstance)
+    internal State Initialize()
     {
     {
-        return _state ??= DoInitialize(functionInstance);
+        var node = (Node) Function;
+        var state = (State) (node.AssociatedData ??= BuildState(Function));
+        return state;
     }
     }
 
 
     internal sealed class State
     internal sealed class State
@@ -110,19 +105,13 @@ internal sealed class JintFunctionDefinition
         }
         }
     }
     }
 
 
-    private State DoInitialize(FunctionInstance functionInstance)
+    internal static State BuildState(IFunction function)
     {
     {
         var state = new State();
         var state = new State();
 
 
-        ProcessParameters(Function, state, out var hasArguments);
-
-        var hoistingScope = HoistingScope.GetFunctionLevelDeclarations(
-            Strict,
-            Function,
-            collectVarNames: true,
-            collectLexicalNames: true,
-            checkArgumentsReference: true);
+        ProcessParameters(function, state, out var hasArguments);
 
 
+        var hoistingScope = HoistingScope.GetFunctionLevelDeclarations(function.Strict, function);
         var functionDeclarations = hoistingScope._functionDeclarations;
         var functionDeclarations = hoistingScope._functionDeclarations;
         var lexicalNames = hoistingScope._lexicalNames;
         var lexicalNames = hoistingScope._lexicalNames;
         state.VarNames = hoistingScope._varNames;
         state.VarNames = hoistingScope._varNames;
@@ -138,7 +127,7 @@ internal sealed class JintFunctionDefinition
                 var fn = d.Id!.Name;
                 var fn = d.Id!.Name;
                 if (state.FunctionNames.Add(fn))
                 if (state.FunctionNames.Add(fn))
                 {
                 {
-                    functionsToInitialize.AddFirst(new JintFunctionDefinition(_engine, d));
+                    functionsToInitialize.AddFirst(new JintFunctionDefinition(d));
                 }
                 }
             }
             }
         }
         }
@@ -148,7 +137,13 @@ internal sealed class JintFunctionDefinition
         const string ParameterNameArguments = "arguments";
         const string ParameterNameArguments = "arguments";
 
 
         state.ArgumentsObjectNeeded = true;
         state.ArgumentsObjectNeeded = true;
-        if (functionInstance._thisMode == FunctionThisMode.Lexical)
+        var thisMode = function.Strict ? FunctionThisMode.Strict : FunctionThisMode.Global;
+        if (function.Type == Nodes.ArrowFunctionExpression)
+        {
+            thisMode = FunctionThisMode.Lexical;
+        }
+
+        if (thisMode == FunctionThisMode.Lexical)
         {
         {
             state.ArgumentsObjectNeeded = false;
             state.ArgumentsObjectNeeded = false;
         }
         }
@@ -165,7 +160,7 @@ internal sealed class JintFunctionDefinition
             }
             }
         }
         }
 
 
-        if (state.ArgumentsObjectNeeded && !_engine._isDebugMode)
+        if (state.ArgumentsObjectNeeded)
         {
         {
             // just one extra check...
             // just one extra check...
             state.ArgumentsObjectNeeded = hoistingScope._hasArgumentsReference;
             state.ArgumentsObjectNeeded = hoistingScope._hasArgumentsReference;
@@ -179,7 +174,6 @@ internal sealed class JintFunctionDefinition
 
 
         state.ParameterBindings = parameterBindings;
         state.ParameterBindings = parameterBindings;
 
 
-
         var varsToInitialize = new List<State.VariableValuePair>();
         var varsToInitialize = new List<State.VariableValuePair>();
         if (!state.HasParameterExpressions)
         if (!state.HasParameterExpressions)
         {
         {

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

@@ -188,7 +188,7 @@ namespace Jint.Runtime.Interpreter
 
 
                 if (d is FunctionDeclaration functionDeclaration)
                 if (d is FunctionDeclaration functionDeclaration)
                 {
                 {
-                    var definition = new JintFunctionDefinition(engine, functionDeclaration);
+                    var definition = new JintFunctionDefinition(functionDeclaration);
                     var fn = definition.Name!;
                     var fn = definition.Name!;
                     var fo = env._engine.Realm.Intrinsics.Function.InstantiateFunctionObject(definition, env, privateEnv);
                     var fo = env._engine.Realm.Intrinsics.Function.InstantiateFunctionObject(definition, env, privateEnv);
                     env.InitializeBinding(fn, fo);
                     env.InitializeBinding(fn, fo);

+ 10 - 10
Jint/Runtime/KnownKeys.cs

@@ -1,12 +1,12 @@
-namespace Jint.Runtime
+namespace Jint.Runtime;
+
+internal static class KnownKeys
 {
 {
-    internal static class KnownKeys
-    {
-        internal static readonly Key Arguments = "arguments";
-        internal static readonly Key Caller = "caller";
-        internal static readonly Key Eval = "eval";
-        internal static readonly Key Length = "length";
-        internal static readonly Key Done = "done";
-        internal static readonly Key Value = "value";
-    }
+    internal static readonly Key Arguments = "arguments";
+    internal static readonly Key Caller = "caller";
+    internal static readonly Key Eval = "eval";
+    internal static readonly Key Length = "length";
+    internal static readonly Key Done = "done";
+    internal static readonly Key Value = "value";
+    internal static readonly Key Undefined = "undefined";
 }
 }

+ 1 - 1
Jint/Runtime/Modules/SourceTextModuleRecord.cs

@@ -316,7 +316,7 @@ internal class SourceTextModuleRecord : CyclicModuleRecord
             {
             {
                 var d = functionDeclarations[i];
                 var d = functionDeclarations[i];
                 var fn = d.Id?.Name ?? "*default*";
                 var fn = d.Id?.Name ?? "*default*";
-                var fd = new JintFunctionDefinition(_engine, d);
+                var fd = new JintFunctionDefinition(d);
                 env.CreateMutableBinding(fn, true);
                 env.CreateMutableBinding(fn, true);
                 // TODO private scope
                 // TODO private scope
                 var fo = realm.Intrinsics.Function.InstantiateFunctionObject(fd, env, privateScope: null);
                 var fo = realm.Intrinsics.Function.InstantiateFunctionObject(fd, env, privateScope: null);